diff options
author | Robert Adams | 2011-08-05 11:01:27 -0700 |
---|---|---|
committer | Mic Bowman | 2011-08-05 11:01:27 -0700 |
commit | 7640b5abf651e51ae2efd5f79f440768a595dbc9 (patch) | |
tree | 0b96cd6d2749f95888566f3e04f9798e04c21acd | |
parent | BulletSim: Update dlls (diff) | |
download | opensim-SC-7640b5abf651e51ae2efd5f79f440768a595dbc9.zip opensim-SC-7640b5abf651e51ae2efd5f79f440768a595dbc9.tar.gz opensim-SC-7640b5abf651e51ae2efd5f79f440768a595dbc9.tar.bz2 opensim-SC-7640b5abf651e51ae2efd5f79f440768a595dbc9.tar.xz |
BulletSim: Parameters settable from ini file. Linksets. Physical property value tuning
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | 11 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 267 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | 207 | ||||
-rw-r--r-- | OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | 44 | ||||
-rwxr-xr-x | bin/BulletSim-x86_64.dll | bin | 754688 -> 755200 bytes | |||
-rwxr-xr-x | bin/BulletSim.dll | bin | 654336 -> 653824 bytes | |||
-rw-r--r-- | bin/OpenSimDefaults.ini | 42 | ||||
-rwxr-xr-x | bin/libBulletSim.so | bin | 1734658 -> 1734700 bytes |
8 files changed, 358 insertions, 213 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 82361ad..9f9ebcc 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -51,8 +51,6 @@ public class BSCharacter : PhysicsActor | |||
51 | private Vector3 _position; | 51 | private Vector3 _position; |
52 | private float _mass = 80f; | 52 | private float _mass = 80f; |
53 | public float _density = 60f; | 53 | public float _density = 60f; |
54 | public float CAPSULE_RADIUS = 0.37f; | ||
55 | public float CAPSULE_LENGTH = 2.140599f; | ||
56 | private Vector3 _force; | 54 | private Vector3 _force; |
57 | private Vector3 _velocity; | 55 | private Vector3 _velocity; |
58 | private Vector3 _torque; | 56 | private Vector3 _torque; |
@@ -96,7 +94,8 @@ public class BSCharacter : PhysicsActor | |||
96 | _velocity = Vector3.Zero; | 94 | _velocity = Vector3.Zero; |
97 | _buoyancy = 0f; // characters return a buoyancy of zero | 95 | _buoyancy = 0f; // characters return a buoyancy of zero |
98 | _scale = new Vector3(1f, 1f, 1f); | 96 | _scale = new Vector3(1f, 1f, 1f); |
99 | float AVvolume = (float) (Math.PI*Math.Pow(CAPSULE_RADIUS, 2)*CAPSULE_LENGTH); | 97 | float AVvolume = (float) (Math.PI*Math.Pow(_scene.Params.avatarCapsuleRadius, 2)*_scene.Params.avatarCapsuleHeight); |
98 | _density = _scene.Params.avatarDensity; | ||
100 | _mass = _density*AVvolume; | 99 | _mass = _density*AVvolume; |
101 | 100 | ||
102 | ShapeData shapeData = new ShapeData(); | 101 | ShapeData shapeData = new ShapeData(); |
@@ -109,6 +108,8 @@ public class BSCharacter : PhysicsActor | |||
109 | shapeData.Mass = _mass; | 108 | shapeData.Mass = _mass; |
110 | shapeData.Buoyancy = isFlying ? 1f : 0f; | 109 | shapeData.Buoyancy = isFlying ? 1f : 0f; |
111 | shapeData.Static = ShapeData.numericFalse; | 110 | shapeData.Static = ShapeData.numericFalse; |
111 | shapeData.Friction = _scene.Params.avatarFriction; | ||
112 | shapeData.Restitution = _scene.Params.defaultRestitution; | ||
112 | 113 | ||
113 | // do actual create at taint time | 114 | // do actual create at taint time |
114 | _scene.TaintedObject(delegate() | 115 | _scene.TaintedObject(delegate() |
@@ -395,9 +396,9 @@ public class BSCharacter : PhysicsActor | |||
395 | _acceleration = entprop.Acceleration; | 396 | _acceleration = entprop.Acceleration; |
396 | changed = true; | 397 | changed = true; |
397 | } | 398 | } |
398 | if (_rotationalVelocity != entprop.AngularVelocity) | 399 | if (_rotationalVelocity != entprop.RotationalVelocity) |
399 | { | 400 | { |
400 | _rotationalVelocity = entprop.AngularVelocity; | 401 | _rotationalVelocity = entprop.RotationalVelocity; |
401 | changed = true; | 402 | changed = true; |
402 | } | 403 | } |
403 | if (changed) | 404 | if (changed) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index f2ab2d9..04cb452 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -71,6 +71,7 @@ public sealed class BSPrim : PhysicsActor | |||
71 | private bool _isPhysical; | 71 | private bool _isPhysical; |
72 | private bool _flying; | 72 | private bool _flying; |
73 | private float _friction; | 73 | private float _friction; |
74 | private float _restitution; | ||
74 | private bool _setAlwaysRun; | 75 | private bool _setAlwaysRun; |
75 | private bool _throttleUpdates; | 76 | private bool _throttleUpdates; |
76 | private bool _isColliding; | 77 | private bool _isColliding; |
@@ -101,7 +102,7 @@ public sealed class BSPrim : PhysicsActor | |||
101 | private float _PIDHoverTao; | 102 | private float _PIDHoverTao; |
102 | 103 | ||
103 | public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, | 104 | public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, |
104 | OMV.Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical) | 105 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) |
105 | { | 106 | { |
106 | // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); | 107 | // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); |
107 | _localID = localID; | 108 | _localID = localID; |
@@ -113,15 +114,16 @@ public sealed class BSPrim : PhysicsActor | |||
113 | _orientation = rotation; | 114 | _orientation = rotation; |
114 | _buoyancy = 1f; | 115 | _buoyancy = 1f; |
115 | _velocity = OMV.Vector3.Zero; | 116 | _velocity = OMV.Vector3.Zero; |
117 | _rotationalVelocity = OMV.Vector3.Zero; | ||
116 | _angularVelocity = OMV.Vector3.Zero; | 118 | _angularVelocity = OMV.Vector3.Zero; |
117 | _mesh = mesh; | ||
118 | _hullKey = 0; | 119 | _hullKey = 0; |
119 | _pbs = pbs; | 120 | _pbs = pbs; |
120 | _isPhysical = pisPhysical; | 121 | _isPhysical = pisPhysical; |
121 | _isVolumeDetect = false; | 122 | _isVolumeDetect = false; |
122 | _subscribedEventsMs = 0; | 123 | _subscribedEventsMs = 0; |
123 | _friction = _scene.DefaultFriction; // TODO: compute based on object material | 124 | _friction = _scene.Params.defaultFriction; // TODO: compute based on object material |
124 | _density = _scene.DefaultDensity; // TODO: compute based on object material | 125 | _density = _scene.Params.defaultDensity; // TODO: compute based on object material |
126 | _restitution = _scene.Params.defaultRestitution; | ||
125 | _parentPrim = null; // not a child or a parent | 127 | _parentPrim = null; // not a child or a parent |
126 | _vehicle = new BSDynamics(this); // add vehicleness | 128 | _vehicle = new BSDynamics(this); // add vehicleness |
127 | _childrenPrims = new List<BSPrim>(); | 129 | _childrenPrims = new List<BSPrim>(); |
@@ -132,8 +134,7 @@ public sealed class BSPrim : PhysicsActor | |||
132 | // do the actual object creation at taint time | 134 | // do the actual object creation at taint time |
133 | _scene.TaintedObject(delegate() | 135 | _scene.TaintedObject(delegate() |
134 | { | 136 | { |
135 | CreateGeom(); | 137 | RecreateGeomAndObject(); |
136 | CreateObject(); | ||
137 | }); | 138 | }); |
138 | } | 139 | } |
139 | 140 | ||
@@ -239,6 +240,7 @@ public sealed class BSPrim : PhysicsActor | |||
239 | return; | 240 | return; |
240 | } | 241 | } |
241 | 242 | ||
243 | // I am the root of a linkset and a new child is being added | ||
242 | public void AddChildToLinkset(BSPrim pchild) | 244 | public void AddChildToLinkset(BSPrim pchild) |
243 | { | 245 | { |
244 | BSPrim child = pchild; | 246 | BSPrim child = pchild; |
@@ -254,6 +256,8 @@ public sealed class BSPrim : PhysicsActor | |||
254 | return; | 256 | return; |
255 | } | 257 | } |
256 | 258 | ||
259 | // I am the root of a linkset and one of my children is being removed. | ||
260 | // Safe to call even if the child is not really in my linkset. | ||
257 | public void RemoveChildFromLinkset(BSPrim pchild) | 261 | public void RemoveChildFromLinkset(BSPrim pchild) |
258 | { | 262 | { |
259 | BSPrim child = pchild; | 263 | BSPrim child = pchild; |
@@ -290,6 +294,17 @@ public sealed class BSPrim : PhysicsActor | |||
290 | get { return (_parentPrim == null && _childrenPrims.Count != 0); } | 294 | get { return (_parentPrim == null && _childrenPrims.Count != 0); } |
291 | } | 295 | } |
292 | 296 | ||
297 | // Set motion values to zero. | ||
298 | // Do it to the properties so the values get set in the physics engine. | ||
299 | // Push the setting of the values to the viewer. | ||
300 | private void ZeroMotion() | ||
301 | { | ||
302 | Velocity = OMV.Vector3.Zero; | ||
303 | _acceleration = OMV.Vector3.Zero; | ||
304 | RotationalVelocity = OMV.Vector3.Zero; | ||
305 | base.RequestPhysicsterseUpdate(); | ||
306 | } | ||
307 | |||
293 | public override void LockAngularMotion(OMV.Vector3 axis) { return; } | 308 | public override void LockAngularMotion(OMV.Vector3 axis) { return; } |
294 | 309 | ||
295 | public override OMV.Vector3 Position { | 310 | public override OMV.Vector3 Position { |
@@ -390,18 +405,6 @@ public sealed class BSPrim : PhysicsActor | |||
390 | }); | 405 | }); |
391 | } | 406 | } |
392 | } | 407 | } |
393 | public OMV.Vector3 AngularVelocity | ||
394 | { | ||
395 | get { return _angularVelocity; } | ||
396 | set | ||
397 | { | ||
398 | _angularVelocity = value; | ||
399 | _scene.TaintedObject(delegate() | ||
400 | { | ||
401 | BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _angularVelocity); | ||
402 | }); | ||
403 | } | ||
404 | } | ||
405 | public override OMV.Vector3 Torque { | 408 | public override OMV.Vector3 Torque { |
406 | get { return _torque; } | 409 | get { return _torque; } |
407 | set { _torque = value; | 410 | set { _torque = value; |
@@ -419,11 +422,11 @@ public sealed class BSPrim : PhysicsActor | |||
419 | get { return _orientation; } | 422 | get { return _orientation; } |
420 | set { | 423 | set { |
421 | _orientation = value; | 424 | _orientation = value; |
425 | // m_log.DebugFormat("{0}: set orientation: id={1}, ori={2}", LogHeader, LocalID, _orientation); | ||
422 | _scene.TaintedObject(delegate() | 426 | _scene.TaintedObject(delegate() |
423 | { | 427 | { |
424 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); | 428 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
425 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); | 429 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); |
426 | // m_log.DebugFormat("{0}: set orientation: {1}", LogHeader, _orientation); | ||
427 | }); | 430 | }); |
428 | } | 431 | } |
429 | } | 432 | } |
@@ -505,8 +508,16 @@ public sealed class BSPrim : PhysicsActor | |||
505 | get { return _rotationalVelocity; } | 508 | get { return _rotationalVelocity; } |
506 | set { _rotationalVelocity = value; | 509 | set { _rotationalVelocity = value; |
507 | // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); | 510 | // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); |
511 | _scene.TaintedObject(delegate() | ||
512 | { | ||
513 | BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); | ||
514 | }); | ||
508 | } | 515 | } |
509 | } | 516 | } |
517 | public OMV.Vector3 AngularVelocity { | ||
518 | get { return _angularVelocity; } | ||
519 | set { _angularVelocity = value; } | ||
520 | } | ||
510 | public override bool Kinematic { | 521 | public override bool Kinematic { |
511 | get { return _kinematic; } | 522 | get { return _kinematic; } |
512 | set { _kinematic = value; | 523 | set { _kinematic = value; |
@@ -866,9 +877,6 @@ public sealed class BSPrim : PhysicsActor | |||
866 | 877 | ||
867 | returnMass = _density * volume; | 878 | returnMass = _density * volume; |
868 | 879 | ||
869 | if (returnMass <= 0) | ||
870 | returnMass = 0.0001f;//ckrinke: Mass must be greater then zero. | ||
871 | |||
872 | if (IsRootOfLinkset) | 880 | if (IsRootOfLinkset) |
873 | { | 881 | { |
874 | foreach (BSPrim prim in _childrenPrims) | 882 | foreach (BSPrim prim in _childrenPrims) |
@@ -877,8 +885,12 @@ public sealed class BSPrim : PhysicsActor | |||
877 | } | 885 | } |
878 | } | 886 | } |
879 | 887 | ||
880 | if (returnMass > _scene.maximumMassObject) | 888 | if (returnMass <= 0) |
881 | returnMass = _scene.maximumMassObject; | 889 | returnMass = 0.0001f; |
890 | |||
891 | if (returnMass > _scene.MaximumObjectMass) | ||
892 | returnMass = _scene.MaximumObjectMass; | ||
893 | |||
882 | return returnMass; | 894 | return returnMass; |
883 | }// end CalculateMass | 895 | }// end CalculateMass |
884 | #endregion Mass Calculation | 896 | #endregion Mass Calculation |
@@ -887,6 +899,15 @@ public sealed class BSPrim : PhysicsActor | |||
887 | // No locking here because this is done when we know physics is not simulating | 899 | // No locking here because this is done when we know physics is not simulating |
888 | private void CreateGeom() | 900 | private void CreateGeom() |
889 | { | 901 | { |
902 | // Since we're recreating new, get rid of any previously generated shape | ||
903 | if (_hullKey != 0) | ||
904 | { | ||
905 | // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); | ||
906 | BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); | ||
907 | _hullKey = 0; | ||
908 | _hulls.Clear(); | ||
909 | } | ||
910 | |||
890 | if (_mesh == null) | 911 | if (_mesh == null) |
891 | { | 912 | { |
892 | // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. | 913 | // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. |
@@ -902,21 +923,13 @@ public sealed class BSPrim : PhysicsActor | |||
902 | } | 923 | } |
903 | else | 924 | else |
904 | { | 925 | { |
905 | // m_log.DebugFormat("{0}: CreateGeom: mesh null. Defaulting to box of size {1}", LogHeader, _size); | 926 | // m_log.DebugFormat("{0}: CreateGeom: mesh null. Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); |
906 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; | 927 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; |
907 | _scale = _size; | 928 | _scale = _size; |
908 | } | 929 | } |
909 | } | 930 | } |
910 | else | 931 | else |
911 | { | 932 | { |
912 | if (_hullKey != 0) | ||
913 | { | ||
914 | // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); | ||
915 | BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); | ||
916 | _hullKey = 0; | ||
917 | _hulls.Clear(); | ||
918 | } | ||
919 | |||
920 | int[] indices = _mesh.getIndexListAsInt(); | 933 | int[] indices = _mesh.getIndexListAsInt(); |
921 | List<OMV.Vector3> vertices = _mesh.getVertexList(); | 934 | List<OMV.Vector3> vertices = _mesh.getVertexList(); |
922 | 935 | ||
@@ -997,7 +1010,7 @@ public sealed class BSPrim : PhysicsActor | |||
997 | 1010 | ||
998 | // create the hull definition in Bullet | 1011 | // create the hull definition in Bullet |
999 | _hullKey = (ulong)_pbs.GetHashCode(); | 1012 | _hullKey = (ulong)_pbs.GetHashCode(); |
1000 | // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid= {1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount); | 1013 | // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount); |
1001 | BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls); | 1014 | BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls); |
1002 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; | 1015 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; |
1003 | // meshes are already scaled by the meshmerizer | 1016 | // meshes are already scaled by the meshmerizer |
@@ -1006,6 +1019,8 @@ public sealed class BSPrim : PhysicsActor | |||
1006 | return; | 1019 | return; |
1007 | } | 1020 | } |
1008 | 1021 | ||
1022 | // Callback from convex hull creater with a newly created hull. | ||
1023 | // Just add it to the collection of hulls for this shape. | ||
1009 | private void HullReturn(ConvexResult result) | 1024 | private void HullReturn(ConvexResult result) |
1010 | { | 1025 | { |
1011 | _hulls.Add(result); | 1026 | _hulls.Add(result); |
@@ -1019,13 +1034,12 @@ public sealed class BSPrim : PhysicsActor | |||
1019 | if (IsRootOfLinkset) | 1034 | if (IsRootOfLinkset) |
1020 | { | 1035 | { |
1021 | // Create a linkset around this object | 1036 | // Create a linkset around this object |
1022 | CreateLinksetWithCompoundHull(); | 1037 | // CreateLinksetWithCompoundHull(); |
1023 | // CreateLinksetWithConstraints(); | 1038 | CreateLinksetWithConstraints(); |
1024 | } | 1039 | } |
1025 | else | 1040 | else |
1026 | { | 1041 | { |
1027 | // simple object | 1042 | // simple object |
1028 | // m_log.DebugFormat("{0}: CreateObject. ID={1}", LogHeader, LocalID); | ||
1029 | ShapeData shape; | 1043 | ShapeData shape; |
1030 | FillShapeInfo(out shape); | 1044 | FillShapeInfo(out shape); |
1031 | BulletSimAPI.CreateObject(_scene.WorldID, shape); | 1045 | BulletSimAPI.CreateObject(_scene.WorldID, shape); |
@@ -1034,6 +1048,7 @@ public sealed class BSPrim : PhysicsActor | |||
1034 | 1048 | ||
1035 | // Create a linkset by creating a compound hull at the root prim that consists of all | 1049 | // Create a linkset by creating a compound hull at the root prim that consists of all |
1036 | // the children. | 1050 | // the children. |
1051 | // NOTE: This does not allow proper collisions with the children prims so it is not a workable solution | ||
1037 | void CreateLinksetWithCompoundHull() | 1052 | void CreateLinksetWithCompoundHull() |
1038 | { | 1053 | { |
1039 | // If I am the root prim of a linkset, replace my physical shape with all the | 1054 | // If I am the root prim of a linkset, replace my physical shape with all the |
@@ -1055,8 +1070,27 @@ public sealed class BSPrim : PhysicsActor | |||
1055 | BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes); | 1070 | BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes); |
1056 | } | 1071 | } |
1057 | 1072 | ||
1073 | // Copy prim's info into the BulletSim shape description structure | ||
1074 | public void FillShapeInfo(out ShapeData shape) | ||
1075 | { | ||
1076 | shape.ID = _localID; | ||
1077 | shape.Type = _shapeType; | ||
1078 | shape.Position = _position; | ||
1079 | shape.Rotation = _orientation; | ||
1080 | shape.Velocity = _velocity; | ||
1081 | shape.Scale = _scale; | ||
1082 | shape.Mass = _isPhysical ? _mass : 0f; | ||
1083 | shape.Buoyancy = _buoyancy; | ||
1084 | shape.MeshKey = _hullKey; | ||
1085 | shape.Friction = _friction; | ||
1086 | shape.Restitution = _restitution; | ||
1087 | shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; | ||
1088 | shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; | ||
1089 | } | ||
1090 | |||
1058 | // Create the linkset by putting constraints between the objects of the set so they cannot move | 1091 | // Create the linkset by putting constraints between the objects of the set so they cannot move |
1059 | // relative to each other. | 1092 | // relative to each other. |
1093 | // TODO: make this more effeicient: a large linkset gets rebuilt over and over and prims are added | ||
1060 | void CreateLinksetWithConstraints() | 1094 | void CreateLinksetWithConstraints() |
1061 | { | 1095 | { |
1062 | // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1); | 1096 | // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1); |
@@ -1070,76 +1104,48 @@ public sealed class BSPrim : PhysicsActor | |||
1070 | // create constraints between the root prim and each of the children | 1104 | // create constraints between the root prim and each of the children |
1071 | foreach (BSPrim prim in _childrenPrims) | 1105 | foreach (BSPrim prim in _childrenPrims) |
1072 | { | 1106 | { |
1073 | // this is a constraint that allows no freedom of movement between the two objects | ||
1074 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | ||
1075 | // m_log.DebugFormat("{0}: CreateObject: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); | 1107 | // m_log.DebugFormat("{0}: CreateObject: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); |
1076 | 1108 | ||
1109 | // Zero motion for children so they don't interpolate | ||
1110 | prim.ZeroMotion(); | ||
1111 | |||
1077 | // relative position normalized to the root prim | 1112 | // relative position normalized to the root prim |
1078 | OMV.Vector3 childRelativePosition = (prim._position - this._position) * OMV.Quaternion.Inverse(this._orientation); | 1113 | OMV.Vector3 childRelativePosition = (prim._position - this._position) * OMV.Quaternion.Inverse(this._orientation); |
1079 | // OMV.Quaternion relativeRotation = OMV.Quaternion.Identity; | ||
1080 | 1114 | ||
1081 | // rotation is pointing up the vector between the object centers | 1115 | // relative rotation of the child to the parent |
1082 | OMV.Quaternion relativeRotation = OMV.Quaternion.CreateFromAxisAngle(childRelativePosition, 0f); | 1116 | OMV.Quaternion relativeRotation = OMV.Quaternion.Inverse(prim._orientation) * this._orientation; |
1083 | |||
1084 | /* // the logic for relative rotation from http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6391 | ||
1085 | OMV.Vector3 rrn = childRelativePosition; | ||
1086 | rrn.Normalize(); | ||
1087 | rrn /= rrn.X; | ||
1088 | OMV.Matrix4 rotmat = new OMV.Matrix4(rrn.X, rrn.Y, rrn.Z, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); | ||
1089 | OMV.Quaternion relativeRotation = OMV.Quaternion.CreateFromRotationMatrix(rotmat); | ||
1090 | */ | ||
1091 | 1117 | ||
1118 | // this is a constraint that allows no freedom of movement between the two objects | ||
1119 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | ||
1092 | BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID, | 1120 | BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID, |
1093 | childRelativePosition / 2, | 1121 | childRelativePosition, |
1094 | relativeRotation, | ||
1095 | -childRelativePosition / 2, | ||
1096 | relativeRotation, | 1122 | relativeRotation, |
1123 | OMV.Vector3.Zero, | ||
1124 | OMV.Quaternion.Identity, | ||
1097 | OMV.Vector3.Zero, OMV.Vector3.Zero, | 1125 | OMV.Vector3.Zero, OMV.Vector3.Zero, |
1098 | OMV.Vector3.Zero, OMV.Vector3.Zero); | 1126 | OMV.Vector3.Zero, OMV.Vector3.Zero); |
1099 | } | 1127 | } |
1100 | } | 1128 | } |
1101 | 1129 | ||
1102 | // Copy prim's info into the BulletSim shape description structure | ||
1103 | public void FillShapeInfo(out ShapeData shape) | ||
1104 | { | ||
1105 | shape.ID = _localID; | ||
1106 | shape.Type = _shapeType; | ||
1107 | shape.Position = _position; | ||
1108 | shape.Rotation = _orientation; | ||
1109 | shape.Velocity = _velocity; | ||
1110 | shape.Scale = _scale; | ||
1111 | shape.Mass = _isPhysical ? _mass : 0f; | ||
1112 | shape.Buoyancy = _buoyancy; | ||
1113 | shape.MeshKey = _hullKey; | ||
1114 | shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; | ||
1115 | shape.Friction = _friction; | ||
1116 | shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; | ||
1117 | } | ||
1118 | |||
1119 | // Rebuild the geometry and object. | 1130 | // Rebuild the geometry and object. |
1120 | // This is called when the shape changes so we need to recreate the mesh/hull. | 1131 | // This is called when the shape changes so we need to recreate the mesh/hull. |
1121 | // No locking here because this is done when the physics engine is not simulating | 1132 | // No locking here because this is done when the physics engine is not simulating |
1122 | private void RecreateGeomAndObject() | 1133 | private void RecreateGeomAndObject() |
1123 | { | 1134 | { |
1124 | if (_hullKey != 0) | ||
1125 | { | ||
1126 | // if a hull already exists, delete the old one | ||
1127 | BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); | ||
1128 | _hullKey = 0; | ||
1129 | } | ||
1130 | // If this object is complex or we are the root of a linkset, build a mesh. | 1135 | // If this object is complex or we are the root of a linkset, build a mesh. |
1131 | // The root of a linkset must be a mesh so we can create the linked compound object. | 1136 | // The root of a linkset must be a mesh so we can create the linked compound object. |
1132 | if (_scene.NeedsMeshing(_pbs) || IsRootOfLinkset ) | 1137 | // if (_scene.NeedsMeshing(_pbs) || IsRootOfLinkset ) |
1138 | if (_scene.NeedsMeshing(_pbs)) // linksets with constraints don't need a root mesh | ||
1133 | { | 1139 | { |
1134 | // m_log.DebugFormat("{0}: RecreateGeomAndObject: creating mesh", LogHeader); | 1140 | // m_log.DebugFormat("{0}: RecreateGeomAndObject: creating mesh", LogHeader); |
1135 | _mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, _scene.meshLOD, _isPhysical); | 1141 | _mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, _scene.MeshLOD, _isPhysical); |
1136 | } | 1142 | } |
1137 | else | 1143 | else |
1138 | { | 1144 | { |
1139 | // it's a BulletSim native shape. | 1145 | // implement the shape with a Bullet native shape. |
1140 | _mesh = null; | 1146 | _mesh = null; |
1141 | } | 1147 | } |
1142 | CreateGeom(); // create the geometry for this prim | 1148 | CreateGeom(); |
1143 | CreateObject(); | 1149 | CreateObject(); |
1144 | return; | 1150 | return; |
1145 | } | 1151 | } |
@@ -1152,48 +1158,82 @@ public sealed class BSPrim : PhysicsActor | |||
1152 | Rotation = 1 << 1, | 1158 | Rotation = 1 << 1, |
1153 | Velocity = 1 << 2, | 1159 | Velocity = 1 << 2, |
1154 | Acceleration = 1 << 3, | 1160 | Acceleration = 1 << 3, |
1155 | AngularVel = 1 << 4 | 1161 | RotationalVel = 1 << 4 |
1156 | } | 1162 | } |
1157 | 1163 | ||
1164 | const float ROTATION_TOLERANCE = 0.01f; | ||
1165 | const float VELOCITY_TOLERANCE = 0.001f; | ||
1166 | const float POSITION_TOLERANCE = 0.05f; | ||
1167 | const float ACCELERATION_TOLERANCE = 0.01f; | ||
1168 | const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; | ||
1169 | const bool SHOULD_DAMP_UPDATES = false; | ||
1170 | |||
1158 | public void UpdateProperties(EntityProperties entprop) | 1171 | public void UpdateProperties(EntityProperties entprop) |
1159 | { | 1172 | { |
1160 | UpdatedProperties changed = 0; | 1173 | UpdatedProperties changed = 0; |
1161 | // assign to the local variables so the normal set action does not happen | 1174 | if (SHOULD_DAMP_UPDATES) |
1162 | if (_position != entprop.Position) | ||
1163 | { | ||
1164 | _position = entprop.Position; | ||
1165 | // m_log.DebugFormat("{0}: UpdateProperties: position = {1}", LogHeader, _position); | ||
1166 | changed |= UpdatedProperties.Position; | ||
1167 | } | ||
1168 | if (_orientation != entprop.Rotation) | ||
1169 | { | ||
1170 | _orientation = entprop.Rotation; | ||
1171 | // m_log.DebugFormat("{0}: UpdateProperties: rotation = {1}", LogHeader, _orientation); | ||
1172 | changed |= UpdatedProperties.Rotation; | ||
1173 | } | ||
1174 | if (_velocity != entprop.Velocity) | ||
1175 | { | ||
1176 | _velocity = entprop.Velocity; | ||
1177 | // m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity); | ||
1178 | changed |= UpdatedProperties.Velocity; | ||
1179 | } | ||
1180 | if (_acceleration != entprop.Acceleration) | ||
1181 | { | ||
1182 | _acceleration = entprop.Acceleration; | ||
1183 | // m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration); | ||
1184 | changed |= UpdatedProperties.Acceleration; | ||
1185 | } | ||
1186 | if (_rotationalVelocity != entprop.AngularVelocity) | ||
1187 | { | 1175 | { |
1188 | _rotationalVelocity = entprop.AngularVelocity; | 1176 | // assign to the local variables so the normal set action does not happen |
1189 | // m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity); | 1177 | // if (_position != entprop.Position) |
1190 | changed |= UpdatedProperties.AngularVel; | 1178 | if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE)) |
1179 | { | ||
1180 | _position = entprop.Position; | ||
1181 | // m_log.DebugFormat("{0}: UpdateProperties: id={1}, pos = {2}", LogHeader, LocalID, _position); | ||
1182 | changed |= UpdatedProperties.Position; | ||
1183 | } | ||
1184 | // if (_orientation != entprop.Rotation) | ||
1185 | if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE)) | ||
1186 | { | ||
1187 | _orientation = entprop.Rotation; | ||
1188 | // m_log.DebugFormat("{0}: UpdateProperties: id={1}, rot = {2}", LogHeader, LocalID, _orientation); | ||
1189 | changed |= UpdatedProperties.Rotation; | ||
1190 | } | ||
1191 | // if (_velocity != entprop.Velocity) | ||
1192 | if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE)) | ||
1193 | { | ||
1194 | _velocity = entprop.Velocity; | ||
1195 | // m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity); | ||
1196 | changed |= UpdatedProperties.Velocity; | ||
1197 | } | ||
1198 | // if (_acceleration != entprop.Acceleration) | ||
1199 | if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE)) | ||
1200 | { | ||
1201 | _acceleration = entprop.Acceleration; | ||
1202 | // m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration); | ||
1203 | changed |= UpdatedProperties.Acceleration; | ||
1204 | } | ||
1205 | // if (_rotationalVelocity != entprop.RotationalVelocity) | ||
1206 | if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE)) | ||
1207 | { | ||
1208 | _rotationalVelocity = entprop.RotationalVelocity; | ||
1209 | // m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity); | ||
1210 | changed |= UpdatedProperties.RotationalVel; | ||
1211 | } | ||
1212 | if (changed != 0) | ||
1213 | { | ||
1214 | // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); | ||
1215 | // Only update the position of single objects and linkset roots | ||
1216 | if (this._parentPrim == null) | ||
1217 | { | ||
1218 | // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); | ||
1219 | base.RequestPhysicsterseUpdate(); | ||
1220 | } | ||
1221 | } | ||
1191 | } | 1222 | } |
1192 | if (changed != 0) | 1223 | else |
1193 | { | 1224 | { |
1194 | // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); | 1225 | // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. |
1195 | if (this._parentPrim == null) | 1226 | if (this._parentPrim == null) |
1227 | { | ||
1228 | // Assign to the local variables so the normal set action does not happen | ||
1229 | _position = entprop.Position; | ||
1230 | _orientation = entprop.Rotation; | ||
1231 | _velocity = entprop.Velocity; | ||
1232 | _acceleration = entprop.Acceleration; | ||
1233 | _rotationalVelocity = entprop.RotationalVelocity; | ||
1234 | // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); | ||
1196 | base.RequestPhysicsterseUpdate(); | 1235 | base.RequestPhysicsterseUpdate(); |
1236 | } | ||
1197 | } | 1237 | } |
1198 | } | 1238 | } |
1199 | 1239 | ||
@@ -1201,7 +1241,8 @@ public sealed class BSPrim : PhysicsActor | |||
1201 | public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) | 1241 | public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) |
1202 | { | 1242 | { |
1203 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); | 1243 | // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); |
1204 | // The following makes IsColliding() and IsCollidingGround() work | 1244 | |
1245 | // The following lines make IsColliding() and IsCollidingGround() work | ||
1205 | _collidingStep = _scene.SimulationStep; | 1246 | _collidingStep = _scene.SimulationStep; |
1206 | if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) | 1247 | if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) |
1207 | { | 1248 | { |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 7c11f2b..de86d59 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -71,11 +71,17 @@ public class BSScene : PhysicsScene | |||
71 | private uint m_worldID; | 71 | private uint m_worldID; |
72 | public uint WorldID { get { return m_worldID; } } | 72 | public uint WorldID { get { return m_worldID; } } |
73 | 73 | ||
74 | private bool m_initialized = false; | ||
75 | |||
74 | public IMesher mesher; | 76 | public IMesher mesher; |
75 | public int meshLOD = 32; | 77 | private int m_meshLOD; |
78 | public int MeshLOD | ||
79 | { | ||
80 | get { return m_meshLOD; } | ||
81 | } | ||
76 | 82 | ||
77 | private int m_maxSubSteps = 10; | 83 | private int m_maxSubSteps; |
78 | private float m_fixedTimeStep = 1f / 60f; | 84 | private float m_fixedTimeStep; |
79 | private long m_simulationStep = 0; | 85 | private long m_simulationStep = 0; |
80 | public long SimulationStep { get { return m_simulationStep; } } | 86 | public long SimulationStep { get { return m_simulationStep; } } |
81 | 87 | ||
@@ -84,68 +90,65 @@ public class BSScene : PhysicsScene | |||
84 | private int m_simulationNowTime; | 90 | private int m_simulationNowTime; |
85 | public int SimulationNowTime { get { return m_simulationNowTime; } } | 91 | public int SimulationNowTime { get { return m_simulationNowTime; } } |
86 | 92 | ||
87 | private int m_maxCollisionsPerFrame = 2048; | 93 | private int m_maxCollisionsPerFrame; |
88 | private CollisionDesc[] m_collisionArray; | 94 | private CollisionDesc[] m_collisionArray; |
89 | private GCHandle m_collisionArrayPinnedHandle; | 95 | private GCHandle m_collisionArrayPinnedHandle; |
90 | 96 | ||
91 | private int m_maxUpdatesPerFrame = 2048; | 97 | private int m_maxUpdatesPerFrame; |
92 | private EntityProperties[] m_updateArray; | 98 | private EntityProperties[] m_updateArray; |
93 | private GCHandle m_updateArrayPinnedHandle; | 99 | private GCHandle m_updateArrayPinnedHandle; |
94 | 100 | ||
95 | private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed | 101 | private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed |
96 | private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes | 102 | private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes |
97 | public float maximumMassObject = 10000.01f; | ||
98 | 103 | ||
99 | public const uint TERRAIN_ID = 0; | 104 | public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero |
100 | public const uint GROUNDPLANE_ID = 1; | 105 | public const uint GROUNDPLANE_ID = 1; |
101 | 106 | ||
102 | public float DefaultFriction = 0.70f; | 107 | public ConfigurationParameters Params |
103 | public float DefaultDensity = 10.000006836f; // Aluminum g/cm3; TODO: compute based on object material | 108 | { |
104 | public Vector3 DefaultGravity = new Vector3(0, 0, -9.80665f); | 109 | get { return m_params[0]; } |
110 | } | ||
111 | public Vector3 DefaultGravity | ||
112 | { | ||
113 | get { return new Vector3(0f, 0f, Params.gravity); } | ||
114 | } | ||
115 | |||
116 | private float m_maximumObjectMass; | ||
117 | public float MaximumObjectMass | ||
118 | { | ||
119 | get { return m_maximumObjectMass; } | ||
120 | } | ||
105 | 121 | ||
106 | public delegate void TaintCallback(); | 122 | public delegate void TaintCallback(); |
107 | private List<TaintCallback> _taintedObjects; | 123 | private List<TaintCallback> _taintedObjects; |
108 | private Object _taintLock = new Object(); | 124 | private Object _taintLock = new Object(); |
109 | 125 | ||
110 | // A pointer to an instance if this structure is passed to the C++ code | 126 | // A pointer to an instance if this structure is passed to the C++ code |
111 | // Format of this structure must match the definition in the C++ code | 127 | ConfigurationParameters[] m_params; |
112 | private struct ConfigurationParameters | ||
113 | { | ||
114 | public float defaultFriction; | ||
115 | public float defaultDensity; | ||
116 | public float collisionMargin; | ||
117 | public float gravity; | ||
118 | |||
119 | public float linearDamping; | ||
120 | public float angularDamping; | ||
121 | public float deactivationTime; | ||
122 | public float linearSleepingThreshold; | ||
123 | public float angularSleepingThreshold; | ||
124 | |||
125 | public float terrainFriction; | ||
126 | public float terrainHitFriction; | ||
127 | public float terrainRestitution; | ||
128 | public float avatarFriction; | ||
129 | public float avatarCapsuleRadius; | ||
130 | public float avatarCapsuleHeight; | ||
131 | } | ||
132 | ConfigurationParameters m_params; | ||
133 | GCHandle m_paramsHandle; | 128 | GCHandle m_paramsHandle; |
134 | 129 | ||
135 | private BulletSimAPI.DebugLogCallback debugLogCallbackHandle; | 130 | private BulletSimAPI.DebugLogCallback debugLogCallbackHandle; |
136 | 131 | ||
137 | public BSScene(string identifier) | 132 | public BSScene(string identifier) |
138 | { | 133 | { |
134 | m_initialized = false; | ||
139 | } | 135 | } |
140 | 136 | ||
141 | public override void Initialise(IMesher meshmerizer, IConfigSource config) | 137 | public override void Initialise(IMesher meshmerizer, IConfigSource config) |
142 | { | 138 | { |
143 | m_params = new ConfigurationParameters(); | 139 | // Allocate pinned memory to pass parameters. |
140 | m_params = new ConfigurationParameters[1]; | ||
144 | m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); | 141 | m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); |
145 | 142 | ||
146 | // Set default values for physics parameters plus any overrides from the ini file | 143 | // Set default values for physics parameters plus any overrides from the ini file |
147 | GetInitialParameterValues(config); | 144 | GetInitialParameterValues(config); |
148 | 145 | ||
146 | // allocate more pinned memory close to the above in an attempt to get the memory all together | ||
147 | m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame]; | ||
148 | m_collisionArrayPinnedHandle = GCHandle.Alloc(m_collisionArray, GCHandleType.Pinned); | ||
149 | m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; | ||
150 | m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); | ||
151 | |||
149 | // if Debug, enable logging from the unmanaged code | 152 | // if Debug, enable logging from the unmanaged code |
150 | if (m_log.IsDebugEnabled) | 153 | if (m_log.IsDebugEnabled) |
151 | { | 154 | { |
@@ -160,68 +163,95 @@ public class BSScene : PhysicsScene | |||
160 | // The bounding box for the simulated world | 163 | // The bounding box for the simulated world |
161 | Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 4096f); | 164 | Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 4096f); |
162 | 165 | ||
163 | // Allocate pinned memory to pass back object property updates and collisions from simulation step | ||
164 | m_collisionArray = new CollisionDesc[m_maxCollisionsPerFrame]; | ||
165 | m_collisionArrayPinnedHandle = GCHandle.Alloc(m_collisionArray, GCHandleType.Pinned); | ||
166 | m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; | ||
167 | m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); | ||
168 | |||
169 | // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); | 166 | // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); |
170 | m_worldID = BulletSimAPI.Initialize(worldExtent, | 167 | m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), |
171 | m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), | 168 | m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), |
172 | m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); | 169 | m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); |
170 | |||
171 | m_initialized = true; | ||
173 | } | 172 | } |
174 | 173 | ||
174 | // All default parameter values are set here. There should be no values set in the | ||
175 | // variable definitions. | ||
175 | private void GetInitialParameterValues(IConfigSource config) | 176 | private void GetInitialParameterValues(IConfigSource config) |
176 | { | 177 | { |
178 | ConfigurationParameters parms = new ConfigurationParameters(); | ||
179 | |||
177 | _meshSculptedPrim = true; // mesh sculpted prims | 180 | _meshSculptedPrim = true; // mesh sculpted prims |
178 | _forceSimplePrimMeshing = false; // use complex meshing if called for | 181 | _forceSimplePrimMeshing = false; // use complex meshing if called for |
179 | 182 | ||
180 | // Set the default values for the physics parameters | 183 | m_meshLOD = 32; |
181 | m_params.defaultFriction = 0.70f; | 184 | |
182 | m_params.defaultDensity = 10.000006836f; // Aluminum g/cm3 | 185 | m_maxSubSteps = 10; |
183 | m_params.collisionMargin = 0.0f; | 186 | m_fixedTimeStep = 1f / 60f; |
184 | m_params.gravity = -9.80665f; | 187 | m_maxCollisionsPerFrame = 2048; |
185 | 188 | m_maxUpdatesPerFrame = 2048; | |
186 | m_params.linearDamping = 0.1f; | 189 | m_maximumObjectMass = 10000.01f; |
187 | m_params.angularDamping = 0.85f; | 190 | |
188 | m_params.deactivationTime = 0.2f; | 191 | parms.defaultFriction = 0.70f; |
189 | m_params.linearSleepingThreshold = 0.8f; | 192 | parms.defaultDensity = 10.000006836f; // Aluminum g/cm3 |
190 | m_params.angularSleepingThreshold = 1.0f; | 193 | parms.defaultRestitution = 0f; |
191 | 194 | parms.collisionMargin = 0.0f; | |
192 | m_params.terrainFriction = 0.85f; | 195 | parms.gravity = -9.80665f; |
193 | m_params.terrainHitFriction = 0.8f; | 196 | |
194 | m_params.terrainRestitution = 0.2f; | 197 | parms.linearDamping = 0.0f; |
195 | m_params.avatarFriction = 0.85f; | 198 | parms.angularDamping = 0.0f; |
196 | m_params.avatarCapsuleRadius = 0.37f; | 199 | parms.deactivationTime = 0.2f; |
197 | m_params.avatarCapsuleHeight = 1.5f; // 2.140599f | 200 | parms.linearSleepingThreshold = 0.8f; |
201 | parms.angularSleepingThreshold = 1.0f; | ||
202 | parms.ccdMotionThreshold = 0.5f; // set to zero to disable | ||
203 | parms.ccdSweptSphereRadius = 0.2f; | ||
204 | |||
205 | parms.terrainFriction = 0.85f; | ||
206 | parms.terrainHitFriction = 0.8f; | ||
207 | parms.terrainRestitution = 0.2f; | ||
208 | parms.avatarFriction = 0.85f; | ||
209 | parms.avatarDensity = 60f; | ||
210 | parms.avatarCapsuleRadius = 0.37f; | ||
211 | parms.avatarCapsuleHeight = 1.5f; // 2.140599f | ||
198 | 212 | ||
199 | if (config != null) | 213 | if (config != null) |
200 | { | 214 | { |
201 | // If there are specifications in the ini file, use those values | 215 | // If there are specifications in the ini file, use those values |
216 | // WHEN ADDING OR UPDATING THIS SECTION, BE SURE TO ALSO UPDATE OpenSimDefaults.ini | ||
202 | IConfig pConfig = config.Configs["BulletSim"]; | 217 | IConfig pConfig = config.Configs["BulletSim"]; |
203 | if (pConfig != null) | 218 | if (pConfig != null) |
204 | { | 219 | { |
205 | _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", true); | 220 | _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); |
206 | _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", false); | 221 | _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); |
207 | 222 | ||
208 | m_params.defaultFriction = pConfig.GetFloat("DefaultFriction", m_params.defaultFriction); | 223 | m_meshLOD = pConfig.GetInt("MeshLevelOfDetail", m_meshLOD); |
209 | m_params.defaultDensity = pConfig.GetFloat("DefaultDensity", m_params.defaultDensity); | 224 | |
210 | m_params.collisionMargin = pConfig.GetFloat("CollisionMargin", m_params.collisionMargin); | 225 | m_maxSubSteps = pConfig.GetInt("MaxSubSteps", m_maxSubSteps); |
211 | m_params.gravity = pConfig.GetFloat("Gravity", m_params.gravity); | 226 | m_fixedTimeStep = pConfig.GetFloat("FixedTimeStep", m_fixedTimeStep); |
212 | m_params.linearDamping = pConfig.GetFloat("LinearDamping", m_params.linearDamping); | 227 | m_maxCollisionsPerFrame = pConfig.GetInt("MaxCollisionsPerFrame", m_maxCollisionsPerFrame); |
213 | m_params.angularDamping = pConfig.GetFloat("AngularDamping", m_params.angularDamping); | 228 | m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame); |
214 | m_params.deactivationTime = pConfig.GetFloat("DeactivationTime", m_params.deactivationTime); | 229 | m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass); |
215 | m_params.linearSleepingThreshold = pConfig.GetFloat("LinearSleepingThreshold", m_params.linearSleepingThreshold); | 230 | |
216 | m_params.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", m_params.angularSleepingThreshold); | 231 | parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction); |
217 | m_params.terrainFriction = pConfig.GetFloat("TerrainFriction", m_params.terrainFriction); | 232 | parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity); |
218 | m_params.terrainHitFriction = pConfig.GetFloat("TerrainHitFriction", m_params.terrainHitFriction); | 233 | parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution); |
219 | m_params.terrainRestitution = pConfig.GetFloat("TerrainRestitution", m_params.terrainRestitution); | 234 | parms.collisionMargin = pConfig.GetFloat("CollisionMargin", parms.collisionMargin); |
220 | m_params.avatarFriction = pConfig.GetFloat("AvatarFriction", m_params.avatarFriction); | 235 | parms.gravity = pConfig.GetFloat("Gravity", parms.gravity); |
221 | m_params.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", m_params.avatarCapsuleRadius); | 236 | |
222 | m_params.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", m_params.avatarCapsuleHeight); | 237 | parms.linearDamping = pConfig.GetFloat("LinearDamping", parms.linearDamping); |
238 | parms.angularDamping = pConfig.GetFloat("AngularDamping", parms.angularDamping); | ||
239 | parms.deactivationTime = pConfig.GetFloat("DeactivationTime", parms.deactivationTime); | ||
240 | parms.linearSleepingThreshold = pConfig.GetFloat("LinearSleepingThreshold", parms.linearSleepingThreshold); | ||
241 | parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold); | ||
242 | parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold); | ||
243 | parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius); | ||
244 | |||
245 | parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction); | ||
246 | parms.terrainHitFriction = pConfig.GetFloat("TerrainHitFriction", parms.terrainHitFriction); | ||
247 | parms.terrainRestitution = pConfig.GetFloat("TerrainRestitution", parms.terrainRestitution); | ||
248 | parms.avatarFriction = pConfig.GetFloat("AvatarFriction", parms.avatarFriction); | ||
249 | parms.avatarDensity = pConfig.GetFloat("AvatarDensity", parms.avatarDensity); | ||
250 | parms.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", parms.avatarCapsuleRadius); | ||
251 | parms.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", parms.avatarCapsuleHeight); | ||
223 | } | 252 | } |
224 | } | 253 | } |
254 | m_params[0] = parms; | ||
225 | } | 255 | } |
226 | 256 | ||
227 | // Called directly from unmanaged code so don't do much | 257 | // Called directly from unmanaged code so don't do much |
@@ -282,20 +312,13 @@ public class BSScene : PhysicsScene | |||
282 | Vector3 size, Quaternion rotation, bool isPhysical, uint localID) | 312 | Vector3 size, Quaternion rotation, bool isPhysical, uint localID) |
283 | { | 313 | { |
284 | // m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName); | 314 | // m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName); |
285 | IMesh mesh = null; | 315 | BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); |
286 | if (NeedsMeshing(pbs)) | ||
287 | { | ||
288 | // if the prim is complex, create the mesh for it. | ||
289 | // If simple (box or sphere) leave 'mesh' null and physics will do a native shape. | ||
290 | mesh = mesher.CreateMesh(primName, pbs, size, this.meshLOD, isPhysical); | ||
291 | } | ||
292 | BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, mesh, pbs, isPhysical); | ||
293 | lock (m_prims) m_prims.Add(localID, prim); | 316 | lock (m_prims) m_prims.Add(localID, prim); |
294 | return prim; | 317 | return prim; |
295 | } | 318 | } |
296 | 319 | ||
297 | // This is a call from the simulator saying that some physical property has been updated. | 320 | // This is a call from the simulator saying that some physical property has been updated. |
298 | // The BulletS driver senses the changing of relevant properties so this taint | 321 | // The BulletSim driver senses the changing of relevant properties so this taint |
299 | // information call is not needed. | 322 | // information call is not needed. |
300 | public override void AddPhysicsActorTaint(PhysicsActor prim) { } | 323 | public override void AddPhysicsActorTaint(PhysicsActor prim) { } |
301 | 324 | ||
@@ -307,6 +330,9 @@ public class BSScene : PhysicsScene | |||
307 | int collidersCount; | 330 | int collidersCount; |
308 | IntPtr collidersPtr; | 331 | IntPtr collidersPtr; |
309 | 332 | ||
333 | // prevent simulation until we've been initialized | ||
334 | if (!m_initialized) return 10.0f; | ||
335 | |||
310 | // update the prim states while we know the physics engine is not busy | 336 | // update the prim states while we know the physics engine is not busy |
311 | ProcessTaints(); | 337 | ProcessTaints(); |
312 | 338 | ||
@@ -360,7 +386,7 @@ public class BSScene : PhysicsScene | |||
360 | } | 386 | } |
361 | } | 387 | } |
362 | 388 | ||
363 | // fps calculation wrong. This calculation always returns about 1 in normal operation. | 389 | // FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. |
364 | return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; | 390 | return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; |
365 | } | 391 | } |
366 | 392 | ||
@@ -369,8 +395,7 @@ public class BSScene : PhysicsScene | |||
369 | { | 395 | { |
370 | if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID) | 396 | if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID) |
371 | { | 397 | { |
372 | // we never send collisions to the terrain | 398 | return; // don't send collisions to the terrain |
373 | return; | ||
374 | } | 399 | } |
375 | 400 | ||
376 | ActorTypes type = ActorTypes.Prim; | 401 | ActorTypes type = ActorTypes.Prim; |
@@ -381,12 +406,12 @@ public class BSScene : PhysicsScene | |||
381 | 406 | ||
382 | BSPrim prim; | 407 | BSPrim prim; |
383 | if (m_prims.TryGetValue(localID, out prim)) { | 408 | if (m_prims.TryGetValue(localID, out prim)) { |
384 | prim.Collide(collidingWith, type, collidePoint, collideNormal, 0.01f); | 409 | prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration); |
385 | return; | 410 | return; |
386 | } | 411 | } |
387 | BSCharacter actor; | 412 | BSCharacter actor; |
388 | if (m_avatars.TryGetValue(localID, out actor)) { | 413 | if (m_avatars.TryGetValue(localID, out actor)) { |
389 | actor.Collide(collidingWith, type, collidePoint, collideNormal, 0.01f); | 414 | actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration); |
390 | return; | 415 | return; |
391 | } | 416 | } |
392 | return; | 417 | return; |
@@ -448,7 +473,7 @@ public class BSScene : PhysicsScene | |||
448 | 473 | ||
449 | if (pbs.SculptEntry && !_meshSculptedPrim) | 474 | if (pbs.SculptEntry && !_meshSculptedPrim) |
450 | { | 475 | { |
451 | // m_log.DebugFormat("{0}: NeedsMeshing: scultpy mesh", LogHeader); | 476 | // Render sculpties as boxes |
452 | return false; | 477 | return false; |
453 | } | 478 | } |
454 | 479 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index ace8158..819fce1 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | |||
@@ -32,12 +32,14 @@ using OpenMetaverse; | |||
32 | 32 | ||
33 | namespace OpenSim.Region.Physics.BulletSPlugin { | 33 | namespace OpenSim.Region.Physics.BulletSPlugin { |
34 | 34 | ||
35 | [StructLayout(LayoutKind.Sequential)] | ||
35 | public struct ConvexHull | 36 | public struct ConvexHull |
36 | { | 37 | { |
37 | Vector3 Offset; | 38 | Vector3 Offset; |
38 | int VertexCount; | 39 | int VertexCount; |
39 | Vector3[] Vertices; | 40 | Vector3[] Vertices; |
40 | } | 41 | } |
42 | [StructLayout(LayoutKind.Sequential)] | ||
41 | public struct ShapeData | 43 | public struct ShapeData |
42 | { | 44 | { |
43 | public enum PhysicsShapeType | 45 | public enum PhysicsShapeType |
@@ -49,6 +51,7 @@ public struct ShapeData | |||
49 | SHAPE_SPHERE = 4, | 51 | SHAPE_SPHERE = 4, |
50 | SHAPE_HULL = 5 | 52 | SHAPE_HULL = 5 |
51 | }; | 53 | }; |
54 | // note that bools are passed as ints since bool size changes by language | ||
52 | public const int numericTrue = 1; | 55 | public const int numericTrue = 1; |
53 | public const int numericFalse = 0; | 56 | public const int numericFalse = 0; |
54 | public uint ID; | 57 | public uint ID; |
@@ -60,11 +63,12 @@ public struct ShapeData | |||
60 | public float Mass; | 63 | public float Mass; |
61 | public float Buoyancy; | 64 | public float Buoyancy; |
62 | public System.UInt64 MeshKey; | 65 | public System.UInt64 MeshKey; |
63 | public int Collidable; | ||
64 | public float Friction; | 66 | public float Friction; |
67 | public float Restitution; | ||
68 | public int Collidable; | ||
65 | public int Static; // true if a static object. Otherwise gravity, etc. | 69 | public int Static; // true if a static object. Otherwise gravity, etc. |
66 | // note that bools are passed as ints since bool size changes by language | ||
67 | } | 70 | } |
71 | [StructLayout(LayoutKind.Sequential)] | ||
68 | public struct SweepHit | 72 | public struct SweepHit |
69 | { | 73 | { |
70 | public uint ID; | 74 | public uint ID; |
@@ -72,12 +76,14 @@ public struct SweepHit | |||
72 | public Vector3 Normal; | 76 | public Vector3 Normal; |
73 | public Vector3 Point; | 77 | public Vector3 Point; |
74 | } | 78 | } |
79 | [StructLayout(LayoutKind.Sequential)] | ||
75 | public struct RaycastHit | 80 | public struct RaycastHit |
76 | { | 81 | { |
77 | public uint ID; | 82 | public uint ID; |
78 | public float Fraction; | 83 | public float Fraction; |
79 | public Vector3 Normal; | 84 | public Vector3 Normal; |
80 | } | 85 | } |
86 | [StructLayout(LayoutKind.Sequential)] | ||
81 | public struct CollisionDesc | 87 | public struct CollisionDesc |
82 | { | 88 | { |
83 | public uint aID; | 89 | public uint aID; |
@@ -85,6 +91,7 @@ public struct CollisionDesc | |||
85 | public Vector3 point; | 91 | public Vector3 point; |
86 | public Vector3 normal; | 92 | public Vector3 normal; |
87 | } | 93 | } |
94 | [StructLayout(LayoutKind.Sequential)] | ||
88 | public struct EntityProperties | 95 | public struct EntityProperties |
89 | { | 96 | { |
90 | public uint ID; | 97 | public uint ID; |
@@ -92,13 +99,42 @@ public struct EntityProperties | |||
92 | public Quaternion Rotation; | 99 | public Quaternion Rotation; |
93 | public Vector3 Velocity; | 100 | public Vector3 Velocity; |
94 | public Vector3 Acceleration; | 101 | public Vector3 Acceleration; |
95 | public Vector3 AngularVelocity; | 102 | public Vector3 RotationalVelocity; |
103 | } | ||
104 | |||
105 | // Format of this structure must match the definition in the C++ code | ||
106 | [StructLayout(LayoutKind.Sequential)] | ||
107 | public struct ConfigurationParameters | ||
108 | { | ||
109 | public float defaultFriction; | ||
110 | public float defaultDensity; | ||
111 | public float defaultRestitution; | ||
112 | public float collisionMargin; | ||
113 | public float gravity; | ||
114 | |||
115 | public float linearDamping; | ||
116 | public float angularDamping; | ||
117 | public float deactivationTime; | ||
118 | public float linearSleepingThreshold; | ||
119 | public float angularSleepingThreshold; | ||
120 | public float ccdMotionThreshold; | ||
121 | public float ccdSweptSphereRadius; | ||
122 | |||
123 | public float terrainFriction; | ||
124 | public float terrainHitFriction; | ||
125 | public float terrainRestitution; | ||
126 | public float avatarFriction; | ||
127 | public float avatarDensity; | ||
128 | public float avatarRestitution; | ||
129 | public float avatarCapsuleRadius; | ||
130 | public float avatarCapsuleHeight; | ||
96 | } | 131 | } |
97 | 132 | ||
98 | static class BulletSimAPI { | 133 | static class BulletSimAPI { |
99 | 134 | ||
100 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 135 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
101 | public static extern uint Initialize(Vector3 maxPosition, int maxCollisions, IntPtr collisionArray, | 136 | public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, |
137 | int maxCollisions, IntPtr collisionArray, | ||
102 | int maxUpdates, IntPtr updateArray); | 138 | int maxUpdates, IntPtr updateArray); |
103 | 139 | ||
104 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 140 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
diff --git a/bin/BulletSim-x86_64.dll b/bin/BulletSim-x86_64.dll index bcdea44..750b2f5 100755 --- a/bin/BulletSim-x86_64.dll +++ b/bin/BulletSim-x86_64.dll | |||
Binary files differ | |||
diff --git a/bin/BulletSim.dll b/bin/BulletSim.dll index 5dc51db..d5c76da 100755 --- a/bin/BulletSim.dll +++ b/bin/BulletSim.dll | |||
Binary files differ | |||
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index bf36228..d487ce6 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini | |||
@@ -159,6 +159,7 @@ | |||
159 | ;physics = basicphysics | 159 | ;physics = basicphysics |
160 | ;physics = POS | 160 | ;physics = POS |
161 | ;physics = modified_BulletX | 161 | ;physics = modified_BulletX |
162 | ;physics = BulletSim | ||
162 | 163 | ||
163 | ; ## | 164 | ; ## |
164 | ; ## PERMISSIONS | 165 | ; ## PERMISSIONS |
@@ -725,6 +726,47 @@ | |||
725 | ; true. Note that this will increase memory usage and region startup time. Default is false. | 726 | ; true. Note that this will increase memory usage and region startup time. Default is false. |
726 | ;force_simple_prim_meshing = true | 727 | ;force_simple_prim_meshing = true |
727 | 728 | ||
729 | [BulletSim] | ||
730 | ; World parameters | ||
731 | DefaultFriction = 0.70 | ||
732 | DefaultDensity = 10.000006836 | ||
733 | DefaultRestitution = 0.0 | ||
734 | Gravity = -9.80665 | ||
735 | |||
736 | TerrainFriction = 0.85 | ||
737 | TerrainHitFriction = 0.8 | ||
738 | TerrainRestitution = 0.2 | ||
739 | AvatarFriction = 0.85 | ||
740 | AvatarDensity = 60.0 | ||
741 | AvatarCapsuleRadius = 0.37 | ||
742 | AvatarCapsuleHeight = 1.5 | ||
743 | |||
744 | MaxObjectMass = 10000.01 | ||
745 | |||
746 | ; Dynamic parameters | ||
747 | LinearDamping = 0.0 | ||
748 | AngularDamping = 0.0 | ||
749 | DeactivationTime = 0.2 | ||
750 | LinearSleepingThreshold = 0.8 | ||
751 | AngularSleepingThreshold = 1.0 | ||
752 | CcdMotionThreshold = 0.5 | ||
753 | CcdSweptSphereRadius = 0.2 | ||
754 | |||
755 | ; Whether to mesh sculpties | ||
756 | MeshSculptedPrim = true | ||
757 | |||
758 | ; If 'true', force simple prims (box and sphere) to be meshed | ||
759 | ForceSimplePrimMeshing = false | ||
760 | |||
761 | ; number^2 non-physical level of detail of the sculpt texture. 32x32 - 1024 verticies | ||
762 | MeshLevelOfDetail = 32 | ||
763 | |||
764 | ; Bullet step parameters | ||
765 | MaxSubSteps = 10; | ||
766 | FixedTimeStep = .01667 | ||
767 | |||
768 | MaxCollisionsPerFrame = 2048 | ||
769 | MaxUpdatesPerFrame = 2048 | ||
728 | 770 | ||
729 | [RemoteAdmin] | 771 | [RemoteAdmin] |
730 | enabled = false | 772 | enabled = false |
diff --git a/bin/libBulletSim.so b/bin/libBulletSim.so index 82d3b34..275355d 100755 --- a/bin/libBulletSim.so +++ b/bin/libBulletSim.so | |||
Binary files differ | |||