aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorRobert Adams2012-11-02 09:53:41 -0700
committerRobert Adams2012-11-03 21:15:30 -0700
commitb0eccd5044b1a20b995a62d6fb76fdd73b712f9a (patch)
tree877464740b99169d2e8f38bc8c75a33b37e9d475
parentBulletSim: Add RawPosition and RawOrientation to BSPhysObject and rename Mass... (diff)
downloadopensim-SC-b0eccd5044b1a20b995a62d6fb76fdd73b712f9a.zip
opensim-SC-b0eccd5044b1a20b995a62d6fb76fdd73b712f9a.tar.gz
opensim-SC-b0eccd5044b1a20b995a62d6fb76fdd73b712f9a.tar.bz2
opensim-SC-b0eccd5044b1a20b995a62d6fb76fdd73b712f9a.tar.xz
BulletSim: debugging of compound shape implementation of linksets.
Add compound shape creation and freeing in shape manager. Add optional taint-time execution method and update code to use it. Add API2 linkage for more compound shape methods (get num, get/remove by index, ...) Modify perferred shape return so linkset children can have differet shapes than root. Add Position and Orientation calls to linksets so children can be moved around by the linkset by its own calculation. Allows for very general linkset implementations.
-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);