aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin
diff options
context:
space:
mode:
authorMelanie2013-05-04 01:22:12 +0100
committerMelanie2013-05-04 01:22:12 +0100
commit3aa83738e2a845d05bb25ab81634d0540971c0bf (patch)
tree411d946b817b020c72f3d9a35926215e28bf2d95 /OpenSim/Region/Physics/BulletSPlugin
parentMerge branch 'master' into careminster (diff)
parentMerge branch 'master' into bulletsim4 (diff)
downloadopensim-SC-3aa83738e2a845d05bb25ab81634d0540971c0bf.zip
opensim-SC-3aa83738e2a845d05bb25ab81634d0540971c0bf.tar.gz
opensim-SC-3aa83738e2a845d05bb25ab81634d0540971c0bf.tar.bz2
opensim-SC-3aa83738e2a845d05bb25ab81634d0540971c0bf.tar.xz
Merge branch 'master' into careminster
Conflicts: OpenSim/Region/Application/OpenSimBase.cs OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs142
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActors.cs8
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs6
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs127
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs2
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs41
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs21
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs272
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs20
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs11
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs74
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs220
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs22
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs21
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs3
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs1021
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs716
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs30
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs60
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs56
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs48
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt18
30 files changed, 1353 insertions, 1638 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
index fdf2cb9..231f0f8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
@@ -75,11 +75,11 @@ private sealed class BulletBodyUnman : BulletBody
75private sealed class BulletShapeUnman : BulletShape 75private sealed class BulletShapeUnman : BulletShape
76{ 76{
77 public IntPtr ptr; 77 public IntPtr ptr;
78 public BulletShapeUnman(IntPtr xx, BSPhysicsShapeType typ) 78 public BulletShapeUnman(IntPtr xx, BSPhysicsShapeType typ)
79 : base() 79 : base()
80 { 80 {
81 ptr = xx; 81 ptr = xx;
82 type = typ; 82 shapeType = typ;
83 } 83 }
84 public override bool HasPhysicalShape 84 public override bool HasPhysicalShape
85 { 85 {
@@ -91,7 +91,7 @@ private sealed class BulletShapeUnman : BulletShape
91 } 91 }
92 public override BulletShape Clone() 92 public override BulletShape Clone()
93 { 93 {
94 return new BulletShapeUnman(ptr, type); 94 return new BulletShapeUnman(ptr, shapeType);
95 } 95 }
96 public override bool ReferenceSame(BulletShape other) 96 public override bool ReferenceSame(BulletShape other)
97 { 97 {
@@ -255,7 +255,7 @@ public override BulletShape CreateHullShape(BulletWorld world, int hullCount, fl
255{ 255{
256 BulletWorldUnman worldu = world as BulletWorldUnman; 256 BulletWorldUnman worldu = world as BulletWorldUnman;
257 return new BulletShapeUnman( 257 return new BulletShapeUnman(
258 BSAPICPP.CreateHullShape2(worldu.ptr, hullCount, hulls), 258 BSAPICPP.CreateHullShape2(worldu.ptr, hullCount, hulls),
259 BSPhysicsShapeType.SHAPE_HULL); 259 BSPhysicsShapeType.SHAPE_HULL);
260} 260}
261 261
@@ -375,7 +375,7 @@ public override BulletShape DuplicateCollisionShape(BulletWorld world, BulletSha
375{ 375{
376 BulletWorldUnman worldu = world as BulletWorldUnman; 376 BulletWorldUnman worldu = world as BulletWorldUnman;
377 BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman; 377 BulletShapeUnman srcShapeu = srcShape as BulletShapeUnman;
378 return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.type); 378 return new BulletShapeUnman(BSAPICPP.DuplicateCollisionShape2(worldu.ptr, srcShapeu.ptr, id), srcShape.shapeType);
379} 379}
380 380
381public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape) 381public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape)
@@ -1503,7 +1503,7 @@ public static extern void DestroyObject2(IntPtr sim, IntPtr obj);
1503public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin); 1503public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
1504 1504
1505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1505[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1506public static extern IntPtr CreateTerrainShape2(uint id, Vector3 size, float minHeight, float maxHeight, 1506public static extern IntPtr CreateTerrainShape2(uint id, Vector3 size, float minHeight, float maxHeight,
1507 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, 1507 [MarshalAs(UnmanagedType.LPArray)] float[] heightMap,
1508 float scaleFactor, float collisionMargin); 1508 float scaleFactor, float collisionMargin);
1509 1509
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index b37265a..59780ae 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -81,11 +81,11 @@ private sealed class BulletBodyXNA : BulletBody
81private sealed class BulletShapeXNA : BulletShape 81private sealed class BulletShapeXNA : BulletShape
82{ 82{
83 public CollisionShape shape; 83 public CollisionShape shape;
84 public BulletShapeXNA(CollisionShape xx, BSPhysicsShapeType typ) 84 public BulletShapeXNA(CollisionShape xx, BSPhysicsShapeType typ)
85 : base() 85 : base()
86 { 86 {
87 shape = xx; 87 shape = xx;
88 type = typ; 88 shapeType = typ;
89 } 89 }
90 public override bool HasPhysicalShape 90 public override bool HasPhysicalShape
91 { 91 {
@@ -97,7 +97,7 @@ private sealed class BulletShapeXNA : BulletShape
97 } 97 }
98 public override BulletShape Clone() 98 public override BulletShape Clone()
99 { 99 {
100 return new BulletShapeXNA(shape, type); 100 return new BulletShapeXNA(shape, shapeType);
101 } 101 }
102 public override bool ReferenceSame(BulletShape other) 102 public override bool ReferenceSame(BulletShape other)
103 { 103 {
@@ -137,8 +137,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
137 internal int LastEntityProperty = 0; 137 internal int LastEntityProperty = 0;
138 138
139 internal EntityProperties[] UpdatedObjects; 139 internal EntityProperties[] UpdatedObjects;
140 internal Dictionary<uint, GhostObject> specialCollisionObjects; 140 internal Dictionary<uint, GhostObject> specialCollisionObjects;
141 141
142 private static int m_collisionsThisFrame; 142 private static int m_collisionsThisFrame;
143 private BSScene PhysicsScene { get; set; } 143 private BSScene PhysicsScene { get; set; }
144 144
@@ -151,7 +151,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
151 } 151 }
152 152
153 /// <summary> 153 /// <summary>
154 /// 154 ///
155 /// </summary> 155 /// </summary>
156 /// <param name="p"></param> 156 /// <param name="p"></param>
157 /// <param name="p_2"></param> 157 /// <param name="p_2"></param>
@@ -174,7 +174,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
174 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 174 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
175 TypedConstraint constraint = (pConstraint as BulletConstraintXNA).constrain; 175 TypedConstraint constraint = (pConstraint as BulletConstraintXNA).constrain;
176 world.AddConstraint(constraint, pDisableCollisionsBetweenLinkedObjects); 176 world.AddConstraint(constraint, pDisableCollisionsBetweenLinkedObjects);
177 177
178 return true; 178 return true;
179 179
180 } 180 }
@@ -300,7 +300,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
300 public override bool GetForceUpdateAllAabbs(BulletWorld pWorld) { 300 public override bool GetForceUpdateAllAabbs(BulletWorld pWorld) {
301 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 301 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
302 return world.GetForceUpdateAllAabbs(); 302 return world.GetForceUpdateAllAabbs();
303 303
304 } 304 }
305 public override void SetForceUpdateAllAabbs(BulletWorld pWorld, bool pForce) 305 public override void SetForceUpdateAllAabbs(BulletWorld pWorld, bool pForce)
306 { 306 {
@@ -404,7 +404,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
404 IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion); 404 IndexedMatrix mat = IndexedMatrix.CreateFromQuaternion(vquaternion);
405 mat._origin = vposition; 405 mat._origin = vposition;
406 collisionObject.SetWorldTransform(mat); 406 collisionObject.SetWorldTransform(mat);
407 407
408 } 408 }
409 409
410 public override Vector3 GetPosition(BulletBody pCollisionObject) 410 public override Vector3 GetPosition(BulletBody pCollisionObject)
@@ -457,7 +457,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
457 { 457 {
458 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody; 458 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
459 collisionObject.Activate(pforceactivation); 459 collisionObject.Activate(pforceactivation);
460 460
461 } 461 }
462 462
463 public override Quaternion GetOrientation(BulletBody pCollisionObject) 463 public override Quaternion GetOrientation(BulletBody pCollisionObject)
@@ -486,7 +486,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
486 { 486 {
487 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody; 487 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
488 return collisionObject.GetCcdSweptSphereRadius(); 488 return collisionObject.GetCcdSweptSphereRadius();
489 489
490 } 490 }
491 491
492 public override IntPtr GetUserPointer(BulletBody pCollisionObject) 492 public override IntPtr GetUserPointer(BulletBody pCollisionObject)
@@ -559,8 +559,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
559 } 559 }
560 560
561 561
562 public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, 562 public override BulletConstraint Create6DofConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
563 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, 563 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
564 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) 564 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
565 565
566 { 566 {
@@ -604,7 +604,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
604 } 604 }
605 605
606 /// <summary> 606 /// <summary>
607 /// 607 ///
608 /// </summary> 608 /// </summary>
609 /// <param name="pWorld"></param> 609 /// <param name="pWorld"></param>
610 /// <param name="pBody1"></param> 610 /// <param name="pBody1"></param>
@@ -824,7 +824,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
824 { 824 {
825 RigidBody body = (pBody as BulletBodyXNA).rigidBody; 825 RigidBody body = (pBody as BulletBodyXNA).rigidBody;
826 float angularDamping = body.GetAngularDamping(); 826 float angularDamping = body.GetAngularDamping();
827 body.SetDamping(lin_damping, angularDamping); 827 body.SetDamping(lin_damping, angularDamping);
828 } 828 }
829 829
830 public override float GetLinearDamping(BulletBody pBody) 830 public override float GetLinearDamping(BulletBody pBody)
@@ -907,7 +907,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
907 RigidBody bo = co as RigidBody; 907 RigidBody bo = co as RigidBody;
908 if (bo == null) 908 if (bo == null)
909 { 909 {
910 910
911 if (world.IsInWorld(co)) 911 if (world.IsInWorld(co))
912 { 912 {
913 world.RemoveCollisionObject(co); 913 world.RemoveCollisionObject(co);
@@ -915,7 +915,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
915 } 915 }
916 else 916 else
917 { 917 {
918 918
919 if (world.IsInWorld(bo)) 919 if (world.IsInWorld(bo))
920 { 920 {
921 world.RemoveRigidBody(bo); 921 world.RemoveRigidBody(bo);
@@ -947,7 +947,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
947 947
948 // TODO: Turn this from a reference copy to a Value Copy. 948 // TODO: Turn this from a reference copy to a Value Copy.
949 BulletShapeXNA shape2 = new BulletShapeXNA(shape1, BSShapeTypeFromBroadPhaseNativeType(shape1.GetShapeType())); 949 BulletShapeXNA shape2 = new BulletShapeXNA(shape1, BSShapeTypeFromBroadPhaseNativeType(shape1.GetShapeType()));
950 950
951 return shape2; 951 return shape2;
952 } 952 }
953 953
@@ -957,7 +957,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
957 return false; 957 return false;
958 } 958 }
959 //(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation); 959 //(sim.ptr, shape.ptr, prim.LocalID, prim.RawPosition, prim.RawOrientation);
960 960
961 public override BulletBody CreateBodyFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) 961 public override BulletBody CreateBodyFromShape(BulletWorld pWorld, BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
962 { 962 {
963 CollisionWorld world = (pWorld as BulletWorldXNA).world; 963 CollisionWorld world = (pWorld as BulletWorldXNA).world;
@@ -993,11 +993,11 @@ private sealed class BulletConstraintXNA : BulletConstraint
993 m_startWorldTransform = IndexedMatrix.Identity; 993 m_startWorldTransform = IndexedMatrix.Identity;
994 */ 994 */
995 body.SetUserPointer(pLocalID); 995 body.SetUserPointer(pLocalID);
996 996
997 return new BulletBodyXNA(pLocalID, body); 997 return new BulletBodyXNA(pLocalID, body);
998 } 998 }
999 999
1000 1000
1001 public override BulletBody CreateBodyWithDefaultMotionState( BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation) 1001 public override BulletBody CreateBodyWithDefaultMotionState( BulletShape pShape, uint pLocalID, Vector3 pRawPosition, Quaternion pRawOrientation)
1002 { 1002 {
1003 1003
@@ -1025,7 +1025,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1025 public override Vector3 GetAnisotripicFriction(BulletConstraint pconstrain) 1025 public override Vector3 GetAnisotripicFriction(BulletConstraint pconstrain)
1026 { 1026 {
1027 1027
1028 /* TODO */ 1028 /* TODO */
1029 return Vector3.Zero; 1029 return Vector3.Zero;
1030 } 1030 }
1031 public override Vector3 SetAnisotripicFriction(BulletConstraint pconstrain, Vector3 frict) { /* TODO */ return Vector3.Zero; } 1031 public override Vector3 SetAnisotripicFriction(BulletConstraint pconstrain, Vector3 frict) { /* TODO */ return Vector3.Zero; }
@@ -1035,7 +1035,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1035 { 1035 {
1036 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody; 1036 CollisionObject collisionObject = (pCollisionObject as BulletBodyXNA).rigidBody;
1037 return collisionObject.IsStaticObject(); 1037 return collisionObject.IsStaticObject();
1038 1038
1039 } 1039 }
1040 public override bool IsKinematicObject(BulletBody pCollisionObject) 1040 public override bool IsKinematicObject(BulletBody pCollisionObject)
1041 { 1041 {
@@ -1098,10 +1098,10 @@ private sealed class BulletConstraintXNA : BulletConstraint
1098 return new BulletWorldXNA(1, PhysicsScene, BSAPIXNA.Initialize2(worldExtent, configparms, maxCollisions, ref collisionArray, maxUpdates, ref updateArray, null)); 1098 return new BulletWorldXNA(1, PhysicsScene, BSAPIXNA.Initialize2(worldExtent, configparms, maxCollisions, ref collisionArray, maxUpdates, ref updateArray, null));
1099 } 1099 }
1100 1100
1101 private static DiscreteDynamicsWorld Initialize2(Vector3 worldExtent, 1101 private static DiscreteDynamicsWorld Initialize2(Vector3 worldExtent,
1102 ConfigurationParameters[] o, 1102 ConfigurationParameters[] o,
1103 int mMaxCollisionsPerFrame, ref CollisionDesc[] collisionArray, 1103 int mMaxCollisionsPerFrame, ref CollisionDesc[] collisionArray,
1104 int mMaxUpdatesPerFrame, ref EntityProperties[] updateArray, 1104 int mMaxUpdatesPerFrame, ref EntityProperties[] updateArray,
1105 object mDebugLogCallbackHandle) 1105 object mDebugLogCallbackHandle)
1106 { 1106 {
1107 CollisionWorld.WorldData.ParamData p = new CollisionWorld.WorldData.ParamData(); 1107 CollisionWorld.WorldData.ParamData p = new CollisionWorld.WorldData.ParamData();
@@ -1138,9 +1138,9 @@ private sealed class BulletConstraintXNA : BulletConstraint
1138 p.avatarCapsuleDepth = BSParam.AvatarCapsuleDepth; 1138 p.avatarCapsuleDepth = BSParam.AvatarCapsuleDepth;
1139 p.avatarCapsuleHeight = BSParam.AvatarCapsuleHeight; 1139 p.avatarCapsuleHeight = BSParam.AvatarCapsuleHeight;
1140 p.avatarContactProcessingThreshold = BSParam.AvatarContactProcessingThreshold; 1140 p.avatarContactProcessingThreshold = BSParam.AvatarContactProcessingThreshold;
1141 1141
1142 p.vehicleAngularDamping = BSParam.VehicleAngularDamping; 1142 p.vehicleAngularDamping = BSParam.VehicleAngularDamping;
1143 1143
1144 p.maxPersistantManifoldPoolSize = o[0].maxPersistantManifoldPoolSize; 1144 p.maxPersistantManifoldPoolSize = o[0].maxPersistantManifoldPoolSize;
1145 p.maxCollisionAlgorithmPoolSize = o[0].maxCollisionAlgorithmPoolSize; 1145 p.maxCollisionAlgorithmPoolSize = o[0].maxCollisionAlgorithmPoolSize;
1146 p.shouldDisableContactPoolDynamicAllocation = o[0].shouldDisableContactPoolDynamicAllocation; 1146 p.shouldDisableContactPoolDynamicAllocation = o[0].shouldDisableContactPoolDynamicAllocation;
@@ -1160,7 +1160,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1160 p.linkConstraintSolverIterations = BSParam.LinkConstraintSolverIterations; 1160 p.linkConstraintSolverIterations = BSParam.LinkConstraintSolverIterations;
1161 p.physicsLoggingFrames = o[0].physicsLoggingFrames; 1161 p.physicsLoggingFrames = o[0].physicsLoggingFrames;
1162 DefaultCollisionConstructionInfo ccci = new DefaultCollisionConstructionInfo(); 1162 DefaultCollisionConstructionInfo ccci = new DefaultCollisionConstructionInfo();
1163 1163
1164 DefaultCollisionConfiguration cci = new DefaultCollisionConfiguration(); 1164 DefaultCollisionConfiguration cci = new DefaultCollisionConfiguration();
1165 CollisionDispatcher m_dispatcher = new CollisionDispatcher(cci); 1165 CollisionDispatcher m_dispatcher = new CollisionDispatcher(cci);
1166 1166
@@ -1263,7 +1263,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1263 } 1263 }
1264 } 1264 }
1265 return ret; 1265 return ret;
1266 1266
1267 } 1267 }
1268 1268
1269 public override float GetAngularMotionDisc(BulletShape pShape) 1269 public override float GetAngularMotionDisc(BulletShape pShape)
@@ -1353,10 +1353,10 @@ private sealed class BulletConstraintXNA : BulletConstraint
1353 CollisionShape shape = (pShape as BulletShapeXNA).shape; 1353 CollisionShape shape = (pShape as BulletShapeXNA).shape;
1354 gObj.SetCollisionShape(shape); 1354 gObj.SetCollisionShape(shape);
1355 gObj.SetUserPointer(pLocalID); 1355 gObj.SetUserPointer(pLocalID);
1356 1356
1357 if (specialCollisionObjects.ContainsKey(pLocalID)) 1357 if (specialCollisionObjects.ContainsKey(pLocalID))
1358 specialCollisionObjects[pLocalID] = gObj; 1358 specialCollisionObjects[pLocalID] = gObj;
1359 else 1359 else
1360 specialCollisionObjects.Add(pLocalID, gObj); 1360 specialCollisionObjects.Add(pLocalID, gObj);
1361 1361
1362 // TODO: Add to Special CollisionObjects! 1362 // TODO: Add to Special CollisionObjects!
@@ -1447,8 +1447,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
1447 return new BulletShapeXNA(ret, BSShapeTypeFromBroadPhaseNativeType(ret.GetShapeType())); 1447 return new BulletShapeXNA(ret, BSShapeTypeFromBroadPhaseNativeType(ret.GetShapeType()));
1448 } 1448 }
1449 1449
1450 public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) { 1450 public override BulletShape GetChildShapeFromCompoundShapeIndex(BulletShape cShape, int indx) {
1451 1451
1452 if (cShape == null) 1452 if (cShape == null)
1453 return null; 1453 return null;
1454 CompoundShape compoundShape = (cShape as BulletShapeXNA).shape as CompoundShape; 1454 CompoundShape compoundShape = (cShape as BulletShapeXNA).shape as CompoundShape;
@@ -1456,7 +1456,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1456 BulletShape retShape = new BulletShapeXNA(shape, BSShapeTypeFromBroadPhaseNativeType(shape.GetShapeType())); 1456 BulletShape retShape = new BulletShapeXNA(shape, BSShapeTypeFromBroadPhaseNativeType(shape.GetShapeType()));
1457 1457
1458 1458
1459 return retShape; 1459 return retShape;
1460 } 1460 }
1461 1461
1462 public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin) 1462 public BSPhysicsShapeType BSShapeTypeFromBroadPhaseNativeType(BroadphaseNativeTypes pin)
@@ -1598,8 +1598,8 @@ private sealed class BulletConstraintXNA : BulletConstraint
1598 return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE); 1598 return new BulletShapeXNA(m_planeshape, BSPhysicsShapeType.SHAPE_GROUNDPLANE);
1599 } 1599 }
1600 1600
1601 public override BulletConstraint Create6DofSpringConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2, 1601 public override BulletConstraint Create6DofSpringConstraint(BulletWorld pWorld, BulletBody pBody1, BulletBody pBody2,
1602 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot, 1602 Vector3 pframe1, Quaternion pframe1rot, Vector3 pframe2, Quaternion pframe2rot,
1603 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies) 1603 bool puseLinearReferenceFrameA, bool pdisableCollisionsBetweenLinkedBodies)
1604 1604
1605 { 1605 {
@@ -1745,7 +1745,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1745 { 1745 {
1746 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 1746 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
1747 CompoundShape compoundshape = new CompoundShape(false); 1747 CompoundShape compoundshape = new CompoundShape(false);
1748 1748
1749 compoundshape.SetMargin(world.WorldSettings.Params.collisionMargin); 1749 compoundshape.SetMargin(world.WorldSettings.Params.collisionMargin);
1750 int ii = 1; 1750 int ii = 1;
1751 1751
@@ -1761,7 +1761,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1761 int ender = ((ii + 4) + (vertexCount*3)); 1761 int ender = ((ii + 4) + (vertexCount*3));
1762 for (int iii = ii + 4; iii < ender; iii+=3) 1762 for (int iii = ii + 4; iii < ender; iii+=3)
1763 { 1763 {
1764 1764
1765 virts.Add(new IndexedVector3(pConvHulls[iii], pConvHulls[iii + 1], pConvHulls[iii +2])); 1765 virts.Add(new IndexedVector3(pConvHulls[iii], pConvHulls[iii + 1], pConvHulls[iii +2]));
1766 } 1766 }
1767 ConvexHullShape convexShape = new ConvexHullShape(virts, vertexCount); 1767 ConvexHullShape convexShape = new ConvexHullShape(virts, vertexCount);
@@ -1769,7 +1769,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1769 compoundshape.AddChildShape(ref childTrans, convexShape); 1769 compoundshape.AddChildShape(ref childTrans, convexShape);
1770 ii += (vertexCount*3 + 4); 1770 ii += (vertexCount*3 + 4);
1771 } 1771 }
1772 1772
1773 return new BulletShapeXNA(compoundshape, BSPhysicsShapeType.SHAPE_HULL); 1773 return new BulletShapeXNA(compoundshape, BSPhysicsShapeType.SHAPE_HULL);
1774 } 1774 }
1775 1775
@@ -1791,13 +1791,13 @@ private sealed class BulletConstraintXNA : BulletConstraint
1791 public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats) 1791 public override BulletShape CreateMeshShape(BulletWorld pWorld, int pIndicesCount, int[] indices, int pVerticesCount, float[] verticesAsFloats)
1792 { 1792 {
1793 //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount); 1793 //DumpRaw(indices,verticesAsFloats,pIndicesCount,pVerticesCount);
1794 1794
1795 for (int iter = 0; iter < pVerticesCount; iter++) 1795 for (int iter = 0; iter < pVerticesCount; iter++)
1796 { 1796 {
1797 if (verticesAsFloats[iter] > 0 && verticesAsFloats[iter] < 0.0001) verticesAsFloats[iter] = 0; 1797 if (verticesAsFloats[iter] > 0 && verticesAsFloats[iter] < 0.0001) verticesAsFloats[iter] = 0;
1798 if (verticesAsFloats[iter] < 0 && verticesAsFloats[iter] > -0.0001) verticesAsFloats[iter] = 0; 1798 if (verticesAsFloats[iter] < 0 && verticesAsFloats[iter] > -0.0001) verticesAsFloats[iter] = 0;
1799 } 1799 }
1800 1800
1801 ObjectArray<int> indicesarr = new ObjectArray<int>(indices); 1801 ObjectArray<int> indicesarr = new ObjectArray<int>(indices);
1802 ObjectArray<float> vertices = new ObjectArray<float>(verticesAsFloats); 1802 ObjectArray<float> vertices = new ObjectArray<float>(verticesAsFloats);
1803 DumpRaw(indicesarr,vertices,pIndicesCount,pVerticesCount); 1803 DumpRaw(indicesarr,vertices,pIndicesCount,pVerticesCount);
@@ -1811,7 +1811,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1811 mesh.m_vertexStride = 3; 1811 mesh.m_vertexStride = 3;
1812 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; 1812 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1813 mesh.m_triangleIndexStride = 3; 1813 mesh.m_triangleIndexStride = 3;
1814 1814
1815 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); 1815 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1816 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); 1816 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1817 BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true); 1817 BvhTriangleMeshShape meshShape = new BvhTriangleMeshShape(tribuilder, true,true);
@@ -1822,7 +1822,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1822 } 1822 }
1823 public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount ) 1823 public static void DumpRaw(ObjectArray<int>indices, ObjectArray<float> vertices, int pIndicesCount,int pVerticesCount )
1824 { 1824 {
1825 1825
1826 String fileName = "objTest3.raw"; 1826 String fileName = "objTest3.raw";
1827 String completePath = System.IO.Path.Combine(Util.configDir(), fileName); 1827 String completePath = System.IO.Path.Combine(Util.configDir(), fileName);
1828 StreamWriter sw = new StreamWriter(completePath); 1828 StreamWriter sw = new StreamWriter(completePath);
@@ -1848,7 +1848,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1848 string s = vertices[indices[i * 3]].ToString("0.0000"); 1848 string s = vertices[indices[i * 3]].ToString("0.0000");
1849 s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000"); 1849 s += " " + vertices[indices[i * 3 + 1]].ToString("0.0000");
1850 s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000"); 1850 s += " " + vertices[indices[i * 3 + 2]].ToString("0.0000");
1851 1851
1852 sw.Write(s + "\n"); 1852 sw.Write(s + "\n");
1853 } 1853 }
1854 1854
@@ -1870,7 +1870,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1870 mesh.m_vertexStride = 3; 1870 mesh.m_vertexStride = 3;
1871 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT; 1871 mesh.m_vertexType = PHY_ScalarType.PHY_FLOAT;
1872 mesh.m_triangleIndexStride = 3; 1872 mesh.m_triangleIndexStride = 3;
1873 1873
1874 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray(); 1874 TriangleIndexVertexArray tribuilder = new TriangleIndexVertexArray();
1875 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER); 1875 tribuilder.AddIndexedMesh(mesh, PHY_ScalarType.PHY_INTEGER);
1876 1876
@@ -1901,7 +1901,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
1901 sw.Close(); 1901 sw.Close();
1902 } 1902 }
1903 1903
1904 public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap, 1904 public override BulletShape CreateTerrainShape(uint id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
1905 float scaleFactor, float collisionMargin) 1905 float scaleFactor, float collisionMargin)
1906 { 1906 {
1907 const int upAxis = 2; 1907 const int upAxis = 2;
@@ -1943,14 +1943,14 @@ private sealed class BulletConstraintXNA : BulletConstraint
1943 /* TODO */ 1943 /* TODO */
1944 updatedEntityCount = 0; 1944 updatedEntityCount = 0;
1945 collidersCount = 0; 1945 collidersCount = 0;
1946 1946
1947 1947
1948 int ret = PhysicsStep2(world,timeStep,maxSubSteps,fixedTimeStep,out updatedEntityCount,out world.physicsScene.m_updateArray, out collidersCount, out world.physicsScene.m_collisionArray); 1948 int ret = PhysicsStep2(world,timeStep,maxSubSteps,fixedTimeStep,out updatedEntityCount,out world.physicsScene.m_updateArray, out collidersCount, out world.physicsScene.m_collisionArray);
1949 1949
1950 return ret; 1950 return ret;
1951 } 1951 }
1952 1952
1953 private int PhysicsStep2(BulletWorld pWorld, float timeStep, int m_maxSubSteps, float m_fixedTimeStep, 1953 private int PhysicsStep2(BulletWorld pWorld, float timeStep, int m_maxSubSteps, float m_fixedTimeStep,
1954 out int updatedEntityCount, out EntityProperties[] updatedEntities, 1954 out int updatedEntityCount, out EntityProperties[] updatedEntities,
1955 out int collidersCount, out CollisionDesc[] colliders) 1955 out int collidersCount, out CollisionDesc[] colliders)
1956 { 1956 {
@@ -1959,24 +1959,24 @@ private sealed class BulletConstraintXNA : BulletConstraint
1959 return epic; 1959 return epic;
1960 } 1960 }
1961 1961
1962 private int PhysicsStepint(BulletWorld pWorld,float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount, 1962 private int PhysicsStepint(BulletWorld pWorld,float timeStep, int m_maxSubSteps, float m_fixedTimeStep, out int updatedEntityCount,
1963 out EntityProperties[] updatedEntities, out int collidersCount, out CollisionDesc[] colliders, int maxCollisions, int maxUpdates) 1963 out EntityProperties[] updatedEntities, out int collidersCount, out CollisionDesc[] colliders, int maxCollisions, int maxUpdates)
1964 { 1964 {
1965 int numSimSteps = 0; 1965 int numSimSteps = 0;
1966 Array.Clear(UpdatedObjects, 0, UpdatedObjects.Length); 1966 Array.Clear(UpdatedObjects, 0, UpdatedObjects.Length);
1967 Array.Clear(UpdatedCollisions, 0, UpdatedCollisions.Length); 1967 Array.Clear(UpdatedCollisions, 0, UpdatedCollisions.Length);
1968 LastEntityProperty=0; 1968 LastEntityProperty=0;
1969 1969
1970 1970
1971 1971
1972 1972
1973 1973
1974 1974
1975 LastCollisionDesc=0; 1975 LastCollisionDesc=0;
1976 1976
1977 updatedEntityCount = 0; 1977 updatedEntityCount = 0;
1978 collidersCount = 0; 1978 collidersCount = 0;
1979 1979
1980 1980
1981 if (pWorld is BulletWorldXNA) 1981 if (pWorld is BulletWorldXNA)
1982 { 1982 {
@@ -2033,7 +2033,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2033 2033
2034 collidersCount = LastCollisionDesc; 2034 collidersCount = LastCollisionDesc;
2035 colliders = UpdatedCollisions; 2035 colliders = UpdatedCollisions;
2036 2036
2037 2037
2038 } 2038 }
2039 else 2039 else
@@ -2041,15 +2041,15 @@ private sealed class BulletConstraintXNA : BulletConstraint
2041 //if (updatedEntities is null) 2041 //if (updatedEntities is null)
2042 //updatedEntities = new List<BulletXNA.EntityProperties>(); 2042 //updatedEntities = new List<BulletXNA.EntityProperties>();
2043 //updatedEntityCount = 0; 2043 //updatedEntityCount = 0;
2044 2044
2045 2045
2046 //collidersCount = 0; 2046 //collidersCount = 0;
2047 2047
2048 updatedEntities = new EntityProperties[0]; 2048 updatedEntities = new EntityProperties[0];
2049 2049
2050 2050
2051 colliders = new CollisionDesc[0]; 2051 colliders = new CollisionDesc[0];
2052 2052
2053 } 2053 }
2054 return numSimSteps; 2054 return numSimSteps;
2055 } 2055 }
@@ -2057,7 +2057,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2057 { 2057 {
2058 IOverlappingPairCache cache = obj.GetOverlappingPairCache(); 2058 IOverlappingPairCache cache = obj.GetOverlappingPairCache();
2059 ObjectArray<BroadphasePair> pairs = cache.GetOverlappingPairArray(); 2059 ObjectArray<BroadphasePair> pairs = cache.GetOverlappingPairArray();
2060 2060
2061 DiscreteDynamicsWorld world = (PhysicsScene.World as BulletWorldXNA).world; 2061 DiscreteDynamicsWorld world = (PhysicsScene.World as BulletWorldXNA).world;
2062 PersistentManifoldArray manifoldArray = new PersistentManifoldArray(); 2062 PersistentManifoldArray manifoldArray = new PersistentManifoldArray();
2063 BroadphasePair collisionPair; 2063 BroadphasePair collisionPair;
@@ -2069,7 +2069,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2069 ManifoldPoint pt; 2069 ManifoldPoint pt;
2070 2070
2071 int numPairs = pairs.Count; 2071 int numPairs = pairs.Count;
2072 2072
2073 for (int i = 0; i < numPairs; i++) 2073 for (int i = 0; i < numPairs; i++)
2074 { 2074 {
2075 manifoldArray.Clear(); 2075 manifoldArray.Clear();
@@ -2078,7 +2078,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2078 collisionPair = world.GetPairCache().FindPair(pairs[i].m_pProxy0, pairs[i].m_pProxy1); 2078 collisionPair = world.GetPairCache().FindPair(pairs[i].m_pProxy0, pairs[i].m_pProxy1);
2079 if (collisionPair == null) 2079 if (collisionPair == null)
2080 continue; 2080 continue;
2081 2081
2082 collisionPair.m_algorithm.GetAllContactManifolds(manifoldArray); 2082 collisionPair.m_algorithm.GetAllContactManifolds(manifoldArray);
2083 for (int j = 0; j < manifoldArray.Count; j++) 2083 for (int j = 0; j < manifoldArray.Count; j++)
2084 { 2084 {
@@ -2101,7 +2101,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2101 } 2101 }
2102 private static void RecordCollision(BSAPIXNA world, CollisionObject objA, CollisionObject objB, IndexedVector3 contact, IndexedVector3 norm, float penetration) 2102 private static void RecordCollision(BSAPIXNA world, CollisionObject objA, CollisionObject objB, IndexedVector3 contact, IndexedVector3 norm, float penetration)
2103 { 2103 {
2104 2104
2105 IndexedVector3 contactNormal = norm; 2105 IndexedVector3 contactNormal = norm;
2106 if ((objA.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0 && 2106 if ((objA.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0 &&
2107 (objB.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0) 2107 (objB.GetCollisionFlags() & BulletXNA.BulletCollision.CollisionFlags.BS_WANTS_COLLISIONS) == 0)
@@ -2171,11 +2171,11 @@ private sealed class BulletConstraintXNA : BulletConstraint
2171 if (NotMe is BulletBodyXNA && NotMe.HasPhysicalBody) 2171 if (NotMe is BulletBodyXNA && NotMe.HasPhysicalBody)
2172 { 2172 {
2173 CollisionObject AvoidBody = (NotMe as BulletBodyXNA).body; 2173 CollisionObject AvoidBody = (NotMe as BulletBodyXNA).body;
2174 2174
2175 IndexedVector3 rOrigin = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z); 2175 IndexedVector3 rOrigin = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z);
2176 IndexedVector3 rEnd = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z - pRayHeight); 2176 IndexedVector3 rEnd = new IndexedVector3(_RayOrigin.X, _RayOrigin.Y, _RayOrigin.Z - pRayHeight);
2177 using ( 2177 using (
2178 ClosestNotMeRayResultCallback rayCallback = 2178 ClosestNotMeRayResultCallback rayCallback =
2179 new ClosestNotMeRayResultCallback(rOrigin, rEnd, AvoidBody) 2179 new ClosestNotMeRayResultCallback(rOrigin, rEnd, AvoidBody)
2180 ) 2180 )
2181 { 2181 {
@@ -2191,9 +2191,9 @@ private sealed class BulletConstraintXNA : BulletConstraint
2191 return false; 2191 return false;
2192 } 2192 }
2193} 2193}
2194
2195 2194
2196 2195
2196
2197 2197
2198 public class SimMotionState : DefaultMotionState 2198 public class SimMotionState : DefaultMotionState
2199 { 2199 {
@@ -2286,12 +2286,12 @@ private sealed class BulletConstraintXNA : BulletConstraint
2286 m_lastProperties = m_properties; 2286 m_lastProperties = m_properties;
2287 if (m_world.LastEntityProperty < m_world.UpdatedObjects.Length) 2287 if (m_world.LastEntityProperty < m_world.UpdatedObjects.Length)
2288 m_world.UpdatedObjects[m_world.LastEntityProperty++]=(m_properties); 2288 m_world.UpdatedObjects[m_world.LastEntityProperty++]=(m_properties);
2289 2289
2290 //(*m_updatesThisFrame)[m_properties.ID] = &m_properties; 2290 //(*m_updatesThisFrame)[m_properties.ID] = &m_properties;
2291 } 2291 }
2292 2292
2293 2293
2294 2294
2295 2295
2296 } 2296 }
2297 public override void SetRigidBody(RigidBody body) 2297 public override void SetRigidBody(RigidBody body)
@@ -2314,7 +2314,7 @@ private sealed class BulletConstraintXNA : BulletConstraint
2314 (((v1.Z - nEpsilon) < v2.Z) && (v2.Z < (v1.Z + nEpsilon))) && 2314 (((v1.Z - nEpsilon) < v2.Z) && (v2.Z < (v1.Z + nEpsilon))) &&
2315 (((v1.W - nEpsilon) < v2.W) && (v2.W < (v1.W + nEpsilon))); 2315 (((v1.W - nEpsilon) < v2.W) && (v2.W < (v1.W + nEpsilon)));
2316 } 2316 }
2317 2317
2318 } 2318 }
2319} 2319}
2320 2320
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
index bd5ee0b1..4e067b5 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -87,8 +87,8 @@ public class BSActorAvatarMove : BSActor
87 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 87 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
88 // Register a prestep action to restore physical requirements before the next simulation step. 88 // Register a prestep action to restore physical requirements before the next simulation step.
89 // Called at taint-time. 89 // Called at taint-time.
90 // BSActor.RemoveBodyDependencies() 90 // BSActor.RemoveDependencies()
91 public override void RemoveBodyDependencies() 91 public override void RemoveDependencies()
92 { 92 {
93 // Nothing to do for the hoverer since it is all software at pre-step action time. 93 // Nothing to do for the hoverer since it is all software at pre-step action time.
94 } 94 }
@@ -115,7 +115,7 @@ public class BSActorAvatarMove : BSActor
115 if (m_velocityMotor == null) 115 if (m_velocityMotor == null)
116 { 116 {
117 // Infinite decay and timescale values so motor only changes current to target values. 117 // Infinite decay and timescale values so motor only changes current to target values.
118 m_velocityMotor = new BSVMotor("BSCharacter.Velocity", 118 m_velocityMotor = new BSVMotor("BSCharacter.Velocity",
119 0.2f, // time scale 119 0.2f, // time scale
120 BSMotor.Infinite, // decay time scale 120 BSMotor.Infinite, // decay time scale
121 BSMotor.InfiniteVector, // friction timescale 121 BSMotor.InfiniteVector, // friction timescale
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
index 92ace66..3630ca8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorHover.cs
@@ -87,8 +87,8 @@ public class BSActorHover : BSActor
87 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 87 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
88 // Register a prestep action to restore physical requirements before the next simulation step. 88 // Register a prestep action to restore physical requirements before the next simulation step.
89 // Called at taint-time. 89 // Called at taint-time.
90 // BSActor.RemoveBodyDependencies() 90 // BSActor.RemoveDependencies()
91 public override void RemoveBodyDependencies() 91 public override void RemoveDependencies()
92 { 92 {
93 // Nothing to do for the hoverer since it is all software at pre-step action time. 93 // Nothing to do for the hoverer since it is all software at pre-step action time.
94 } 94 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
index 09ee32b..7801d8e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorLockAxis.cs
@@ -63,7 +63,7 @@ public class BSActorLockAxis : BSActor
63 // BSActor.Refresh() 63 // BSActor.Refresh()
64 public override void Refresh() 64 public override void Refresh()
65 { 65 {
66 m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,lockedAxis={1},enabled={2},pActive={3}", 66 m_physicsScene.DetailLog("{0},BSActorLockAxis,refresh,lockedAxis={1},enabled={2},pActive={3}",
67 m_controllingPrim.LocalID, m_controllingPrim.LockedAxis, Enabled, m_controllingPrim.IsPhysicallyActive); 67 m_controllingPrim.LocalID, m_controllingPrim.LockedAxis, Enabled, m_controllingPrim.IsPhysicallyActive);
68 // If all the axis are free, we don't need to exist 68 // If all the axis are free, we don't need to exist
69 if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree) 69 if (m_controllingPrim.LockedAxis == m_controllingPrim.LockedAxisFree)
@@ -85,8 +85,8 @@ public class BSActorLockAxis : BSActor
85 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 85 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
86 // Register a prestep action to restore physical requirements before the next simulation step. 86 // Register a prestep action to restore physical requirements before the next simulation step.
87 // Called at taint-time. 87 // Called at taint-time.
88 // BSActor.RemoveBodyDependencies() 88 // BSActor.RemoveDependencies()
89 public override void RemoveBodyDependencies() 89 public override void RemoveDependencies()
90 { 90 {
91 if (LockAxisConstraint != null) 91 if (LockAxisConstraint != null)
92 { 92 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
index 56aacc5..1b598fd 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorMoveToTarget.cs
@@ -88,8 +88,8 @@ public class BSActorMoveToTarget : BSActor
88 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 88 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
89 // Register a prestep action to restore physical requirements before the next simulation step. 89 // Register a prestep action to restore physical requirements before the next simulation step.
90 // Called at taint-time. 90 // Called at taint-time.
91 // BSActor.RemoveBodyDependencies() 91 // BSActor.RemoveDependencies()
92 public override void RemoveBodyDependencies() 92 public override void RemoveDependencies()
93 { 93 {
94 // Nothing to do for the moveToTarget since it is all software at pre-step action time. 94 // Nothing to do for the moveToTarget since it is all software at pre-step action time.
95 } 95 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
index 3ad138d..c0f40fd 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetForce.cs
@@ -89,8 +89,8 @@ public class BSActorSetForce : BSActor
89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
90 // Register a prestep action to restore physical requirements before the next simulation step. 90 // Register a prestep action to restore physical requirements before the next simulation step.
91 // Called at taint-time. 91 // Called at taint-time.
92 // BSActor.RemoveBodyDependencies() 92 // BSActor.RemoveDependencies()
93 public override void RemoveBodyDependencies() 93 public override void RemoveDependencies()
94 { 94 {
95 // Nothing to do for the hoverer since it is all software at pre-step action time. 95 // Nothing to do for the hoverer since it is all software at pre-step action time.
96 } 96 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
index 7a791ec..b3806e1 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorSetTorque.cs
@@ -89,8 +89,8 @@ public class BSActorSetTorque : BSActor
89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 89 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
90 // Register a prestep action to restore physical requirements before the next simulation step. 90 // Register a prestep action to restore physical requirements before the next simulation step.
91 // Called at taint-time. 91 // Called at taint-time.
92 // BSActor.RemoveBodyDependencies() 92 // BSActor.RemoveDependencies()
93 public override void RemoveBodyDependencies() 93 public override void RemoveDependencies()
94 { 94 {
95 // Nothing to do for the hoverer since it is all software at pre-step action time. 95 // Nothing to do for the hoverer since it is all software at pre-step action time.
96 } 96 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
index 12a8817..fff63e4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActors.cs
@@ -106,9 +106,9 @@ public class BSActorCollection
106 { 106 {
107 ForEachActor(a => a.Refresh()); 107 ForEachActor(a => a.Refresh());
108 } 108 }
109 public void RemoveBodyDependencies() 109 public void RemoveDependencies()
110 { 110 {
111 ForEachActor(a => a.RemoveBodyDependencies()); 111 ForEachActor(a => a.RemoveDependencies());
112 } 112 }
113} 113}
114 114
@@ -117,7 +117,7 @@ public class BSActorCollection
117/// Each physical object can have 'actors' who are pushing the object around. 117/// Each physical object can have 'actors' who are pushing the object around.
118/// This can be used for hover, locking axis, making vehicles, etc. 118/// This can be used for hover, locking axis, making vehicles, etc.
119/// Each physical object can have multiple actors acting on it. 119/// Each physical object can have multiple actors acting on it.
120/// 120///
121/// An actor usually registers itself with physics scene events (pre-step action) 121/// An actor usually registers itself with physics scene events (pre-step action)
122/// and modifies the parameters on the host physical object. 122/// and modifies the parameters on the host physical object.
123/// </summary> 123/// </summary>
@@ -154,7 +154,7 @@ public abstract class BSActor
154 public abstract void Refresh(); 154 public abstract void Refresh();
155 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...). 155 // The object's physical representation is being rebuilt so pick up any physical dependencies (constraints, ...).
156 // Register a prestep action to restore physical requirements before the next simulation step. 156 // Register a prestep action to restore physical requirements before the next simulation step.
157 public abstract void RemoveBodyDependencies(); 157 public abstract void RemoveDependencies();
158 158
159} 159}
160} 160}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
index bfeec24..3378c93 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
@@ -298,7 +298,7 @@ public abstract class BSAPITemplate
298{ 298{
299// Returns the name of the underlying Bullet engine 299// Returns the name of the underlying Bullet engine
300public abstract string BulletEngineName { get; } 300public abstract string BulletEngineName { get; }
301public abstract string BulletEngineVersion { get; protected set;} 301public abstract string BulletEngineVersion { get; protected set;}
302 302
303// Initialization and simulation 303// Initialization and simulation
304public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms, 304public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms,
@@ -373,7 +373,7 @@ public abstract void DestroyObject(BulletWorld sim, BulletBody obj);
373// ===================================================================================== 373// =====================================================================================
374public abstract BulletShape CreateGroundPlaneShape(UInt32 id, float height, float collisionMargin); 374public abstract BulletShape CreateGroundPlaneShape(UInt32 id, float height, float collisionMargin);
375 375
376public abstract BulletShape CreateTerrainShape(UInt32 id, Vector3 size, float minHeight, float maxHeight, float[] heightMap, 376public abstract BulletShape CreateTerrainShape(UInt32 id, Vector3 size, float minHeight, float maxHeight, float[] heightMap,
377 float scaleFactor, float collisionMargin); 377 float scaleFactor, float collisionMargin);
378 378
379// ===================================================================================== 379// =====================================================================================
@@ -388,7 +388,7 @@ public abstract BulletConstraint Create6DofConstraintToPoint(BulletWorld world,
388 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 388 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
389 389
390public abstract BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1, 390public abstract BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1,
391 Vector3 frameInBloc, Quaternion frameInBrot, 391 Vector3 frameInBloc, Quaternion frameInBrot,
392 bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies); 392 bool useLinearReferenceFrameB, bool disableCollisionsBetweenLinkedBodies);
393 393
394public abstract BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2, 394public abstract BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2,
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index a0d58d3..542f732 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -95,18 +95,18 @@ public sealed class BSCharacter : BSPhysObject
95 // the avatar seeking to reach the motor's target speed. 95 // the avatar seeking to reach the motor's target speed.
96 // This motor runs as a prestep action for the avatar so it will keep the avatar 96 // This motor runs as a prestep action for the avatar so it will keep the avatar
97 // standing as well as moving. Destruction of the avatar will destroy the pre-step action. 97 // standing as well as moving. Destruction of the avatar will destroy the pre-step action.
98 m_moveActor = new BSActorAvatarMove(PhysicsScene, this, AvatarMoveActorName); 98 m_moveActor = new BSActorAvatarMove(PhysScene, this, AvatarMoveActorName);
99 PhysicalActors.Add(AvatarMoveActorName, m_moveActor); 99 PhysicalActors.Add(AvatarMoveActorName, m_moveActor);
100 100
101 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", 101 DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
102 LocalID, _size, Scale, Density, _avatarVolume, RawMass); 102 LocalID, _size, Scale, Density, _avatarVolume, RawMass);
103 103
104 // do actual creation in taint time 104 // do actual creation in taint time
105 PhysicsScene.TaintedObject("BSCharacter.create", delegate() 105 PhysScene.TaintedObject("BSCharacter.create", delegate()
106 { 106 {
107 DetailLog("{0},BSCharacter.create,taint", LocalID); 107 DetailLog("{0},BSCharacter.create,taint", LocalID);
108 // New body and shape into PhysBody and PhysShape 108 // New body and shape into PhysBody and PhysShape
109 PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this); 109 PhysScene.Shapes.GetBodyAndShape(true, PhysScene.World, this);
110 110
111 SetPhysicalProperties(); 111 SetPhysicalProperties();
112 }); 112 });
@@ -119,18 +119,18 @@ public sealed class BSCharacter : BSPhysObject
119 base.Destroy(); 119 base.Destroy();
120 120
121 DetailLog("{0},BSCharacter.Destroy", LocalID); 121 DetailLog("{0},BSCharacter.Destroy", LocalID);
122 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() 122 PhysScene.TaintedObject("BSCharacter.destroy", delegate()
123 { 123 {
124 PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */); 124 PhysScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
125 PhysBody.Clear(); 125 PhysBody.Clear();
126 PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */); 126 PhysShape.Dereference(PhysScene);
127 PhysShape.Clear(); 127 PhysShape = new BSShapeNull();
128 }); 128 });
129 } 129 }
130 130
131 private void SetPhysicalProperties() 131 private void SetPhysicalProperties()
132 { 132 {
133 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 133 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
134 134
135 ZeroMotion(true); 135 ZeroMotion(true);
136 ForcePosition = _position; 136 ForcePosition = _position;
@@ -145,35 +145,35 @@ public sealed class BSCharacter : BSPhysObject
145 // Needs to be reset especially when an avatar is recreated after crossing a region boundry. 145 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
146 Flying = _flying; 146 Flying = _flying;
147 147
148 PhysicsScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution); 148 PhysScene.PE.SetRestitution(PhysBody, BSParam.AvatarRestitution);
149 PhysicsScene.PE.SetMargin(PhysShape, PhysicsScene.Params.collisionMargin); 149 PhysScene.PE.SetMargin(PhysShape.physShapeInfo, PhysScene.Params.collisionMargin);
150 PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); 150 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
151 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 151 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
152 if (BSParam.CcdMotionThreshold > 0f) 152 if (BSParam.CcdMotionThreshold > 0f)
153 { 153 {
154 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 154 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
155 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 155 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
156 } 156 }
157 157
158 UpdatePhysicalMassProperties(RawMass, false); 158 UpdatePhysicalMassProperties(RawMass, false);
159 159
160 // Make so capsule does not fall over 160 // Make so capsule does not fall over
161 PhysicsScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero); 161 PhysScene.PE.SetAngularFactorV(PhysBody, OMV.Vector3.Zero);
162 162
163 // The avatar mover sets some parameters. 163 // The avatar mover sets some parameters.
164 PhysicalActors.Refresh(); 164 PhysicalActors.Refresh();
165 165
166 PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT); 166 PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_CHARACTER_OBJECT);
167 167
168 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); 168 PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody);
169 169
170 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); 170 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
171 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION); 171 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_DEACTIVATION);
172 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); 172 PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody);
173 173
174 // Do this after the object has been added to the world 174 // Do this after the object has been added to the world
175 PhysBody.collisionType = CollisionType.Avatar; 175 PhysBody.collisionType = CollisionType.Avatar;
176 PhysBody.ApplyCollisionMask(PhysicsScene); 176 PhysBody.ApplyCollisionMask(PhysScene);
177 } 177 }
178 178
179 179
@@ -203,14 +203,14 @@ public sealed class BSCharacter : BSPhysObject
203 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", 203 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
204 LocalID, _size, Scale, Density, _avatarVolume, RawMass); 204 LocalID, _size, Scale, Density, _avatarVolume, RawMass);
205 205
206 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() 206 PhysScene.TaintedObject("BSCharacter.setSize", delegate()
207 { 207 {
208 if (PhysBody.HasPhysicalBody && PhysShape.HasPhysicalShape) 208 if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape)
209 { 209 {
210 PhysicsScene.PE.SetLocalScaling(PhysShape, Scale); 210 PhysScene.PE.SetLocalScaling(PhysShape.physShapeInfo, Scale);
211 UpdatePhysicalMassProperties(RawMass, true); 211 UpdatePhysicalMassProperties(RawMass, true);
212 // Make sure this change appears as a property update event 212 // Make sure this change appears as a property update event
213 PhysicsScene.PE.PushUpdate(PhysBody); 213 PhysScene.PE.PushUpdate(PhysBody);
214 } 214 }
215 }); 215 });
216 216
@@ -221,11 +221,6 @@ public sealed class BSCharacter : BSPhysObject
221 { 221 {
222 set { BaseShape = value; } 222 set { BaseShape = value; }
223 } 223 }
224 // I want the physics engine to make an avatar capsule
225 public override BSPhysicsShapeType PreferredPhysicalShape
226 {
227 get {return BSPhysicsShapeType.SHAPE_CAPSULE; }
228 }
229 224
230 public override bool Grabbed { 225 public override bool Grabbed {
231 set { _grabbed = value; } 226 set { _grabbed = value; }
@@ -252,24 +247,24 @@ public sealed class BSCharacter : BSPhysObject
252 _rotationalVelocity = OMV.Vector3.Zero; 247 _rotationalVelocity = OMV.Vector3.Zero;
253 248
254 // Zero some other properties directly into the physics engine 249 // Zero some other properties directly into the physics engine
255 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() 250 PhysScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
256 { 251 {
257 if (PhysBody.HasPhysicalBody) 252 if (PhysBody.HasPhysicalBody)
258 PhysicsScene.PE.ClearAllForces(PhysBody); 253 PhysScene.PE.ClearAllForces(PhysBody);
259 }); 254 });
260 } 255 }
261 public override void ZeroAngularMotion(bool inTaintTime) 256 public override void ZeroAngularMotion(bool inTaintTime)
262 { 257 {
263 _rotationalVelocity = OMV.Vector3.Zero; 258 _rotationalVelocity = OMV.Vector3.Zero;
264 259
265 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() 260 PhysScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate()
266 { 261 {
267 if (PhysBody.HasPhysicalBody) 262 if (PhysBody.HasPhysicalBody)
268 { 263 {
269 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero); 264 PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, OMV.Vector3.Zero);
270 PhysicsScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero); 265 PhysScene.PE.SetAngularVelocity(PhysBody, OMV.Vector3.Zero);
271 // The next also get rid of applied linear force but the linear velocity is untouched. 266 // The next also get rid of applied linear force but the linear velocity is untouched.
272 PhysicsScene.PE.ClearForces(PhysBody); 267 PhysScene.PE.ClearForces(PhysBody);
273 } 268 }
274 }); 269 });
275 } 270 }
@@ -291,7 +286,7 @@ public sealed class BSCharacter : BSPhysObject
291 set { 286 set {
292 _position = value; 287 _position = value;
293 288
294 PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() 289 PhysScene.TaintedObject("BSCharacter.setPosition", delegate()
295 { 290 {
296 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 291 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
297 PositionSanityCheck(); 292 PositionSanityCheck();
@@ -301,14 +296,14 @@ public sealed class BSCharacter : BSPhysObject
301 } 296 }
302 public override OMV.Vector3 ForcePosition { 297 public override OMV.Vector3 ForcePosition {
303 get { 298 get {
304 _position = PhysicsScene.PE.GetPosition(PhysBody); 299 _position = PhysScene.PE.GetPosition(PhysBody);
305 return _position; 300 return _position;
306 } 301 }
307 set { 302 set {
308 _position = value; 303 _position = value;
309 if (PhysBody.HasPhysicalBody) 304 if (PhysBody.HasPhysicalBody)
310 { 305 {
311 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 306 PhysScene.PE.SetTranslation(PhysBody, _position, _orientation);
312 } 307 }
313 } 308 }
314 } 309 }
@@ -322,18 +317,18 @@ public sealed class BSCharacter : BSPhysObject
322 bool ret = false; 317 bool ret = false;
323 318
324 // TODO: check for out of bounds 319 // TODO: check for out of bounds
325 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) 320 if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
326 { 321 {
327 // The character is out of the known/simulated area. 322 // The character is out of the known/simulated area.
328 // Force the avatar position to be within known. ScenePresence will use the position 323 // Force the avatar position to be within known. ScenePresence will use the position
329 // plus the velocity to decide if the avatar is moving out of the region. 324 // plus the velocity to decide if the avatar is moving out of the region.
330 RawPosition = PhysicsScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition); 325 RawPosition = PhysScene.TerrainManager.ClampPositionIntoKnownTerrain(RawPosition);
331 DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition); 326 DetailLog("{0},BSCharacter.PositionSanityCheck,notWithinKnownTerrain,clampedPos={1}", LocalID, RawPosition);
332 return true; 327 return true;
333 } 328 }
334 329
335 // If below the ground, move the avatar up 330 // If below the ground, move the avatar up
336 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); 331 float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
337 if (Position.Z < terrainHeight) 332 if (Position.Z < terrainHeight)
338 { 333 {
339 DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, _position, terrainHeight); 334 DetailLog("{0},BSCharacter.PositionSanityCheck,adjustForUnderGround,pos={1},terrain={2}", LocalID, _position, terrainHeight);
@@ -342,7 +337,7 @@ public sealed class BSCharacter : BSPhysObject
342 } 337 }
343 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 338 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
344 { 339 {
345 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); 340 float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(_position);
346 if (Position.Z < waterHeight) 341 if (Position.Z < waterHeight)
347 { 342 {
348 _position.Z = waterHeight; 343 _position.Z = waterHeight;
@@ -363,7 +358,7 @@ public sealed class BSCharacter : BSPhysObject
363 { 358 {
364 // The new position value must be pushed into the physics engine but we can't 359 // The new position value must be pushed into the physics engine but we can't
365 // just assign to "Position" because of potential call loops. 360 // just assign to "Position" because of potential call loops.
366 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() 361 PhysScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
367 { 362 {
368 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 363 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
369 ForcePosition = _position; 364 ForcePosition = _position;
@@ -376,13 +371,13 @@ public sealed class BSCharacter : BSPhysObject
376 public override float Mass { get { return _mass; } } 371 public override float Mass { get { return _mass; } }
377 372
378 // used when we only want this prim's mass and not the linkset thing 373 // used when we only want this prim's mass and not the linkset thing
379 public override float RawMass { 374 public override float RawMass {
380 get {return _mass; } 375 get {return _mass; }
381 } 376 }
382 public override void UpdatePhysicalMassProperties(float physMass, bool inWorld) 377 public override void UpdatePhysicalMassProperties(float physMass, bool inWorld)
383 { 378 {
384 OMV.Vector3 localInertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); 379 OMV.Vector3 localInertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
385 PhysicsScene.PE.SetMassProps(PhysBody, physMass, localInertia); 380 PhysScene.PE.SetMassProps(PhysBody, physMass, localInertia);
386 } 381 }
387 382
388 public override OMV.Vector3 Force { 383 public override OMV.Vector3 Force {
@@ -390,11 +385,11 @@ public sealed class BSCharacter : BSPhysObject
390 set { 385 set {
391 RawForce = value; 386 RawForce = value;
392 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 387 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
393 PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() 388 PhysScene.TaintedObject("BSCharacter.SetForce", delegate()
394 { 389 {
395 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce); 390 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce);
396 if (PhysBody.HasPhysicalBody) 391 if (PhysBody.HasPhysicalBody)
397 PhysicsScene.PE.SetObjectForce(PhysBody, RawForce); 392 PhysScene.PE.SetObjectForce(PhysBody, RawForce);
398 }); 393 });
399 } 394 }
400 } 395 }
@@ -437,7 +432,7 @@ public sealed class BSCharacter : BSPhysObject
437 set { 432 set {
438 RawVelocity = value; 433 RawVelocity = value;
439 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity); 434 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity);
440 PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() 435 PhysScene.TaintedObject("BSCharacter.setVelocity", delegate()
441 { 436 {
442 if (m_moveActor != null) 437 if (m_moveActor != null)
443 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */); 438 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */);
@@ -450,11 +445,11 @@ public sealed class BSCharacter : BSPhysObject
450 public override OMV.Vector3 ForceVelocity { 445 public override OMV.Vector3 ForceVelocity {
451 get { return RawVelocity; } 446 get { return RawVelocity; }
452 set { 447 set {
453 PhysicsScene.AssertInTaintTime("BSCharacter.ForceVelocity"); 448 PhysScene.AssertInTaintTime("BSCharacter.ForceVelocity");
454 449
455 RawVelocity = value; 450 RawVelocity = value;
456 PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity); 451 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
457 PhysicsScene.PE.Activate(PhysBody, true); 452 PhysScene.PE.Activate(PhysBody, true);
458 } 453 }
459 } 454 }
460 public override OMV.Vector3 Torque { 455 public override OMV.Vector3 Torque {
@@ -484,7 +479,7 @@ public sealed class BSCharacter : BSPhysObject
484 if (_orientation != value) 479 if (_orientation != value)
485 { 480 {
486 _orientation = value; 481 _orientation = value;
487 PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() 482 PhysScene.TaintedObject("BSCharacter.setOrientation", delegate()
488 { 483 {
489 ForceOrientation = _orientation; 484 ForceOrientation = _orientation;
490 }); 485 });
@@ -496,7 +491,7 @@ public sealed class BSCharacter : BSPhysObject
496 { 491 {
497 get 492 get
498 { 493 {
499 _orientation = PhysicsScene.PE.GetOrientation(PhysBody); 494 _orientation = PhysScene.PE.GetOrientation(PhysBody);
500 return _orientation; 495 return _orientation;
501 } 496 }
502 set 497 set
@@ -505,7 +500,7 @@ public sealed class BSCharacter : BSPhysObject
505 if (PhysBody.HasPhysicalBody) 500 if (PhysBody.HasPhysicalBody)
506 { 501 {
507 // _position = PhysicsScene.PE.GetPosition(BSBody); 502 // _position = PhysicsScene.PE.GetPosition(BSBody);
508 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 503 PhysScene.PE.SetTranslation(PhysBody, _position, _orientation);
509 } 504 }
510 } 505 }
511 } 506 }
@@ -554,14 +549,14 @@ public sealed class BSCharacter : BSPhysObject
554 public override bool FloatOnWater { 549 public override bool FloatOnWater {
555 set { 550 set {
556 _floatOnWater = value; 551 _floatOnWater = value;
557 PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() 552 PhysScene.TaintedObject("BSCharacter.setFloatOnWater", delegate()
558 { 553 {
559 if (PhysBody.HasPhysicalBody) 554 if (PhysBody.HasPhysicalBody)
560 { 555 {
561 if (_floatOnWater) 556 if (_floatOnWater)
562 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 557 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
563 else 558 else
564 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 559 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
565 } 560 }
566 }); 561 });
567 } 562 }
@@ -582,7 +577,7 @@ public sealed class BSCharacter : BSPhysObject
582 public override float Buoyancy { 577 public override float Buoyancy {
583 get { return _buoyancy; } 578 get { return _buoyancy; }
584 set { _buoyancy = value; 579 set { _buoyancy = value;
585 PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() 580 PhysScene.TaintedObject("BSCharacter.setBuoyancy", delegate()
586 { 581 {
587 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 582 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
588 ForceBuoyancy = _buoyancy; 583 ForceBuoyancy = _buoyancy;
@@ -591,8 +586,8 @@ public sealed class BSCharacter : BSPhysObject
591 } 586 }
592 public override float ForceBuoyancy { 587 public override float ForceBuoyancy {
593 get { return _buoyancy; } 588 get { return _buoyancy; }
594 set { 589 set {
595 PhysicsScene.AssertInTaintTime("BSCharacter.ForceBuoyancy"); 590 PhysScene.AssertInTaintTime("BSCharacter.ForceBuoyancy");
596 591
597 _buoyancy = value; 592 _buoyancy = value;
598 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 593 DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
@@ -600,7 +595,7 @@ public sealed class BSCharacter : BSPhysObject
600 float grav = BSParam.Gravity * (1f - _buoyancy); 595 float grav = BSParam.Gravity * (1f - _buoyancy);
601 Gravity = new OMV.Vector3(0f, 0f, grav); 596 Gravity = new OMV.Vector3(0f, 0f, grav);
602 if (PhysBody.HasPhysicalBody) 597 if (PhysBody.HasPhysicalBody)
603 PhysicsScene.PE.SetGravity(PhysBody, Gravity); 598 PhysScene.PE.SetGravity(PhysBody, Gravity);
604 } 599 }
605 } 600 }
606 601
@@ -618,7 +613,7 @@ public sealed class BSCharacter : BSPhysObject
618 public override void AddForce(OMV.Vector3 force, bool pushforce) 613 public override void AddForce(OMV.Vector3 force, bool pushforce)
619 { 614 {
620 // Since this force is being applied in only one step, make this a force per second. 615 // Since this force is being applied in only one step, make this a force per second.
621 OMV.Vector3 addForce = force / PhysicsScene.LastTimeStep; 616 OMV.Vector3 addForce = force / PhysScene.LastTimeStep;
622 AddForce(addForce, pushforce, false); 617 AddForce(addForce, pushforce, false);
623 } 618 }
624 private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 619 private void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
@@ -627,13 +622,13 @@ public sealed class BSCharacter : BSPhysObject
627 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 622 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
628 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); 623 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce);
629 624
630 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() 625 PhysScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate()
631 { 626 {
632 // Bullet adds this central force to the total force for this tick 627 // Bullet adds this central force to the total force for this tick
633 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce); 628 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce);
634 if (PhysBody.HasPhysicalBody) 629 if (PhysBody.HasPhysicalBody)
635 { 630 {
636 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); 631 PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
637 } 632 }
638 }); 633 });
639 } 634 }
@@ -652,7 +647,7 @@ public sealed class BSCharacter : BSPhysObject
652 private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size) 647 private OMV.Vector3 ComputeAvatarScale(OMV.Vector3 size)
653 { 648 {
654 OMV.Vector3 newScale; 649 OMV.Vector3 newScale;
655 650
656 // Bullet's capsule total height is the "passed height + radius * 2"; 651 // Bullet's capsule total height is the "passed height + radius * 2";
657 // The base capsule is 1 diameter and 2 height (passed radius=0.5, passed height = 1) 652 // The base capsule is 1 diameter and 2 height (passed radius=0.5, passed height = 1)
658 // The number we pass in for 'scaling' is the multiplier to get that base 653 // The number we pass in for 'scaling' is the multiplier to get that base
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
index 7714a03..ed89f63 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs
@@ -45,7 +45,7 @@ public sealed class BSConstraintHinge : BSConstraint
45 m_body1 = obj1; 45 m_body1 = obj1;
46 m_body2 = obj2; 46 m_body2 = obj2;
47 m_constraint = PhysicsScene.PE.CreateHingeConstraint(world, obj1, obj2, 47 m_constraint = PhysicsScene.PE.CreateHingeConstraint(world, obj1, obj2,
48 pivotInA, pivotInB, axisInA, axisInB, 48 pivotInA, pivotInB, axisInA, axisInB,
49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); 49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
50 m_enabled = true; 50 m_enabled = true;
51 } 51 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index 612c68b..c5bee6d 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -559,9 +559,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
559 break; 559 break;
560 } 560 }
561 561
562 // Update any physical parameters based on this type.
563 Refresh();
564
565 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, 562 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale,
566 m_linearMotorDecayTimescale, m_linearFrictionTimescale, 563 m_linearMotorDecayTimescale, m_linearFrictionTimescale,
567 1f); 564 1f);
@@ -589,6 +586,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
589 { 586 {
590 RegisterForSceneEvents(); 587 RegisterForSceneEvents();
591 } 588 }
589
590 // Update any physical parameters based on this type.
591 Refresh();
592 } 592 }
593 #endregion // Vehicle parameter setting 593 #endregion // Vehicle parameter setting
594 594
@@ -596,6 +596,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
596 public override void Refresh() 596 public override void Refresh()
597 { 597 {
598 // If asking for a refresh, reset the physical parameters before the next simulation step. 598 // If asking for a refresh, reset the physical parameters before the next simulation step.
599 // Called whether active or not since the active state may be updated before the next step.
599 m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate() 600 m_physicsScene.PostTaintObject("BSDynamics.Refresh", ControllingPrim.LocalID, delegate()
600 { 601 {
601 SetPhysicalParameters(); 602 SetPhysicalParameters();
@@ -625,7 +626,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
625 // Vehicles report collision events so we know when it's on the ground 626 // Vehicles report collision events so we know when it's on the ground
626 m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); 627 m_physicsScene.PE.AddToCollisionFlags(ControllingPrim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS);
627 628
628 ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape, m_vehicleMass); 629 ControllingPrim.Inertia = m_physicsScene.PE.CalculateLocalInertia(ControllingPrim.PhysShape.physShapeInfo, m_vehicleMass);
629 m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia); 630 m_physicsScene.PE.SetMassProps(ControllingPrim.PhysBody, m_vehicleMass, ControllingPrim.Inertia);
630 m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody); 631 m_physicsScene.PE.UpdateInertiaTensor(ControllingPrim.PhysBody);
631 632
@@ -649,7 +650,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
649 } 650 }
650 651
651 // BSActor.RemoveBodyDependencies 652 // BSActor.RemoveBodyDependencies
652 public override void RemoveBodyDependencies() 653 public override void RemoveDependencies()
653 { 654 {
654 Refresh(); 655 Refresh();
655 } 656 }
@@ -789,7 +790,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
789 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos) 790 if ((m_knownHas & m_knownChangedTerrainHeight) == 0 || pos != lastRememberedHeightPos)
790 { 791 {
791 lastRememberedHeightPos = pos; 792 lastRememberedHeightPos = pos;
792 m_knownTerrainHeight = ControllingPrim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); 793 m_knownTerrainHeight = ControllingPrim.PhysScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
793 m_knownHas |= m_knownChangedTerrainHeight; 794 m_knownHas |= m_knownChangedTerrainHeight;
794 } 795 }
795 return m_knownTerrainHeight; 796 return m_knownTerrainHeight;
@@ -801,7 +802,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
801 { 802 {
802 if ((m_knownHas & m_knownChangedWaterLevel) == 0) 803 if ((m_knownHas & m_knownChangedWaterLevel) == 0)
803 { 804 {
804 m_knownWaterLevel = ControllingPrim.PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(pos); 805 m_knownWaterLevel = ControllingPrim.PhysScene.TerrainManager.GetWaterLevelAtXYZ(pos);
805 m_knownHas |= m_knownChangedWaterLevel; 806 m_knownHas |= m_knownChangedWaterLevel;
806 } 807 }
807 return (float)m_knownWaterLevel; 808 return (float)m_knownWaterLevel;
@@ -1019,7 +1020,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1019 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG 1020 Vector3 origVelW = VehicleVelocity; // DEBUG DEBUG
1020 VehicleVelocity /= VehicleVelocity.Length(); 1021 VehicleVelocity /= VehicleVelocity.Length();
1021 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity; 1022 VehicleVelocity *= BSParam.VehicleMaxLinearVelocity;
1022 VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}", 1023 VDetailLog("{0}, MoveLinear,clampMax,origVelW={1},lenSq={2},maxVelSq={3},,newVelW={4}",
1023 ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity); 1024 ControllingPrim.LocalID, origVelW, newVelocityLengthSq, BSParam.VehicleMaxLinearVelocitySquared, VehicleVelocity);
1024 } 1025 }
1025 else if (newVelocityLengthSq < 0.001f) 1026 else if (newVelocityLengthSq < 0.001f)
@@ -1094,7 +1095,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1094 if (VehiclePosition.Z > m_VhoverTargetHeight) 1095 if (VehiclePosition.Z > m_VhoverTargetHeight)
1095 m_VhoverTargetHeight = VehiclePosition.Z; 1096 m_VhoverTargetHeight = VehiclePosition.Z;
1096 } 1097 }
1097 1098
1098 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) 1099 if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
1099 { 1100 {
1100 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f) 1101 if (Math.Abs(VehiclePosition.Z - m_VhoverTargetHeight) > 0.2f)
@@ -1188,7 +1189,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1188 // used with conjunction with banking: the strength of the banking will decay when the 1189 // used with conjunction with banking: the strength of the banking will decay when the
1189 // vehicle no longer experiences collisions. The decay timescale is the same as 1190 // vehicle no longer experiences collisions. The decay timescale is the same as
1190 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering 1191 // VEHICLE_BANKING_TIMESCALE. This is to help prevent ground vehicles from steering
1191 // when they are in mid jump. 1192 // when they are in mid jump.
1192 // TODO: this code is wrong. Also, what should it do for boats (height from water)? 1193 // TODO: this code is wrong. Also, what should it do for boats (height from water)?
1193 // This is just using the ground and a general collision check. Should really be using 1194 // This is just using the ground and a general collision check. Should really be using
1194 // a downward raycast to find what is below. 1195 // a downward raycast to find what is below.
@@ -1254,7 +1255,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1254 1255
1255 VehicleAddForce(appliedGravity); 1256 VehicleAddForce(appliedGravity);
1256 1257
1257 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={3}", 1258 VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={3}",
1258 ControllingPrim.LocalID, m_VehicleGravity, 1259 ControllingPrim.LocalID, m_VehicleGravity,
1259 ControllingPrim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity); 1260 ControllingPrim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity);
1260 } 1261 }
@@ -1330,7 +1331,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1330 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : 1331 // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags :
1331 // This flag prevents linear deflection parallel to world z-axis. This is useful 1332 // This flag prevents linear deflection parallel to world z-axis. This is useful
1332 // for preventing ground vehicles with large linear deflection, like bumper cars, 1333 // for preventing ground vehicles with large linear deflection, like bumper cars,
1333 // from climbing their linear deflection into the sky. 1334 // from climbing their linear deflection into the sky.
1334 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement 1335 // That is, NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
1335 // TODO: This is here because this is where ODE put it but documentation says it 1336 // TODO: This is here because this is where ODE put it but documentation says it
1336 // is a linear effect. Where should this check go? 1337 // is a linear effect. Where should this check go?
@@ -1463,7 +1464,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1463 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation); 1464 VehicleRotationalVelocity += (vertContributionV * VehicleOrientation);
1464 1465
1465 VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}", 1466 VDetailLog("{0}, MoveAngular,verticalAttraction,,origRotVW={1},vertError={2},unscaledV={3},eff={4},ts={5},vertContribV={6}",
1466 Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV, 1467 Prim.LocalID, origRotVelW, verticalError, unscaledContribVerticalErrorV,
1467 m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV); 1468 m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV);
1468 */ 1469 */
1469 } 1470 }
@@ -1530,13 +1531,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1530 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude 1531 // produce a angular velocity around the yaw-axis, causing the vehicle to turn. The magnitude
1531 // of the yaw effect will be proportional to the 1532 // of the yaw effect will be proportional to the
1532 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's 1533 // VEHICLE_BANKING_EFFICIENCY, the angle of the roll rotation, and sometimes the vehicle's
1533 // velocity along its preferred axis of motion. 1534 // velocity along its preferred axis of motion.
1534 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any 1535 // The VEHICLE_BANKING_EFFICIENCY can vary between -1 and +1. When it is positive then any
1535 // positive rotation (by the right-hand rule) about the roll-axis will effect a 1536 // positive rotation (by the right-hand rule) about the roll-axis will effect a
1536 // (negative) torque around the yaw-axis, making it turn to the right--that is the 1537 // (negative) torque around the yaw-axis, making it turn to the right--that is the
1537 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work. 1538 // vehicle will lean into the turn, which is how real airplanes and motorcycle's work.
1538 // Negating the banking coefficient will make it so that the vehicle leans to the 1539 // Negating the banking coefficient will make it so that the vehicle leans to the
1539 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?). 1540 // outside of the turn (not very "physical" but might allow interesting vehicles so why not?).
1540 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making 1541 // The VEHICLE_BANKING_MIX is a fake (i.e. non-physical) parameter that is useful for making
1541 // banking vehicles do what you want rather than what the laws of physics allow. 1542 // banking vehicles do what you want rather than what the laws of physics allow.
1542 // For example, consider a real motorcycle...it must be moving forward in order for 1543 // For example, consider a real motorcycle...it must be moving forward in order for
@@ -1548,11 +1549,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1548 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the 1549 // totally static (0.0) and totally dynamic (1.0). By "static" we mean that the
1549 // banking effect depends only on the vehicle's rotation about its roll-axis compared 1550 // banking effect depends only on the vehicle's rotation about its roll-axis compared
1550 // to "dynamic" where the banking is also proportional to its velocity along its 1551 // to "dynamic" where the banking is also proportional to its velocity along its
1551 // roll-axis. Finding the best value of the "mixture" will probably require trial and error. 1552 // roll-axis. Finding the best value of the "mixture" will probably require trial and error.
1552 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the 1553 // The time it takes for the banking behavior to defeat a preexisting angular velocity about the
1553 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to 1554 // world z-axis is determined by the VEHICLE_BANKING_TIMESCALE. So if you want the vehicle to
1554 // bank quickly then give it a banking timescale of about a second or less, otherwise you can 1555 // bank quickly then give it a banking timescale of about a second or less, otherwise you can
1555 // make a sluggish vehicle by giving it a timescale of several seconds. 1556 // make a sluggish vehicle by giving it a timescale of several seconds.
1556 public void ComputeAngularBanking() 1557 public void ComputeAngularBanking()
1557 { 1558 {
1558 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) 1559 if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff)
@@ -1581,7 +1582,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1581 1582
1582 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; 1583 //VehicleRotationalVelocity += bankingContributionV * VehicleOrientation;
1583 VehicleRotationalVelocity += bankingContributionV; 1584 VehicleRotationalVelocity += bankingContributionV;
1584 1585
1585 1586
1586 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", 1587 VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}",
1587 ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); 1588 ControllingPrim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV);
@@ -1637,8 +1638,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
1637 // Invoke the detailed logger and output something if it's enabled. 1638 // Invoke the detailed logger and output something if it's enabled.
1638 private void VDetailLog(string msg, params Object[] args) 1639 private void VDetailLog(string msg, params Object[] args)
1639 { 1640 {
1640 if (ControllingPrim.PhysicsScene.VehicleLoggingEnabled) 1641 if (ControllingPrim.PhysScene.VehicleLoggingEnabled)
1641 ControllingPrim.PhysicsScene.DetailLog(msg, args); 1642 ControllingPrim.PhysScene.DetailLog(msg, args);
1642 } 1643 }
1643 } 1644 }
1644} 1645}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 4ece1eb..76c2187 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -80,7 +80,7 @@ public abstract class BSLinkset
80 80
81 public BSPrimLinkable LinksetRoot { get; protected set; } 81 public BSPrimLinkable LinksetRoot { get; protected set; }
82 82
83 public BSScene PhysicsScene { get; private set; } 83 protected BSScene m_physicsScene { get; private set; }
84 84
85 static int m_nextLinksetID = 1; 85 static int m_nextLinksetID = 1;
86 public int LinksetID { get; private set; } 86 public int LinksetID { get; private set; }
@@ -93,13 +93,6 @@ public abstract class BSLinkset
93 // to the physical representation is done via the tainting mechenism. 93 // to the physical representation is done via the tainting mechenism.
94 protected object m_linksetActivityLock = new Object(); 94 protected object m_linksetActivityLock = new Object();
95 95
96 // Some linksets have a preferred physical shape.
97 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
98 public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
99 {
100 return BSPhysicsShapeType.SHAPE_UNKNOWN;
101 }
102
103 // We keep the prim's mass in the linkset structure since it could be dependent on other prims 96 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
104 public float LinksetMass { get; protected set; } 97 public float LinksetMass { get; protected set; }
105 98
@@ -122,7 +115,7 @@ public abstract class BSLinkset
122 // We create LOTS of linksets. 115 // We create LOTS of linksets.
123 if (m_nextLinksetID <= 0) 116 if (m_nextLinksetID <= 0)
124 m_nextLinksetID = 1; 117 m_nextLinksetID = 1;
125 PhysicsScene = scene; 118 m_physicsScene = scene;
126 LinksetRoot = parent; 119 LinksetRoot = parent;
127 m_children = new HashSet<BSPrimLinkable>(); 120 m_children = new HashSet<BSPrimLinkable>();
128 LinksetMass = parent.RawMass; 121 LinksetMass = parent.RawMass;
@@ -165,7 +158,7 @@ public abstract class BSLinkset
165 } 158 }
166 159
167 // The child is down to a linkset of just itself 160 // The child is down to a linkset of just itself
168 return BSLinkset.Factory(PhysicsScene, child); 161 return BSLinkset.Factory(m_physicsScene, child);
169 } 162 }
170 163
171 // Return 'true' if the passed object is the root object of this linkset 164 // Return 'true' if the passed object is the root object of this linkset
@@ -221,7 +214,7 @@ public abstract class BSLinkset
221 // I am the root of a linkset and a new child is being added 214 // I am the root of a linkset and a new child is being added
222 // Called while LinkActivity is locked. 215 // Called while LinkActivity is locked.
223 protected abstract void AddChildToLinkset(BSPrimLinkable child); 216 protected abstract void AddChildToLinkset(BSPrimLinkable child);
224 217
225 // I am the root of a linkset and one of my children is being removed. 218 // I am the root of a linkset and one of my children is being removed.
226 // Safe to call even if the child is not really in my linkset. 219 // Safe to call even if the child is not really in my linkset.
227 protected abstract void RemoveChildFromLinkset(BSPrimLinkable child); 220 protected abstract void RemoveChildFromLinkset(BSPrimLinkable child);
@@ -263,7 +256,7 @@ public abstract class BSLinkset
263 // This is called when the root body is changing. 256 // This is called when the root body is changing.
264 // Returns 'true' of something was actually removed and would need restoring 257 // Returns 'true' of something was actually removed and would need restoring
265 // Called at taint-time!! 258 // Called at taint-time!!
266 public abstract bool RemoveBodyDependencies(BSPrimLinkable child); 259 public abstract bool RemoveDependencies(BSPrimLinkable child);
267 260
268 // ================================================================ 261 // ================================================================
269 protected virtual float ComputeLinksetMass() 262 protected virtual float ComputeLinksetMass()
@@ -323,8 +316,8 @@ public abstract class BSLinkset
323 // Invoke the detailed logger and output something if it's enabled. 316 // Invoke the detailed logger and output something if it's enabled.
324 protected void DetailLog(string msg, params Object[] args) 317 protected void DetailLog(string msg, params Object[] args)
325 { 318 {
326 if (PhysicsScene.PhysicsLogging.Enabled) 319 if (m_physicsScene.PhysicsLogging.Enabled)
327 PhysicsScene.DetailLog(msg, args); 320 m_physicsScene.DetailLog(msg, args);
328 } 321 }
329 322
330} 323}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index e05562a..1f16cc8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -35,6 +35,7 @@ using OMV = OpenMetaverse;
35namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37 37
38 /*
38// When a child is linked, the relationship position of the child to the parent 39// When a child is linked, the relationship position of the child to the parent
39// is remembered so the child's world position can be recomputed when it is 40// is remembered so the child's world position can be recomputed when it is
40// removed from the linkset. 41// removed from the linkset.
@@ -88,6 +89,7 @@ sealed class BSLinksetCompoundInfo : BSLinksetInfo
88 return buff.ToString(); 89 return buff.ToString();
89 } 90 }
90}; 91};
92 */
91 93
92public sealed class BSLinksetCompound : BSLinkset 94public sealed class BSLinksetCompound : BSLinkset
93{ 95{
@@ -98,19 +100,6 @@ public sealed class BSLinksetCompound : BSLinkset
98 { 100 {
99 } 101 }
100 102
101 // For compound implimented linksets, if there are children, use compound shape for the root.
102 public override BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
103 {
104 // Returning 'unknown' means we don't have a preference.
105 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
106 if (IsRoot(requestor) && HasAnyChildren)
107 {
108 ret = BSPhysicsShapeType.SHAPE_COMPOUND;
109 }
110 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
111 return ret;
112 }
113
114 // When physical properties are changed the linkset needs to recalculate 103 // When physical properties are changed the linkset needs to recalculate
115 // its internal properties. 104 // its internal properties.
116 public override void Refresh(BSPrimLinkable requestor) 105 public override void Refresh(BSPrimLinkable requestor)
@@ -124,14 +113,14 @@ public sealed class BSLinksetCompound : BSLinkset
124 // Schedule a refresh to happen after all the other taint processing. 113 // Schedule a refresh to happen after all the other taint processing.
125 private void ScheduleRebuild(BSPrimLinkable requestor) 114 private void ScheduleRebuild(BSPrimLinkable requestor)
126 { 115 {
127 DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}", 116 DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}",
128 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren)); 117 requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren));
129 // When rebuilding, it is possible to set properties that would normally require a rebuild. 118 // When rebuilding, it is possible to set properties that would normally require a rebuild.
130 // If already rebuilding, don't request another rebuild. 119 // If already rebuilding, don't request another rebuild.
131 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding. 120 // If a linkset with just a root prim (simple non-linked prim) don't bother rebuilding.
132 if (!Rebuilding && HasAnyChildren) 121 if (!Rebuilding && HasAnyChildren)
133 { 122 {
134 PhysicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate() 123 m_physicsScene.PostTaintObject("BSLinksetCompound.ScheduleRebuild", LinksetRoot.LocalID, delegate()
135 { 124 {
136 if (HasAnyChildren) 125 if (HasAnyChildren)
137 RecomputeLinksetCompound(); 126 RecomputeLinksetCompound();
@@ -153,26 +142,11 @@ public sealed class BSLinksetCompound : BSLinkset
153 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly. 142 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
154 ScheduleRebuild(LinksetRoot); 143 ScheduleRebuild(LinksetRoot);
155 } 144 }
156 else
157 {
158 // The origional prims are removed from the world as the shape of the root compound
159 // shape takes over.
160 PhysicsScene.PE.AddToCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
161 PhysicsScene.PE.ForceActivationState(child.PhysBody, ActivationState.DISABLE_SIMULATION);
162 // We don't want collisions from the old linkset children.
163 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
164
165 child.PhysBody.collisionType = CollisionType.LinksetChild;
166
167 ret = true;
168 }
169 return ret; 145 return ret;
170 } 146 }
171 147
172 // The object is going static (non-physical). Do any setup necessary for a static linkset. 148 // The object is going static (non-physical). We do not do anything for static linksets.
173 // Return 'true' if any properties updated on the passed object. 149 // Return 'true' if any properties updated on the passed object.
174 // This doesn't normally happen -- OpenSim removes the objects from the physical
175 // world if it is a static linkset.
176 // Called at taint-time! 150 // Called at taint-time!
177 public override bool MakeStatic(BSPrimLinkable child) 151 public override bool MakeStatic(BSPrimLinkable child)
178 { 152 {
@@ -180,19 +154,9 @@ public sealed class BSLinksetCompound : BSLinkset
180 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); 154 DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
181 if (IsRoot(child)) 155 if (IsRoot(child))
182 { 156 {
157 // Schedule a rebuild to verify that the root shape is set to the real shape.
183 ScheduleRebuild(LinksetRoot); 158 ScheduleRebuild(LinksetRoot);
184 } 159 }
185 else
186 {
187 // The non-physical children can come back to life.
188 PhysicsScene.PE.RemoveFromCollisionFlags(child.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
189
190 child.PhysBody.collisionType = CollisionType.LinksetChild;
191
192 // Don't force activation so setting of DISABLE_SIMULATION can stay if used.
193 PhysicsScene.PE.Activate(child.PhysBody, false);
194 ret = true;
195 }
196 return ret; 160 return ret;
197 } 161 }
198 162
@@ -200,13 +164,20 @@ public sealed class BSLinksetCompound : BSLinkset
200 // Called at taint-time. 164 // Called at taint-time.
201 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated) 165 public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated)
202 { 166 {
167 if (!LinksetRoot.IsPhysicallyActive)
168 {
169 // No reason to do this physical stuff for static linksets.
170 DetailLog("{0},BSLinksetCompound.UpdateProperties,notPhysical", LinksetRoot.LocalID);
171 return;
172 }
173
203 // The user moving a child around requires the rebuilding of the linkset compound shape 174 // The user moving a child around requires the rebuilding of the linkset compound shape
204 // One problem is this happens when a border is crossed -- the simulator implementation 175 // One problem is this happens when a border is crossed -- the simulator implementation
205 // stores the position into the group which causes the move of the object 176 // stores the position into the group which causes the move of the object
206 // but it also means all the child positions get updated. 177 // but it also means all the child positions get updated.
207 // What would cause an unnecessary rebuild so we make sure the linkset is in a 178 // What would cause an unnecessary rebuild so we make sure the linkset is in a
208 // region before bothering to do a rebuild. 179 // region before bothering to do a rebuild.
209 if (!IsRoot(updated) && PhysicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition)) 180 if (!IsRoot(updated) && m_physicsScene.TerrainManager.IsWithinKnownTerrain(LinksetRoot.RawPosition))
210 { 181 {
211 // If a child of the linkset is updating only the position or rotation, that can be done 182 // If a child of the linkset is updating only the position or rotation, that can be done
212 // without rebuilding the linkset. 183 // without rebuilding the linkset.
@@ -218,22 +189,22 @@ public sealed class BSLinksetCompound : BSLinkset
218 // and that is caused by us updating the object. 189 // and that is caused by us updating the object.
219 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0) 190 if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
220 { 191 {
221 // Find the physical instance of the child 192 // Find the physical instance of the child
222 if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) 193 if (LinksetRoot.PhysShape.HasPhysicalShape && m_physicsScene.PE.IsCompound(LinksetRoot.PhysShape.physShapeInfo))
223 { 194 {
224 // It is possible that the linkset is still under construction and the child is not yet 195 // It is possible that the linkset is still under construction and the child is not yet
225 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will 196 // inserted into the compound shape. A rebuild of the linkset in a pre-step action will
226 // build the whole thing with the new position or rotation. 197 // build the whole thing with the new position or rotation.
227 // The index must be checked because Bullet references the child array but does no validity 198 // The index must be checked because Bullet references the child array but does no validity
228 // checking of the child index passed. 199 // checking of the child index passed.
229 int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape); 200 int numLinksetChildren = m_physicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape.physShapeInfo);
230 if (updated.LinksetChildIndex < numLinksetChildren) 201 if (updated.LinksetChildIndex < numLinksetChildren)
231 { 202 {
232 BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex); 203 BulletShape linksetChildShape = m_physicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex);
233 if (linksetChildShape.HasPhysicalShape) 204 if (linksetChildShape.HasPhysicalShape)
234 { 205 {
235 // Found the child shape within the compound shape 206 // Found the child shape within the compound shape
236 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex, 207 m_physicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape.physShapeInfo, updated.LinksetChildIndex,
237 updated.RawPosition - LinksetRoot.RawPosition, 208 updated.RawPosition - LinksetRoot.RawPosition,
238 updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation), 209 updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
239 true /* shouldRecalculateLocalAabb */); 210 true /* shouldRecalculateLocalAabb */);
@@ -275,75 +246,22 @@ public sealed class BSLinksetCompound : BSLinkset
275 } 246 }
276 247
277 // Routine called when rebuilding the body of some member of the linkset. 248 // Routine called when rebuilding the body of some member of the linkset.
278 // Since we don't keep in world relationships, do nothing unless it's a child changing. 249 // If one of the bodies is being changed, the linkset needs rebuilding.
250 // For instance, a linkset is built and then a mesh asset is read in and the mesh is recreated.
279 // Returns 'true' of something was actually removed and would need restoring 251 // Returns 'true' of something was actually removed and would need restoring
280 // Called at taint-time!! 252 // Called at taint-time!!
281 public override bool RemoveBodyDependencies(BSPrimLinkable child) 253 public override bool RemoveDependencies(BSPrimLinkable child)
282 { 254 {
283 bool ret = false; 255 bool ret = false;
284 256
285 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", 257 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
286 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child)); 258 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child));
287 259
288 if (!IsRoot(child)) 260 ScheduleRebuild(child);
289 {
290 // Because it is a convenient time, recompute child world position and rotation based on
291 // its position in the linkset.
292 RecomputeChildWorldPosition(child, true /* inTaintTime */);
293 child.LinksetInfo = null;
294 }
295
296 // Cannot schedule a refresh/rebuild here because this routine is called when
297 // the linkset is being rebuilt.
298 // InternalRefresh(LinksetRoot);
299 261
300 return ret; 262 return ret;
301 } 263 }
302 264
303 // When the linkset is built, the child shape is added to the compound shape relative to the
304 // root shape. The linkset then moves around but this does not move the actual child
305 // prim. The child prim's location must be recomputed based on the location of the root shape.
306 private void RecomputeChildWorldPosition(BSPrimLinkable child, bool inTaintTime)
307 {
308 // For the moment (20130201), disable this computation (converting the child physical addr back to
309 // a region address) until we have a good handle on center-of-mass offsets and what the physics
310 // engine moving a child actually means.
311 // The simulator keeps track of where children should be as the linkset moves. Setting
312 // the pos/rot here does not effect that knowledge as there is no good way for the
313 // physics engine to send the simulator an update for a child.
314
315 /*
316 BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo;
317 if (lci != null)
318 {
319 if (inTaintTime)
320 {
321 OMV.Vector3 oldPos = child.RawPosition;
322 child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetFromRoot;
323 child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
324 DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
325 child.LocalID, oldPos, lci, child.RawPosition);
326 }
327 else
328 {
329 // TaintedObject is not used here so the raw position is set now and not at taint-time.
330 child.Position = LinksetRoot.RawPosition + lci.OffsetFromRoot;
331 child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
332 }
333 }
334 else
335 {
336 // This happens when children have been added to the linkset but the linkset
337 // has not been constructed yet. So like, at taint time, adding children to a linkset
338 // and then changing properties of the children (makePhysical, for instance)
339 // but the post-print action of actually rebuilding the linkset has not yet happened.
340 // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}",
341 // LogHeader, child.LocalID);
342 DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID);
343 }
344 */
345 }
346
347 // ================================================================ 265 // ================================================================
348 266
349 // Add a new child to the linkset. 267 // Add a new child to the linkset.
@@ -376,7 +294,6 @@ public sealed class BSLinksetCompound : BSLinkset
376 child.LocalID, child.PhysBody.AddrString); 294 child.LocalID, child.PhysBody.AddrString);
377 295
378 // Cause the child's body to be rebuilt and thus restored to normal operation 296 // Cause the child's body to be rebuilt and thus restored to normal operation
379 RecomputeChildWorldPosition(child, false);
380 child.LinksetInfo = null; 297 child.LinksetInfo = null;
381 child.ForceBodyShapeRebuild(false); 298 child.ForceBodyShapeRebuild(false);
382 299
@@ -399,108 +316,105 @@ public sealed class BSLinksetCompound : BSLinkset
399 // Constraint linksets are rebuilt every time. 316 // Constraint linksets are rebuilt every time.
400 // Note that this works for rebuilding just the root after a linkset is taken apart. 317 // Note that this works for rebuilding just the root after a linkset is taken apart.
401 // Called at taint time!! 318 // Called at taint time!!
402 private bool disableCOM = true; // DEBUG DEBUG: disable until we get this debugged 319 private bool UseBulletSimRootOffsetHack = false; // Attempt to have Bullet track the coords of root compound shape
320 private bool disableCOM = true; // For basic linkset debugging, turn off the center-of-mass setting
403 private void RecomputeLinksetCompound() 321 private void RecomputeLinksetCompound()
404 { 322 {
405 try 323 try
406 { 324 {
407 // Suppress rebuilding while rebuilding. (We know rebuilding is on only one thread.)
408 Rebuilding = true; 325 Rebuilding = true;
409 326
410 // Cause the root shape to be rebuilt as a compound object with just the root in it 327 // No matter what is being done, force the root prim's PhysBody and PhysShape to get set
411 LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime */); 328 // to what they should be as if the root was not in a linkset.
329 // Not that bad since we only get into this routine if there are children in the linkset and
330 // something has been updated/changed.
331 LinksetRoot.ForceBodyShapeRebuild(true);
332
333 // There is no reason to build all this physical stuff for a non-physical linkset.
334 if (!LinksetRoot.IsPhysicallyActive)
335 {
336 // Clean up any old linkset shape and make sure the root shape is set to the root object.
337 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID);
338
339 return; // Note the 'finally' clause at the botton which will get executed.
340 }
341
342 // Get a new compound shape to build the linkset shape in.
343 BSShape linksetShape = BSShapeCompound.GetReference(m_physicsScene);
412 344
413 // The center of mass for the linkset is the geometric center of the group. 345 // The center of mass for the linkset is the geometric center of the group.
414 // Compute a displacement for each component so it is relative to the center-of-mass. 346 // Compute a displacement for each component so it is relative to the center-of-mass.
415 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass 347 // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
416 OMV.Vector3 centerOfMassW = LinksetRoot.RawPosition; 348 OMV.Vector3 centerOfMassW = ComputeLinksetCenterOfMass();
417 if (!disableCOM) // DEBUG DEBUG
418 {
419 // Compute a center-of-mass in world coordinates.
420 centerOfMassW = ComputeLinksetCenterOfMass();
421 }
422 349
423 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); 350 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
424 351
425 // 'centerDisplacement' is the value to subtract from children to give physical offset position 352 // 'centerDisplacement' is the value to subtract from children to give physical offset position
426 OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation; 353 OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation;
427 LinksetRoot.SetEffectiveCenterOfMassW(centerDisplacement); 354 if (UseBulletSimRootOffsetHack || disableCOM)
428 355 {
429 // This causes the physical position of the root prim to be offset to accomodate for the displacements 356 centerDisplacement = OMV.Vector3.Zero;
430 LinksetRoot.ForcePosition = LinksetRoot.RawPosition; 357 LinksetRoot.ClearDisplacement();
431 358 }
432 // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM 359 else
433 PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */, 360 {
434 -centerDisplacement, 361 LinksetRoot.SetEffectiveCenterOfMassDisplacement(centerDisplacement);
435 OMV.Quaternion.Identity, // LinksetRoot.RawOrientation, 362 }
436 false /* shouldRecalculateLocalAabb (is done later after linkset built) */); 363 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,rootPos={1},com={2},comDisp={3}",
437 364 LinksetRoot.LocalID, LinksetRoot.RawPosition, centerOfMassW, centerDisplacement);
438 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
439 LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement);
440
441 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
442 LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
443 365
444 // Add a shape for each of the other children in the linkset 366 // Add the shapes of all the components of the linkset
445 int memberIndex = 1; 367 int memberIndex = 1;
446 ForEachMember(delegate(BSPrimLinkable cPrim) 368 ForEachMember(delegate(BSPrimLinkable cPrim)
447 { 369 {
448 if (IsRoot(cPrim)) 370 // Root shape is always index zero.
371 cPrim.LinksetChildIndex = IsRoot(cPrim) ? 0 : memberIndex;
372
373 // Get a reference to the shape of the child and add that shape to the linkset compound shape
374 BSShape childShape = cPrim.PhysShape.GetReference(m_physicsScene, cPrim);
375 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
376 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
377 m_physicsScene.PE.AddChildShapeToCompoundShape(linksetShape.physShapeInfo, childShape.physShapeInfo, offsetPos, offsetRot);
378 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addChild,indx={1},cShape={2},offPos={3},offRot={4}",
379 LinksetRoot.LocalID, memberIndex, childShape, offsetPos, offsetRot);
380
381 // Since we are borrowing the shape of the child, disable the origional child body
382 if (!IsRoot(cPrim))
449 { 383 {
450 cPrim.LinksetChildIndex = 0; 384 m_physicsScene.PE.AddToCollisionFlags(cPrim.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
385 m_physicsScene.PE.ForceActivationState(cPrim.PhysBody, ActivationState.DISABLE_SIMULATION);
386 // We don't want collisions from the old linkset children.
387 m_physicsScene.PE.RemoveFromCollisionFlags(cPrim.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
388 cPrim.PhysBody.collisionType = CollisionType.LinksetChild;
451 } 389 }
452 else
453 {
454 cPrim.LinksetChildIndex = memberIndex;
455 390
456 if (cPrim.PhysShape.isNativeShape) 391 memberIndex++;
457 {
458 // A native shape is turned into a hull collision shape because native
459 // shapes are not shared so we have to hullify it so it will be tracked
460 // and freed at the correct time. This also solves the scaling problem
461 // (native shapes scale but hull/meshes are assumed to not be).
462 // TODO: decide of the native shape can just be used in the compound shape.
463 // Use call to CreateGeomNonSpecial().
464 BulletShape saveShape = cPrim.PhysShape;
465 cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
466 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
467 BulletShape newShape = cPrim.PhysShape;
468 cPrim.PhysShape = saveShape;
469
470 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
471 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
472 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
473 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
474 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
475 }
476 else
477 {
478 // For the shared shapes (meshes and hulls), just use the shape in the child.
479 // The reference count added here will be decremented when the compound shape
480 // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced).
481 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
482 {
483 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
484 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
485 }
486 OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
487 OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
488 PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
489 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNonNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
490 LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
491 392
492 }
493 memberIndex++;
494 }
495 return false; // 'false' says to move onto the next child in the list 393 return false; // 'false' says to move onto the next child in the list
496 }); 394 });
497 395
396 // Replace the root shape with the built compound shape.
397 // Object removed and added to world to get collision cache rebuilt for new shape.
398 LinksetRoot.PhysShape.Dereference(m_physicsScene);
399 LinksetRoot.PhysShape = linksetShape;
400 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, LinksetRoot.PhysBody);
401 m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, LinksetRoot.PhysBody, linksetShape.physShapeInfo);
402 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, LinksetRoot.PhysBody);
403 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addBody,body={1},shape={2}",
404 LinksetRoot.LocalID, LinksetRoot.PhysBody, linksetShape);
405
498 // With all of the linkset packed into the root prim, it has the mass of everyone. 406 // With all of the linkset packed into the root prim, it has the mass of everyone.
499 LinksetMass = ComputeLinksetMass(); 407 LinksetMass = ComputeLinksetMass();
500 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); 408 LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
501 409
502 // Enable the physical position updator to return the position and rotation of the root shape 410 if (UseBulletSimRootOffsetHack)
503 PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE); 411 {
412 // Enable the physical position updator to return the position and rotation of the root shape.
413 // This enables a feature in the C++ code to return the world coordinates of the first shape in the
414 // compound shape. This eleviates the need to offset the returned physical position by the
415 // center-of-mass offset.
416 m_physicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
417 }
504 } 418 }
505 finally 419 finally
506 { 420 {
@@ -508,7 +422,7 @@ public sealed class BSLinksetCompound : BSLinkset
508 } 422 }
509 423
510 // See that the Aabb surrounds the new shape 424 // See that the Aabb surrounds the new shape
511 PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); 425 m_physicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape.physShapeInfo);
512 } 426 }
513} 427}
514} \ No newline at end of file 428} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index 6d252ca..a06a44d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -51,7 +51,7 @@ public sealed class BSLinksetConstraints : BSLinkset
51 if (HasAnyChildren && IsRoot(requestor)) 51 if (HasAnyChildren && IsRoot(requestor))
52 { 52 {
53 // Queue to happen after all the other taint processing 53 // Queue to happen after all the other taint processing
54 PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() 54 m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
55 { 55 {
56 if (HasAnyChildren && IsRoot(requestor)) 56 if (HasAnyChildren && IsRoot(requestor))
57 RecomputeLinksetConstraints(); 57 RecomputeLinksetConstraints();
@@ -93,11 +93,11 @@ public sealed class BSLinksetConstraints : BSLinkset
93 // up to rebuild the constraints before the next simulation step. 93 // up to rebuild the constraints before the next simulation step.
94 // Returns 'true' of something was actually removed and would need restoring 94 // Returns 'true' of something was actually removed and would need restoring
95 // Called at taint-time!! 95 // Called at taint-time!!
96 public override bool RemoveBodyDependencies(BSPrimLinkable child) 96 public override bool RemoveDependencies(BSPrimLinkable child)
97 { 97 {
98 bool ret = false; 98 bool ret = false;
99 99
100 DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", 100 DetailLog("{0},BSLinksetConstraint.RemoveDependencies,removeChildrenForRoot,rID={1},rBody={2}",
101 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString); 101 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString);
102 102
103 lock (m_linksetActivityLock) 103 lock (m_linksetActivityLock)
@@ -142,7 +142,7 @@ public sealed class BSLinksetConstraints : BSLinkset
142 rootx.LocalID, rootx.PhysBody.AddrString, 142 rootx.LocalID, rootx.PhysBody.AddrString,
143 childx.LocalID, childx.PhysBody.AddrString); 143 childx.LocalID, childx.PhysBody.AddrString);
144 144
145 PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() 145 m_physicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate()
146 { 146 {
147 PhysicallyUnlinkAChildFromRoot(rootx, childx); 147 PhysicallyUnlinkAChildFromRoot(rootx, childx);
148 }); 148 });
@@ -187,7 +187,7 @@ public sealed class BSLinksetConstraints : BSLinkset
187 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 187 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
188 188
189 BSConstraint6Dof constrain = new BSConstraint6Dof( 189 BSConstraint6Dof constrain = new BSConstraint6Dof(
190 PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true ); 190 m_physicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true );
191 // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true ); 191 // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true );
192 192
193 /* NOTE: below is an attempt to build constraint with full frame computation, etc. 193 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
@@ -216,7 +216,7 @@ public sealed class BSLinksetConstraints : BSLinkset
216 // ================================================================================== 216 // ==================================================================================
217 */ 217 */
218 218
219 PhysicsScene.Constraints.AddConstraint(constrain); 219 m_physicsScene.Constraints.AddConstraint(constrain);
220 220
221 // zero linear and angular limits makes the objects unable to move in relation to each other 221 // zero linear and angular limits makes the objects unable to move in relation to each other
222 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 222 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
@@ -248,10 +248,10 @@ public sealed class BSLinksetConstraints : BSLinkset
248 childPrim.LocalID, childPrim.PhysBody.AddrString); 248 childPrim.LocalID, childPrim.PhysBody.AddrString);
249 249
250 // Find the constraint for this link and get rid of it from the overall collection and from my list 250 // Find the constraint for this link and get rid of it from the overall collection and from my list
251 if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) 251 if (m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
252 { 252 {
253 // Make the child refresh its location 253 // Make the child refresh its location
254 PhysicsScene.PE.PushUpdate(childPrim.PhysBody); 254 m_physicsScene.PE.PushUpdate(childPrim.PhysBody);
255 ret = true; 255 ret = true;
256 } 256 }
257 257
@@ -265,7 +265,7 @@ public sealed class BSLinksetConstraints : BSLinkset
265 { 265 {
266 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); 266 DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
267 267
268 return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody); 268 return m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody);
269 } 269 }
270 270
271 // Call each of the constraints that make up this linkset and recompute the 271 // Call each of the constraints that make up this linkset and recompute the
@@ -289,7 +289,7 @@ public sealed class BSLinksetConstraints : BSLinkset
289 child.UpdatePhysicalMassProperties(linksetMass, true); 289 child.UpdatePhysicalMassProperties(linksetMass, true);
290 290
291 BSConstraint constrain; 291 BSConstraint constrain;
292 if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) 292 if (!m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain))
293 { 293 {
294 // If constraint doesn't exist yet, create it. 294 // If constraint doesn't exist yet, create it.
295 constrain = BuildConstraint(LinksetRoot, child); 295 constrain = BuildConstraint(LinksetRoot, child);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
index 9501e2d..0128d8d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
@@ -102,7 +102,7 @@ public class BSVMotor : BSMotor
102 return ErrorIsZero(LastError); 102 return ErrorIsZero(LastError);
103 } 103 }
104 public virtual bool ErrorIsZero(Vector3 err) 104 public virtual bool ErrorIsZero(Vector3 err)
105 { 105 {
106 return (err == Vector3.Zero || err.ApproxEquals(Vector3.Zero, ErrorZeroThreshold)); 106 return (err == Vector3.Zero || err.ApproxEquals(Vector3.Zero, ErrorZeroThreshold));
107 } 107 }
108 108
@@ -115,7 +115,7 @@ public class BSVMotor : BSMotor
115 CurrentValue = TargetValue = Vector3.Zero; 115 CurrentValue = TargetValue = Vector3.Zero;
116 ErrorZeroThreshold = 0.001f; 116 ErrorZeroThreshold = 0.001f;
117 } 117 }
118 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) 118 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
119 : this(useName) 119 : this(useName)
120 { 120 {
121 TimeScale = timeScale; 121 TimeScale = timeScale;
@@ -237,7 +237,7 @@ public class BSVMotor : BSMotor
237 MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName); 237 MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName);
238 MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},frictTS={4},eff={5},curr={6},tgt={7}", 238 MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},frictTS={4},eff={5},curr={6},tgt={7}",
239 BSScene.DetailLogZero, UseName, 239 BSScene.DetailLogZero, UseName,
240 TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency, 240 TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency,
241 CurrentValue, TargetValue); 241 CurrentValue, TargetValue);
242 242
243 LastError = BSMotor.InfiniteVector; 243 LastError = BSMotor.InfiniteVector;
@@ -248,7 +248,7 @@ public class BSVMotor : BSMotor
248 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep); 248 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue, LastError, lastStep);
249 } 249 }
250 MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName); 250 MDetailLog("{0},BSVMotor.Test,{1},===================================== END Test Output", BSScene.DetailLogZero, UseName);
251 251
252 252
253 } 253 }
254 254
@@ -279,7 +279,7 @@ public class BSFMotor : BSMotor
279 return ErrorIsZero(LastError); 279 return ErrorIsZero(LastError);
280 } 280 }
281 public virtual bool ErrorIsZero(float err) 281 public virtual bool ErrorIsZero(float err)
282 { 282 {
283 return (err >= -ErrorZeroThreshold && err <= ErrorZeroThreshold); 283 return (err >= -ErrorZeroThreshold && err <= ErrorZeroThreshold);
284 } 284 }
285 285
@@ -410,7 +410,7 @@ public class BSPIDVMotor : BSVMotor
410 // The factors are vectors for the three dimensions. This is the proportional of each 410 // The factors are vectors for the three dimensions. This is the proportional of each
411 // that is applied. This could be multiplied through the actual factors but it 411 // that is applied. This could be multiplied through the actual factors but it
412 // is sometimes easier to manipulate the factors and their mix separately. 412 // is sometimes easier to manipulate the factors and their mix separately.
413 // to 413 // to
414 public Vector3 FactorMix; 414 public Vector3 FactorMix;
415 415
416 // Arbritrary factor range. 416 // Arbritrary factor range.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 980d405..2ac68e3 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -37,7 +37,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
37{ 37{
38public static class BSParam 38public static class BSParam
39{ 39{
40 private static string LogHeader = "[BULLETSIM PARAMETERS]"; 40 private static string LogHeader = "[BULLETSIM PARAMETERS]";
41 41
42 // Tuning notes: 42 // Tuning notes:
43 // From: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6575 43 // From: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6575
@@ -51,7 +51,7 @@ public static class BSParam
51 // This is separate/independent from the collision margin. The collision margin increases the object a bit 51 // This is separate/independent from the collision margin. The collision margin increases the object a bit
52 // to improve collision detection performance and accuracy. 52 // to improve collision detection performance and accuracy.
53 // =================== 53 // ===================
54 // From: 54 // From:
55 55
56 // Level of Detail values kept as float because that's what the Meshmerizer wants 56 // Level of Detail values kept as float because that's what the Meshmerizer wants
57 public static float MeshLOD { get; private set; } 57 public static float MeshLOD { get; private set; }
@@ -87,6 +87,7 @@ public static class BSParam
87 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects 87 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
88 public static bool ShouldRemoveZeroWidthTriangles { get; private set; } 88 public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
89 public static bool ShouldUseBulletHACD { get; set; } 89 public static bool ShouldUseBulletHACD { get; set; }
90 public static bool ShouldUseSingleConvexHullForPrims { get; set; }
90 91
91 public static float TerrainImplementation { get; private set; } 92 public static float TerrainImplementation { get; private set; }
92 public static int TerrainMeshMagnification { get; private set; } 93 public static int TerrainMeshMagnification { get; private set; }
@@ -342,6 +343,10 @@ public static class BSParam
342 false, 343 false,
343 (s) => { return ShouldUseBulletHACD; }, 344 (s) => { return ShouldUseBulletHACD; },
344 (s,v) => { ShouldUseBulletHACD = v; } ), 345 (s,v) => { ShouldUseBulletHACD = v; } ),
346 new ParameterDefn<bool>("ShouldUseSingleConvexHullForPrims", "If true, use a single convex hull shape for physical prims",
347 true,
348 (s) => { return ShouldUseSingleConvexHullForPrims; },
349 (s,v) => { ShouldUseSingleConvexHullForPrims = v; } ),
345 350
346 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions", 351 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
347 5, 352 5,
@@ -636,7 +641,7 @@ public static class BSParam
636 new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", 641 new ParameterDefn<bool>("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
637 false, 642 false,
638 (s) => { return ShouldDisableContactPoolDynamicAllocation; }, 643 (s) => { return ShouldDisableContactPoolDynamicAllocation; },
639 (s,v) => { ShouldDisableContactPoolDynamicAllocation = v; 644 (s,v) => { ShouldDisableContactPoolDynamicAllocation = v;
640 s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ), 645 s.UnmanagedParams[0].shouldDisableContactPoolDynamicAllocation = NumericBool(v); } ),
641 new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", 646 new ParameterDefn<bool>("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
642 false, 647 false,
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index f047176..e796804 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -38,7 +38,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
38 * Class to wrap all objects. 38 * Class to wrap all objects.
39 * The rest of BulletSim doesn't need to keep checking for avatars or prims 39 * The rest of BulletSim doesn't need to keep checking for avatars or prims
40 * unless the difference is significant. 40 * unless the difference is significant.
41 * 41 *
42 * Variables in the physicsl objects are in three forms: 42 * Variables in the physicsl objects are in three forms:
43 * VariableName: used by the simulator and performs taint operations, etc 43 * VariableName: used by the simulator and performs taint operations, etc
44 * RawVariableName: direct reference to the BulletSim storage for the variable value 44 * RawVariableName: direct reference to the BulletSim storage for the variable value
@@ -52,7 +52,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce 52 * SOP.ApplyImpulse SOP.ApplyAngularImpulse SOP.SetAngularImpulse SOP.SetForce
53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse 53 * SOG.ApplyImpulse SOG.ApplyAngularImpulse SOG.SetAngularImpulse
54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v 54 * PA.AddForce PA.AddAngularForce PA.Torque = v PA.Force = v
55 * BS.ApplyCentralForce BS.ApplyTorque 55 * BS.ApplyCentralForce BS.ApplyTorque
56 */ 56 */
57 57
58// Flags used to denote which properties updates when making UpdateProperties calls to linksets, etc. 58// Flags used to denote which properties updates when making UpdateProperties calls to linksets, etc.
@@ -72,14 +72,14 @@ public abstract class BSPhysObject : PhysicsActor
72 } 72 }
73 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName) 73 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName)
74 { 74 {
75 PhysicsScene = parentScene; 75 PhysScene = parentScene;
76 LocalID = localID; 76 LocalID = localID;
77 PhysObjectName = name; 77 PhysObjectName = name;
78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate. 78 Name = name; // PhysicsActor also has the name of the object. Someday consolidate.
79 TypeName = typeName; 79 TypeName = typeName;
80 80
81 // The collection of things that push me around 81 // The collection of things that push me around
82 PhysicalActors = new BSActorCollection(PhysicsScene); 82 PhysicalActors = new BSActorCollection(PhysScene);
83 83
84 // Initialize variables kept in base. 84 // Initialize variables kept in base.
85 GravModifier = 1.0f; 85 GravModifier = 1.0f;
@@ -88,7 +88,7 @@ public abstract class BSPhysObject : PhysicsActor
88 88
89 // We don't have any physical representation yet. 89 // We don't have any physical representation yet.
90 PhysBody = new BulletBody(localID); 90 PhysBody = new BulletBody(localID);
91 PhysShape = new BulletShape(); 91 PhysShape = new BSShapeNull();
92 92
93 PrimAssetState = PrimAssetCondition.Unknown; 93 PrimAssetState = PrimAssetCondition.Unknown;
94 94
@@ -115,13 +115,13 @@ public abstract class BSPhysObject : PhysicsActor
115 public virtual void Destroy() 115 public virtual void Destroy()
116 { 116 {
117 PhysicalActors.Enable(false); 117 PhysicalActors.Enable(false);
118 PhysicsScene.TaintedObject("BSPhysObject.Destroy", delegate() 118 PhysScene.TaintedObject("BSPhysObject.Destroy", delegate()
119 { 119 {
120 PhysicalActors.Dispose(); 120 PhysicalActors.Dispose();
121 }); 121 });
122 } 122 }
123 123
124 public BSScene PhysicsScene { get; protected set; } 124 public BSScene PhysScene { get; protected set; }
125 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor 125 // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor
126 public string PhysObjectName { get; protected set; } 126 public string PhysObjectName { get; protected set; }
127 public string TypeName { get; protected set; } 127 public string TypeName { get; protected set; }
@@ -141,7 +141,7 @@ public abstract class BSPhysObject : PhysicsActor
141 // Reference to the physical body (btCollisionObject) of this object 141 // Reference to the physical body (btCollisionObject) of this object
142 public BulletBody PhysBody; 142 public BulletBody PhysBody;
143 // Reference to the physical shape (btCollisionShape) of this object 143 // Reference to the physical shape (btCollisionShape) of this object
144 public BulletShape PhysShape; 144 public BSShape PhysShape;
145 145
146 // The physical representation of the prim might require an asset fetch. 146 // The physical representation of the prim might require an asset fetch.
147 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'. 147 // The asset state is first 'Unknown' then 'Waiting' then either 'Failed' or 'Fetched'.
@@ -154,13 +154,6 @@ public abstract class BSPhysObject : PhysicsActor
154 // The objects base shape information. Null if not a prim type shape. 154 // The objects base shape information. Null if not a prim type shape.
155 public PrimitiveBaseShape BaseShape { get; protected set; } 155 public PrimitiveBaseShape BaseShape { get; protected set; }
156 156
157 // Some types of objects have preferred physical representations.
158 // Returns SHAPE_UNKNOWN if there is no preference.
159 public virtual BSPhysicsShapeType PreferredPhysicalShape
160 {
161 get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
162 }
163
164 // When the physical properties are updated, an EntityProperty holds the update values. 157 // When the physical properties are updated, an EntityProperty holds the update values.
165 // Keep the current and last EntityProperties to enable computation of differences 158 // Keep the current and last EntityProperties to enable computation of differences
166 // between the current update and the previous values. 159 // between the current update and the previous values.
@@ -269,7 +262,8 @@ public abstract class BSPhysObject : PhysicsActor
269 262
270 // The user can optionally set the center of mass. The user's setting will override any 263 // The user can optionally set the center of mass. The user's setting will override any
271 // computed center-of-mass (like in linksets). 264 // computed center-of-mass (like in linksets).
272 public OMV.Vector3? UserSetCenterOfMass { get; set; } 265 // Note this is a displacement from the root's coordinates. Zero means use the root prim as center-of-mass.
266 public OMV.Vector3? UserSetCenterOfMassDisplacement { get; set; }
273 267
274 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. 268 public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free.
275 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free 269 public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free
@@ -280,7 +274,7 @@ public abstract class BSPhysObject : PhysicsActor
280 public void ActivateIfPhysical(bool forceIt) 274 public void ActivateIfPhysical(bool forceIt)
281 { 275 {
282 if (IsPhysical && PhysBody.HasPhysicalBody) 276 if (IsPhysical && PhysBody.HasPhysicalBody)
283 PhysicsScene.PE.Activate(PhysBody, forceIt); 277 PhysScene.PE.Activate(PhysBody, forceIt);
284 } 278 }
285 279
286 // 'actors' act on the physical object to change or constrain its motion. These can range from 280 // 'actors' act on the physical object to change or constrain its motion. These can range from
@@ -343,29 +337,29 @@ public abstract class BSPhysObject : PhysicsActor
343 protected long CollisionAccumulation { get; set; } 337 protected long CollisionAccumulation { get; set; }
344 338
345 public override bool IsColliding { 339 public override bool IsColliding {
346 get { return (CollidingStep == PhysicsScene.SimulationStep); } 340 get { return (CollidingStep == PhysScene.SimulationStep); }
347 set { 341 set {
348 if (value) 342 if (value)
349 CollidingStep = PhysicsScene.SimulationStep; 343 CollidingStep = PhysScene.SimulationStep;
350 else 344 else
351 CollidingStep = 0; 345 CollidingStep = 0;
352 } 346 }
353 } 347 }
354 public override bool CollidingGround { 348 public override bool CollidingGround {
355 get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } 349 get { return (CollidingGroundStep == PhysScene.SimulationStep); }
356 set 350 set
357 { 351 {
358 if (value) 352 if (value)
359 CollidingGroundStep = PhysicsScene.SimulationStep; 353 CollidingGroundStep = PhysScene.SimulationStep;
360 else 354 else
361 CollidingGroundStep = 0; 355 CollidingGroundStep = 0;
362 } 356 }
363 } 357 }
364 public override bool CollidingObj { 358 public override bool CollidingObj {
365 get { return (CollidingObjectStep == PhysicsScene.SimulationStep); } 359 get { return (CollidingObjectStep == PhysScene.SimulationStep); }
366 set { 360 set {
367 if (value) 361 if (value)
368 CollidingObjectStep = PhysicsScene.SimulationStep; 362 CollidingObjectStep = PhysScene.SimulationStep;
369 else 363 else
370 CollidingObjectStep = 0; 364 CollidingObjectStep = 0;
371 } 365 }
@@ -390,14 +384,14 @@ public abstract class BSPhysObject : PhysicsActor
390 bool ret = false; 384 bool ret = false;
391 385
392 // The following lines make IsColliding(), CollidingGround() and CollidingObj work 386 // The following lines make IsColliding(), CollidingGround() and CollidingObj work
393 CollidingStep = PhysicsScene.SimulationStep; 387 CollidingStep = PhysScene.SimulationStep;
394 if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) 388 if (collidingWith <= PhysScene.TerrainManager.HighestTerrainID)
395 { 389 {
396 CollidingGroundStep = PhysicsScene.SimulationStep; 390 CollidingGroundStep = PhysScene.SimulationStep;
397 } 391 }
398 else 392 else
399 { 393 {
400 CollidingObjectStep = PhysicsScene.SimulationStep; 394 CollidingObjectStep = PhysScene.SimulationStep;
401 } 395 }
402 396
403 CollisionAccumulation++; 397 CollisionAccumulation++;
@@ -407,10 +401,10 @@ public abstract class BSPhysObject : PhysicsActor
407 401
408 // Make a collection of the collisions that happened the last simulation tick. 402 // Make a collection of the collisions that happened the last simulation tick.
409 // This is different than the collection created for sending up to the simulator as it is cleared every tick. 403 // This is different than the collection created for sending up to the simulator as it is cleared every tick.
410 if (CollisionsLastTickStep != PhysicsScene.SimulationStep) 404 if (CollisionsLastTickStep != PhysScene.SimulationStep)
411 { 405 {
412 CollisionsLastTick = new CollisionEventUpdate(); 406 CollisionsLastTick = new CollisionEventUpdate();
413 CollisionsLastTickStep = PhysicsScene.SimulationStep; 407 CollisionsLastTickStep = PhysScene.SimulationStep;
414 } 408 }
415 CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 409 CollisionsLastTick.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
416 410
@@ -437,9 +431,9 @@ public abstract class BSPhysObject : PhysicsActor
437 bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0); 431 bool force = (CollisionCollection.Count == 0 && CollisionsLastReported.Count != 0);
438 432
439 // throttle the collisions to the number of milliseconds specified in the subscription 433 // throttle the collisions to the number of milliseconds specified in the subscription
440 if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) 434 if (force || (PhysScene.SimulationNowTime >= NextCollisionOkTime))
441 { 435 {
442 NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; 436 NextCollisionOkTime = PhysScene.SimulationNowTime + SubscribedEventsMs;
443 437
444 // We are called if we previously had collisions. If there are no collisions 438 // We are called if we previously had collisions. If there are no collisions
445 // this time, send up one last empty event so OpenSim can sense collision end. 439 // this time, send up one last empty event so OpenSim can sense collision end.
@@ -457,7 +451,7 @@ public abstract class BSPhysObject : PhysicsActor
457 451
458 // The CollisionCollection instance is passed around in the simulator. 452 // The CollisionCollection instance is passed around in the simulator.
459 // Make sure we don't have a handle to that one and that a new one is used for next time. 453 // Make sure we don't have a handle to that one and that a new one is used for next time.
460 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here, 454 // This fixes an interesting 'gotcha'. If we call CollisionCollection.Clear() here,
461 // a race condition is created for the other users of this instance. 455 // a race condition is created for the other users of this instance.
462 CollisionCollection = new CollisionEventUpdate(); 456 CollisionCollection = new CollisionEventUpdate();
463 } 457 }
@@ -474,10 +468,10 @@ public abstract class BSPhysObject : PhysicsActor
474 // make sure first collision happens 468 // make sure first collision happens
475 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); 469 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
476 470
477 PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 471 PhysScene.TaintedObject(TypeName+".SubscribeEvents", delegate()
478 { 472 {
479 if (PhysBody.HasPhysicalBody) 473 if (PhysBody.HasPhysicalBody)
480 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 474 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
481 }); 475 });
482 } 476 }
483 else 477 else
@@ -489,11 +483,11 @@ public abstract class BSPhysObject : PhysicsActor
489 public override void UnSubscribeEvents() { 483 public override void UnSubscribeEvents() {
490 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); 484 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
491 SubscribedEventsMs = 0; 485 SubscribedEventsMs = 0;
492 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 486 PhysScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
493 { 487 {
494 // Make sure there is a body there because sometimes destruction happens in an un-ideal order. 488 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
495 if (PhysBody.HasPhysicalBody) 489 if (PhysBody.HasPhysicalBody)
496 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 490 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
497 }); 491 });
498 } 492 }
499 // Return 'true' if the simulator wants collision events 493 // Return 'true' if the simulator wants collision events
@@ -507,7 +501,7 @@ public abstract class BSPhysObject : PhysicsActor
507 { 501 {
508 // Scale the collision count by the time since the last collision. 502 // Scale the collision count by the time since the last collision.
509 // The "+1" prevents dividing by zero. 503 // The "+1" prevents dividing by zero.
510 long timeAgo = PhysicsScene.SimulationStep - CollidingStep + 1; 504 long timeAgo = PhysScene.SimulationStep - CollidingStep + 1;
511 CollisionScore = CollisionAccumulation / timeAgo; 505 CollisionScore = CollisionAccumulation / timeAgo;
512 } 506 }
513 public override float CollisionScore { get; set; } 507 public override float CollisionScore { get; set; }
@@ -534,8 +528,8 @@ public abstract class BSPhysObject : PhysicsActor
534 // High performance detailed logging routine used by the physical objects. 528 // High performance detailed logging routine used by the physical objects.
535 protected void DetailLog(string msg, params Object[] args) 529 protected void DetailLog(string msg, params Object[] args)
536 { 530 {
537 if (PhysicsScene.PhysicsLogging.Enabled) 531 if (PhysScene.PhysicsLogging.Enabled)
538 PhysicsScene.DetailLog(msg, args); 532 PhysScene.DetailLog(msg, args);
539 } 533 }
540 534
541} 535}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 4bc266b..d3f3475 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -101,21 +101,21 @@ public class BSPrim : BSPhysObject
101 _isVolumeDetect = false; 101 _isVolumeDetect = false;
102 102
103 // We keep a handle to the vehicle actor so we can set vehicle parameters later. 103 // We keep a handle to the vehicle actor so we can set vehicle parameters later.
104 VehicleActor = new BSDynamics(PhysicsScene, this, VehicleActorName); 104 VehicleActor = new BSDynamics(PhysScene, this, VehicleActorName);
105 PhysicalActors.Add(VehicleActorName, VehicleActor); 105 PhysicalActors.Add(VehicleActorName, VehicleActor);
106 106
107 _mass = CalculateMass(); 107 _mass = CalculateMass();
108 108
109 // DetailLog("{0},BSPrim.constructor,call", LocalID); 109 // DetailLog("{0},BSPrim.constructor,call", LocalID);
110 // do the actual object creation at taint time 110 // do the actual object creation at taint time
111 PhysicsScene.TaintedObject("BSPrim.create", delegate() 111 PhysScene.TaintedObject("BSPrim.create", delegate()
112 { 112 {
113 // Make sure the object is being created with some sanity. 113 // Make sure the object is being created with some sanity.
114 ExtremeSanityCheck(true /* inTaintTime */); 114 ExtremeSanityCheck(true /* inTaintTime */);
115 115
116 CreateGeomAndObject(true); 116 CreateGeomAndObject(true);
117 117
118 CurrentCollisionFlags = PhysicsScene.PE.GetCollisionFlags(PhysBody); 118 CurrentCollisionFlags = PhysScene.PE.GetCollisionFlags(PhysBody);
119 }); 119 });
120 } 120 }
121 121
@@ -128,14 +128,14 @@ public class BSPrim : BSPhysObject
128 // Undo any vehicle properties 128 // Undo any vehicle properties
129 this.VehicleType = (int)Vehicle.TYPE_NONE; 129 this.VehicleType = (int)Vehicle.TYPE_NONE;
130 130
131 PhysicsScene.TaintedObject("BSPrim.Destroy", delegate() 131 PhysScene.TaintedObject("BSPrim.Destroy", delegate()
132 { 132 {
133 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 133 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
134 // If there are physical body and shape, release my use of same. 134 // If there are physical body and shape, release my use of same.
135 PhysicsScene.Shapes.DereferenceBody(PhysBody, null); 135 PhysScene.Shapes.DereferenceBody(PhysBody, null);
136 PhysBody.Clear(); 136 PhysBody.Clear();
137 PhysicsScene.Shapes.DereferenceShape(PhysShape, null); 137 PhysShape.Dereference(PhysScene);
138 PhysShape.Clear(); 138 PhysShape = new BSShapeNull();
139 }); 139 });
140 } 140 }
141 141
@@ -161,25 +161,13 @@ public class BSPrim : BSPhysObject
161 ForceBodyShapeRebuild(false); 161 ForceBodyShapeRebuild(false);
162 } 162 }
163 } 163 }
164 // 'unknown' says to choose the best type
165 public override BSPhysicsShapeType PreferredPhysicalShape
166 { get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } }
167
168 public override bool ForceBodyShapeRebuild(bool inTaintTime) 164 public override bool ForceBodyShapeRebuild(bool inTaintTime)
169 { 165 {
170 if (inTaintTime) 166 PhysScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
171 { 167 {
172 _mass = CalculateMass(); // changing the shape changes the mass 168 _mass = CalculateMass(); // changing the shape changes the mass
173 CreateGeomAndObject(true); 169 CreateGeomAndObject(true);
174 } 170 });
175 else
176 {
177 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate()
178 {
179 _mass = CalculateMass(); // changing the shape changes the mass
180 CreateGeomAndObject(true);
181 });
182 }
183 return true; 171 return true;
184 } 172 }
185 public override bool Grabbed { 173 public override bool Grabbed {
@@ -192,7 +180,7 @@ public class BSPrim : BSPhysObject
192 if (value != _isSelected) 180 if (value != _isSelected)
193 { 181 {
194 _isSelected = value; 182 _isSelected = value;
195 PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() 183 PhysScene.TaintedObject("BSPrim.setSelected", delegate()
196 { 184 {
197 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); 185 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
198 SetObjectDynamic(false); 186 SetObjectDynamic(false);
@@ -238,23 +226,23 @@ public class BSPrim : BSPhysObject
238 _rotationalVelocity = OMV.Vector3.Zero; 226 _rotationalVelocity = OMV.Vector3.Zero;
239 227
240 // Zero some other properties in the physics engine 228 // Zero some other properties in the physics engine
241 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 229 PhysScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
242 { 230 {
243 if (PhysBody.HasPhysicalBody) 231 if (PhysBody.HasPhysicalBody)
244 PhysicsScene.PE.ClearAllForces(PhysBody); 232 PhysScene.PE.ClearAllForces(PhysBody);
245 }); 233 });
246 } 234 }
247 public override void ZeroAngularMotion(bool inTaintTime) 235 public override void ZeroAngularMotion(bool inTaintTime)
248 { 236 {
249 _rotationalVelocity = OMV.Vector3.Zero; 237 _rotationalVelocity = OMV.Vector3.Zero;
250 // Zero some other properties in the physics engine 238 // Zero some other properties in the physics engine
251 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 239 PhysScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate()
252 { 240 {
253 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); 241 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
254 if (PhysBody.HasPhysicalBody) 242 if (PhysBody.HasPhysicalBody)
255 { 243 {
256 PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); 244 PhysScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
257 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 245 PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
258 } 246 }
259 }); 247 });
260 } 248 }
@@ -272,11 +260,11 @@ public class BSPrim : BSPhysObject
272 260
273 EnableActor(LockedAxis != LockedAxisFree, LockedAxisActorName, delegate() 261 EnableActor(LockedAxis != LockedAxisFree, LockedAxisActorName, delegate()
274 { 262 {
275 return new BSActorLockAxis(PhysicsScene, this, LockedAxisActorName); 263 return new BSActorLockAxis(PhysScene, this, LockedAxisActorName);
276 }); 264 });
277 265
278 // Update parameters so the new actor's Refresh() action is called at the right time. 266 // Update parameters so the new actor's Refresh() action is called at the right time.
279 PhysicsScene.TaintedObject("BSPrim.LockAngularMotion", delegate() 267 PhysScene.TaintedObject("BSPrim.LockAngularMotion", delegate()
280 { 268 {
281 UpdatePhysicalParameters(); 269 UpdatePhysicalParameters();
282 }); 270 });
@@ -306,7 +294,7 @@ public class BSPrim : BSPhysObject
306 _position = value; 294 _position = value;
307 PositionSanityCheck(false); 295 PositionSanityCheck(false);
308 296
309 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() 297 PhysScene.TaintedObject("BSPrim.setPosition", delegate()
310 { 298 {
311 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 299 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
312 ForcePosition = _position; 300 ForcePosition = _position;
@@ -316,14 +304,14 @@ public class BSPrim : BSPhysObject
316 304
317 public override OMV.Vector3 ForcePosition { 305 public override OMV.Vector3 ForcePosition {
318 get { 306 get {
319 _position = PhysicsScene.PE.GetPosition(PhysBody); 307 _position = PhysScene.PE.GetPosition(PhysBody);
320 return _position; 308 return _position;
321 } 309 }
322 set { 310 set {
323 _position = value; 311 _position = value;
324 if (PhysBody.HasPhysicalBody) 312 if (PhysBody.HasPhysicalBody)
325 { 313 {
326 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 314 PhysScene.PE.SetTranslation(PhysBody, _position, _orientation);
327 ActivateIfPhysical(false); 315 ActivateIfPhysical(false);
328 } 316 }
329 } 317 }
@@ -340,7 +328,7 @@ public class BSPrim : BSPhysObject
340 if (!IsPhysicallyActive) 328 if (!IsPhysicallyActive)
341 return ret; 329 return ret;
342 330
343 if (!PhysicsScene.TerrainManager.IsWithinKnownTerrain(RawPosition)) 331 if (!PhysScene.TerrainManager.IsWithinKnownTerrain(RawPosition))
344 { 332 {
345 // The physical object is out of the known/simulated area. 333 // The physical object is out of the known/simulated area.
346 // Upper levels of code will handle the transition to other areas so, for 334 // Upper levels of code will handle the transition to other areas so, for
@@ -348,7 +336,7 @@ public class BSPrim : BSPhysObject
348 return ret; 336 return ret;
349 } 337 }
350 338
351 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); 339 float terrainHeight = PhysScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
352 OMV.Vector3 upForce = OMV.Vector3.Zero; 340 OMV.Vector3 upForce = OMV.Vector3.Zero;
353 float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z)); 341 float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z));
354 if ((RawPosition.Z + approxSize / 2f) < terrainHeight) 342 if ((RawPosition.Z + approxSize / 2f) < terrainHeight)
@@ -369,7 +357,7 @@ public class BSPrim : BSPhysObject
369 357
370 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 358 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
371 { 359 {
372 float waterHeight = PhysicsScene.TerrainManager.GetWaterLevelAtXYZ(_position); 360 float waterHeight = PhysScene.TerrainManager.GetWaterLevelAtXYZ(_position);
373 // TODO: a floating motor so object will bob in the water 361 // TODO: a floating motor so object will bob in the water
374 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f) 362 if (Math.Abs(RawPosition.Z - waterHeight) > 0.1f)
375 { 363 {
@@ -377,7 +365,7 @@ public class BSPrim : BSPhysObject
377 upForce.Z = (waterHeight - RawPosition.Z) * 1f; 365 upForce.Z = (waterHeight - RawPosition.Z) * 1f;
378 366
379 // Apply upforce and overcome gravity. 367 // Apply upforce and overcome gravity.
380 OMV.Vector3 correctionForce = upForce - PhysicsScene.DefaultGravity; 368 OMV.Vector3 correctionForce = upForce - PhysScene.DefaultGravity;
381 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce); 369 DetailLog("{0},BSPrim.PositionSanityCheck,applyForce,pos={1},upForce={2},correctionForce={3}", LocalID, _position, upForce, correctionForce);
382 AddForce(correctionForce, false, inTaintTime); 370 AddForce(correctionForce, false, inTaintTime);
383 ret = true; 371 ret = true;
@@ -432,7 +420,7 @@ public class BSPrim : BSPhysObject
432 get { return _mass; } 420 get { return _mass; }
433 } 421 }
434 // used when we only want this prim's mass and not the linkset thing 422 // used when we only want this prim's mass and not the linkset thing
435 public override float RawMass { 423 public override float RawMass {
436 get { return _mass; } 424 get { return _mass; }
437 } 425 }
438 // Set the physical mass to the passed mass. 426 // Set the physical mass to the passed mass.
@@ -443,10 +431,10 @@ public class BSPrim : BSPhysObject
443 { 431 {
444 if (IsStatic) 432 if (IsStatic)
445 { 433 {
446 PhysicsScene.PE.SetGravity(PhysBody, PhysicsScene.DefaultGravity); 434 PhysScene.PE.SetGravity(PhysBody, PhysScene.DefaultGravity);
447 Inertia = OMV.Vector3.Zero; 435 Inertia = OMV.Vector3.Zero;
448 PhysicsScene.PE.SetMassProps(PhysBody, 0f, Inertia); 436 PhysScene.PE.SetMassProps(PhysBody, 0f, Inertia);
449 PhysicsScene.PE.UpdateInertiaTensor(PhysBody); 437 PhysScene.PE.UpdateInertiaTensor(PhysBody);
450 } 438 }
451 else 439 else
452 { 440 {
@@ -455,16 +443,16 @@ public class BSPrim : BSPhysObject
455 // Changing interesting properties doesn't change proxy and collision cache 443 // Changing interesting properties doesn't change proxy and collision cache
456 // information. The Bullet solution is to re-add the object to the world 444 // information. The Bullet solution is to re-add the object to the world
457 // after parameters are changed. 445 // after parameters are changed.
458 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 446 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
459 } 447 }
460 448
461 // The computation of mass props requires gravity to be set on the object. 449 // The computation of mass props requires gravity to be set on the object.
462 Gravity = ComputeGravity(Buoyancy); 450 Gravity = ComputeGravity(Buoyancy);
463 PhysicsScene.PE.SetGravity(PhysBody, Gravity); 451 PhysScene.PE.SetGravity(PhysBody, Gravity);
464 452
465 Inertia = PhysicsScene.PE.CalculateLocalInertia(PhysShape, physMass); 453 Inertia = PhysScene.PE.CalculateLocalInertia(PhysShape.physShapeInfo, physMass);
466 PhysicsScene.PE.SetMassProps(PhysBody, physMass, Inertia); 454 PhysScene.PE.SetMassProps(PhysBody, physMass, Inertia);
467 PhysicsScene.PE.UpdateInertiaTensor(PhysBody); 455 PhysScene.PE.UpdateInertiaTensor(PhysBody);
468 456
469 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}", 457 DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2},grav={3},inWorld={4}",
470 LocalID, physMass, Inertia, Gravity, inWorld); 458 LocalID, physMass, Inertia, Gravity, inWorld);
@@ -480,7 +468,7 @@ public class BSPrim : BSPhysObject
480 // Return what gravity should be set to this very moment 468 // Return what gravity should be set to this very moment
481 public OMV.Vector3 ComputeGravity(float buoyancy) 469 public OMV.Vector3 ComputeGravity(float buoyancy)
482 { 470 {
483 OMV.Vector3 ret = PhysicsScene.DefaultGravity; 471 OMV.Vector3 ret = PhysScene.DefaultGravity;
484 472
485 if (!IsStatic) 473 if (!IsStatic)
486 { 474 {
@@ -509,7 +497,7 @@ public class BSPrim : BSPhysObject
509 RawForce = value; 497 RawForce = value;
510 EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate() 498 EnableActor(RawForce != OMV.Vector3.Zero, SetForceActorName, delegate()
511 { 499 {
512 return new BSActorSetForce(PhysicsScene, this, SetForceActorName); 500 return new BSActorSetForce(PhysScene, this, SetForceActorName);
513 }); 501 });
514 } 502 }
515 } 503 }
@@ -521,9 +509,9 @@ public class BSPrim : BSPhysObject
521 set { 509 set {
522 Vehicle type = (Vehicle)value; 510 Vehicle type = (Vehicle)value;
523 511
524 PhysicsScene.TaintedObject("setVehicleType", delegate() 512 PhysScene.TaintedObject("setVehicleType", delegate()
525 { 513 {
526 // Vehicle code changes the parameters for this vehicle type. 514 ZeroMotion(true /* inTaintTime */);
527 VehicleActor.ProcessTypeChange(type); 515 VehicleActor.ProcessTypeChange(type);
528 ActivateIfPhysical(false); 516 ActivateIfPhysical(false);
529 }); 517 });
@@ -531,7 +519,7 @@ public class BSPrim : BSPhysObject
531 } 519 }
532 public override void VehicleFloatParam(int param, float value) 520 public override void VehicleFloatParam(int param, float value)
533 { 521 {
534 PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 522 PhysScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
535 { 523 {
536 VehicleActor.ProcessFloatVehicleParam((Vehicle)param, value); 524 VehicleActor.ProcessFloatVehicleParam((Vehicle)param, value);
537 ActivateIfPhysical(false); 525 ActivateIfPhysical(false);
@@ -539,7 +527,7 @@ public class BSPrim : BSPhysObject
539 } 527 }
540 public override void VehicleVectorParam(int param, OMV.Vector3 value) 528 public override void VehicleVectorParam(int param, OMV.Vector3 value)
541 { 529 {
542 PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 530 PhysScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
543 { 531 {
544 VehicleActor.ProcessVectorVehicleParam((Vehicle)param, value); 532 VehicleActor.ProcessVectorVehicleParam((Vehicle)param, value);
545 ActivateIfPhysical(false); 533 ActivateIfPhysical(false);
@@ -547,7 +535,7 @@ public class BSPrim : BSPhysObject
547 } 535 }
548 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 536 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
549 { 537 {
550 PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 538 PhysScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
551 { 539 {
552 VehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation); 540 VehicleActor.ProcessRotationVehicleParam((Vehicle)param, rotation);
553 ActivateIfPhysical(false); 541 ActivateIfPhysical(false);
@@ -555,7 +543,7 @@ public class BSPrim : BSPhysObject
555 } 543 }
556 public override void VehicleFlags(int param, bool remove) 544 public override void VehicleFlags(int param, bool remove)
557 { 545 {
558 PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() 546 PhysScene.TaintedObject("BSPrim.VehicleFlags", delegate()
559 { 547 {
560 VehicleActor.ProcessVehicleFlags(param, remove); 548 VehicleActor.ProcessVehicleFlags(param, remove);
561 }); 549 });
@@ -567,7 +555,7 @@ public class BSPrim : BSPhysObject
567 if (_isVolumeDetect != newValue) 555 if (_isVolumeDetect != newValue)
568 { 556 {
569 _isVolumeDetect = newValue; 557 _isVolumeDetect = newValue;
570 PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() 558 PhysScene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
571 { 559 {
572 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); 560 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
573 SetObjectDynamic(true); 561 SetObjectDynamic(true);
@@ -578,7 +566,7 @@ public class BSPrim : BSPhysObject
578 public override void SetMaterial(int material) 566 public override void SetMaterial(int material)
579 { 567 {
580 base.SetMaterial(material); 568 base.SetMaterial(material);
581 PhysicsScene.TaintedObject("BSPrim.SetMaterial", delegate() 569 PhysScene.TaintedObject("BSPrim.SetMaterial", delegate()
582 { 570 {
583 UpdatePhysicalParameters(); 571 UpdatePhysicalParameters();
584 }); 572 });
@@ -591,7 +579,7 @@ public class BSPrim : BSPhysObject
591 if (base.Friction != value) 579 if (base.Friction != value)
592 { 580 {
593 base.Friction = value; 581 base.Friction = value;
594 PhysicsScene.TaintedObject("BSPrim.setFriction", delegate() 582 PhysScene.TaintedObject("BSPrim.setFriction", delegate()
595 { 583 {
596 UpdatePhysicalParameters(); 584 UpdatePhysicalParameters();
597 }); 585 });
@@ -606,7 +594,7 @@ public class BSPrim : BSPhysObject
606 if (base.Restitution != value) 594 if (base.Restitution != value)
607 { 595 {
608 base.Restitution = value; 596 base.Restitution = value;
609 PhysicsScene.TaintedObject("BSPrim.setRestitution", delegate() 597 PhysScene.TaintedObject("BSPrim.setRestitution", delegate()
610 { 598 {
611 UpdatePhysicalParameters(); 599 UpdatePhysicalParameters();
612 }); 600 });
@@ -623,7 +611,7 @@ public class BSPrim : BSPhysObject
623 if (base.Density != value) 611 if (base.Density != value)
624 { 612 {
625 base.Density = value; 613 base.Density = value;
626 PhysicsScene.TaintedObject("BSPrim.setDensity", delegate() 614 PhysScene.TaintedObject("BSPrim.setDensity", delegate()
627 { 615 {
628 UpdatePhysicalParameters(); 616 UpdatePhysicalParameters();
629 }); 617 });
@@ -638,7 +626,7 @@ public class BSPrim : BSPhysObject
638 if (base.GravModifier != value) 626 if (base.GravModifier != value)
639 { 627 {
640 base.GravModifier = value; 628 base.GravModifier = value;
641 PhysicsScene.TaintedObject("BSPrim.setGravityModifier", delegate() 629 PhysScene.TaintedObject("BSPrim.setGravityModifier", delegate()
642 { 630 {
643 UpdatePhysicalParameters(); 631 UpdatePhysicalParameters();
644 }); 632 });
@@ -649,7 +637,7 @@ public class BSPrim : BSPhysObject
649 get { return RawVelocity; } 637 get { return RawVelocity; }
650 set { 638 set {
651 RawVelocity = value; 639 RawVelocity = value;
652 PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() 640 PhysScene.TaintedObject("BSPrim.setVelocity", delegate()
653 { 641 {
654 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity); 642 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity);
655 ForceVelocity = RawVelocity; 643 ForceVelocity = RawVelocity;
@@ -659,13 +647,13 @@ public class BSPrim : BSPhysObject
659 public override OMV.Vector3 ForceVelocity { 647 public override OMV.Vector3 ForceVelocity {
660 get { return RawVelocity; } 648 get { return RawVelocity; }
661 set { 649 set {
662 PhysicsScene.AssertInTaintTime("BSPrim.ForceVelocity"); 650 PhysScene.AssertInTaintTime("BSPrim.ForceVelocity");
663 651
664 RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity); 652 RawVelocity = Util.ClampV(value, BSParam.MaxLinearVelocity);
665 if (PhysBody.HasPhysicalBody) 653 if (PhysBody.HasPhysicalBody)
666 { 654 {
667 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity); 655 DetailLog("{0},BSPrim.ForceVelocity,taint,vel={1}", LocalID, RawVelocity);
668 PhysicsScene.PE.SetLinearVelocity(PhysBody, RawVelocity); 656 PhysScene.PE.SetLinearVelocity(PhysBody, RawVelocity);
669 ActivateIfPhysical(false); 657 ActivateIfPhysical(false);
670 } 658 }
671 } 659 }
@@ -676,7 +664,7 @@ public class BSPrim : BSPhysObject
676 RawTorque = value; 664 RawTorque = value;
677 EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate() 665 EnableActor(RawTorque != OMV.Vector3.Zero, SetTorqueActorName, delegate()
678 { 666 {
679 return new BSActorSetTorque(PhysicsScene, this, SetTorqueActorName); 667 return new BSActorSetTorque(PhysScene, this, SetTorqueActorName);
680 }); 668 });
681 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque); 669 DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, RawTorque);
682 } 670 }
@@ -699,7 +687,7 @@ public class BSPrim : BSPhysObject
699 return; 687 return;
700 _orientation = value; 688 _orientation = value;
701 689
702 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() 690 PhysScene.TaintedObject("BSPrim.setOrientation", delegate()
703 { 691 {
704 ForceOrientation = _orientation; 692 ForceOrientation = _orientation;
705 }); 693 });
@@ -710,14 +698,14 @@ public class BSPrim : BSPhysObject
710 { 698 {
711 get 699 get
712 { 700 {
713 _orientation = PhysicsScene.PE.GetOrientation(PhysBody); 701 _orientation = PhysScene.PE.GetOrientation(PhysBody);
714 return _orientation; 702 return _orientation;
715 } 703 }
716 set 704 set
717 { 705 {
718 _orientation = value; 706 _orientation = value;
719 if (PhysBody.HasPhysicalBody) 707 if (PhysBody.HasPhysicalBody)
720 PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation); 708 PhysScene.PE.SetTranslation(PhysBody, _position, _orientation);
721 } 709 }
722 } 710 }
723 public override int PhysicsActorType { 711 public override int PhysicsActorType {
@@ -730,7 +718,7 @@ public class BSPrim : BSPhysObject
730 if (_isPhysical != value) 718 if (_isPhysical != value)
731 { 719 {
732 _isPhysical = value; 720 _isPhysical = value;
733 PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() 721 PhysScene.TaintedObject("BSPrim.setIsPhysical", delegate()
734 { 722 {
735 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); 723 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
736 SetObjectDynamic(true); 724 SetObjectDynamic(true);
@@ -779,13 +767,13 @@ public class BSPrim : BSPhysObject
779 if (!PhysBody.HasPhysicalBody) 767 if (!PhysBody.HasPhysicalBody)
780 { 768 {
781 // This would only happen if updates are called for during initialization when the body is not set up yet. 769 // This would only happen if updates are called for during initialization when the body is not set up yet.
782 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID); 770 // DetailLog("{0},BSPrim.UpdatePhysicalParameters,taint,calledWithNoPhysBody", LocalID);
783 return; 771 return;
784 } 772 }
785 773
786 // Mangling all the physical properties requires the object not be in the physical world. 774 // Mangling all the physical properties requires the object not be in the physical world.
787 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). 775 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
788 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, PhysBody); 776 PhysScene.PE.RemoveObjectFromWorld(PhysScene.World, PhysBody);
789 777
790 // Set up the object physicalness (does gravity and collisions move this object) 778 // Set up the object physicalness (does gravity and collisions move this object)
791 MakeDynamic(IsStatic); 779 MakeDynamic(IsStatic);
@@ -802,10 +790,11 @@ public class BSPrim : BSPhysObject
802 AddObjectToPhysicalWorld(); 790 AddObjectToPhysicalWorld();
803 791
804 // Rebuild its shape 792 // Rebuild its shape
805 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody); 793 PhysScene.PE.UpdateSingleAabb(PhysScene.World, PhysBody);
806 794
807 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}", 795 DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}",
808 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape); 796 LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(),
797 CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
809 } 798 }
810 799
811 // "Making dynamic" means changing to and from static. 800 // "Making dynamic" means changing to and from static.
@@ -818,28 +807,28 @@ public class BSPrim : BSPhysObject
818 if (makeStatic) 807 if (makeStatic)
819 { 808 {
820 // Become a Bullet 'static' object type 809 // Become a Bullet 'static' object type
821 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); 810 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
822 // Stop all movement 811 // Stop all movement
823 ZeroMotion(true); 812 ZeroMotion(true);
824 813
825 // Set various physical properties so other object interact properly 814 // Set various physical properties so other object interact properly
826 PhysicsScene.PE.SetFriction(PhysBody, Friction); 815 PhysScene.PE.SetFriction(PhysBody, Friction);
827 PhysicsScene.PE.SetRestitution(PhysBody, Restitution); 816 PhysScene.PE.SetRestitution(PhysBody, Restitution);
828 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 817 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
829 818
830 // Mass is zero which disables a bunch of physics stuff in Bullet 819 // Mass is zero which disables a bunch of physics stuff in Bullet
831 UpdatePhysicalMassProperties(0f, false); 820 UpdatePhysicalMassProperties(0f, false);
832 // Set collision detection parameters 821 // Set collision detection parameters
833 if (BSParam.CcdMotionThreshold > 0f) 822 if (BSParam.CcdMotionThreshold > 0f)
834 { 823 {
835 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 824 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
836 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 825 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
837 } 826 }
838 827
839 // The activation state is 'disabled' so Bullet will not try to act on it. 828 // The activation state is 'disabled' so Bullet will not try to act on it.
840 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION); 829 // PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.DISABLE_SIMULATION);
841 // Start it out sleeping and physical actions could wake it up. 830 // Start it out sleeping and physical actions could wake it up.
842 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING); 831 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ISLAND_SLEEPING);
843 832
844 // This collides like a static object 833 // This collides like a static object
845 PhysBody.collisionType = CollisionType.Static; 834 PhysBody.collisionType = CollisionType.Static;
@@ -847,11 +836,11 @@ public class BSPrim : BSPhysObject
847 else 836 else
848 { 837 {
849 // Not a Bullet static object 838 // Not a Bullet static object
850 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT); 839 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_STATIC_OBJECT);
851 840
852 // Set various physical properties so other object interact properly 841 // Set various physical properties so other object interact properly
853 PhysicsScene.PE.SetFriction(PhysBody, Friction); 842 PhysScene.PE.SetFriction(PhysBody, Friction);
854 PhysicsScene.PE.SetRestitution(PhysBody, Restitution); 843 PhysScene.PE.SetRestitution(PhysBody, Restitution);
855 // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution); 844 // DetailLog("{0},BSPrim.MakeDynamic,frict={1},rest={2}", LocalID, Friction, Restitution);
856 845
857 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 846 // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382
@@ -869,22 +858,22 @@ public class BSPrim : BSPhysObject
869 // Set collision detection parameters 858 // Set collision detection parameters
870 if (BSParam.CcdMotionThreshold > 0f) 859 if (BSParam.CcdMotionThreshold > 0f)
871 { 860 {
872 PhysicsScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold); 861 PhysScene.PE.SetCcdMotionThreshold(PhysBody, BSParam.CcdMotionThreshold);
873 PhysicsScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius); 862 PhysScene.PE.SetCcdSweptSphereRadius(PhysBody, BSParam.CcdSweptSphereRadius);
874 } 863 }
875 864
876 // Various values for simulation limits 865 // Various values for simulation limits
877 PhysicsScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping); 866 PhysScene.PE.SetDamping(PhysBody, BSParam.LinearDamping, BSParam.AngularDamping);
878 PhysicsScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime); 867 PhysScene.PE.SetDeactivationTime(PhysBody, BSParam.DeactivationTime);
879 PhysicsScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold); 868 PhysScene.PE.SetSleepingThresholds(PhysBody, BSParam.LinearSleepingThreshold, BSParam.AngularSleepingThreshold);
880 PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold); 869 PhysScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
881 870
882 // This collides like an object. 871 // This collides like an object.
883 PhysBody.collisionType = CollisionType.Dynamic; 872 PhysBody.collisionType = CollisionType.Dynamic;
884 873
885 // Force activation of the object so Bullet will act on it. 874 // Force activation of the object so Bullet will act on it.
886 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. 875 // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
887 PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG); 876 PhysScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
888 } 877 }
889 } 878 }
890 879
@@ -894,7 +883,7 @@ public class BSPrim : BSPhysObject
894 // the functions after this one set up the state of a possibly newly created collision body. 883 // the functions after this one set up the state of a possibly newly created collision body.
895 private void MakeSolid(bool makeSolid) 884 private void MakeSolid(bool makeSolid)
896 { 885 {
897 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(PhysBody); 886 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysScene.PE.GetBodyType(PhysBody);
898 if (makeSolid) 887 if (makeSolid)
899 { 888 {
900 // Verify the previous code created the correct shape for this type of thing. 889 // Verify the previous code created the correct shape for this type of thing.
@@ -902,7 +891,7 @@ public class BSPrim : BSPhysObject
902 { 891 {
903 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); 892 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType);
904 } 893 }
905 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); 894 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
906 } 895 }
907 else 896 else
908 { 897 {
@@ -910,7 +899,7 @@ public class BSPrim : BSPhysObject
910 { 899 {
911 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); 900 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
912 } 901 }
913 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); 902 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE);
914 903
915 // Change collision info from a static object to a ghosty collision object 904 // Change collision info from a static object to a ghosty collision object
916 PhysBody.collisionType = CollisionType.VolumeDetect; 905 PhysBody.collisionType = CollisionType.VolumeDetect;
@@ -922,11 +911,11 @@ public class BSPrim : BSPhysObject
922 { 911 {
923 if (wantsCollisionEvents) 912 if (wantsCollisionEvents)
924 { 913 {
925 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 914 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
926 } 915 }
927 else 916 else
928 { 917 {
929 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 918 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
930 } 919 }
931 } 920 }
932 921
@@ -937,7 +926,7 @@ public class BSPrim : BSPhysObject
937 { 926 {
938 if (PhysBody.HasPhysicalBody) 927 if (PhysBody.HasPhysicalBody)
939 { 928 {
940 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, PhysBody); 929 PhysScene.PE.AddObjectToWorld(PhysScene.World, PhysBody);
941 } 930 }
942 else 931 else
943 { 932 {
@@ -972,12 +961,12 @@ public class BSPrim : BSPhysObject
972 public override bool FloatOnWater { 961 public override bool FloatOnWater {
973 set { 962 set {
974 _floatOnWater = value; 963 _floatOnWater = value;
975 PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() 964 PhysScene.TaintedObject("BSPrim.setFloatOnWater", delegate()
976 { 965 {
977 if (_floatOnWater) 966 if (_floatOnWater)
978 CurrentCollisionFlags = PhysicsScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 967 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
979 else 968 else
980 CurrentCollisionFlags = PhysicsScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 969 CurrentCollisionFlags = PhysScene.PE.RemoveFromCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
981 }); 970 });
982 } 971 }
983 } 972 }
@@ -989,7 +978,7 @@ public class BSPrim : BSPhysObject
989 _rotationalVelocity = value; 978 _rotationalVelocity = value;
990 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity); 979 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity);
991 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 980 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
992 PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 981 PhysScene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
993 { 982 {
994 ForceRotationalVelocity = _rotationalVelocity; 983 ForceRotationalVelocity = _rotationalVelocity;
995 }); 984 });
@@ -1004,7 +993,7 @@ public class BSPrim : BSPhysObject
1004 if (PhysBody.HasPhysicalBody) 993 if (PhysBody.HasPhysicalBody)
1005 { 994 {
1006 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 995 DetailLog("{0},BSPrim.ForceRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
1007 PhysicsScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity); 996 PhysScene.PE.SetAngularVelocity(PhysBody, _rotationalVelocity);
1008 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity); 997 // PhysicsScene.PE.SetInterpolationAngularVelocity(PhysBody, _rotationalVelocity);
1009 ActivateIfPhysical(false); 998 ActivateIfPhysical(false);
1010 } 999 }
@@ -1020,7 +1009,7 @@ public class BSPrim : BSPhysObject
1020 get { return _buoyancy; } 1009 get { return _buoyancy; }
1021 set { 1010 set {
1022 _buoyancy = value; 1011 _buoyancy = value;
1023 PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() 1012 PhysScene.TaintedObject("BSPrim.setBuoyancy", delegate()
1024 { 1013 {
1025 ForceBuoyancy = _buoyancy; 1014 ForceBuoyancy = _buoyancy;
1026 }); 1015 });
@@ -1043,7 +1032,7 @@ public class BSPrim : BSPhysObject
1043 base.MoveToTargetActive = value; 1032 base.MoveToTargetActive = value;
1044 EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate() 1033 EnableActor(MoveToTargetActive, MoveToTargetActorName, delegate()
1045 { 1034 {
1046 return new BSActorMoveToTarget(PhysicsScene, this, MoveToTargetActorName); 1035 return new BSActorMoveToTarget(PhysScene, this, MoveToTargetActorName);
1047 }); 1036 });
1048 } 1037 }
1049 } 1038 }
@@ -1055,7 +1044,7 @@ public class BSPrim : BSPhysObject
1055 base.HoverActive = value; 1044 base.HoverActive = value;
1056 EnableActor(HoverActive, HoverActorName, delegate() 1045 EnableActor(HoverActive, HoverActorName, delegate()
1057 { 1046 {
1058 return new BSActorHover(PhysicsScene, this, HoverActorName); 1047 return new BSActorHover(PhysScene, this, HoverActorName);
1059 }); 1048 });
1060 } 1049 }
1061 } 1050 }
@@ -1065,7 +1054,7 @@ public class BSPrim : BSPhysObject
1065 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 1054 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
1066 1055
1067 // Since this force is being applied in only one step, make this a force per second. 1056 // Since this force is being applied in only one step, make this a force per second.
1068 addForce /= PhysicsScene.LastTimeStep; 1057 addForce /= PhysScene.LastTimeStep;
1069 AddForce(addForce, pushforce, false /* inTaintTime */); 1058 AddForce(addForce, pushforce, false /* inTaintTime */);
1070 } 1059 }
1071 1060
@@ -1080,13 +1069,13 @@ public class BSPrim : BSPhysObject
1080 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); 1069 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
1081 1070
1082 OMV.Vector3 addForce = force; 1071 OMV.Vector3 addForce = force;
1083 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() 1072 PhysScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
1084 { 1073 {
1085 // Bullet adds this central force to the total force for this tick 1074 // Bullet adds this central force to the total force for this tick
1086 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce); 1075 DetailLog("{0},BSPrim.addForce,taint,force={1}", LocalID, addForce);
1087 if (PhysBody.HasPhysicalBody) 1076 if (PhysBody.HasPhysicalBody)
1088 { 1077 {
1089 PhysicsScene.PE.ApplyCentralForce(PhysBody, addForce); 1078 PhysScene.PE.ApplyCentralForce(PhysBody, addForce);
1090 ActivateIfPhysical(false); 1079 ActivateIfPhysical(false);
1091 } 1080 }
1092 }); 1081 });
@@ -1108,13 +1097,13 @@ public class BSPrim : BSPhysObject
1108 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude); 1097 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude);
1109 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse); 1098 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse);
1110 1099
1111 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate() 1100 PhysScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate()
1112 { 1101 {
1113 // Bullet adds this impulse immediately to the velocity 1102 // Bullet adds this impulse immediately to the velocity
1114 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse); 1103 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse);
1115 if (PhysBody.HasPhysicalBody) 1104 if (PhysBody.HasPhysicalBody)
1116 { 1105 {
1117 PhysicsScene.PE.ApplyCentralImpulse(PhysBody, addImpulse); 1106 PhysScene.PE.ApplyCentralImpulse(PhysBody, addImpulse);
1118 ActivateIfPhysical(false); 1107 ActivateIfPhysical(false);
1119 } 1108 }
1120 }); 1109 });
@@ -1133,12 +1122,12 @@ public class BSPrim : BSPhysObject
1133 if (force.IsFinite()) 1122 if (force.IsFinite())
1134 { 1123 {
1135 OMV.Vector3 angForce = force; 1124 OMV.Vector3 angForce = force;
1136 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() 1125 PhysScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
1137 { 1126 {
1138 if (PhysBody.HasPhysicalBody) 1127 if (PhysBody.HasPhysicalBody)
1139 { 1128 {
1140 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce); 1129 DetailLog("{0},BSPrim.AddAngularForce,taint,angForce={1}", LocalID, angForce);
1141 PhysicsScene.PE.ApplyTorque(PhysBody, angForce); 1130 PhysScene.PE.ApplyTorque(PhysBody, angForce);
1142 ActivateIfPhysical(false); 1131 ActivateIfPhysical(false);
1143 } 1132 }
1144 }); 1133 });
@@ -1157,11 +1146,11 @@ public class BSPrim : BSPhysObject
1157 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) 1146 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1158 { 1147 {
1159 OMV.Vector3 applyImpulse = impulse; 1148 OMV.Vector3 applyImpulse = impulse;
1160 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() 1149 PhysScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
1161 { 1150 {
1162 if (PhysBody.HasPhysicalBody) 1151 if (PhysBody.HasPhysicalBody)
1163 { 1152 {
1164 PhysicsScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse); 1153 PhysScene.PE.ApplyTorqueImpulse(PhysBody, applyImpulse);
1165 ActivateIfPhysical(false); 1154 ActivateIfPhysical(false);
1166 } 1155 }
1167 }); 1156 });
@@ -1463,12 +1452,13 @@ public class BSPrim : BSPhysObject
1463 // Create the correct physical representation for this type of object. 1452 // Create the correct physical representation for this type of object.
1464 // Updates base.PhysBody and base.PhysShape with the new information. 1453 // Updates base.PhysBody and base.PhysShape with the new information.
1465 // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary. 1454 // Ignore 'forceRebuild'. 'GetBodyAndShape' makes the right choices and changes of necessary.
1466 PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody) 1455 PhysScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysScene.World, this, delegate(BulletBody pBody, BulletShape pShape)
1467 { 1456 {
1468 // Called if the current prim body is about to be destroyed. 1457 // Called if the current prim body is about to be destroyed.
1469 // Remove all the physical dependencies on the old body. 1458 // Remove all the physical dependencies on the old body.
1470 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) 1459 // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
1471 RemoveBodyDependencies(); 1460 // Note: this virtual function is overloaded by BSPrimLinkable to remove linkset constraints.
1461 RemoveDependencies();
1472 }); 1462 });
1473 1463
1474 // Make sure the properties are set on the new object 1464 // Make sure the properties are set on the new object
@@ -1477,9 +1467,9 @@ public class BSPrim : BSPhysObject
1477 } 1467 }
1478 1468
1479 // Called at taint-time 1469 // Called at taint-time
1480 protected virtual void RemoveBodyDependencies() 1470 protected virtual void RemoveDependencies()
1481 { 1471 {
1482 PhysicalActors.RemoveBodyDependencies(); 1472 PhysicalActors.RemoveDependencies();
1483 } 1473 }
1484 1474
1485 // The physics engine says that properties have updated. Update same and inform 1475 // The physics engine says that properties have updated. Update same and inform
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
index f1c3b5c..f5ee671 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
@@ -78,14 +78,16 @@ public class BSPrimDisplaced : BSPrim
78 // Set this sets and computes the displacement from the passed prim to the center-of-mass. 78 // Set this sets and computes the displacement from the passed prim to the center-of-mass.
79 // A user set value for center-of-mass overrides whatever might be passed in here. 79 // A user set value for center-of-mass overrides whatever might be passed in here.
80 // The displacement is in local coordinates (relative to root prim in linkset oriented coordinates). 80 // The displacement is in local coordinates (relative to root prim in linkset oriented coordinates).
81 public virtual void SetEffectiveCenterOfMassW(Vector3 centerOfMassDisplacement) 81 public virtual void SetEffectiveCenterOfMassDisplacement(Vector3 centerOfMassDisplacement)
82 { 82 {
83 Vector3 comDisp; 83 Vector3 comDisp;
84 if (UserSetCenterOfMass.HasValue) 84 if (UserSetCenterOfMassDisplacement.HasValue)
85 comDisp = (OMV.Vector3)UserSetCenterOfMass; 85 comDisp = (OMV.Vector3)UserSetCenterOfMassDisplacement;
86 else 86 else
87 comDisp = centerOfMassDisplacement; 87 comDisp = centerOfMassDisplacement;
88 88
89 DetailLog("{0},BSPrimDisplaced.SetEffectiveCenterOfMassDisplacement,userSet={1},comDisp={2}",
90 LocalID, UserSetCenterOfMassDisplacement.HasValue, comDisp);
89 if (comDisp == Vector3.Zero) 91 if (comDisp == Vector3.Zero)
90 { 92 {
91 // If there is no diplacement. Things get reset. 93 // If there is no diplacement. Things get reset.
@@ -107,9 +109,15 @@ public class BSPrimDisplaced : BSPrim
107 set 109 set
108 { 110 {
109 if (PositionDisplacement != OMV.Vector3.Zero) 111 if (PositionDisplacement != OMV.Vector3.Zero)
110 base.ForcePosition = value - (PositionDisplacement * RawOrientation); 112 {
113 OMV.Vector3 displacedPos = value - (PositionDisplacement * RawOrientation);
114 DetailLog("{0},BSPrimDisplaced.ForcePosition,val={1},disp={2},newPos={3}", LocalID, value, PositionDisplacement, displacedPos);
115 base.ForcePosition = displacedPos;
116 }
111 else 117 else
118 {
112 base.ForcePosition = value; 119 base.ForcePosition = value;
120 }
113 } 121 }
114 } 122 }
115 123
@@ -118,6 +126,7 @@ public class BSPrimDisplaced : BSPrim
118 get { return base.ForceOrientation; } 126 get { return base.ForceOrientation; }
119 set 127 set
120 { 128 {
129 // TODO:
121 base.ForceOrientation = value; 130 base.ForceOrientation = value;
122 } 131 }
123 } 132 }
@@ -143,7 +152,10 @@ public class BSPrimDisplaced : BSPrim
143 { 152 {
144 // Correct for any rotation around the center-of-mass 153 // Correct for any rotation around the center-of-mass
145 // TODO!!! 154 // TODO!!!
146 entprop.Position = entprop.Position + (PositionDisplacement * entprop.Rotation); 155
156 OMV.Vector3 displacedPos = entprop.Position + (PositionDisplacement * entprop.Rotation);
157 DetailLog("{0},BSPrimDisplaced.ForcePosition,physPos={1},disp={2},newPos={3}", LocalID, entprop.Position, PositionDisplacement, displacedPos);
158 entprop.Position = displacedPos;
147 // entprop.Rotation = something; 159 // entprop.Rotation = something;
148 } 160 }
149 161
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
index 28242d4..235da78 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
@@ -47,9 +47,9 @@ public class BSPrimLinkable : BSPrimDisplaced
47 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 47 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
48 : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical) 48 : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical)
49 { 49 {
50 Linkset = BSLinkset.Factory(PhysicsScene, this); 50 Linkset = BSLinkset.Factory(PhysScene, this);
51 51
52 PhysicsScene.TaintedObject("BSPrimLinksetCompound.Refresh", delegate() 52 PhysScene.TaintedObject("BSPrimLinksetCompound.Refresh", delegate()
53 { 53 {
54 Linkset.Refresh(this); 54 Linkset.Refresh(this);
55 }); 55 });
@@ -61,9 +61,6 @@ public class BSPrimLinkable : BSPrimDisplaced
61 base.Destroy(); 61 base.Destroy();
62 } 62 }
63 63
64 public override BSPhysicsShapeType PreferredPhysicalShape
65 { get { return Linkset.PreferredPhysicalShape(this); } }
66
67 public override void link(Manager.PhysicsActor obj) 64 public override void link(Manager.PhysicsActor obj)
68 { 65 {
69 BSPrimLinkable parent = obj as BSPrimLinkable; 66 BSPrimLinkable parent = obj as BSPrimLinkable;
@@ -102,7 +99,7 @@ public class BSPrimLinkable : BSPrimDisplaced
102 set 99 set
103 { 100 {
104 base.Position = value; 101 base.Position = value;
105 PhysicsScene.TaintedObject("BSPrimLinkset.setPosition", delegate() 102 PhysScene.TaintedObject("BSPrimLinkset.setPosition", delegate()
106 { 103 {
107 Linkset.UpdateProperties(UpdatedProperties.Position, this); 104 Linkset.UpdateProperties(UpdatedProperties.Position, this);
108 }); 105 });
@@ -116,7 +113,7 @@ public class BSPrimLinkable : BSPrimDisplaced
116 set 113 set
117 { 114 {
118 base.Orientation = value; 115 base.Orientation = value;
119 PhysicsScene.TaintedObject("BSPrimLinkset.setOrientation", delegate() 116 PhysScene.TaintedObject("BSPrimLinkset.setOrientation", delegate()
120 { 117 {
121 Linkset.UpdateProperties(UpdatedProperties.Orientation, this); 118 Linkset.UpdateProperties(UpdatedProperties.Orientation, this);
122 }); 119 });
@@ -149,10 +146,10 @@ public class BSPrimLinkable : BSPrimDisplaced
149 } 146 }
150 147
151 // Body is being taken apart. Remove physical dependencies and schedule a rebuild. 148 // Body is being taken apart. Remove physical dependencies and schedule a rebuild.
152 protected override void RemoveBodyDependencies() 149 protected override void RemoveDependencies()
153 { 150 {
154 Linkset.RemoveBodyDependencies(this); 151 Linkset.RemoveDependencies(this);
155 base.RemoveBodyDependencies(); 152 base.RemoveDependencies();
156 } 153 }
157 154
158 public override void UpdateProperties(EntityProperties entprop) 155 public override void UpdateProperties(EntityProperties entprop)
@@ -185,6 +182,10 @@ public class BSPrimLinkable : BSPrimDisplaced
185 { 182 {
186 return false; 183 return false;
187 } 184 }
185
186 // TODO: handle collisions of other objects with with children of linkset.
187 // This is a problem for LinksetCompound since the children are packed into the root.
188
188 return base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth); 189 return base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth);
189 } 190 }
190} 191}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 8e05b58..a4a8794 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -316,7 +316,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
316 break; 316 break;
317 case "bulletxna": 317 case "bulletxna":
318 ret = new BSAPIXNA(engineName, this); 318 ret = new BSAPIXNA(engineName, this);
319 // Disable some features that are not implemented in BulletXNA
320 m_log.InfoFormat("{0} Disabling some physics features not implemented by BulletXNA", LogHeader);
319 BSParam.ShouldUseBulletHACD = false; 321 BSParam.ShouldUseBulletHACD = false;
322 BSParam.ShouldUseSingleConvexHullForPrims = false;
320 break; 323 break;
321 } 324 }
322 325
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 57e74a3..64aaa15 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -38,38 +38,15 @@ public sealed class BSShapeCollection : IDisposable
38{ 38{
39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; 39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
40 40
41 private BSScene PhysicsScene { get; set; } 41 private BSScene m_physicsScene { get; set; }
42 42
43 private Object m_collectionActivityLock = new Object(); 43 private Object m_collectionActivityLock = new Object();
44 44
45 // Description of a Mesh
46 private struct MeshDesc
47 {
48 public BulletShape shape;
49 public int referenceCount;
50 public DateTime lastReferenced;
51 public UInt64 shapeKey;
52 }
53
54 // Description of a hull.
55 // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations.
56 private struct HullDesc
57 {
58 public BulletShape shape;
59 public int referenceCount;
60 public DateTime lastReferenced;
61 public UInt64 shapeKey;
62 }
63
64 // The sharable set of meshes and hulls. Indexed by their shape hash.
65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
67
68 private bool DDetail = false; 45 private bool DDetail = false;
69 46
70 public BSShapeCollection(BSScene physScene) 47 public BSShapeCollection(BSScene physScene)
71 { 48 {
72 PhysicsScene = physScene; 49 m_physicsScene = physScene;
73 // Set the next to 'true' for very detailed shape update detailed logging (detailed details?) 50 // Set the next to 'true' for very detailed shape update detailed logging (detailed details?)
74 // While detailed debugging is still active, this is better than commenting out all the 51 // While detailed debugging is still active, this is better than commenting out all the
75 // DetailLog statements. When debugging slows down, this and the protected logging 52 // DetailLog statements. When debugging slows down, this and the protected logging
@@ -86,22 +63,18 @@ public sealed class BSShapeCollection : IDisposable
86 // Mostly used for changing bodies out from under Linksets. 63 // Mostly used for changing bodies out from under Linksets.
87 // Useful for other cases where parameters need saving. 64 // Useful for other cases where parameters need saving.
88 // Passing 'null' says no callback. 65 // Passing 'null' says no callback.
89 public delegate void ShapeDestructionCallback(BulletShape shape); 66 public delegate void PhysicalDestructionCallback(BulletBody pBody, BulletShape pShape);
90 public delegate void BodyDestructionCallback(BulletBody body);
91 67
92 // Called to update/change the body and shape for an object. 68 // Called to update/change the body and shape for an object.
93 // First checks the shape and updates that if necessary then makes 69 // The object has some shape and body on it. Here we decide if that is the correct shape
94 // sure the body is of the right type. 70 // for the current state of the object (static/dynamic/...).
71 // If bodyCallback is not null, it is called if either the body or the shape are changed
72 // so dependencies (like constraints) can be removed before the physical object is dereferenced.
95 // Return 'true' if either the body or the shape changed. 73 // Return 'true' if either the body or the shape changed.
96 // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before 74 // Called at taint-time.
97 // the current shape or body is destroyed. This allows the caller to remove any 75 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim, PhysicalDestructionCallback bodyCallback)
98 // higher level dependencies on the shape or body. Mostly used for LinkSets to
99 // remove the physical constraints before the body is destroyed.
100 // Called at taint-time!!
101 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim,
102 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
103 { 76 {
104 PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); 77 m_physicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
105 78
106 bool ret = false; 79 bool ret = false;
107 80
@@ -111,12 +84,12 @@ public sealed class BSShapeCollection : IDisposable
111 // Do we have the correct geometry for this type of object? 84 // Do we have the correct geometry for this type of object?
112 // Updates prim.BSShape with information/pointers to shape. 85 // Updates prim.BSShape with information/pointers to shape.
113 // Returns 'true' of BSShape is changed to a new shape. 86 // Returns 'true' of BSShape is changed to a new shape.
114 bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); 87 bool newGeom = CreateGeom(forceRebuild, prim, bodyCallback);
115 // If we had to select a new shape geometry for the object, 88 // If we had to select a new shape geometry for the object,
116 // rebuild the body around it. 89 // rebuild the body around it.
117 // Updates prim.BSBody with information/pointers to requested body 90 // Updates prim.BSBody with information/pointers to requested body
118 // Returns 'true' if BSBody was changed. 91 // Returns 'true' if BSBody was changed.
119 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, bodyCallback); 92 bool newBody = CreateBody((newGeom || forceRebuild), prim, m_physicsScene.World, bodyCallback);
120 ret = newGeom || newBody; 93 ret = newGeom || newBody;
121 } 94 }
122 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", 95 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
@@ -127,271 +100,20 @@ public sealed class BSShapeCollection : IDisposable
127 100
128 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim) 101 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
129 { 102 {
130 return GetBodyAndShape(forceRebuild, sim, prim, null, null); 103 return GetBodyAndShape(forceRebuild, sim, prim, null);
131 }
132
133 // Track another user of a body.
134 // We presume the caller has allocated the body.
135 // Bodies only have one user so the body is just put into the world if not already there.
136 private void ReferenceBody(BulletBody body)
137 {
138 lock (m_collectionActivityLock)
139 {
140 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
141 if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
142 {
143 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body);
144 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
145 }
146 }
147 }
148
149 // Release the usage of a body.
150 // Called when releasing use of a BSBody. BSShape is handled separately.
151 // Called in taint time.
152 public void DereferenceBody(BulletBody body, BodyDestructionCallback bodyCallback )
153 {
154 if (!body.HasPhysicalBody)
155 return;
156
157 PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
158
159 lock (m_collectionActivityLock)
160 {
161 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
162 // If the caller needs to know the old body is going away, pass the event up.
163 if (bodyCallback != null) bodyCallback(body);
164
165 // Removing an object not in the world is a NOOP
166 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
167
168 // Zero any reference to the shape so it is not freed when the body is deleted.
169 PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null);
170 PhysicsScene.PE.DestroyObject(PhysicsScene.World, body);
171 }
172 }
173
174 // Track the datastructures and use count for a shape.
175 // When creating a hull, this is called first to reference the mesh
176 // and then again to reference the hull.
177 // Meshes and hulls for the same shape have the same hash key.
178 // NOTE that native shapes are not added to the mesh list or removed.
179 // Returns 'true' if this is the initial reference to the shape. Otherwise reused.
180 public bool ReferenceShape(BulletShape shape)
181 {
182 bool ret = false;
183 switch (shape.type)
184 {
185 case BSPhysicsShapeType.SHAPE_MESH:
186 MeshDesc meshDesc;
187 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
188 {
189 // There is an existing instance of this mesh.
190 meshDesc.referenceCount++;
191 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
192 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
193 }
194 else
195 {
196 // This is a new reference to a mesh
197 meshDesc.shape = shape.Clone();
198 meshDesc.shapeKey = shape.shapeKey;
199 // We keep a reference to the underlying IMesh data so a hull can be built
200 meshDesc.referenceCount = 1;
201 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
202 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
203 ret = true;
204 }
205 meshDesc.lastReferenced = System.DateTime.Now;
206 Meshes[shape.shapeKey] = meshDesc;
207 break;
208 case BSPhysicsShapeType.SHAPE_HULL:
209 HullDesc hullDesc;
210 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
211 {
212 // There is an existing instance of this hull.
213 hullDesc.referenceCount++;
214 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
215 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
216 }
217 else
218 {
219 // This is a new reference to a hull
220 hullDesc.shape = shape.Clone();
221 hullDesc.shapeKey = shape.shapeKey;
222 hullDesc.referenceCount = 1;
223 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
224 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
225 ret = true;
226
227 }
228 hullDesc.lastReferenced = System.DateTime.Now;
229 Hulls[shape.shapeKey] = hullDesc;
230 break;
231 case BSPhysicsShapeType.SHAPE_UNKNOWN:
232 break;
233 default:
234 // Native shapes are not tracked and they don't go into any list
235 break;
236 }
237 return ret;
238 }
239
240 // Release the usage of a shape.
241 public void DereferenceShape(BulletShape shape, ShapeDestructionCallback shapeCallback)
242 {
243 if (!shape.HasPhysicalShape)
244 return;
245
246 PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceShape");
247
248 if (shape.HasPhysicalShape)
249 {
250 if (shape.isNativeShape)
251 {
252 // Native shapes are not tracked and are released immediately
253 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1}",
254 BSScene.DetailLogZero, shape.AddrString);
255 if (shapeCallback != null) shapeCallback(shape);
256 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
257 }
258 else
259 {
260 switch (shape.type)
261 {
262 case BSPhysicsShapeType.SHAPE_HULL:
263 DereferenceHull(shape, shapeCallback);
264 break;
265 case BSPhysicsShapeType.SHAPE_MESH:
266 DereferenceMesh(shape, shapeCallback);
267 break;
268 case BSPhysicsShapeType.SHAPE_COMPOUND:
269 DereferenceCompound(shape, shapeCallback);
270 break;
271 case BSPhysicsShapeType.SHAPE_UNKNOWN:
272 break;
273 default:
274 break;
275 }
276 }
277 }
278 }
279
280 // Count down the reference count for a mesh shape
281 // Called at taint-time.
282 private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback)
283 {
284 MeshDesc meshDesc;
285 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
286 {
287 meshDesc.referenceCount--;
288 // TODO: release the Bullet storage
289 if (shapeCallback != null) shapeCallback(shape);
290 meshDesc.lastReferenced = System.DateTime.Now;
291 Meshes[shape.shapeKey] = meshDesc;
292 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
293 BSScene.DetailLogZero, shape, meshDesc.referenceCount);
294
295 }
296 }
297
298 // Count down the reference count for a hull shape
299 // Called at taint-time.
300 private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback)
301 {
302 HullDesc hullDesc;
303 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
304 {
305 hullDesc.referenceCount--;
306 // TODO: release the Bullet storage (aging old entries?)
307
308 // Tell upper layers that, if they have dependencies on this shape, this link is going away
309 if (shapeCallback != null) shapeCallback(shape);
310
311 hullDesc.lastReferenced = System.DateTime.Now;
312 Hulls[shape.shapeKey] = hullDesc;
313 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
314 BSScene.DetailLogZero, shape, hullDesc.referenceCount);
315 }
316 }
317
318 // Remove a reference to a compound shape.
319 // Taking a compound shape apart is a little tricky because if you just delete the
320 // physical shape, it will free all the underlying children. We can't do that because
321 // they could be shared. So, this removes each of the children from the compound and
322 // dereferences them separately before destroying the compound collision object itself.
323 // Called at taint-time.
324 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback)
325 {
326 if (!PhysicsScene.PE.IsCompound(shape))
327 {
328 // Failed the sanity check!!
329 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
330 LogHeader, shape.type, shape.AddrString);
331 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
332 BSScene.DetailLogZero, shape.type, shape.AddrString);
333 return;
334 }
335
336 int numChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(shape);
337 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
338
339 for (int ii = numChildren - 1; ii >= 0; ii--)
340 {
341 BulletShape childShape = PhysicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(shape, ii);
342 DereferenceAnonCollisionShape(childShape);
343 }
344 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
345 } 104 }
346 105
347 // Sometimes we have a pointer to a collision shape but don't know what type it is. 106 // If the existing prim's shape is to be replaced, remove the tie to the existing shape
348 // Figure out type and call the correct dereference routine. 107 // before replacing it.
349 // Called at taint-time. 108 private void DereferenceExistingShape(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
350 private void DereferenceAnonCollisionShape(BulletShape shapeInfo)
351 { 109 {
352 MeshDesc meshDesc; 110 if (prim.PhysShape.HasPhysicalShape)
353 HullDesc hullDesc;
354
355 if (TryGetMeshByPtr(shapeInfo, out meshDesc))
356 {
357 shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH;
358 shapeInfo.shapeKey = meshDesc.shapeKey;
359 }
360 else
361 {
362 if (TryGetHullByPtr(shapeInfo, out hullDesc))
363 {
364 shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL;
365 shapeInfo.shapeKey = hullDesc.shapeKey;
366 }
367 else
368 {
369 if (PhysicsScene.PE.IsCompound(shapeInfo))
370 {
371 shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND;
372 }
373 else
374 {
375 if (PhysicsScene.PE.IsNativeShape(shapeInfo))
376 {
377 shapeInfo.isNativeShape = true;
378 shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
379 }
380 }
381 }
382 }
383
384 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
385
386 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
387 {
388 DereferenceShape(shapeInfo, null);
389 }
390 else
391 { 111 {
392 PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", 112 if (shapeCallback != null)
393 LogHeader, PhysicsScene.RegionName, shapeInfo.AddrString); 113 shapeCallback(prim.PhysBody, prim.PhysShape.physShapeInfo);
114 prim.PhysShape.Dereference(m_physicsScene);
394 } 115 }
116 prim.PhysShape = new BSShapeNull();
395 } 117 }
396 118
397 // Create the geometry information in Bullet for later use. 119 // Create the geometry information in Bullet for later use.
@@ -402,60 +124,41 @@ public sealed class BSShapeCollection : IDisposable
402 // Info in prim.BSShape is updated to the new shape. 124 // Info in prim.BSShape is updated to the new shape.
403 // Returns 'true' if the geometry was rebuilt. 125 // Returns 'true' if the geometry was rebuilt.
404 // Called at taint-time! 126 // Called at taint-time!
405 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) 127 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
406 { 128 {
407 bool ret = false; 129 bool ret = false;
408 bool haveShape = false; 130 bool haveShape = false;
131 bool nativeShapePossible = true;
132 PrimitiveBaseShape pbs = prim.BaseShape;
409 133
410 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) 134 // Kludge to create the capsule for the avatar.
135 // TDOD: Remove/redo this when BSShapeAvatar is working!!
136 BSCharacter theChar = prim as BSCharacter;
137 if (theChar != null)
411 { 138 {
412 // an avatar capsule is close to a native shape (it is not shared) 139 DereferenceExistingShape(prim, shapeCallback);
413 GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback); 140 prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
414 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); 141 BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE);
415 ret = true; 142 ret = true;
416 haveShape = true; 143 haveShape = true;
417 } 144 }
418 145
419 // Compound shapes are handled special as they are rebuilt from scratch.
420 // This isn't too great a hardship since most of the child shapes will have already been created.
421 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
422 {
423 ret = GetReferenceToCompoundShape(prim, shapeCallback);
424 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
425 haveShape = true;
426 }
427
428 if (!haveShape)
429 {
430 ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback);
431 }
432
433 return ret;
434 }
435
436 // Create a mesh, hull or native shape.
437 // Return 'true' if the prim's shape was changed.
438 public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
439 {
440 bool ret = false;
441 bool haveShape = false;
442 bool nativeShapePossible = true;
443 PrimitiveBaseShape pbs = prim.BaseShape;
444
445 // If the prim attributes are simple, this could be a simple Bullet native shape 146 // If the prim attributes are simple, this could be a simple Bullet native shape
147 // Native shapes work whether to object is static or physical.
446 if (!haveShape 148 if (!haveShape
447 && nativeShapePossible 149 && nativeShapePossible
448 && pbs != null 150 && pbs != null
449 && !pbs.SculptEntry 151 && PrimHasNoCuts(pbs)
450 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) ) 152 && ( !pbs.SculptEntry || (pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) )
153 )
451 { 154 {
452 // Get the scale of any existing shape so we can see if the new shape is same native type and same size. 155 // Get the scale of any existing shape so we can see if the new shape is same native type and same size.
453 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; 156 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
454 if (prim.PhysShape.HasPhysicalShape) 157 if (prim.PhysShape.HasPhysicalShape)
455 scaleOfExistingShape = PhysicsScene.PE.GetLocalScaling(prim.PhysShape); 158 scaleOfExistingShape = m_physicsScene.PE.GetLocalScaling(prim.PhysShape.physShapeInfo);
456 159
457 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", 160 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
458 prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type); 161 prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.physShapeInfo.shapeType);
459 162
460 // It doesn't look like Bullet scales native spheres so make sure the scales are all equal 163 // It doesn't look like Bullet scales native spheres so make sure the scales are all equal
461 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) 164 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
@@ -463,26 +166,30 @@ public sealed class BSShapeCollection : IDisposable
463 { 166 {
464 haveShape = true; 167 haveShape = true;
465 if (forceRebuild 168 if (forceRebuild
466 || prim.Scale != scaleOfExistingShape 169 || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_SPHERE
467 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE 170 )
468 )
469 { 171 {
470 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, 172 DereferenceExistingShape(prim, shapeCallback);
471 FixedShapeKey.KEY_SPHERE, shapeCallback); 173 prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
174 BSPhysicsShapeType.SHAPE_SPHERE, FixedShapeKey.KEY_SPHERE);
175 ret = true;
472 } 176 }
473 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}", 177 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}",
474 prim.LocalID, forceRebuild, ret, prim.PhysShape); 178 prim.LocalID, forceRebuild, ret, prim.PhysShape);
475 } 179 }
180 // If we didn't make a sphere, maybe a box will work.
476 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 181 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
477 { 182 {
478 haveShape = true; 183 haveShape = true;
479 if (forceRebuild 184 if (forceRebuild
480 || prim.Scale != scaleOfExistingShape 185 || prim.Scale != scaleOfExistingShape
481 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX 186 || prim.PhysShape.ShapeType != BSPhysicsShapeType.SHAPE_BOX
482 ) 187 )
483 { 188 {
484 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, 189 DereferenceExistingShape(prim, shapeCallback);
485 FixedShapeKey.KEY_BOX, shapeCallback); 190 prim.PhysShape = BSShapeNative.GetReference(m_physicsScene, prim,
191 BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
192 ret = true;
486 } 193 }
487 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}", 194 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}",
488 prim.LocalID, forceRebuild, ret, prim.PhysShape); 195 prim.LocalID, forceRebuild, ret, prim.PhysShape);
@@ -499,7 +206,7 @@ public sealed class BSShapeCollection : IDisposable
499 } 206 }
500 207
501 // return 'true' if this shape description does not include any cutting or twisting. 208 // return 'true' if this shape description does not include any cutting or twisting.
502 private bool PrimHasNoCuts(PrimitiveBaseShape pbs) 209 public static bool PrimHasNoCuts(PrimitiveBaseShape pbs)
503 { 210 {
504 return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 211 return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
505 && pbs.ProfileHollow == 0 212 && pbs.ProfileHollow == 0
@@ -511,7 +218,7 @@ public sealed class BSShapeCollection : IDisposable
511 } 218 }
512 219
513 // return 'true' if the prim's shape was changed. 220 // return 'true' if the prim's shape was changed.
514 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 221 private bool CreateGeomMeshOrHull(BSPhysObject prim, PhysicalDestructionCallback shapeCallback)
515 { 222 {
516 223
517 bool ret = false; 224 bool ret = false;
@@ -519,540 +226,110 @@ public sealed class BSShapeCollection : IDisposable
519 // made. Native shapes work in either case. 226 // made. Native shapes work in either case.
520 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) 227 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
521 { 228 {
522 // Update prim.BSShape to reference a hull of this shape. 229 // Use a simple, single mesh convex hull shape if the object is simple enough
523 ret = GetReferenceToHull(prim, shapeCallback); 230 BSShape potentialHull = null;
524 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
525 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
526 }
527 else
528 {
529 ret = GetReferenceToMesh(prim, shapeCallback);
530 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
531 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
532 }
533 return ret;
534 }
535
536 // Creates a native shape and assignes it to prim.BSShape.
537 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape().
538 private bool GetReferenceToNativeShape(BSPhysObject prim,
539 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey,
540 ShapeDestructionCallback shapeCallback)
541 {
542 // release any previous shape
543 DereferenceShape(prim.PhysShape, shapeCallback);
544
545 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
546
547 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
548 if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
549 prim.LocalID, newShape, prim.Scale);
550
551 // native shapes are scaled by Bullet
552 prim.PhysShape = newShape;
553 return true;
554 }
555
556 private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType,
557 FixedShapeKey shapeKey)
558 {
559 BulletShape newShape;
560 // Need to make sure the passed shape information is for the native type.
561 ShapeData nativeShapeData = new ShapeData();
562 nativeShapeData.Type = shapeType;
563 nativeShapeData.ID = prim.LocalID;
564 nativeShapeData.Scale = prim.Scale;
565 nativeShapeData.Size = prim.Scale; // unneeded, I think.
566 nativeShapeData.MeshKey = (ulong)shapeKey;
567 nativeShapeData.HullKey = (ulong)shapeKey;
568
569 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
570 {
571 231
572 newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale); 232 PrimitiveBaseShape pbs = prim.BaseShape;
573 if (DDetail) DetailLog("{0},BSShapeCollection.BuildPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 233 if (BSParam.ShouldUseSingleConvexHullForPrims
574 } 234 && pbs != null
575 else 235 && !pbs.SculptEntry
576 { 236 && PrimHasNoCuts(pbs)
577 // Native shapes are scaled in Bullet so set the scaling to the size 237 )
578 newShape = PhysicsScene.PE.BuildNativeShape(PhysicsScene.World, nativeShapeData);
579
580 }
581 if (!newShape.HasPhysicalShape)
582 {
583 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
584 LogHeader, prim.LocalID, shapeType);
585 }
586 newShape.shapeKey = (System.UInt64)shapeKey;
587 newShape.isNativeShape = true;
588
589 return newShape;
590 }
591
592 // Builds a mesh shape in the physical world and updates prim.BSShape.
593 // Dereferences previous shape in BSShape and adds a reference for this new shape.
594 // Returns 'true' of a mesh was actually built. Otherwise .
595 // Called at taint-time!
596 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
597 {
598 BulletShape newShape = new BulletShape();
599
600 float lod;
601 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
602
603 // if this new shape is the same as last time, don't recreate the mesh
604 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
605 return false;
606
607 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2},size={3},lod={4}",
608 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
609
610 // Since we're recreating new, get rid of the reference to the previous shape
611 DereferenceShape(prim.PhysShape, shapeCallback);
612
613 newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod);
614 // Take evasive action if the mesh was not constructed.
615 newShape = VerifyMeshCreated(PhysicsScene, newShape, prim);
616
617 ReferenceShape(newShape);
618
619 prim.PhysShape = newShape;
620
621 return true; // 'true' means a new shape has been added to this prim
622 }
623
624 private BulletShape CreatePhysicalMesh(BSPhysObject prim, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
625 {
626 BulletShape newShape = new BulletShape();
627
628 MeshDesc meshDesc;
629 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
630 {
631 // If the mesh has already been built just use it.
632 newShape = meshDesc.shape.Clone();
633 }
634 else
635 {
636 IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
637 true,
638 false, // say it is not physical so a bounding box is not built
639 false, // do not cache the mesh and do not use previously built versions
640 false // It's NOT for ODE
641 );
642
643 if (meshData != null)
644 { 238 {
645 239 potentialHull = BSShapeConvexHull.GetReference(m_physicsScene, false /* forceRebuild */, prim);
646 int[] indices = meshData.getIndexListAsInt(); 240 }
647 int realIndicesIndex = indices.Length; 241 else
648 float[] verticesAsFloats = meshData.getVertexListAsFloat(); 242 {
649 243 potentialHull = BSShapeHull.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
650 if (BSParam.ShouldRemoveZeroWidthTriangles)
651 {
652 // Remove degenerate triangles. These are triangles with two of the vertices
653 // are the same. This is complicated by the problem that vertices are not
654 // made unique in sculpties so we have to compare the values in the vertex.
655 realIndicesIndex = 0;
656 for (int tri = 0; tri < indices.Length; tri += 3)
657 {
658 // Compute displacements into vertex array for each vertex of the triangle
659 int v1 = indices[tri + 0] * 3;
660 int v2 = indices[tri + 1] * 3;
661 int v3 = indices[tri + 2] * 3;
662 // Check to see if any two of the vertices are the same
663 if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0]
664 && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1]
665 && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2])
666 || ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0]
667 && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1]
668 && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2])
669 || ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0]
670 && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1]
671 && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) )
672 )
673 {
674 // None of the vertices of the triangles are the same. This is a good triangle;
675 indices[realIndicesIndex + 0] = indices[tri + 0];
676 indices[realIndicesIndex + 1] = indices[tri + 1];
677 indices[realIndicesIndex + 2] = indices[tri + 2];
678 realIndicesIndex += 3;
679 }
680 }
681 }
682 DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}",
683 BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
684
685 if (realIndicesIndex != 0)
686 {
687 newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World,
688 realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats);
689 }
690 else
691 {
692 PhysicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}",
693 LogHeader, prim.PhysObjectName, prim.RawPosition, PhysicsScene.Name);
694 }
695 } 244 }
696 }
697 newShape.shapeKey = newMeshKey;
698
699 return newShape;
700 }
701
702 // See that hull shape exists in the physical world and update prim.BSShape.
703 // We could be creating the hull because scale changed or whatever.
704 // Return 'true' if a new hull was built. Otherwise, returning a shared hull instance.
705 private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
706 {
707 BulletShape newShape;
708
709 float lod;
710 System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
711
712 // if the hull hasn't changed, don't rebuild it
713 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
714 return false;
715
716 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
717 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
718
719 // Remove usage of the previous shape.
720 DereferenceShape(prim.PhysShape, shapeCallback);
721
722 newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod);
723 // It might not have been created if we're waiting for an asset.
724 newShape = VerifyMeshCreated(PhysicsScene, newShape, prim);
725
726 ReferenceShape(newShape);
727
728 prim.PhysShape = newShape;
729 return true; // 'true' means a new shape has been added to this prim
730 }
731
732 List<ConvexResult> m_hulls;
733 private BulletShape CreatePhysicalHull(BSPhysObject prim, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
734 {
735
736 BulletShape newShape = new BulletShape();
737 IntPtr hullPtr = IntPtr.Zero;
738 245
739 HullDesc hullDesc; 246 // If the current shape is not what is on the prim at the moment, time to change.
740 if (Hulls.TryGetValue(newHullKey, out hullDesc)) 247 if (!prim.PhysShape.HasPhysicalShape
741 { 248 || potentialHull.ShapeType != prim.PhysShape.ShapeType
742 // If the hull shape already has been created, just use the one shared instance. 249 || potentialHull.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
743 newShape = hullDesc.shape.Clone(); 250 {
251 DereferenceExistingShape(prim, shapeCallback);
252 prim.PhysShape = potentialHull;
253 ret = true;
254 }
255 else
256 {
257 // The current shape on the prim is the correct one. We don't need the potential reference.
258 potentialHull.Dereference(m_physicsScene);
259 }
260 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1}", prim.LocalID, prim.PhysShape);
744 } 261 }
745 else 262 else
746 { 263 {
747 if (BSParam.ShouldUseBulletHACD) 264 // Update prim.BSShape to reference a mesh of this shape.
265 BSShape potentialMesh = BSShapeMesh.GetReference(m_physicsScene, false /*forceRebuild*/, prim);
266 // If the current shape is not what is on the prim at the moment, time to change.
267 if (!prim.PhysShape.HasPhysicalShape
268 || potentialMesh.ShapeType != prim.PhysShape.ShapeType
269 || potentialMesh.physShapeInfo.shapeKey != prim.PhysShape.physShapeInfo.shapeKey)
748 { 270 {
749 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID); 271 DereferenceExistingShape(prim, shapeCallback);
750 MeshDesc meshDesc; 272 prim.PhysShape = potentialMesh;
751 if (!Meshes.TryGetValue(newHullKey, out meshDesc)) 273 ret = true;
752 {
753 // That's odd because the mesh should have been created before the hull
754 // but, since it doesn't exist, create it.
755 newShape = CreatePhysicalMesh(prim, newHullKey, prim.BaseShape, prim.Size, lod);
756 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,noMeshBuiltNew,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
757
758 if (newShape.HasPhysicalShape)
759 {
760 ReferenceShape(newShape);
761 Meshes.TryGetValue(newHullKey, out meshDesc);
762 }
763 }
764 if (meshDesc.shape.HasPhysicalShape)
765 {
766 HACDParams parms;
767 parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
768 parms.minClusters = BSParam.BHullMinClusters;
769 parms.compacityWeight = BSParam.BHullCompacityWeight;
770 parms.volumeWeight = BSParam.BHullVolumeWeight;
771 parms.concavity = BSParam.BHullConcavity;
772 parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
773 parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
774 parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
775 parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
776
777 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
778 newShape = PhysicsScene.PE.BuildHullShapeFromMesh(PhysicsScene.World, meshDesc.shape, parms);
779 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
780 }
781 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
782 } 274 }
783 if (!newShape.HasPhysicalShape) 275 else
784 { 276 {
785 // Build a new hull in the physical world. 277 // We don't need this reference to the mesh that is already being using.
786 // Pass true for physicalness as this prevents the creation of bounding box which is not needed 278 potentialMesh.Dereference(m_physicsScene);
787 IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */, false, false);
788 if (meshData != null)
789 {
790 int[] indices = meshData.getIndexListAsInt();
791 List<OMV.Vector3> vertices = meshData.getVertexList();
792
793 //format conversion from IMesh format to DecompDesc format
794 List<int> convIndices = new List<int>();
795 List<float3> convVertices = new List<float3>();
796 for (int ii = 0; ii < indices.GetLength(0); ii++)
797 {
798 convIndices.Add(indices[ii]);
799 }
800 foreach (OMV.Vector3 vv in vertices)
801 {
802 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
803 }
804
805 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
806 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
807 {
808 // Simple primitive shapes we know are convex so they are better implemented with
809 // fewer hulls.
810 // Check for simple shape (prim without cuts) and reduce split parameter if so.
811 if (PrimHasNoCuts(pbs))
812 {
813 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
814 }
815 }
816
817 // setup and do convex hull conversion
818 m_hulls = new List<ConvexResult>();
819 DecompDesc dcomp = new DecompDesc();
820 dcomp.mIndices = convIndices;
821 dcomp.mVertices = convVertices;
822 dcomp.mDepth = maxDepthSplit;
823 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
824 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
825 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
826 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
827 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
828 // create the hull into the _hulls variable
829 convexBuilder.process(dcomp);
830
831 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
832 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
833
834 // Convert the vertices and indices for passing to unmanaged.
835 // The hull information is passed as a large floating point array.
836 // The format is:
837 // convHulls[0] = number of hulls
838 // convHulls[1] = number of vertices in first hull
839 // convHulls[2] = hull centroid X coordinate
840 // convHulls[3] = hull centroid Y coordinate
841 // convHulls[4] = hull centroid Z coordinate
842 // convHulls[5] = first hull vertex X
843 // convHulls[6] = first hull vertex Y
844 // convHulls[7] = first hull vertex Z
845 // convHulls[8] = second hull vertex X
846 // ...
847 // convHulls[n] = number of vertices in second hull
848 // convHulls[n+1] = second hull centroid X coordinate
849 // ...
850 //
851 // TODO: is is very inefficient. Someday change the convex hull generator to return
852 // data structures that do not need to be converted in order to pass to Bullet.
853 // And maybe put the values directly into pinned memory rather than marshaling.
854 int hullCount = m_hulls.Count;
855 int totalVertices = 1; // include one for the count of the hulls
856 foreach (ConvexResult cr in m_hulls)
857 {
858 totalVertices += 4; // add four for the vertex count and centroid
859 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
860 }
861 float[] convHulls = new float[totalVertices];
862
863 convHulls[0] = (float)hullCount;
864 int jj = 1;
865 foreach (ConvexResult cr in m_hulls)
866 {
867 // copy vertices for index access
868 float3[] verts = new float3[cr.HullVertices.Count];
869 int kk = 0;
870 foreach (float3 ff in cr.HullVertices)
871 {
872 verts[kk++] = ff;
873 }
874
875 // add to the array one hull's worth of data
876 convHulls[jj++] = cr.HullIndices.Count;
877 convHulls[jj++] = 0f; // centroid x,y,z
878 convHulls[jj++] = 0f;
879 convHulls[jj++] = 0f;
880 foreach (int ind in cr.HullIndices)
881 {
882 convHulls[jj++] = verts[ind].x;
883 convHulls[jj++] = verts[ind].y;
884 convHulls[jj++] = verts[ind].z;
885 }
886 }
887 // create the hull data structure in Bullet
888 newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
889 }
890 } 279 }
891 newShape.shapeKey = newHullKey; 280 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1}", prim.LocalID, prim.PhysShape);
892 } 281 }
893 282 return ret;
894 return newShape;
895 }
896
897 // Callback from convex hull creater with a newly created hull.
898 // Just add it to our collection of hulls for this shape.
899 private void HullReturn(ConvexResult result)
900 {
901 m_hulls.Add(result);
902 return;
903 } 283 }
904 284
905 // Compound shapes are always built from scratch. 285 // Track another user of a body.
906 // This shouldn't be to bad since most of the parts will be meshes that had been built previously. 286 // We presume the caller has allocated the body.
907 private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 287 // Bodies only have one user so the body is just put into the world if not already there.
288 private void ReferenceBody(BulletBody body)
908 { 289 {
909 // Remove reference to the old shape 290 lock (m_collectionActivityLock)
910 // Don't need to do this as the shape is freed when the new root shape is created below. 291 {
911 // DereferenceShape(prim.PhysShape, true, shapeCallback); 292 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
912 293 if (!m_physicsScene.PE.IsInWorld(m_physicsScene.World, body))
913 BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false); 294 {
914 295 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, body);
915 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. 296 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
916 CreateGeomMeshOrHull(prim, shapeCallback); 297 }
917 PhysicsScene.PE.AddChildShapeToCompoundShape(cShape, prim.PhysShape, OMV.Vector3.Zero, OMV.Quaternion.Identity); 298 }
918 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
919 prim.LocalID, cShape, prim.PhysShape);
920
921 prim.PhysShape = cShape;
922
923 return true;
924 } 299 }
925 300
926 // Create a hash of all the shape parameters to be used as a key 301 // Release the usage of a body.
927 // for this particular shape. 302 // Called when releasing use of a BSBody. BSShape is handled separately.
928 public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) 303 // Called in taint time.
929 { 304 public void DereferenceBody(BulletBody body, PhysicalDestructionCallback bodyCallback )
930 // level of detail based on size and type of the object
931 float lod = BSParam.MeshLOD;
932
933 // prims with curvy internal cuts need higher lod
934 if (pbs.HollowShape == HollowShape.Circle)
935 lod = BSParam.MeshCircularLOD;
936
937 if (pbs.SculptEntry)
938 lod = BSParam.SculptLOD;
939
940 // Mega prims usually get more detail because one can interact with shape approximations at this size.
941 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
942 if (maxAxis > BSParam.MeshMegaPrimThreshold)
943 lod = BSParam.MeshMegaPrimLOD;
944
945 retLod = lod;
946 return pbs.GetMeshKey(size, lod);
947 }
948 // For those who don't want the LOD
949 public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
950 { 305 {
951 float lod; 306 if (!body.HasPhysicalBody)
952 return ComputeShapeKey(size, pbs, out lod); 307 return;
953 }
954 308
955 // The creation of a mesh or hull can fail if an underlying asset is not available. 309 m_physicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody");
956 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
957 // and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
958 // The first case causes the asset to be fetched. The second case requires
959 // us to not loop forever.
960 // Called after creating a physical mesh or hull. If the physical shape was created,
961 // just return.
962 public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
963 {
964 // If the shape was successfully created, nothing more to do
965 if (newShape.HasPhysicalShape)
966 return newShape;
967 310
968 // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been 311 lock (m_collectionActivityLock)
969 // fetched but we end up here again, the meshing of the asset must have failed.
970 // Prevent trying to keep fetching the mesh by declaring failure.
971 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
972 {
973 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
974 physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
975 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
976 }
977 else
978 { 312 {
979 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset 313 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body);
980 if (prim.BaseShape.SculptEntry 314 // If the caller needs to know the old body is going away, pass the event up.
981 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed 315 if (bodyCallback != null)
982 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting 316 bodyCallback(body, null);
983 && prim.BaseShape.SculptTexture != OMV.UUID.Zero
984 )
985 {
986 physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
987 // Multiple requestors will know we're waiting for this asset
988 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
989
990 BSPhysObject xprim = prim;
991 Util.FireAndForget(delegate
992 {
993 RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
994 if (assetProvider != null)
995 {
996 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
997 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
998 {
999 bool assetFound = false;
1000 string mismatchIDs = String.Empty; // DEBUG DEBUG
1001 if (asset != null && yprim.BaseShape.SculptEntry)
1002 {
1003 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
1004 {
1005 yprim.BaseShape.SculptData = asset.Data;
1006 // This will cause the prim to see that the filler shape is not the right
1007 // one and try again to build the object.
1008 // No race condition with the normal shape setting since the rebuild is at taint time.
1009 yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
1010 assetFound = true;
1011 }
1012 else
1013 {
1014 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
1015 }
1016 }
1017 if (assetFound)
1018 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
1019 else
1020 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
1021 physicsScene.DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
1022 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
1023 317
1024 }); 318 // Removing an object not in the world is a NOOP
1025 } 319 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, body);
1026 else
1027 {
1028 xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
1029 physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
1030 LogHeader, physicsScene.Name);
1031 }
1032 });
1033 }
1034 else
1035 {
1036 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
1037 {
1038 physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
1039 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
1040 }
1041 }
1042 }
1043 320
1044 // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object. 321 // Zero any reference to the shape so it is not freed when the body is deleted.
1045 BulletShape fillinShape = physicsScene.Shapes.BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); 322 m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, body, null);
1046 physicsScene.DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
1047 323
1048 return fillinShape; 324 m_physicsScene.PE.DestroyObject(m_physicsScene.World, body);
325 }
1049 } 326 }
1050 327
1051 // Create a body object in Bullet. 328 // Create a body object in Bullet.
1052 // Updates prim.BSBody with the information about the new body if one is created. 329 // Updates prim.BSBody with the information about the new body if one is created.
1053 // Returns 'true' if an object was actually created. 330 // Returns 'true' if an object was actually created.
1054 // Called at taint-time. 331 // Called at taint-time.
1055 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BodyDestructionCallback bodyCallback) 332 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, PhysicalDestructionCallback bodyCallback)
1056 { 333 {
1057 bool ret = false; 334 bool ret = false;
1058 335
@@ -1063,7 +340,7 @@ public sealed class BSShapeCollection : IDisposable
1063 // If not a solid object, body is a GhostObject. Otherwise a RigidBody. 340 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
1064 if (!mustRebuild) 341 if (!mustRebuild)
1065 { 342 {
1066 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(prim.PhysBody); 343 CollisionObjectTypes bodyType = (CollisionObjectTypes)m_physicsScene.PE.GetBodyType(prim.PhysBody);
1067 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY 344 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
1068 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) 345 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
1069 { 346 {
@@ -1081,12 +358,12 @@ public sealed class BSShapeCollection : IDisposable
1081 BulletBody aBody; 358 BulletBody aBody;
1082 if (prim.IsSolid) 359 if (prim.IsSolid)
1083 { 360 {
1084 aBody = PhysicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); 361 aBody = m_physicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
1085 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody); 362 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,rigid,body={1}", prim.LocalID, aBody);
1086 } 363 }
1087 else 364 else
1088 { 365 {
1089 aBody = PhysicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); 366 aBody = m_physicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape.physShapeInfo, prim.LocalID, prim.RawPosition, prim.RawOrientation);
1090 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody); 367 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody);
1091 } 368 }
1092 369
@@ -1100,46 +377,10 @@ public sealed class BSShapeCollection : IDisposable
1100 return ret; 377 return ret;
1101 } 378 }
1102 379
1103 private bool TryGetMeshByPtr(BulletShape shape, out MeshDesc outDesc)
1104 {
1105 bool ret = false;
1106 MeshDesc foundDesc = new MeshDesc();
1107 foreach (MeshDesc md in Meshes.Values)
1108 {
1109 if (md.shape.ReferenceSame(shape))
1110 {
1111 foundDesc = md;
1112 ret = true;
1113 break;
1114 }
1115
1116 }
1117 outDesc = foundDesc;
1118 return ret;
1119 }
1120
1121 private bool TryGetHullByPtr(BulletShape shape, out HullDesc outDesc)
1122 {
1123 bool ret = false;
1124 HullDesc foundDesc = new HullDesc();
1125 foreach (HullDesc hd in Hulls.Values)
1126 {
1127 if (hd.shape.ReferenceSame(shape))
1128 {
1129 foundDesc = hd;
1130 ret = true;
1131 break;
1132 }
1133
1134 }
1135 outDesc = foundDesc;
1136 return ret;
1137 }
1138
1139 private void DetailLog(string msg, params Object[] args) 380 private void DetailLog(string msg, params Object[] args)
1140 { 381 {
1141 if (PhysicsScene.PhysicsLogging.Enabled) 382 if (m_physicsScene.PhysicsLogging.Enabled)
1142 PhysicsScene.DetailLog(msg, args); 383 m_physicsScene.DetailLog(msg, args);
1143 } 384 }
1144} 385}
1145} 386}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index dd5ae1a..1008184 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -31,6 +31,7 @@ using System.Text;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager; 33using OpenSim.Region.Physics.Manager;
34using OpenSim.Region.Physics.ConvexDecompositionDotNet;
34 35
35using OMV = OpenMetaverse; 36using OMV = OpenMetaverse;
36 37
@@ -38,74 +39,39 @@ namespace OpenSim.Region.Physics.BulletSPlugin
38{ 39{
39public abstract class BSShape 40public abstract class BSShape
40{ 41{
42 private static string LogHeader = "[BULLETSIM SHAPE]";
43
41 public int referenceCount { get; set; } 44 public int referenceCount { get; set; }
42 public DateTime lastReferenced { get; set; } 45 public DateTime lastReferenced { get; set; }
43 public BulletShape physShapeInfo { get; set; } 46 public BulletShape physShapeInfo { get; set; }
44 47
45 public BSShape() 48 public BSShape()
46 { 49 {
47 referenceCount = 0; 50 referenceCount = 1;
48 lastReferenced = DateTime.Now; 51 lastReferenced = DateTime.Now;
49 physShapeInfo = new BulletShape(); 52 physShapeInfo = new BulletShape();
50 } 53 }
51 public BSShape(BulletShape pShape) 54 public BSShape(BulletShape pShape)
52 { 55 {
53 referenceCount = 0; 56 referenceCount = 1;
54 lastReferenced = DateTime.Now; 57 lastReferenced = DateTime.Now;
55 physShapeInfo = pShape; 58 physShapeInfo = pShape;
56 } 59 }
57 60
58 // Get a reference to a physical shape. Create if it doesn't exist 61 // Get another reference to this shape.
59 public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 62 public abstract BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim);
60 {
61 BSShape ret = null;
62
63 if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
64 {
65 // an avatar capsule is close to a native shape (it is not shared)
66 ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE,
67 FixedShapeKey.KEY_CAPSULE);
68 physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret);
69 }
70
71 // Compound shapes are handled special as they are rebuilt from scratch.
72 // This isn't too great a hardship since most of the child shapes will have already been created.
73 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
74 {
75 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
76 ret = BSShapeCompound.GetReference(prim);
77 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
78 }
79
80 // Avatars have their own unique shape
81 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_AVATAR)
82 {
83 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
84 ret = BSShapeAvatar.GetReference(prim);
85 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,avatarShape,shape={1}", prim.LocalID, ret);
86 }
87
88 if (ret == null)
89 ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);
90
91 return ret;
92 }
93 private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
94 {
95 BSShapeMesh.GetReference(physicsScene, forceRebuild, prim);
96 BSShapeHull.GetReference(physicsScene, forceRebuild, prim);
97 return null;
98 }
99 63
100 // Called when this shape is being used again. 64 // Called when this shape is being used again.
101 public virtual void IncrementReference() 65 // Used internally. External callers should call instance.GetReference() to properly copy/reference
66 // the shape.
67 protected virtual void IncrementReference()
102 { 68 {
103 referenceCount++; 69 referenceCount++;
104 lastReferenced = DateTime.Now; 70 lastReferenced = DateTime.Now;
105 } 71 }
106 72
107 // Called when this shape is being used again. 73 // Called when this shape is being used again.
108 public virtual void DecrementReference() 74 protected virtual void DecrementReference()
109 { 75 {
110 referenceCount--; 76 referenceCount--;
111 lastReferenced = DateTime.Now; 77 lastReferenced = DateTime.Now;
@@ -114,22 +80,178 @@ public abstract class BSShape
114 // Release the use of a physical shape. 80 // Release the use of a physical shape.
115 public abstract void Dereference(BSScene physicsScene); 81 public abstract void Dereference(BSScene physicsScene);
116 82
83 // Return 'true' if there is an allocated physics physical shape under this class instance.
84 public virtual bool HasPhysicalShape
85 {
86 get
87 {
88 if (physShapeInfo != null)
89 return physShapeInfo.HasPhysicalShape;
90 return false;
91 }
92 }
93 public virtual BSPhysicsShapeType ShapeType
94 {
95 get
96 {
97 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
98 if (physShapeInfo != null && physShapeInfo.HasPhysicalShape)
99 ret = physShapeInfo.shapeType;
100 return ret;
101 }
102 }
103
117 // Returns a string for debugging that uniquily identifies the memory used by this instance 104 // Returns a string for debugging that uniquily identifies the memory used by this instance
118 public virtual string AddrString 105 public virtual string AddrString
119 { 106 {
120 get { return "unknown"; } 107 get
108 {
109 if (physShapeInfo != null)
110 return physShapeInfo.AddrString;
111 return "unknown";
112 }
121 } 113 }
122 114
123 public override string ToString() 115 public override string ToString()
124 { 116 {
125 StringBuilder buff = new StringBuilder(); 117 StringBuilder buff = new StringBuilder();
126 buff.Append("<p="); 118 if (physShapeInfo == null)
127 buff.Append(AddrString); 119 {
120 buff.Append(",noPhys");
121 }
122 else
123 {
124 buff.Append(",phy=");
125 buff.Append(physShapeInfo.ToString());
126 }
128 buff.Append(",c="); 127 buff.Append(",c=");
129 buff.Append(referenceCount.ToString()); 128 buff.Append(referenceCount.ToString());
130 buff.Append(">"); 129 buff.Append(">");
131 return buff.ToString(); 130 return buff.ToString();
132 } 131 }
132
133 #region Common shape routines
134 // Create a hash of all the shape parameters to be used as a key for this particular shape.
135 public static System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
136 {
137 // level of detail based on size and type of the object
138 float lod = BSParam.MeshLOD;
139 if (pbs.SculptEntry)
140 lod = BSParam.SculptLOD;
141
142 // Mega prims usually get more detail because one can interact with shape approximations at this size.
143 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
144 if (maxAxis > BSParam.MeshMegaPrimThreshold)
145 lod = BSParam.MeshMegaPrimLOD;
146
147 retLod = lod;
148 return pbs.GetMeshKey(size, lod);
149 }
150
151 // The creation of a mesh or hull can fail if an underlying asset is not available.
152 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
153 // and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
154 // The first case causes the asset to be fetched. The second case requires
155 // us to not loop forever.
156 // Called after creating a physical mesh or hull. If the physical shape was created,
157 // just return.
158 public static BulletShape VerifyMeshCreated(BSScene physicsScene, BulletShape newShape, BSPhysObject prim)
159 {
160 // If the shape was successfully created, nothing more to do
161 if (newShape.HasPhysicalShape)
162 return newShape;
163
164 // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been
165 // fetched but we end up here again, the meshing of the asset must have failed.
166 // Prevent trying to keep fetching the mesh by declaring failure.
167 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
168 {
169 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
170 physicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
171 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
172 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,setFailed,objNam={1},tex={2}",
173 prim.LocalID, prim.PhysObjectName, prim.BaseShape.SculptTexture);
174 }
175 else
176 {
177 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
178 if (prim.BaseShape.SculptEntry
179 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed
180 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting
181 && prim.BaseShape.SculptTexture != OMV.UUID.Zero
182 )
183 {
184 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,fetchAsset,objNam={1},tex={2}",
185 prim.LocalID, prim.PhysObjectName, prim.BaseShape.SculptTexture);
186 // Multiple requestors will know we're waiting for this asset
187 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
188
189 BSPhysObject xprim = prim;
190 Util.FireAndForget(delegate
191 {
192 // physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,inFireAndForget", xprim.LocalID);
193 RequestAssetDelegate assetProvider = physicsScene.RequestAssetMethod;
194 if (assetProvider != null)
195 {
196 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
197 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
198 {
199 // physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,assetProviderCallback", xprim.LocalID);
200 bool assetFound = false;
201 string mismatchIDs = String.Empty; // DEBUG DEBUG
202 if (asset != null && yprim.BaseShape.SculptEntry)
203 {
204 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
205 {
206 yprim.BaseShape.SculptData = asset.Data;
207 // This will cause the prim to see that the filler shape is not the right
208 // one and try again to build the object.
209 // No race condition with the normal shape setting since the rebuild is at taint time.
210 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
211 yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
212 assetFound = true;
213 }
214 else
215 {
216 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
217 }
218 }
219 if (!assetFound)
220 {
221 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
222 }
223 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
224 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
225 });
226 }
227 else
228 {
229 xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
230 physicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
231 LogHeader, physicsScene.Name);
232 }
233 });
234 }
235 else
236 {
237 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
238 {
239 physicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
240 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
241 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,wasFailed,objNam={1},tex={2}",
242 prim.LocalID, prim.PhysObjectName, prim.BaseShape.SculptTexture);
243 }
244 }
245 }
246
247 // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object.
248 BSShape fillShape = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
249 physicsScene.DetailLog("{0},BSShape.VerifyMeshCreated,boxTempShape", prim.LocalID);
250
251 return fillShape.physShapeInfo;
252 }
253
254 #endregion // Common shape routines
133} 255}
134 256
135// ============================================================================================================ 257// ============================================================================================================
@@ -139,6 +261,7 @@ public class BSShapeNull : BSShape
139 { 261 {
140 } 262 }
141 public static BSShape GetReference() { return new BSShapeNull(); } 263 public static BSShape GetReference() { return new BSShapeNull(); }
264 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim) { return new BSShapeNull(); }
142 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ } 265 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ }
143} 266}
144 267
@@ -150,24 +273,34 @@ public class BSShapeNative : BSShape
150 { 273 {
151 } 274 }
152 275
153 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, 276 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
154 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) 277 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
155 { 278 {
156 // Native shapes are not shared and are always built anew. 279 // Native shapes are not shared and are always built anew.
157 return new BSShapeNative(CreatePhysicalNativeShape(physicsScene, prim, shapeType, shapeKey)); 280 return new BSShapeNative(CreatePhysicalNativeShape(physicsScene, prim, shapeType, shapeKey));
158 } 281 }
159 282
283 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
284 {
285 // Native shapes are not shared so we return a new shape.
286 return new BSShapeNative(CreatePhysicalNativeShape(pPhysicsScene, pPrim,
287 physShapeInfo.shapeType, (FixedShapeKey)physShapeInfo.shapeKey) );
288 }
289
160 // Make this reference to the physical shape go away since native shapes are not shared. 290 // Make this reference to the physical shape go away since native shapes are not shared.
161 public override void Dereference(BSScene physicsScene) 291 public override void Dereference(BSScene physicsScene)
162 { 292 {
163 // Native shapes are not tracked and are released immediately 293 // Native shapes are not tracked and are released immediately
164 if (physShapeInfo.HasPhysicalShape) 294 lock (physShapeInfo)
165 { 295 {
166 physicsScene.DetailLog("{0},BSShapeNative.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this); 296 if (physShapeInfo.HasPhysicalShape)
167 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo); 297 {
298 physicsScene.DetailLog("{0},BSShapeNative.Dereference,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
299 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
300 }
301 physShapeInfo.Clear();
302 // Garbage collection will free up this instance.
168 } 303 }
169 physShapeInfo.Clear();
170 // Garbage collection will free up this instance.
171 } 304 }
172 305
173 private static BulletShape CreatePhysicalNativeShape(BSScene physicsScene, BSPhysObject prim, 306 private static BulletShape CreatePhysicalNativeShape(BSScene physicsScene, BSPhysObject prim,
@@ -197,7 +330,7 @@ public class BSShapeNative : BSShape
197 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 330 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
198 LogHeader, prim.LocalID, shapeType); 331 LogHeader, prim.LocalID, shapeType);
199 } 332 }
200 newShape.type = shapeType; 333 newShape.shapeType = shapeType;
201 newShape.isNativeShape = true; 334 newShape.isNativeShape = true;
202 newShape.shapeKey = (UInt64)shapeKey; 335 newShape.shapeKey = (UInt64)shapeKey;
203 return newShape; 336 return newShape;
@@ -209,7 +342,7 @@ public class BSShapeNative : BSShape
209public class BSShapeMesh : BSShape 342public class BSShapeMesh : BSShape
210{ 343{
211 private static string LogHeader = "[BULLETSIM SHAPE MESH]"; 344 private static string LogHeader = "[BULLETSIM SHAPE MESH]";
212 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>(); 345 public static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
213 346
214 public BSShapeMesh(BulletShape pShape) : base(pShape) 347 public BSShapeMesh(BulletShape pShape) : base(pShape)
215 { 348 {
@@ -217,12 +350,9 @@ public class BSShapeMesh : BSShape
217 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 350 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
218 { 351 {
219 float lod; 352 float lod;
220 System.UInt64 newMeshKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); 353 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
221 354
222 physicsScene.DetailLog("{0},BSShapeMesh,create,oldKey={1},newKey={2},size={3},lod={4}", 355 BSShapeMesh retMesh = null;
223 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
224
225 BSShapeMesh retMesh;
226 lock (Meshes) 356 lock (Meshes)
227 { 357 {
228 if (Meshes.TryGetValue(newMeshKey, out retMesh)) 358 if (Meshes.TryGetValue(newMeshKey, out retMesh))
@@ -232,39 +362,80 @@ public class BSShapeMesh : BSShape
232 } 362 }
233 else 363 else
234 { 364 {
365 retMesh = new BSShapeMesh(new BulletShape());
235 // An instance of this mesh has not been created. Build and remember same. 366 // An instance of this mesh has not been created. Build and remember same.
236 BulletShape newShape = CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod); 367 BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
237 // Take evasive action if the mesh was not constructed.
238 newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
239 368
240 retMesh = new BSShapeMesh(newShape); 369 // Check to see if mesh was created (might require an asset).
370 newShape = VerifyMeshCreated(physicsScene, newShape, prim);
371 if (!newShape.isNativeShape)
372 {
373 // If a mesh was what was created, remember the built shape for later sharing.
374 Meshes.Add(newMeshKey, retMesh);
375 }
241 376
242 Meshes.Add(newMeshKey, retMesh); 377 retMesh.physShapeInfo = newShape;
243 } 378 }
244 } 379 }
380 physicsScene.DetailLog("{0},BSShapeMesh,getReference,mesh={1},size={2},lod={3}", prim.LocalID, retMesh, prim.Size, lod);
245 return retMesh; 381 return retMesh;
246 } 382 }
383 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
384 {
385 // Another reference to this shape is just counted.
386 IncrementReference();
387 return this;
388 }
247 public override void Dereference(BSScene physicsScene) 389 public override void Dereference(BSScene physicsScene)
248 { 390 {
249 lock (Meshes) 391 lock (Meshes)
250 { 392 {
251 this.DecrementReference(); 393 this.DecrementReference();
394 physicsScene.DetailLog("{0},BSShapeMesh.Dereference,shape={1}", BSScene.DetailLogZero, this);
252 // TODO: schedule aging and destruction of unused meshes. 395 // TODO: schedule aging and destruction of unused meshes.
253 } 396 }
254 } 397 }
398 // Loop through all the known meshes and return the description based on the physical address.
399 public static bool TryGetMeshByPtr(BulletShape pShape, out BSShapeMesh outMesh)
400 {
401 bool ret = false;
402 BSShapeMesh foundDesc = null;
403 lock (Meshes)
404 {
405 foreach (BSShapeMesh sm in Meshes.Values)
406 {
407 if (sm.physShapeInfo.ReferenceSame(pShape))
408 {
409 foundDesc = sm;
410 ret = true;
411 break;
412 }
255 413
256 private static BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey, 414 }
415 }
416 outMesh = foundDesc;
417 return ret;
418 }
419 private BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
257 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 420 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
258 { 421 {
259 BulletShape newShape = null; 422 BulletShape newShape = new BulletShape();
260 423
261 IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, 424 IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod,
262 false, // say it is not physical so a bounding box is not built 425 false, // say it is not physical so a bounding box is not built
263 false // do not cache the mesh and do not use previously built versions 426 false, // do not cache the mesh and do not use previously built versions
427 false,
428 false
264 ); 429 );
265 430
266 if (meshData != null) 431 if (meshData != null)
267 { 432 {
433 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
434 {
435 // Release the fetched asset data once it has been used.
436 pbs.SculptData = new byte[0];
437 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
438 }
268 439
269 int[] indices = meshData.getIndexListAsInt(); 440 int[] indices = meshData.getIndexListAsInt();
270 int realIndicesIndex = indices.Length; 441 int realIndicesIndex = indices.Length;
@@ -302,8 +473,8 @@ public class BSShapeMesh : BSShape
302 } 473 }
303 } 474 }
304 } 475 }
305 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}", 476 physicsScene.DetailLog("{0},BSShapeMesh.CreatePhysicalMesh,key={1},origTri={2},realTri={3},numVerts={4}",
306 BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3); 477 BSScene.DetailLogZero, newMeshKey.ToString("X"), indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3);
307 478
308 if (realIndicesIndex != 0) 479 if (realIndicesIndex != 0)
309 { 480 {
@@ -326,17 +497,239 @@ public class BSShapeMesh : BSShape
326public class BSShapeHull : BSShape 497public class BSShapeHull : BSShape
327{ 498{
328 private static string LogHeader = "[BULLETSIM SHAPE HULL]"; 499 private static string LogHeader = "[BULLETSIM SHAPE HULL]";
329 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>(); 500 public static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
330 501
331 public BSShapeHull(BulletShape pShape) : base(pShape) 502 public BSShapeHull(BulletShape pShape) : base(pShape)
332 { 503 {
333 } 504 }
334 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 505 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
335 { 506 {
336 return new BSShapeNull(); 507 float lod;
508 System.UInt64 newHullKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
509
510 BSShapeHull retHull = null;
511 lock (Hulls)
512 {
513 if (Hulls.TryGetValue(newHullKey, out retHull))
514 {
515 // The mesh has already been created. Return a new reference to same.
516 retHull.IncrementReference();
517 }
518 else
519 {
520 retHull = new BSShapeHull(new BulletShape());
521 // An instance of this mesh has not been created. Build and remember same.
522 BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod);
523
524 // Check to see if hull was created (might require an asset).
525 newShape = VerifyMeshCreated(physicsScene, newShape, prim);
526 if (!newShape.isNativeShape)
527 {
528 // If a mesh was what was created, remember the built shape for later sharing.
529 Hulls.Add(newHullKey, retHull);
530 }
531 retHull.physShapeInfo = newShape;
532 }
533 }
534 physicsScene.DetailLog("{0},BSShapeHull,getReference,hull={1},size={2},lod={3}", prim.LocalID, retHull, prim.Size, lod);
535 return retHull;
536 }
537 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
538 {
539 // Another reference to this shape is just counted.
540 IncrementReference();
541 return this;
337 } 542 }
338 public override void Dereference(BSScene physicsScene) 543 public override void Dereference(BSScene physicsScene)
339 { 544 {
545 lock (Hulls)
546 {
547 this.DecrementReference();
548 physicsScene.DetailLog("{0},BSShapeHull.Dereference,shape={1}", BSScene.DetailLogZero, this);
549 // TODO: schedule aging and destruction of unused meshes.
550 }
551 }
552 List<ConvexResult> m_hulls;
553 private BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, System.UInt64 newHullKey,
554 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
555 {
556 BulletShape newShape = new BulletShape();
557 IntPtr hullPtr = IntPtr.Zero;
558
559 if (BSParam.ShouldUseBulletHACD)
560 {
561 // Build the hull shape from an existing mesh shape.
562 // The mesh should have already been created in Bullet.
563 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
564 BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);
565
566 if (meshShape.physShapeInfo.HasPhysicalShape)
567 {
568 HACDParams parms;
569 parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
570 parms.minClusters = BSParam.BHullMinClusters;
571 parms.compacityWeight = BSParam.BHullCompacityWeight;
572 parms.volumeWeight = BSParam.BHullVolumeWeight;
573 parms.concavity = BSParam.BHullConcavity;
574 parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
575 parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
576 parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
577 parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
578
579 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
580 newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
581 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
582
583 // Now done with the mesh shape.
584 meshShape.Dereference(physicsScene);
585 }
586 physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
587 }
588 if (!newShape.HasPhysicalShape)
589 {
590 // Build a new hull in the physical world using the C# HACD algorigthm.
591 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
592 IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */, false, false);
593 if (meshData != null)
594 {
595 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
596 {
597 // Release the fetched asset data once it has been used.
598 pbs.SculptData = new byte[0];
599 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
600 }
601
602 int[] indices = meshData.getIndexListAsInt();
603 List<OMV.Vector3> vertices = meshData.getVertexList();
604
605 //format conversion from IMesh format to DecompDesc format
606 List<int> convIndices = new List<int>();
607 List<float3> convVertices = new List<float3>();
608 for (int ii = 0; ii < indices.GetLength(0); ii++)
609 {
610 convIndices.Add(indices[ii]);
611 }
612 foreach (OMV.Vector3 vv in vertices)
613 {
614 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
615 }
616
617 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
618 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
619 {
620 // Simple primitive shapes we know are convex so they are better implemented with
621 // fewer hulls.
622 // Check for simple shape (prim without cuts) and reduce split parameter if so.
623 if (BSShapeCollection.PrimHasNoCuts(pbs))
624 {
625 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
626 }
627 }
628
629 // setup and do convex hull conversion
630 m_hulls = new List<ConvexResult>();
631 DecompDesc dcomp = new DecompDesc();
632 dcomp.mIndices = convIndices;
633 dcomp.mVertices = convVertices;
634 dcomp.mDepth = maxDepthSplit;
635 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
636 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
637 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
638 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
639 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
640 // create the hull into the _hulls variable
641 convexBuilder.process(dcomp);
642
643 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
644 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
645
646 // Convert the vertices and indices for passing to unmanaged.
647 // The hull information is passed as a large floating point array.
648 // The format is:
649 // convHulls[0] = number of hulls
650 // convHulls[1] = number of vertices in first hull
651 // convHulls[2] = hull centroid X coordinate
652 // convHulls[3] = hull centroid Y coordinate
653 // convHulls[4] = hull centroid Z coordinate
654 // convHulls[5] = first hull vertex X
655 // convHulls[6] = first hull vertex Y
656 // convHulls[7] = first hull vertex Z
657 // convHulls[8] = second hull vertex X
658 // ...
659 // convHulls[n] = number of vertices in second hull
660 // convHulls[n+1] = second hull centroid X coordinate
661 // ...
662 //
663 // TODO: is is very inefficient. Someday change the convex hull generator to return
664 // data structures that do not need to be converted in order to pass to Bullet.
665 // And maybe put the values directly into pinned memory rather than marshaling.
666 int hullCount = m_hulls.Count;
667 int totalVertices = 1; // include one for the count of the hulls
668 foreach (ConvexResult cr in m_hulls)
669 {
670 totalVertices += 4; // add four for the vertex count and centroid
671 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
672 }
673 float[] convHulls = new float[totalVertices];
674
675 convHulls[0] = (float)hullCount;
676 int jj = 1;
677 foreach (ConvexResult cr in m_hulls)
678 {
679 // copy vertices for index access
680 float3[] verts = new float3[cr.HullVertices.Count];
681 int kk = 0;
682 foreach (float3 ff in cr.HullVertices)
683 {
684 verts[kk++] = ff;
685 }
686
687 // add to the array one hull's worth of data
688 convHulls[jj++] = cr.HullIndices.Count;
689 convHulls[jj++] = 0f; // centroid x,y,z
690 convHulls[jj++] = 0f;
691 convHulls[jj++] = 0f;
692 foreach (int ind in cr.HullIndices)
693 {
694 convHulls[jj++] = verts[ind].x;
695 convHulls[jj++] = verts[ind].y;
696 convHulls[jj++] = verts[ind].z;
697 }
698 }
699 // create the hull data structure in Bullet
700 newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
701 }
702 newShape.shapeKey = newHullKey;
703 }
704 return newShape;
705 }
706 // Callback from convex hull creater with a newly created hull.
707 // Just add it to our collection of hulls for this shape.
708 private void HullReturn(ConvexResult result)
709 {
710 m_hulls.Add(result);
711 return;
712 }
713 // Loop through all the known hulls and return the description based on the physical address.
714 public static bool TryGetHullByPtr(BulletShape pShape, out BSShapeHull outHull)
715 {
716 bool ret = false;
717 BSShapeHull foundDesc = null;
718 lock (Hulls)
719 {
720 foreach (BSShapeHull sh in Hulls.Values)
721 {
722 if (sh.physShapeInfo.ReferenceSame(pShape))
723 {
724 foundDesc = sh;
725 ret = true;
726 break;
727 }
728
729 }
730 }
731 outHull = foundDesc;
732 return ret;
340 } 733 }
341} 734}
342 735
@@ -344,14 +737,169 @@ public class BSShapeHull : BSShape
344public class BSShapeCompound : BSShape 737public class BSShapeCompound : BSShape
345{ 738{
346 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; 739 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
347 public BSShapeCompound() : base() 740 public BSShapeCompound(BulletShape pShape) : base(pShape)
348 { 741 {
349 } 742 }
350 public static BSShape GetReference(BSPhysObject prim) 743 public static BSShape GetReference(BSScene physicsScene)
351 { 744 {
352 return new BSShapeNull(); 745 // Base compound shapes are not shared so this returns a raw shape.
746 // A built compound shape can be reused in linksets.
747 return new BSShapeCompound(CreatePhysicalCompoundShape(physicsScene));
748 }
749 public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
750 {
751 // Calling this reference means we want another handle to an existing compound shape
752 // (usually linksets) so return this copy.
753 IncrementReference();
754 return this;
755 }
756 // Dereferencing a compound shape releases the hold on all the child shapes.
757 public override void Dereference(BSScene physicsScene)
758 {
759 lock (physShapeInfo)
760 {
761 this.DecrementReference();
762 physicsScene.DetailLog("{0},BSShapeCompound.Dereference,shape={1}", BSScene.DetailLogZero, this);
763 if (referenceCount <= 0)
764 {
765 if (!physicsScene.PE.IsCompound(physShapeInfo))
766 {
767 // Failed the sanity check!!
768 physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
769 LogHeader, physShapeInfo.shapeType, physShapeInfo.AddrString);
770 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
771 BSScene.DetailLogZero, physShapeInfo.shapeType, physShapeInfo.AddrString);
772 return;
773 }
774
775 int numChildren = physicsScene.PE.GetNumberOfCompoundChildren(physShapeInfo);
776 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}",
777 BSScene.DetailLogZero, physShapeInfo, numChildren);
778
779 // Loop through all the children dereferencing each.
780 for (int ii = numChildren - 1; ii >= 0; ii--)
781 {
782 BulletShape childShape = physicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(physShapeInfo, ii);
783 DereferenceAnonCollisionShape(physicsScene, childShape);
784 }
785 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
786 }
787 }
788 }
789 private static BulletShape CreatePhysicalCompoundShape(BSScene physicsScene)
790 {
791 BulletShape cShape = physicsScene.PE.CreateCompoundShape(physicsScene.World, false);
792 return cShape;
793 }
794 // Sometimes we have a pointer to a collision shape but don't know what type it is.
795 // Figure out type and call the correct dereference routine.
796 // Called at taint-time.
797 private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape)
798 {
799 BSShapeMesh meshDesc;
800 if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc))
801 {
802 meshDesc.Dereference(physicsScene);
803 }
804 else
805 {
806 BSShapeHull hullDesc;
807 if (BSShapeHull.TryGetHullByPtr(pShape, out hullDesc))
808 {
809 hullDesc.Dereference(physicsScene);
810 }
811 else
812 {
813 if (physicsScene.PE.IsCompound(pShape))
814 {
815 BSShapeCompound recursiveCompound = new BSShapeCompound(pShape);
816 recursiveCompound.Dereference(physicsScene);
817 }
818 else
819 {
820 if (physicsScene.PE.IsNativeShape(pShape))
821 {
822 BSShapeNative nativeShape = new BSShapeNative(pShape);
823 nativeShape.Dereference(physicsScene);
824 }
825 }
826 }
827 }
828 }
829}
830
831// ============================================================================================================
832public class BSShapeConvexHull : BSShape
833{
834 private static string LogHeader = "[BULLETSIM SHAPE CONVEX HULL]";
835 public static Dictionary<System.UInt64, BSShapeConvexHull> ConvexHulls = new Dictionary<System.UInt64, BSShapeConvexHull>();
836
837 public BSShapeConvexHull(BulletShape pShape) : base(pShape)
838 {
839 }
840 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
841 {
842 float lod;
843 System.UInt64 newMeshKey = BSShape.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
844
845 physicsScene.DetailLog("{0},BSShapeMesh,getReference,newKey={1},size={2},lod={3}",
846 prim.LocalID, newMeshKey.ToString("X"), prim.Size, lod);
847
848 BSShapeConvexHull retConvexHull = null;
849 lock (ConvexHulls)
850 {
851 if (ConvexHulls.TryGetValue(newMeshKey, out retConvexHull))
852 {
853 // The mesh has already been created. Return a new reference to same.
854 retConvexHull.IncrementReference();
855 }
856 else
857 {
858 retConvexHull = new BSShapeConvexHull(new BulletShape());
859 BulletShape convexShape = null;
860
861 // Get a handle to a mesh to build the hull from
862 BSShape baseMesh = BSShapeMesh.GetReference(physicsScene, false /* forceRebuild */, prim);
863 if (baseMesh.physShapeInfo.isNativeShape)
864 {
865 // We get here if the mesh was not creatable. Could be waiting for an asset from the disk.
866 // In the short term, we return the native shape and a later ForceBodyShapeRebuild should
867 // get back to this code with a buildable mesh.
868 // TODO: not sure the temp native shape is freed when the mesh is rebuilt. When does this get freed?
869 convexShape = baseMesh.physShapeInfo;
870 }
871 else
872 {
873 convexShape = physicsScene.PE.BuildConvexHullShapeFromMesh(physicsScene.World, baseMesh.physShapeInfo);
874 convexShape.shapeKey = newMeshKey;
875 ConvexHulls.Add(convexShape.shapeKey, retConvexHull);
876 }
877
878 // Done with the base mesh
879 baseMesh.Dereference(physicsScene);
880
881 retConvexHull.physShapeInfo = convexShape;
882 }
883 }
884 return retConvexHull;
885 }
886 public override BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
887 {
888 // Calling this reference means we want another handle to an existing shape
889 // (usually linksets) so return this copy.
890 IncrementReference();
891 return this;
892 }
893 // Dereferencing a compound shape releases the hold on all the child shapes.
894 public override void Dereference(BSScene physicsScene)
895 {
896 lock (ConvexHulls)
897 {
898 this.DecrementReference();
899 physicsScene.DetailLog("{0},BSShapeConvexHull.Dereference,shape={1}", BSScene.DetailLogZero, this);
900 // TODO: schedule aging and destruction of unused meshes.
901 }
353 } 902 }
354 public override void Dereference(BSScene physicsScene) { }
355} 903}
356 904
357// ============================================================================================================ 905// ============================================================================================================
@@ -361,8 +909,12 @@ public class BSShapeAvatar : BSShape
361 public BSShapeAvatar() : base() 909 public BSShapeAvatar() : base()
362 { 910 {
363 } 911 }
364 public static BSShape GetReference(BSPhysObject prim) 912 public static BSShape GetReference(BSPhysObject prim)
365 { 913 {
914 return new BSShapeNull();
915 }
916 public override BSShape GetReference(BSScene pPhysicsScene, BSPhysObject pPrim)
917 {
366 return new BSShapeNull(); 918 return new BSShapeNull();
367 } 919 }
368 public override void Dereference(BSScene physicsScene) { } 920 public override void Dereference(BSScene physicsScene) { }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
index e4fecc3..c7deb4e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
@@ -68,7 +68,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
68 68
69 // This minCoords and maxCoords passed in give the size of the terrain (min and max Z 69 // This minCoords and maxCoords passed in give the size of the terrain (min and max Z
70 // are the high and low points of the heightmap). 70 // are the high and low points of the heightmap).
71 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, 71 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
72 Vector3 minCoords, Vector3 maxCoords) 72 Vector3 minCoords, Vector3 maxCoords)
73 : base(physicsScene, regionBase, id) 73 : base(physicsScene, regionBase, id)
74 { 74 {
@@ -92,7 +92,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
92 private void BuildHeightmapTerrain() 92 private void BuildHeightmapTerrain()
93 { 93 {
94 // Create the terrain shape from the mapInfo 94 // Create the terrain shape from the mapInfo
95 m_mapInfo.terrainShape = PhysicsScene.PE.CreateTerrainShape( m_mapInfo.ID, 95 m_mapInfo.terrainShape = m_physicsScene.PE.CreateTerrainShape( m_mapInfo.ID,
96 new Vector3(m_mapInfo.sizeX, m_mapInfo.sizeY, 0), m_mapInfo.minZ, m_mapInfo.maxZ, 96 new Vector3(m_mapInfo.sizeX, m_mapInfo.sizeY, 0), m_mapInfo.minZ, m_mapInfo.maxZ,
97 m_mapInfo.heightMap, 1f, BSParam.TerrainCollisionMargin); 97 m_mapInfo.heightMap, 1f, BSParam.TerrainCollisionMargin);
98 98
@@ -103,26 +103,26 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
103 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f); 103 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f);
104 centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f); 104 centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f);
105 105
106 m_mapInfo.terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_mapInfo.terrainShape, 106 m_mapInfo.terrainBody = m_physicsScene.PE.CreateBodyWithDefaultMotionState(m_mapInfo.terrainShape,
107 m_mapInfo.ID, centerPos, Quaternion.Identity); 107 m_mapInfo.ID, centerPos, Quaternion.Identity);
108 108
109 // Set current terrain attributes 109 // Set current terrain attributes
110 PhysicsScene.PE.SetFriction(m_mapInfo.terrainBody, BSParam.TerrainFriction); 110 m_physicsScene.PE.SetFriction(m_mapInfo.terrainBody, BSParam.TerrainFriction);
111 PhysicsScene.PE.SetHitFraction(m_mapInfo.terrainBody, BSParam.TerrainHitFraction); 111 m_physicsScene.PE.SetHitFraction(m_mapInfo.terrainBody, BSParam.TerrainHitFraction);
112 PhysicsScene.PE.SetRestitution(m_mapInfo.terrainBody, BSParam.TerrainRestitution); 112 m_physicsScene.PE.SetRestitution(m_mapInfo.terrainBody, BSParam.TerrainRestitution);
113 PhysicsScene.PE.SetCollisionFlags(m_mapInfo.terrainBody, CollisionFlags.CF_STATIC_OBJECT); 113 m_physicsScene.PE.SetCollisionFlags(m_mapInfo.terrainBody, CollisionFlags.CF_STATIC_OBJECT);
114 114
115 // Return the new terrain to the world of physical objects 115 // Return the new terrain to the world of physical objects
116 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_mapInfo.terrainBody); 116 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_mapInfo.terrainBody);
117 117
118 // redo its bounding box now that it is in the world 118 // redo its bounding box now that it is in the world
119 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_mapInfo.terrainBody); 119 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_mapInfo.terrainBody);
120 120
121 m_mapInfo.terrainBody.collisionType = CollisionType.Terrain; 121 m_mapInfo.terrainBody.collisionType = CollisionType.Terrain;
122 m_mapInfo.terrainBody.ApplyCollisionMask(PhysicsScene); 122 m_mapInfo.terrainBody.ApplyCollisionMask(m_physicsScene);
123 123
124 // Make it so the terrain will not move or be considered for movement. 124 // Make it so the terrain will not move or be considered for movement.
125 PhysicsScene.PE.ForceActivationState(m_mapInfo.terrainBody, ActivationState.DISABLE_SIMULATION); 125 m_physicsScene.PE.ForceActivationState(m_mapInfo.terrainBody, ActivationState.DISABLE_SIMULATION);
126 126
127 return; 127 return;
128 } 128 }
@@ -134,9 +134,9 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
134 { 134 {
135 if (m_mapInfo.terrainBody.HasPhysicalBody) 135 if (m_mapInfo.terrainBody.HasPhysicalBody)
136 { 136 {
137 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_mapInfo.terrainBody); 137 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_mapInfo.terrainBody);
138 // Frees both the body and the shape. 138 // Frees both the body and the shape.
139 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_mapInfo.terrainBody); 139 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_mapInfo.terrainBody);
140 } 140 }
141 } 141 }
142 m_mapInfo = null; 142 m_mapInfo = null;
@@ -155,7 +155,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
155 catch 155 catch
156 { 156 {
157 // Sometimes they give us wonky values of X and Y. Give a warning and return something. 157 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
158 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", 158 m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
159 LogHeader, m_mapInfo.terrainRegionBase, pos); 159 LogHeader, m_mapInfo.terrainRegionBase, pos);
160 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; 160 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
161 } 161 }
@@ -165,7 +165,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
165 // The passed position is relative to the base of the region. 165 // The passed position is relative to the base of the region.
166 public override float GetWaterLevelAtXYZ(Vector3 pos) 166 public override float GetWaterLevelAtXYZ(Vector3 pos)
167 { 167 {
168 return PhysicsScene.SimpleWaterLevel; 168 return m_physicsScene.SimpleWaterLevel;
169 } 169 }
170} 170}
171} 171}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 5240ad8..c4807c4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -50,14 +50,14 @@ public abstract class BSTerrainPhys : IDisposable
50 Mesh = 1 50 Mesh = 1
51 } 51 }
52 52
53 public BSScene PhysicsScene { get; private set; } 53 protected BSScene m_physicsScene { get; private set; }
54 // Base of the region in world coordinates. Coordinates inside the region are relative to this. 54 // Base of the region in world coordinates. Coordinates inside the region are relative to this.
55 public Vector3 TerrainBase { get; private set; } 55 public Vector3 TerrainBase { get; private set; }
56 public uint ID { get; private set; } 56 public uint ID { get; private set; }
57 57
58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id) 58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id)
59 { 59 {
60 PhysicsScene = physicsScene; 60 m_physicsScene = physicsScene;
61 TerrainBase = regionBase; 61 TerrainBase = regionBase;
62 ID = id; 62 ID = id;
63 } 63 }
@@ -86,7 +86,7 @@ public sealed class BSTerrainManager : IDisposable
86 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 86 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
87 87
88 // The scene that I am part of 88 // The scene that I am part of
89 private BSScene PhysicsScene { get; set; } 89 private BSScene m_physicsScene { get; set; }
90 90
91 // The ground plane created to keep thing from falling to infinity. 91 // The ground plane created to keep thing from falling to infinity.
92 private BulletBody m_groundPlane; 92 private BulletBody m_groundPlane;
@@ -113,7 +113,7 @@ public sealed class BSTerrainManager : IDisposable
113 113
114 public BSTerrainManager(BSScene physicsScene) 114 public BSTerrainManager(BSScene physicsScene)
115 { 115 {
116 PhysicsScene = physicsScene; 116 m_physicsScene = physicsScene;
117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>(); 117 m_terrains = new Dictionary<Vector3,BSTerrainPhys>();
118 118
119 // Assume one region of default size 119 // Assume one region of default size
@@ -132,21 +132,21 @@ public sealed class BSTerrainManager : IDisposable
132 // safe to call Bullet in real time. We hope no one is moving prims around yet. 132 // safe to call Bullet in real time. We hope no one is moving prims around yet.
133 public void CreateInitialGroundPlaneAndTerrain() 133 public void CreateInitialGroundPlaneAndTerrain()
134 { 134 {
135 DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName); 135 DetailLog("{0},BSTerrainManager.CreateInitialGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, m_physicsScene.RegionName);
136 // The ground plane is here to catch things that are trying to drop to negative infinity 136 // The ground plane is here to catch things that are trying to drop to negative infinity
137 BulletShape groundPlaneShape = PhysicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin); 137 BulletShape groundPlaneShape = m_physicsScene.PE.CreateGroundPlaneShape(BSScene.GROUNDPLANE_ID, 1f, BSParam.TerrainCollisionMargin);
138 m_groundPlane = PhysicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape, 138 m_groundPlane = m_physicsScene.PE.CreateBodyWithDefaultMotionState(groundPlaneShape,
139 BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity); 139 BSScene.GROUNDPLANE_ID, Vector3.Zero, Quaternion.Identity);
140 140
141 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_groundPlane); 141 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_groundPlane);
142 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_groundPlane); 142 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_groundPlane);
143 // Ground plane does not move 143 // Ground plane does not move
144 PhysicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION); 144 m_physicsScene.PE.ForceActivationState(m_groundPlane, ActivationState.DISABLE_SIMULATION);
145 // Everything collides with the ground plane. 145 // Everything collides with the ground plane.
146 m_groundPlane.collisionType = CollisionType.Groundplane; 146 m_groundPlane.collisionType = CollisionType.Groundplane;
147 m_groundPlane.ApplyCollisionMask(PhysicsScene); 147 m_groundPlane.ApplyCollisionMask(m_physicsScene);
148 148
149 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize); 149 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(m_physicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
150 lock (m_terrains) 150 lock (m_terrains)
151 { 151 {
152 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain. 152 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
@@ -157,12 +157,12 @@ public sealed class BSTerrainManager : IDisposable
157 // Release all the terrain structures we might have allocated 157 // Release all the terrain structures we might have allocated
158 public void ReleaseGroundPlaneAndTerrain() 158 public void ReleaseGroundPlaneAndTerrain()
159 { 159 {
160 DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, PhysicsScene.RegionName); 160 DetailLog("{0},BSTerrainManager.ReleaseGroundPlaneAndTerrain,region={1}", BSScene.DetailLogZero, m_physicsScene.RegionName);
161 if (m_groundPlane.HasPhysicalBody) 161 if (m_groundPlane.HasPhysicalBody)
162 { 162 {
163 if (PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_groundPlane)) 163 if (m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_groundPlane))
164 { 164 {
165 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_groundPlane); 165 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_groundPlane);
166 } 166 }
167 m_groundPlane.Clear(); 167 m_groundPlane.Clear();
168 } 168 }
@@ -188,7 +188,7 @@ public sealed class BSTerrainManager : IDisposable
188 float[] localHeightMap = heightMap; 188 float[] localHeightMap = heightMap;
189 // If there are multiple requests for changes to the same terrain between ticks, 189 // If there are multiple requests for changes to the same terrain between ticks,
190 // only do that last one. 190 // only do that last one.
191 PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate() 191 m_physicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate()
192 { 192 {
193 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) 193 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null)
194 { 194 {
@@ -219,7 +219,7 @@ public sealed class BSTerrainManager : IDisposable
219 private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) 219 private void AddMegaRegionChildTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
220 { 220 {
221 // Since we are called by another region's thread, the action must be rescheduled onto our processing thread. 221 // Since we are called by another region's thread, the action must be rescheduled onto our processing thread.
222 PhysicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + minCoords.ToString(), id, delegate() 222 m_physicsScene.PostTaintObject("TerrainManager.AddMegaRegionChild" + minCoords.ToString(), id, delegate()
223 { 223 {
224 UpdateTerrain(id, heightMap, minCoords, maxCoords); 224 UpdateTerrain(id, heightMap, minCoords, maxCoords);
225 }); 225 });
@@ -318,26 +318,26 @@ public sealed class BSTerrainManager : IDisposable
318 // TODO: redo terrain implementation selection to allow other base types than heightMap. 318 // TODO: redo terrain implementation selection to allow other base types than heightMap.
319 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords) 319 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
320 { 320 {
321 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}", 321 m_physicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",
322 LogHeader, PhysicsScene.RegionName, terrainRegionBase, 322 LogHeader, m_physicsScene.RegionName, terrainRegionBase,
323 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation); 323 (BSTerrainPhys.TerrainImplementation)BSParam.TerrainImplementation);
324 BSTerrainPhys newTerrainPhys = null; 324 BSTerrainPhys newTerrainPhys = null;
325 switch ((int)BSParam.TerrainImplementation) 325 switch ((int)BSParam.TerrainImplementation)
326 { 326 {
327 case (int)BSTerrainPhys.TerrainImplementation.Heightmap: 327 case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
328 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id, 328 newTerrainPhys = new BSTerrainHeightmap(m_physicsScene, terrainRegionBase, id,
329 heightMap, minCoords, maxCoords); 329 heightMap, minCoords, maxCoords);
330 break; 330 break;
331 case (int)BSTerrainPhys.TerrainImplementation.Mesh: 331 case (int)BSTerrainPhys.TerrainImplementation.Mesh:
332 newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id, 332 newTerrainPhys = new BSTerrainMesh(m_physicsScene, terrainRegionBase, id,
333 heightMap, minCoords, maxCoords); 333 heightMap, minCoords, maxCoords);
334 break; 334 break;
335 default: 335 default:
336 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}", 336 m_physicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}",
337 LogHeader, 337 LogHeader,
338 (int)BSParam.TerrainImplementation, 338 (int)BSParam.TerrainImplementation,
339 BSParam.TerrainImplementation, 339 BSParam.TerrainImplementation,
340 PhysicsScene.RegionName, terrainRegionBase); 340 m_physicsScene.RegionName, terrainRegionBase);
341 break; 341 break;
342 } 342 }
343 return newTerrainPhys; 343 return newTerrainPhys;
@@ -429,8 +429,8 @@ public sealed class BSTerrainManager : IDisposable
429 } 429 }
430 else 430 else
431 { 431 {
432 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", 432 m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
433 LogHeader, PhysicsScene.RegionName, tX, tY); 433 LogHeader, m_physicsScene.RegionName, tX, tY);
434 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}", 434 DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXYZ,terrainNotFound,pos={1},base={2}",
435 BSScene.DetailLogZero, pos, terrainBaseXYZ); 435 BSScene.DetailLogZero, pos, terrainBaseXYZ);
436 } 436 }
@@ -451,8 +451,8 @@ public sealed class BSTerrainManager : IDisposable
451 } 451 }
452 else 452 else
453 { 453 {
454 PhysicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}", 454 m_physicsScene.Logger.ErrorFormat("{0} GetWaterHeightAtXY: terrain not found: pos={1}, terrainBase={2}, height={3}",
455 LogHeader, PhysicsScene.RegionName, pos, terrainBaseXYZ, ret); 455 LogHeader, m_physicsScene.RegionName, pos, terrainBaseXYZ, ret);
456 } 456 }
457 return ret; 457 return ret;
458 } 458 }
@@ -564,7 +564,7 @@ public sealed class BSTerrainManager : IDisposable
564 564
565 private void DetailLog(string msg, params Object[] args) 565 private void DetailLog(string msg, params Object[] args)
566 { 566 {
567 PhysicsScene.PhysicsLogging.Write(msg, args); 567 m_physicsScene.PhysicsLogging.Write(msg, args);
568 } 568 }
569} 569}
570} 570}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
index 2ce1513..e4ca098 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
@@ -51,7 +51,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
51 BulletShape m_terrainShape; 51 BulletShape m_terrainShape;
52 BulletBody m_terrainBody; 52 BulletBody m_terrainBody;
53 53
54 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize) 54 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
55 : base(physicsScene, regionBase, id) 55 : base(physicsScene, regionBase, id)
56 { 56 {
57 } 57 }
@@ -62,7 +62,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
62 } 62 }
63 63
64 // Create terrain mesh from a heightmap. 64 // Create terrain mesh from a heightmap.
65 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap, 65 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
66 Vector3 minCoords, Vector3 maxCoords) 66 Vector3 minCoords, Vector3 maxCoords)
67 : base(physicsScene, regionBase, id) 67 : base(physicsScene, regionBase, id)
68 { 68 {
@@ -80,7 +80,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
80 if (BSParam.TerrainMeshMagnification == 1) 80 if (BSParam.TerrainMeshMagnification == 1)
81 { 81 {
82 // If a magnification of one, use the old routine that is tried and true. 82 // If a magnification of one, use the old routine that is tried and true.
83 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, 83 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh(m_physicsScene,
84 initialMap, m_sizeX, m_sizeY, // input size 84 initialMap, m_sizeX, m_sizeY, // input size
85 Vector3.Zero, // base for mesh 85 Vector3.Zero, // base for mesh
86 out indicesCount, out indices, out verticesCount, out vertices); 86 out indicesCount, out indices, out verticesCount, out vertices);
@@ -88,7 +88,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
88 else 88 else
89 { 89 {
90 // Other magnifications use the newer routine 90 // Other magnifications use the newer routine
91 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh2(PhysicsScene, 91 meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh2(m_physicsScene,
92 initialMap, m_sizeX, m_sizeY, // input size 92 initialMap, m_sizeX, m_sizeY, // input size
93 BSParam.TerrainMeshMagnification, 93 BSParam.TerrainMeshMagnification,
94 physicsScene.TerrainManager.DefaultRegionSize, 94 physicsScene.TerrainManager.DefaultRegionSize,
@@ -98,21 +98,21 @@ public sealed class BSTerrainMesh : BSTerrainPhys
98 if (!meshCreationSuccess) 98 if (!meshCreationSuccess)
99 { 99 {
100 // DISASTER!! 100 // DISASTER!!
101 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, ID); 101 m_physicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap,id={1}", BSScene.DetailLogZero, ID);
102 PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase); 102 m_physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
103 // Something is very messed up and a crash is in our future. 103 // Something is very messed up and a crash is in our future.
104 return; 104 return;
105 } 105 }
106 106
107 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}", 107 m_physicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,id={1},indices={2},indSz={3},vertices={4},vertSz={5}",
108 BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length); 108 BSScene.DetailLogZero, ID, indicesCount, indices.Length, verticesCount, vertices.Length);
109 109
110 m_terrainShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, indicesCount, indices, verticesCount, vertices); 110 m_terrainShape = m_physicsScene.PE.CreateMeshShape(m_physicsScene.World, indicesCount, indices, verticesCount, vertices);
111 if (!m_terrainShape.HasPhysicalShape) 111 if (!m_terrainShape.HasPhysicalShape)
112 { 112 {
113 // DISASTER!! 113 // DISASTER!!
114 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, ID); 114 m_physicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape,id={1}", BSScene.DetailLogZero, ID);
115 PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase); 115 m_physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
116 // Something is very messed up and a crash is in our future. 116 // Something is very messed up and a crash is in our future.
117 return; 117 return;
118 } 118 }
@@ -120,52 +120,52 @@ public sealed class BSTerrainMesh : BSTerrainPhys
120 Vector3 pos = regionBase; 120 Vector3 pos = regionBase;
121 Quaternion rot = Quaternion.Identity; 121 Quaternion rot = Quaternion.Identity;
122 122
123 m_terrainBody = PhysicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot); 123 m_terrainBody = m_physicsScene.PE.CreateBodyWithDefaultMotionState(m_terrainShape, ID, pos, rot);
124 if (!m_terrainBody.HasPhysicalBody) 124 if (!m_terrainBody.HasPhysicalBody)
125 { 125 {
126 // DISASTER!! 126 // DISASTER!!
127 PhysicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); 127 m_physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
128 // Something is very messed up and a crash is in our future. 128 // Something is very messed up and a crash is in our future.
129 return; 129 return;
130 } 130 }
131 physicsScene.PE.SetShapeCollisionMargin(m_terrainShape, BSParam.TerrainCollisionMargin); 131 physicsScene.PE.SetShapeCollisionMargin(m_terrainShape, BSParam.TerrainCollisionMargin);
132 132
133 // Set current terrain attributes 133 // Set current terrain attributes
134 PhysicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction); 134 m_physicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction);
135 PhysicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction); 135 m_physicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction);
136 PhysicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution); 136 m_physicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution);
137 PhysicsScene.PE.SetContactProcessingThreshold(m_terrainBody, BSParam.TerrainContactProcessingThreshold); 137 m_physicsScene.PE.SetContactProcessingThreshold(m_terrainBody, BSParam.TerrainContactProcessingThreshold);
138 PhysicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT); 138 m_physicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT);
139 139
140 // Static objects are not very massive. 140 // Static objects are not very massive.
141 PhysicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero); 141 m_physicsScene.PE.SetMassProps(m_terrainBody, 0f, Vector3.Zero);
142 142
143 // Put the new terrain to the world of physical objects 143 // Put the new terrain to the world of physical objects
144 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, m_terrainBody); 144 m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, m_terrainBody);
145 145
146 // Redo its bounding box now that it is in the world 146 // Redo its bounding box now that it is in the world
147 PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, m_terrainBody); 147 m_physicsScene.PE.UpdateSingleAabb(m_physicsScene.World, m_terrainBody);
148 148
149 m_terrainBody.collisionType = CollisionType.Terrain; 149 m_terrainBody.collisionType = CollisionType.Terrain;
150 m_terrainBody.ApplyCollisionMask(PhysicsScene); 150 m_terrainBody.ApplyCollisionMask(m_physicsScene);
151 151
152 if (BSParam.UseSingleSidedMeshes) 152 if (BSParam.UseSingleSidedMeshes)
153 { 153 {
154 PhysicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id); 154 m_physicsScene.DetailLog("{0},BSTerrainMesh.settingCustomMaterial,id={1}", BSScene.DetailLogZero, id);
155 PhysicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK); 155 m_physicsScene.PE.AddToCollisionFlags(m_terrainBody, CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
156 } 156 }
157 157
158 // Make it so the terrain will not move or be considered for movement. 158 // Make it so the terrain will not move or be considered for movement.
159 PhysicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION); 159 m_physicsScene.PE.ForceActivationState(m_terrainBody, ActivationState.DISABLE_SIMULATION);
160 } 160 }
161 161
162 public override void Dispose() 162 public override void Dispose()
163 { 163 {
164 if (m_terrainBody.HasPhysicalBody) 164 if (m_terrainBody.HasPhysicalBody)
165 { 165 {
166 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, m_terrainBody); 166 m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, m_terrainBody);
167 // Frees both the body and the shape. 167 // Frees both the body and the shape.
168 PhysicsScene.PE.DestroyObject(PhysicsScene.World, m_terrainBody); 168 m_physicsScene.PE.DestroyObject(m_physicsScene.World, m_terrainBody);
169 m_terrainBody.Clear(); 169 m_terrainBody.Clear();
170 m_terrainShape.Clear(); 170 m_terrainShape.Clear();
171 } 171 }
@@ -185,7 +185,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
185 catch 185 catch
186 { 186 {
187 // Sometimes they give us wonky values of X and Y. Give a warning and return something. 187 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
188 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}", 188 m_physicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
189 LogHeader, TerrainBase, pos); 189 LogHeader, TerrainBase, pos);
190 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; 190 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
191 } 191 }
@@ -195,7 +195,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
195 // The passed position is relative to the base of the region. 195 // The passed position is relative to the base of the region.
196 public override float GetWaterLevelAtXYZ(Vector3 pos) 196 public override float GetWaterLevelAtXYZ(Vector3 pos)
197 { 197 {
198 return PhysicsScene.SimpleWaterLevel; 198 return m_physicsScene.SimpleWaterLevel;
199 } 199 }
200 200
201 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2(). 201 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
index 8012d91..d5060e3 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimData.cs
@@ -104,11 +104,11 @@ public class BulletShape
104{ 104{
105 public BulletShape() 105 public BulletShape()
106 { 106 {
107 type = BSPhysicsShapeType.SHAPE_UNKNOWN; 107 shapeType = BSPhysicsShapeType.SHAPE_UNKNOWN;
108 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE; 108 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
109 isNativeShape = false; 109 isNativeShape = false;
110 } 110 }
111 public BSPhysicsShapeType type; 111 public BSPhysicsShapeType shapeType;
112 public System.UInt64 shapeKey; 112 public System.UInt64 shapeKey;
113 public bool isNativeShape; 113 public bool isNativeShape;
114 114
@@ -133,7 +133,7 @@ public class BulletShape
133 buff.Append("<p="); 133 buff.Append("<p=");
134 buff.Append(AddrString); 134 buff.Append(AddrString);
135 buff.Append(",s="); 135 buff.Append(",s=");
136 buff.Append(type.ToString()); 136 buff.Append(shapeType.ToString());
137 buff.Append(",k="); 137 buff.Append(",k=");
138 buff.Append(shapeKey.ToString("X")); 138 buff.Append(shapeKey.ToString("X"));
139 buff.Append(",n="); 139 buff.Append(",n=");
@@ -224,42 +224,42 @@ public static class BulletSimData
224// As mentioned above, don't use the CollisionFilterGroups definitions directly in the code 224// As mentioned above, don't use the CollisionFilterGroups definitions directly in the code
225// but, instead, use references to this dictionary. Finding and debugging 225// but, instead, use references to this dictionary. Finding and debugging
226// collision flag problems will be made easier. 226// collision flag problems will be made easier.
227public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks 227public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks
228 = new Dictionary<CollisionType, CollisionTypeFilterGroup>() 228 = new Dictionary<CollisionType, CollisionTypeFilterGroup>()
229{ 229{
230 { CollisionType.Avatar, 230 { CollisionType.Avatar,
231 new CollisionTypeFilterGroup(CollisionType.Avatar, 231 new CollisionTypeFilterGroup(CollisionType.Avatar,
232 (uint)CollisionFilterGroups.BCharacterGroup, 232 (uint)CollisionFilterGroups.BCharacterGroup,
233 (uint)CollisionFilterGroups.BAllGroup) 233 (uint)CollisionFilterGroups.BAllGroup)
234 }, 234 },
235 { CollisionType.Groundplane, 235 { CollisionType.Groundplane,
236 new CollisionTypeFilterGroup(CollisionType.Groundplane, 236 new CollisionTypeFilterGroup(CollisionType.Groundplane,
237 (uint)CollisionFilterGroups.BGroundPlaneGroup, 237 (uint)CollisionFilterGroups.BGroundPlaneGroup,
238 (uint)CollisionFilterGroups.BAllGroup) 238 (uint)CollisionFilterGroups.BAllGroup)
239 }, 239 },
240 { CollisionType.Terrain, 240 { CollisionType.Terrain,
241 new CollisionTypeFilterGroup(CollisionType.Terrain, 241 new CollisionTypeFilterGroup(CollisionType.Terrain,
242 (uint)CollisionFilterGroups.BTerrainGroup, 242 (uint)CollisionFilterGroups.BTerrainGroup,
243 (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup)) 243 (uint)(CollisionFilterGroups.BAllGroup & ~CollisionFilterGroups.BStaticGroup))
244 }, 244 },
245 { CollisionType.Static, 245 { CollisionType.Static,
246 new CollisionTypeFilterGroup(CollisionType.Static, 246 new CollisionTypeFilterGroup(CollisionType.Static,
247 (uint)CollisionFilterGroups.BStaticGroup, 247 (uint)CollisionFilterGroups.BStaticGroup,
248 (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) 248 (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
249 }, 249 },
250 { CollisionType.Dynamic, 250 { CollisionType.Dynamic,
251 new CollisionTypeFilterGroup(CollisionType.Dynamic, 251 new CollisionTypeFilterGroup(CollisionType.Dynamic,
252 (uint)CollisionFilterGroups.BSolidGroup, 252 (uint)CollisionFilterGroups.BSolidGroup,
253 (uint)(CollisionFilterGroups.BAllGroup)) 253 (uint)(CollisionFilterGroups.BAllGroup))
254 }, 254 },
255 { CollisionType.VolumeDetect, 255 { CollisionType.VolumeDetect,
256 new CollisionTypeFilterGroup(CollisionType.VolumeDetect, 256 new CollisionTypeFilterGroup(CollisionType.VolumeDetect,
257 (uint)CollisionFilterGroups.BSensorTrigger, 257 (uint)CollisionFilterGroups.BSensorTrigger,
258 (uint)(~CollisionFilterGroups.BSensorTrigger)) 258 (uint)(~CollisionFilterGroups.BSensorTrigger))
259 }, 259 },
260 { CollisionType.LinksetChild, 260 { CollisionType.LinksetChild,
261 new CollisionTypeFilterGroup(CollisionType.LinksetChild, 261 new CollisionTypeFilterGroup(CollisionType.LinksetChild,
262 (uint)CollisionFilterGroups.BLinksetChildGroup, 262 (uint)CollisionFilterGroups.BLinksetChildGroup,
263 (uint)(CollisionFilterGroups.BNoneGroup)) 263 (uint)(CollisionFilterGroups.BNoneGroup))
264 // (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup)) 264 // (uint)(CollisionFilterGroups.BCharacterGroup | CollisionFilterGroups.BSolidGroup))
265 }, 265 },
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index 1284ae7..5792ae6 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -1,3 +1,12 @@
1PROBLEMS TO LOOK INTO
2=================================================
3Nebadon vehicle ride, get up, ride again. Second time vehicle does not act correctly.
4 Have to rez new vehicle and delete the old to fix situation.
5Hitting RESET on Nebadon's vehicle while riding causes vehicle to get into odd
6 position state where it will not settle onto ground properly, etc
7Two of Nebadon vehicles in a sim max the CPU. This is new.
8A sitting, active vehicle bobs up and down a small amount.
9
1CURRENT PRIORITIES 10CURRENT PRIORITIES
2================================================= 11=================================================
3Use the HACD convex hull routine in Bullet rather than the C# version. 12Use the HACD convex hull routine in Bullet rather than the C# version.
@@ -11,6 +20,8 @@ Deleting a linkset while standing on the root will leave the physical shape of t
11Linkset child rotations. 20Linkset child rotations.
12 Nebadon spiral tube has middle sections which are rotated wrong. 21 Nebadon spiral tube has middle sections which are rotated wrong.
13 Select linked spiral tube. Delink and note where the middle section ends up. 22 Select linked spiral tube. Delink and note where the middle section ends up.
23Refarb compound linkset creation to create a pseudo-root for center-of-mass
24 Let children change their shape to physical indendently and just add shapes to compound
14Vehicle angular vertical attraction 25Vehicle angular vertical attraction
15vehicle angular banking 26vehicle angular banking
16Center-of-gravity 27Center-of-gravity
@@ -27,14 +38,13 @@ llLookAt
27Avatars walking up stairs (HALF DONE) 38Avatars walking up stairs (HALF DONE)
28Avatar movement 39Avatar movement
29 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE) 40 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
30 walking up stairs is not calibrated correctly (stairs out of Kepler cabin) 41 walking up stairs is not calibrated correctly (stairs out of Kepler cabin) (DONE)
31 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution) 42 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution)
32Vehicle script tuning/debugging 43Vehicle script tuning/debugging
33 Avanti speed script 44 Avanti speed script
34 Weapon shooter script 45 Weapon shooter script
35Move material definitions (friction, ...) into simulator. 46Move material definitions (friction, ...) into simulator.
36Add material densities to the material types. 47Add material densities to the material types.
37Terrain detail: double terrain mesh detail
38One sided meshes? Should terrain be built into a closed shape? 48One sided meshes? Should terrain be built into a closed shape?
39 When meshes get partially wedged into the terrain, they cannot push themselves out. 49 When meshes get partially wedged into the terrain, they cannot push themselves out.
40 It is possible that Bullet processes collisions whether entering or leaving a mesh. 50 It is possible that Bullet processes collisions whether entering or leaving a mesh.
@@ -42,6 +52,9 @@ One sided meshes? Should terrain be built into a closed shape?
42 52
43VEHICLES TODO LIST: 53VEHICLES TODO LIST:
44================================================= 54=================================================
55LINEAR_MOTOR_DIRECTION values should be clamped to reasonable numbers.
56 What are the limits in SL?
57 Same for other velocity settings.
45UBit improvements to remove rubber-banding of avatars sitting on vehicle child prims: 58UBit improvements to remove rubber-banding of avatars sitting on vehicle child prims:
46 https://github.com/UbitUmarov/Ubit-opensim 59 https://github.com/UbitUmarov/Ubit-opensim
47Border crossing with linked vehicle causes crash 60Border crossing with linked vehicle causes crash
@@ -347,4 +360,5 @@ Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
347 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates. 360 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates.
348Nebadon vehicles turning funny in arena (DONE) 361Nebadon vehicles turning funny in arena (DONE)
349Lock axis (DONE 20130401) 362Lock axis (DONE 20130401)
363Terrain detail: double terrain mesh detail (DONE)
350 364