aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs13
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs19
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs106
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs4
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs52
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs12
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs152
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs21
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs15
10 files changed, 274 insertions, 132 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 9e1206a..2a5397e 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -200,7 +200,9 @@ public sealed class BSCharacter : BSPhysObject
200 } 200 }
201 // I want the physics engine to make an avatar capsule 201 // I want the physics engine to make an avatar capsule
202 public override ShapeData.PhysicsShapeType PreferredPhysicalShape 202 public override ShapeData.PhysicsShapeType PreferredPhysicalShape
203 { get { return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } } 203 {
204 get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; }
205 }
204 206
205 public override bool Grabbed { 207 public override bool Grabbed {
206 set { _grabbed = value; } 208 set { _grabbed = value; }
@@ -238,6 +240,7 @@ public sealed class BSCharacter : BSPhysObject
238 } 240 }
239 public override OMV.Vector3 Position { 241 public override OMV.Vector3 Position {
240 get { 242 get {
243 // Don't refetch the position because this function is called a zillion times
241 // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); 244 // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID);
242 return _position; 245 return _position;
243 } 246 }
@@ -304,15 +307,11 @@ public sealed class BSCharacter : BSPhysObject
304 { 307 {
305 // The new position value must be pushed into the physics engine but we can't 308 // The new position value must be pushed into the physics engine but we can't
306 // just assign to "Position" because of potential call loops. 309 // just assign to "Position" because of potential call loops.
307 BSScene.TaintCallback sanityOperation = delegate() 310 PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate()
308 { 311 {
309 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 312 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
310 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 313 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
311 }; 314 });
312 if (inTaintTime)
313 sanityOperation();
314 else
315 PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation);
316 ret = true; 315 ret = true;
317 } 316 }
318 return ret; 317 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 9e0f499..8f973f4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -48,7 +48,8 @@ public abstract class BSLinkset
48 */ 48 */
49 49
50 // at the moment, there is only one 50 // at the moment, there is only one
51 ret = new BSLinksetConstraints(physScene, parent); 51 // ret = new BSLinksetConstraints(physScene, parent);
52 ret = new BSLinksetCompound(physScene, parent);
52 53
53 return ret; 54 return ret;
54 } 55 }
@@ -69,10 +70,19 @@ public abstract class BSLinkset
69 protected object m_linksetActivityLock = new Object(); 70 protected object m_linksetActivityLock = new Object();
70 71
71 // Some linksets have a preferred physical shape. 72 // Some linksets have a preferred physical shape.
72 // Returns SHAPE_UNKNOWN if there is no preference. 73 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
73 public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape 74 public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
74 { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } 75 {
76 return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
77 }
75 78
79 // Linksets move around the children so the linkset might need to compute the child position
80 public virtual OMV.Vector3 Position(BSPhysObject member)
81 { return member.RawPosition; }
82 public virtual OMV.Quaternion Orientation(BSPhysObject member)
83 { return member.RawOrientation; }
84 // TODO: does this need to be done for Velocity and RotationalVelocityy?
85
76 // We keep the prim's mass in the linkset structure since it could be dependent on other prims 86 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
77 protected float m_mass; 87 protected float m_mass;
78 public float LinksetMass 88 public float LinksetMass
@@ -177,7 +187,6 @@ public abstract class BSLinkset
177 } 187 }
178 188
179 // Perform an action on each member of the linkset including root prim. 189 // Perform an action on each member of the linkset including root prim.
180 // The action is performed only on the objects that are physically in the linkset.
181 // Depends on the action on whether this should be done at taint time. 190 // Depends on the action on whether this should be done at taint time.
182 public delegate bool ForEachMemberAction(BSPhysObject obj); 191 public delegate bool ForEachMemberAction(BSPhysObject obj);
183 public virtual bool ForEachMember(ForEachMemberAction action) 192 public virtual bool ForEachMember(ForEachMemberAction action)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index 638fae1..8b97ebb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -41,18 +41,31 @@ public sealed class BSLinksetCompound : BSLinkset
41 base.Initialize(scene, parent); 41 base.Initialize(scene, parent);
42 } 42 }
43 43
44 // For compound implimented linksets, if there are children, use compound shape for the root.
45 public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
46 {
47 ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
48 if (IsRoot(requestor) && HasAnyChildren)
49 {
50 ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND;
51 }
52 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
53 return ret;
54 }
55
44 // When physical properties are changed the linkset needs to recalculate 56 // When physical properties are changed the linkset needs to recalculate
45 // its internal properties. 57 // its internal properties.
46 // This is queued in the 'post taint' queue so the 58 // This is queued in the 'post taint' queue so the
47 // refresh will happen once after all the other taints are applied. 59 // refresh will happen once after all the other taints are applied.
48 public override void Refresh(BSPhysObject requestor) 60 public override void Refresh(BSPhysObject requestor)
49 { 61 {
62 DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID);
50 // Queue to happen after all the other taint processing 63 // Queue to happen after all the other taint processing
51 PhysicsScene.PostTaintObject("BSLinksetcompound.Refresh", requestor.LocalID, delegate() 64 PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate()
52 { 65 {
53 if (HasAnyChildren && IsRoot(requestor)) 66 if (IsRoot(requestor) && HasAnyChildren)
54 RecomputeLinksetCompound(); 67 RecomputeLinksetCompound();
55 }); 68 });
56 } 69 }
57 70
58 // The object is going dynamic (physical). Do any setup necessary 71 // The object is going dynamic (physical). Do any setup necessary
@@ -63,8 +76,17 @@ public sealed class BSLinksetCompound : BSLinkset
63 // Called at taint-time! 76 // Called at taint-time!
64 public override bool MakeDynamic(BSPhysObject child) 77 public override bool MakeDynamic(BSPhysObject child)
65 { 78 {
66 // What is done for each object in BSPrim is what we want. 79 bool ret = false;
67 return false; 80 DetailLog("{0},BSLinksetCompound.MakeDynamic,call,isChild={1}", child.LocalID, HasChild(child));
81 if (HasChild(child))
82 {
83 // Physical children are removed from the world as the shape ofthe root compound
84 // shape takes over.
85 BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
86 BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION);
87 ret = true;
88 }
89 return ret;
68 } 90 }
69 91
70 // The object is going static (non-physical). Do any setup necessary for a static linkset. 92 // The object is going static (non-physical). Do any setup necessary for a static linkset.
@@ -74,8 +96,17 @@ public sealed class BSLinksetCompound : BSLinkset
74 // Called at taint-time! 96 // Called at taint-time!
75 public override bool MakeStatic(BSPhysObject child) 97 public override bool MakeStatic(BSPhysObject child)
76 { 98 {
77 // What is done for each object in BSPrim is what we want. 99 bool ret = false;
78 return false; 100 DetailLog("{0},BSLinksetCompound.MakeStatic,call,hasChild={1}", child.LocalID, HasChild(child));
101 if (HasChild(child))
102 {
103 // The non-physical children can come back to life.
104 BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
105 // Don't force activation so setting of DISABLE_SIMULATION can stay.
106 BulletSimAPI.Activate2(child.PhysBody.ptr, false);
107 ret = true;
108 }
109 return ret;
79 } 110 }
80 111
81 // Called at taint-time!! 112 // Called at taint-time!!
@@ -84,20 +115,35 @@ public sealed class BSLinksetCompound : BSLinkset
84 // Nothing to do for constraints on property updates 115 // Nothing to do for constraints on property updates
85 } 116 }
86 117
118 // The children move around in relationship to the root.
119 // Just grab the current values of wherever it is right now.
120 public override OMV.Vector3 Position(BSPhysObject member)
121 {
122 return BulletSimAPI.GetPosition2(member.PhysBody.ptr);
123 }
124
125 public override OMV.Quaternion Orientation(BSPhysObject member)
126 {
127 return BulletSimAPI.GetOrientation2(member.PhysBody.ptr);
128 }
129
87 // Routine called when rebuilding the body of some member of the linkset. 130 // Routine called when rebuilding the body of some member of the linkset.
88 // Destroy all the constraints have have been made to root and set 131 // Since we don't keep in-physical world relationships, do nothing unless it's a child changing.
89 // up to rebuild the constraints before the next simulation step.
90 // Returns 'true' of something was actually removed and would need restoring 132 // Returns 'true' of something was actually removed and would need restoring
91 // Called at taint-time!! 133 // Called at taint-time!!
92 public override bool RemoveBodyDependencies(BSPrim child) 134 public override bool RemoveBodyDependencies(BSPrim child)
93 { 135 {
94 bool ret = false; 136 bool ret = false;
95 137
96 DetailLog("{0},BSLinksetcompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", 138 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2},isRoot={3}",
97 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); 139 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child));
98 140
99 // Cause the current shape to be freed and the new one to be built. 141 if (!IsRoot(child))
100 Refresh(LinksetRoot); 142 {
143 // Cause the current shape to be freed and the new one to be built.
144 Refresh(LinksetRoot);
145 ret = true;
146 }
101 147
102 return ret; 148 return ret;
103 } 149 }
@@ -139,13 +185,19 @@ public sealed class BSLinksetCompound : BSLinkset
139 LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), 185 LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"),
140 child.LocalID, child.PhysBody.ptr.ToString("X")); 186 child.LocalID, child.PhysBody.ptr.ToString("X"));
141 187
142 // See that the linkset parameters are recomputed at the end of the taint time. 188 // Cause the child's body to be rebuilt and thus restored to normal operation
143 Refresh(LinksetRoot); 189 child.ForceBodyShapeRebuild(false);
144 } 190
145 else 191 if (!HasAnyChildren)
146 { 192 {
147 // Non-fatal occurance. 193 // The linkset is now empty. The root needs rebuilding.
148 // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); 194 LinksetRoot.ForceBodyShapeRebuild(false);
195 }
196 else
197 {
198 // Schedule a rebuild of the linkset before the next simulation tick.
199 Refresh(LinksetRoot);
200 }
149 } 201 }
150 return; 202 return;
151 } 203 }
@@ -158,16 +210,18 @@ public sealed class BSLinksetCompound : BSLinkset
158 // Called at taint time!! 210 // Called at taint time!!
159 private void RecomputeLinksetCompound() 211 private void RecomputeLinksetCompound()
160 { 212 {
161 // Release the existing shape 213 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},numChildren={2}",
162 PhysicsScene.Shapes.DereferenceShape(LinksetRoot.PhysShape, true, null); 214 LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), NumberOfChildren);
163 215
216 LinksetRoot.ForceBodyShapeRebuild(true);
217
164 float linksetMass = LinksetMass; 218 float linksetMass = LinksetMass;
165 LinksetRoot.UpdatePhysicalMassProperties(linksetMass); 219 LinksetRoot.UpdatePhysicalMassProperties(linksetMass);
166 220
167 // DEBUG: see of inter-linkset collisions are causing problems 221 // DEBUG: see of inter-linkset collisions are causing problems
168 // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, 222 // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr,
169 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); 223 // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask);
170 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,set,rBody={1},linksetMass={2}", 224 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,end,rBody={1},linksetMass={2}",
171 LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); 225 LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass);
172 226
173 227
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index 65aed77..67a59ef 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -84,6 +84,18 @@ public sealed class BSLinksetConstraints : BSLinkset
84 // Nothing to do for constraints on property updates 84 // Nothing to do for constraints on property updates
85 } 85 }
86 86
87 // The children of the linkset are moved around by the constraints.
88 // Just grab the current values of wherever it is right now.
89 public override OMV.Vector3 Position(BSPhysObject member)
90 {
91 return BulletSimAPI.GetPosition2(member.PhysBody.ptr);
92 }
93
94 public override OMV.Quaternion Orientation(BSPhysObject member)
95 {
96 return BulletSimAPI.GetOrientation2(member.PhysBody.ptr);
97 }
98
87 // Routine called when rebuilding the body of some member of the linkset. 99 // Routine called when rebuilding the body of some member of the linkset.
88 // Destroy all the constraints have have been made to root and set 100 // Destroy all the constraints have have been made to root and set
89 // up to rebuild the constraints before the next simulation step. 101 // up to rebuild the constraints before the next simulation step.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 65d7f34..7127aaf 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -81,7 +81,9 @@ public abstract class BSPhysObject : PhysicsActor
81 // Some types of objects have preferred physical representations. 81 // Some types of objects have preferred physical representations.
82 // Returns SHAPE_UNKNOWN if there is no preference. 82 // Returns SHAPE_UNKNOWN if there is no preference.
83 public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape 83 public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape
84 { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } 84 {
85 get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; }
86 }
85 87
86 // When the physical properties are updated, an EntityProperty holds the update values. 88 // When the physical properties are updated, an EntityProperty holds the update values.
87 // Keep the current and last EntityProperties to enable computation of differences 89 // Keep the current and last EntityProperties to enable computation of differences
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 1754be6..af403aa 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -173,20 +173,16 @@ public sealed class BSPrim : BSPhysObject
173 } 173 }
174 // Whatever the linkset wants is what I want. 174 // Whatever the linkset wants is what I want.
175 public override ShapeData.PhysicsShapeType PreferredPhysicalShape 175 public override ShapeData.PhysicsShapeType PreferredPhysicalShape
176 { get { return Linkset.PreferredPhysicalShape; } } 176 { get { return Linkset.PreferredPhysicalShape(this); } }
177 177
178 public override bool ForceBodyShapeRebuild(bool inTaintTime) 178 public override bool ForceBodyShapeRebuild(bool inTaintTime)
179 { 179 {
180 LastAssetBuildFailed = false; 180 LastAssetBuildFailed = false;
181 BSScene.TaintCallback rebuildOperation = delegate() 181 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate()
182 { 182 {
183 _mass = CalculateMass(); // changing the shape changes the mass 183 _mass = CalculateMass(); // changing the shape changes the mass
184 CreateGeomAndObject(true); 184 CreateGeomAndObject(true);
185 }; 185 });
186 if (inTaintTime)
187 rebuildOperation();
188 else
189 PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation);
190 return true; 186 return true;
191 } 187 }
192 public override bool Grabbed { 188 public override bool Grabbed {
@@ -263,9 +259,9 @@ public sealed class BSPrim : BSPhysObject
263 } 259 }
264 public override OMV.Vector3 Position { 260 public override OMV.Vector3 Position {
265 get { 261 get {
262 // child prims move around based on their parent. Need to get the latest location
266 if (!Linkset.IsRoot(this)) 263 if (!Linkset.IsRoot(this))
267 // child prims move around based on their parent. Need to get the latest location 264 _position = Linkset.Position(this);
268 _position = BulletSimAPI.GetPosition2(PhysBody.ptr);
269 265
270 // don't do the GetObjectPosition for root elements because this function is called a zillion times 266 // don't do the GetObjectPosition for root elements because this function is called a zillion times
271 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); 267 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
@@ -344,16 +340,11 @@ public sealed class BSPrim : BSPhysObject
344 { 340 {
345 // The new position value must be pushed into the physics engine but we can't 341 // The new position value must be pushed into the physics engine but we can't
346 // just assign to "Position" because of potential call loops. 342 // just assign to "Position" because of potential call loops.
347 BSScene.TaintCallback sanityOperation = delegate() 343 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate()
348 { 344 {
349 DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); 345 DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
350 ForcePosition = _position; 346 ForcePosition = _position;
351 }; 347 });
352 if (inTaintTime)
353 sanityOperation();
354 else
355 PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation);
356
357 ret = true; 348 ret = true;
358 } 349 }
359 return ret; 350 return ret;
@@ -542,10 +533,10 @@ public sealed class BSPrim : BSPhysObject
542 } 533 }
543 public override OMV.Quaternion Orientation { 534 public override OMV.Quaternion Orientation {
544 get { 535 get {
536 // Children move around because tied to parent. Get a fresh value.
545 if (!Linkset.IsRoot(this)) 537 if (!Linkset.IsRoot(this))
546 { 538 {
547 // Children move around because tied to parent. Get a fresh value. 539 _orientation = Linkset.Orientation(this);
548 _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr);
549 } 540 }
550 return _orientation; 541 return _orientation;
551 } 542 }
@@ -946,7 +937,7 @@ public sealed class BSPrim : BSPhysObject
946 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 937 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
947 return; 938 return;
948 } 939 }
949 BSScene.TaintCallback addForceOperation = delegate() 940 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate()
950 { 941 {
951 OMV.Vector3 fSum = OMV.Vector3.Zero; 942 OMV.Vector3 fSum = OMV.Vector3.Zero;
952 lock (m_accumulatedForces) 943 lock (m_accumulatedForces)
@@ -961,11 +952,7 @@ public sealed class BSPrim : BSPhysObject
961 DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); 952 DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum);
962 if (fSum != OMV.Vector3.Zero) 953 if (fSum != OMV.Vector3.Zero)
963 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); 954 BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum);
964 }; 955 });
965 if (inTaintTime)
966 addForceOperation();
967 else
968 PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation);
969 } 956 }
970 957
971 private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>(); 958 private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>();
@@ -985,7 +972,7 @@ public sealed class BSPrim : BSPhysObject
985 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); 972 m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID);
986 return; 973 return;
987 } 974 }
988 BSScene.TaintCallback addAngularForceOperation = delegate() 975 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate()
989 { 976 {
990 OMV.Vector3 fSum = OMV.Vector3.Zero; 977 OMV.Vector3 fSum = OMV.Vector3.Zero;
991 lock (m_accumulatedAngularForces) 978 lock (m_accumulatedAngularForces)
@@ -1003,26 +990,19 @@ public sealed class BSPrim : BSPhysObject
1003 BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); 990 BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum);
1004 _torque = fSum; 991 _torque = fSum;
1005 } 992 }
1006 }; 993 });
1007 if (inTaintTime)
1008 addAngularForceOperation();
1009 else
1010 PhysicsScene.TaintedObject("BSPrim.AddAngularForce", addAngularForceOperation);
1011 } 994 }
1012 // A torque impulse. 995 // A torque impulse.
1013 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) 996 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1014 { 997 {
1015 OMV.Vector3 applyImpulse = impulse; 998 OMV.Vector3 applyImpulse = impulse;
1016 BSScene.TaintCallback applyTorqueImpulseOperation = delegate() 999 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate()
1017 { 1000 {
1018 DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); 1001 DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse);
1019 BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); 1002 BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse);
1020 }; 1003 });
1021 if (inTaintTime)
1022 applyTorqueImpulseOperation();
1023 else
1024 PhysicsScene.TaintedObject("BSPrim.ApplyTorqueImpulse", applyTorqueImpulseOperation);
1025 } 1004 }
1005
1026 public override void SetMomentum(OMV.Vector3 momentum) { 1006 public override void SetMomentum(OMV.Vector3 momentum) {
1027 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); 1007 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
1028 } 1008 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index cc5dbb2..dcfcb83 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -692,6 +692,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
692 return; 692 return;
693 } 693 }
694 694
695 // Sometimes a potentially tainted operation can be used in and out of taint time.
696 // This routine executes the command immediately if in taint-time otherwise it is queued.
697 public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback)
698 {
699 if (inTaintTime)
700 callback();
701 else
702 TaintedObject(ident, callback);
703 }
704
695 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues 705 // When someone tries to change a property on a BSPrim or BSCharacter, the object queues
696 // a callback into itself to do the actual property change. That callback is called 706 // a callback into itself to do the actual property change. That callback is called
697 // here just before the physics engine is called to step the simulation. 707 // here just before the physics engine is called to step the simulation.
@@ -1438,7 +1448,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1438 { 1448 {
1439 PhysicsLogging.Write(msg, args); 1449 PhysicsLogging.Write(msg, args);
1440 // Add the Flush() if debugging crashes to get all the messages written out. 1450 // Add the Flush() if debugging crashes to get all the messages written out.
1441 // PhysicsLogging.Flush(); 1451 PhysicsLogging.Flush();
1442 } 1452 }
1443 // Used to fill in the LocalID when there isn't one. It's the correct number of characters. 1453 // Used to fill in the LocalID when there isn't one. It's the correct number of characters.
1444 public const string DetailLogZero = "0000000000"; 1454 public const string DetailLogZero = "0000000000";
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index e131919..107befe 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -122,18 +122,14 @@ public sealed class BSShapeCollection : IDisposable
122 lock (m_collectionActivityLock) 122 lock (m_collectionActivityLock)
123 { 123 {
124 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); 124 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body);
125 BSScene.TaintCallback createOperation = delegate() 125 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate()
126 { 126 {
127 if (!BulletSimAPI.IsInWorld2(body.ptr)) 127 if (!BulletSimAPI.IsInWorld2(body.ptr))
128 { 128 {
129 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); 129 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
130 DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); 130 DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
131 } 131 }
132 }; 132 });
133 if (inTaintTime)
134 createOperation();
135 else
136 PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation);
137 } 133 }
138 } 134 }
139 135
@@ -146,7 +142,7 @@ public sealed class BSShapeCollection : IDisposable
146 142
147 lock (m_collectionActivityLock) 143 lock (m_collectionActivityLock)
148 { 144 {
149 BSScene.TaintCallback removeOperation = delegate() 145 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate()
150 { 146 {
151 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", 147 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}",
152 body.ID, body.ptr.ToString("X"), inTaintTime); 148 body.ID, body.ptr.ToString("X"), inTaintTime);
@@ -159,12 +155,7 @@ public sealed class BSShapeCollection : IDisposable
159 // Zero any reference to the shape so it is not freed when the body is deleted. 155 // Zero any reference to the shape so it is not freed when the body is deleted.
160 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); 156 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
161 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); 157 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
162 }; 158 });
163 // If already in taint-time, do the operations now. Otherwise queue for later.
164 if (inTaintTime)
165 removeOperation();
166 else
167 PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation);
168 } 159 }
169 } 160 }
170 161
@@ -238,7 +229,7 @@ public sealed class BSShapeCollection : IDisposable
238 if (shape.ptr == IntPtr.Zero) 229 if (shape.ptr == IntPtr.Zero)
239 return; 230 return;
240 231
241 BSScene.TaintCallback dereferenceOperation = delegate() 232 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate()
242 { 233 {
243 if (shape.ptr != IntPtr.Zero) 234 if (shape.ptr != IntPtr.Zero)
244 { 235 {
@@ -270,18 +261,7 @@ public sealed class BSShapeCollection : IDisposable
270 } 261 }
271 } 262 }
272 } 263 }
273 }; 264 });
274 if (inTaintTime)
275 {
276 lock (m_collectionActivityLock)
277 {
278 dereferenceOperation();
279 }
280 }
281 else
282 {
283 PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation);
284 }
285 } 265 }
286 266
287 // Count down the reference count for a mesh shape 267 // Count down the reference count for a mesh shape
@@ -311,7 +291,10 @@ public sealed class BSShapeCollection : IDisposable
311 { 291 {
312 hullDesc.referenceCount--; 292 hullDesc.referenceCount--;
313 // TODO: release the Bullet storage (aging old entries?) 293 // TODO: release the Bullet storage (aging old entries?)
294
295 // Tell upper layers that, if they have dependencies on this shape, this link is going away
314 if (shapeCallback != null) shapeCallback(shape); 296 if (shapeCallback != null) shapeCallback(shape);
297
315 hullDesc.lastReferenced = System.DateTime.Now; 298 hullDesc.lastReferenced = System.DateTime.Now;
316 Hulls[shape.shapeKey] = hullDesc; 299 Hulls[shape.shapeKey] = hullDesc;
317 DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", 300 DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}",
@@ -320,10 +303,48 @@ public sealed class BSShapeCollection : IDisposable
320 } 303 }
321 304
322 // Remove a reference to a compound shape. 305 // Remove a reference to a compound shape.
306 // Taking a compound shape apart is a little tricky because if you just delete the
307 // physical object, it will free all the underlying children. We can't do that because
308 // they could be shared. So, this removes each of the children from the compound and
309 // dereferences them separately before destroying the compound collision object itself.
323 // Called at taint-time. 310 // Called at taint-time.
324 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) 311 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback)
325 { 312 {
326 // Compound shape is made of a bunch of meshes and natives. 313 if (!BulletSimAPI.IsCompound2(shape.ptr))
314 {
315 // Failed the sanity check!!
316 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
317 LogHeader, shape.type, shape.ptr.ToString("X"));
318 DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
319 BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X"));
320 return;
321 }
322 int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr);
323 for (int ii = 0; ii < numChildren; ii++)
324 {
325 IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii);
326 DereferenceAnonCollisionShape(childShape);
327 }
328 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
329 }
330
331 // Sometimes we have a pointer to a collision shape but don't know what type it is.
332 // Figure out type and call the correct dereference routine.
333 // This is coming from a compound shape that we created so we know it is either native or mesh.
334 // Called at taint-time.
335 private void DereferenceAnonCollisionShape(IntPtr cShape)
336 {
337 BulletShape shapeInfo = new BulletShape(cShape, ShapeData.PhysicsShapeType.SHAPE_MESH);
338 if (BulletSimAPI.IsCompound2(cShape))
339 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND;
340
341 if (BulletSimAPI.IsNativeShape2(cShape))
342 {
343 shapeInfo.isNativeShape = true;
344 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
345 }
346
347 DereferenceShape(shapeInfo, true, null);
327 } 348 }
328 349
329 // Create the geometry information in Bullet for later use. 350 // Create the geometry information in Bullet for later use.
@@ -338,10 +359,8 @@ public sealed class BSShapeCollection : IDisposable
338 { 359 {
339 bool ret = false; 360 bool ret = false;
340 bool haveShape = false; 361 bool haveShape = false;
341 bool nativeShapePossible = true;
342 PrimitiveBaseShape pbs = prim.BaseShape;
343 362
344 if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 363 if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
345 { 364 {
346 // an avatar capsule is close to a native shape (it is not shared) 365 // an avatar capsule is close to a native shape (it is not shared)
347 ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, 366 ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR,
@@ -350,6 +369,31 @@ public sealed class BSShapeCollection : IDisposable
350 ret = true; 369 ret = true;
351 haveShape = true; 370 haveShape = true;
352 } 371 }
372
373 // Compound shapes are handled special as they are rebuilt from scratch.
374 // This isn't too great a hardship since most of the child shapes will already been created.
375 if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND)
376 {
377 ret = GetReferenceToCompoundShape(prim, shapeCallback);
378 DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
379 haveShape = true;
380 }
381
382 if (!haveShape)
383 {
384 ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback);
385 }
386
387 return ret;
388 }
389
390 private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
391 {
392 bool ret = false;
393 bool haveShape = false;
394 bool nativeShapePossible = true;
395 PrimitiveBaseShape pbs = prim.BaseShape;
396
353 // If the prim attributes are simple, this could be a simple Bullet native shape 397 // If the prim attributes are simple, this could be a simple Bullet native shape
354 if (!haveShape 398 if (!haveShape
355 && pbs != null 399 && pbs != null
@@ -363,6 +407,7 @@ public sealed class BSShapeCollection : IDisposable
363 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 407 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
364 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) 408 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
365 { 409 {
410 // It doesn't look like Bullet scales spheres so make sure the scales are all equal
366 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) 411 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
367 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) 412 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
368 { 413 {
@@ -378,7 +423,7 @@ public sealed class BSShapeCollection : IDisposable
378 prim.LocalID, forceRebuild, prim.PhysShape); 423 prim.LocalID, forceRebuild, prim.PhysShape);
379 } 424 }
380 } 425 }
381 if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 426 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
382 { 427 {
383 haveShape = true; 428 haveShape = true;
384 if (forceRebuild 429 if (forceRebuild
@@ -393,9 +438,10 @@ public sealed class BSShapeCollection : IDisposable
393 } 438 }
394 } 439 }
395 } 440 }
441
396 // If a simple shape is not happening, create a mesh and possibly a hull. 442 // If a simple shape is not happening, create a mesh and possibly a hull.
397 // Note that if it's a native shape, the check for physical/non-physical is not 443 // Note that if it's a native shape, the check for physical/non-physical is not
398 // made. Native shapes are best used in either case. 444 // made. Native shapes work in either case.
399 if (!haveShape && pbs != null) 445 if (!haveShape && pbs != null)
400 { 446 {
401 if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) 447 if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects)
@@ -487,7 +533,7 @@ public sealed class BSShapeCollection : IDisposable
487 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) 533 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH)
488 return false; 534 return false;
489 535
490 DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", 536 DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
491 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); 537 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
492 538
493 // Since we're recreating new, get rid of the reference to the previous shape 539 // Since we're recreating new, get rid of the reference to the previous shape
@@ -535,7 +581,7 @@ public sealed class BSShapeCollection : IDisposable
535 verticesAsFloats[vi++] = vv.Z; 581 verticesAsFloats[vi++] = vv.Z;
536 } 582 }
537 583
538 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", 584 // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
539 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); 585 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
540 586
541 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, 587 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
@@ -561,7 +607,7 @@ public sealed class BSShapeCollection : IDisposable
561 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) 607 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL)
562 return false; 608 return false;
563 609
564 DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", 610 DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
565 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); 611 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
566 612
567 // Remove usage of the previous shape. 613 // Remove usage of the previous shape.
@@ -693,6 +739,42 @@ public sealed class BSShapeCollection : IDisposable
693 return; 739 return;
694 } 740 }
695 741
742 // Compound shapes are always built from scratch.
743 // This shouldn't be to bad since most of the parts will be meshes that had been built previously.
744 private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
745 {
746 BulletShape cShape = new BulletShape(
747 BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr), ShapeData.PhysicsShapeType.SHAPE_COMPOUND);
748
749 // The prim's linkset is the source of the children.
750 // TODO: there is too much knowledge here about the internals of linksets and too much
751 // dependency on the relationship of compound shapes and linksets (what if we want to use
752 // compound shapes for something else?). Think through this and clean up so the
753 // appropriate knowledge is used at the correct software levels.
754
755 // Recreate the geometry of the root prim (might have been a linkset root in the past)
756 CreateGeomNonSpecial(true, prim, null);
757
758 BSPhysObject rootPrim = prim.Linkset.LinksetRoot;
759
760 prim.Linkset.ForEachMember(delegate(BSPhysObject cPrim)
761 {
762 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(rootPrim.RawOrientation);
763 OMV.Vector3 displacementPos = (cPrim.RawPosition - rootPrim.RawPosition) * invRootOrientation;
764 OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
765
766 DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
767 prim.LocalID, cPrim.LocalID, cPrim.PhysShape.ptr.ToString("X"), displacementPos, displacementRot);
768
769 BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot);
770 return false;
771 });
772
773 prim.PhysShape = cShape;
774
775 return true;
776 }
777
696 // Create a hash of all the shape parameters to be used as a key 778 // Create a hash of all the shape parameters to be used as a key
697 // for this particular shape. 779 // for this particular shape.
698 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) 780 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 11298fe..7c34af2 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -238,7 +238,7 @@ public sealed class BSTerrainManager
238 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", 238 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
239 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); 239 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
240 240
241 BSScene.TaintCallback rebuildOperation = delegate() 241 PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate()
242 { 242 {
243 if (MegaRegionParentPhysicsScene != null) 243 if (MegaRegionParentPhysicsScene != null)
244 { 244 {
@@ -337,14 +337,7 @@ public sealed class BSTerrainManager
337 BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); 337 BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
338 338
339 m_terrainModified = true; 339 m_terrainModified = true;
340 }; 340 });
341
342 // There is the option to do the changes now (we're already in 'taint time'), or
343 // to do the Bullet operations later.
344 if (inTaintTime)
345 rebuildOperation();
346 else
347 PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
348 } 341 }
349 else 342 else
350 { 343 {
@@ -364,7 +357,7 @@ public sealed class BSTerrainManager
364 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); 357 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
365 358
366 // Code that must happen at taint-time 359 // Code that must happen at taint-time
367 BSScene.TaintCallback createOperation = delegate() 360 PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate()
368 { 361 {
369 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); 362 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y);
370 // Create a new mapInfo that will be filled with the new info 363 // Create a new mapInfo that will be filled with the new info
@@ -377,13 +370,7 @@ public sealed class BSTerrainManager
377 UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); 370 UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
378 371
379 m_terrainModified = true; 372 m_terrainModified = true;
380 }; 373 });
381
382 // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
383 if (inTaintTime)
384 createOperation();
385 else
386 PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
387 } 374 }
388 } 375 }
389 376
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 3b6355c..143b8be 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -399,8 +399,6 @@ public enum CollisionFilterGroups : uint
399 399
400}; 400};
401 401
402
403
404// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 402// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
405// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. 403// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2.
406public enum ConstraintParams : int 404public enum ConstraintParams : int
@@ -618,10 +616,19 @@ public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float
618public static extern IntPtr CreateCompoundShape2(IntPtr sim); 616public static extern IntPtr CreateCompoundShape2(IntPtr sim);
619 617
620[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 618[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
621public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); 619public static extern int GetNumberOfCompoundChildren2(IntPtr cShape);
620
621[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
622public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot);
623
624[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
625public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx);
626
627[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
628public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx);
622 629
623[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 630[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
624public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape); 631public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape);
625 632
626[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 633[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
627public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); 634public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id);