diff options
author | Melanie | 2013-05-04 01:22:12 +0100 |
---|---|---|
committer | Melanie | 2013-05-04 01:22:12 +0100 |
commit | 3aa83738e2a845d05bb25ab81634d0540971c0bf (patch) | |
tree | 411d946b817b020c72f3d9a35926215e28bf2d95 /OpenSim/Region/Physics/BulletSPlugin | |
parent | Merge branch 'master' into careminster (diff) | |
parent | Merge branch 'master' into bulletsim4 (diff) | |
download | opensim-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')
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 | |||
75 | private sealed class BulletShapeUnman : BulletShape | 75 | private 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 | ||
381 | public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape) | 381 | public override bool DeleteCollisionShape(BulletWorld world, BulletShape shape) |
@@ -1503,7 +1503,7 @@ public static extern void DestroyObject2(IntPtr sim, IntPtr obj); | |||
1503 | public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin); | 1503 | public 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] |
1506 | public static extern IntPtr CreateTerrainShape2(uint id, Vector3 size, float minHeight, float maxHeight, | 1506 | public 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 | |||
81 | private sealed class BulletShapeXNA : BulletShape | 81 | private 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 |
300 | public abstract string BulletEngineName { get; } | 300 | public abstract string BulletEngineName { get; } |
301 | public abstract string BulletEngineVersion { get; protected set;} | 301 | public abstract string BulletEngineVersion { get; protected set;} |
302 | 302 | ||
303 | // Initialization and simulation | 303 | // Initialization and simulation |
304 | public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms, | 304 | public abstract BulletWorld Initialize(Vector3 maxPosition, ConfigurationParameters parms, |
@@ -373,7 +373,7 @@ public abstract void DestroyObject(BulletWorld sim, BulletBody obj); | |||
373 | // ===================================================================================== | 373 | // ===================================================================================== |
374 | public abstract BulletShape CreateGroundPlaneShape(UInt32 id, float height, float collisionMargin); | 374 | public abstract BulletShape CreateGroundPlaneShape(UInt32 id, float height, float collisionMargin); |
375 | 375 | ||
376 | public abstract BulletShape CreateTerrainShape(UInt32 id, Vector3 size, float minHeight, float maxHeight, float[] heightMap, | 376 | public 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 | ||
390 | public abstract BulletConstraint Create6DofConstraintFixed(BulletWorld world, BulletBody obj1, | 390 | public 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 | ||
394 | public abstract BulletConstraint Create6DofSpringConstraint(BulletWorld world, BulletBody obj1, BulletBody obj2, | 394 | public 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; | |||
35 | namespace OpenSim.Region.Physics.BulletSPlugin | 35 | namespace 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 | ||
92 | public sealed class BSLinksetCompound : BSLinkset | 94 | public 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 | { |
38 | public static class BSParam | 38 | public 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 | ||
32 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | using OpenSim.Region.Physics.Manager; | 33 | using OpenSim.Region.Physics.Manager; |
34 | using OpenSim.Region.Physics.ConvexDecompositionDotNet; | ||
34 | 35 | ||
35 | using OMV = OpenMetaverse; | 36 | using OMV = OpenMetaverse; |
36 | 37 | ||
@@ -38,74 +39,39 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
38 | { | 39 | { |
39 | public abstract class BSShape | 40 | public 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 | |||
209 | public class BSShapeMesh : BSShape | 342 | public 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 | |||
326 | public class BSShapeHull : BSShape | 497 | public 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 | |||
344 | public class BSShapeCompound : BSShape | 737 | public 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 | // ============================================================================================================ | ||
832 | public 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. |
227 | public static Dictionary<CollisionType, CollisionTypeFilterGroup> CollisionTypeMasks | 227 | public 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 @@ | |||
1 | PROBLEMS TO LOOK INTO | ||
2 | ================================================= | ||
3 | Nebadon 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. | ||
5 | Hitting 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 | ||
7 | Two of Nebadon vehicles in a sim max the CPU. This is new. | ||
8 | A sitting, active vehicle bobs up and down a small amount. | ||
9 | |||
1 | CURRENT PRIORITIES | 10 | CURRENT PRIORITIES |
2 | ================================================= | 11 | ================================================= |
3 | Use the HACD convex hull routine in Bullet rather than the C# version. | 12 | Use 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 | |||
11 | Linkset child rotations. | 20 | Linkset 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. |
23 | Refarb 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 | ||
14 | Vehicle angular vertical attraction | 25 | Vehicle angular vertical attraction |
15 | vehicle angular banking | 26 | vehicle angular banking |
16 | Center-of-gravity | 27 | Center-of-gravity |
@@ -27,14 +38,13 @@ llLookAt | |||
27 | Avatars walking up stairs (HALF DONE) | 38 | Avatars walking up stairs (HALF DONE) |
28 | Avatar movement | 39 | Avatar 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) |
32 | Vehicle script tuning/debugging | 43 | Vehicle script tuning/debugging |
33 | Avanti speed script | 44 | Avanti speed script |
34 | Weapon shooter script | 45 | Weapon shooter script |
35 | Move material definitions (friction, ...) into simulator. | 46 | Move material definitions (friction, ...) into simulator. |
36 | Add material densities to the material types. | 47 | Add material densities to the material types. |
37 | Terrain detail: double terrain mesh detail | ||
38 | One sided meshes? Should terrain be built into a closed shape? | 48 | One 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 | ||
43 | VEHICLES TODO LIST: | 53 | VEHICLES TODO LIST: |
44 | ================================================= | 54 | ================================================= |
55 | LINEAR_MOTOR_DIRECTION values should be clamped to reasonable numbers. | ||
56 | What are the limits in SL? | ||
57 | Same for other velocity settings. | ||
45 | UBit improvements to remove rubber-banding of avatars sitting on vehicle child prims: | 58 | UBit 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 |
47 | Border crossing with linked vehicle causes crash | 60 | Border 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. |
348 | Nebadon vehicles turning funny in arena (DONE) | 361 | Nebadon vehicles turning funny in arena (DONE) |
349 | Lock axis (DONE 20130401) | 362 | Lock axis (DONE 20130401) |
363 | Terrain detail: double terrain mesh detail (DONE) | ||
350 | 364 | ||