aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorRobert Adams2012-12-10 15:35:53 -0800
committerRobert Adams2012-12-10 15:35:53 -0800
commit9df85eadf4b3719a898fda8769313ae023962c25 (patch)
treeaf055fb53368d75c236959bfde56d43f23e6f741 /OpenSim/Region/Physics
parentBulletSim: some comments about rebuilding linksets (having to recompute and r... (diff)
downloadopensim-SC-9df85eadf4b3719a898fda8769313ae023962c25.zip
opensim-SC-9df85eadf4b3719a898fda8769313ae023962c25.tar.gz
opensim-SC-9df85eadf4b3719a898fda8769313ae023962c25.tar.bz2
opensim-SC-9df85eadf4b3719a898fda8769313ae023962c25.tar.xz
BulletSim: Fix crash on the destruction of physical linksets.
While fixing the above, add methods to physical body and shape pointer wrapper so routines won't have to know that IntPtr.Zero means no physical instance. Fix problem with physical linksets failing after a few sits and unsits by properly restoring child prom positions for compound linksets after multiple selection and deselections.
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs8
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs113
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs5
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs16
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs6
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs23
12 files changed, 155 insertions, 38 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 21aa9be..88460cc 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -124,7 +124,9 @@ public sealed class BSCharacter : BSPhysObject
124 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() 124 PhysicsScene.TaintedObject("BSCharacter.destroy", delegate()
125 { 125 {
126 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); 126 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
127 PhysBody.Clear();
127 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); 128 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
129 PhysShape.Clear();
128 }); 130 });
129 } 131 }
130 132
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 65fac00..6b1e304 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -57,7 +57,7 @@ public abstract class BSConstraint : IDisposable
57 if (m_enabled) 57 if (m_enabled)
58 { 58 {
59 m_enabled = false; 59 m_enabled = false;
60 if (m_constraint.ptr != IntPtr.Zero) 60 if (m_constraint.HasPhysicalConstraint)
61 { 61 {
62 bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); 62 bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr);
63 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", 63 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
@@ -65,7 +65,7 @@ public abstract class BSConstraint : IDisposable
65 m_body1.ID, m_body1.ptr.ToString("X"), 65 m_body1.ID, m_body1.ptr.ToString("X"),
66 m_body2.ID, m_body2.ptr.ToString("X"), 66 m_body2.ID, m_body2.ptr.ToString("X"),
67 success); 67 success);
68 m_constraint.ptr = System.IntPtr.Zero; 68 m_constraint.Clear();
69 } 69 }
70 } 70 }
71 } 71 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
index 23ef052..b073555 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
@@ -65,7 +65,7 @@ public sealed class BSConstraint6Dof : BSConstraint
65 m_world = world; 65 m_world = world;
66 m_body1 = obj1; 66 m_body1 = obj1;
67 m_body2 = obj2; 67 m_body2 = obj2;
68 if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) 68 if (!obj1.HasPhysicalBody || !obj2.HasPhysicalBody)
69 { 69 {
70 world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", 70 world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
71 BSScene.DetailLogZero, world.worldID, 71 BSScene.DetailLogZero, world.worldID,
@@ -83,7 +83,7 @@ public sealed class BSConstraint6Dof : BSConstraint
83 world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", 83 world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}",
84 BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"), 84 BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"),
85 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); 85 obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X"));
86 if (m_constraint.ptr == IntPtr.Zero) 86 if (!m_constraint.HasPhysicalConstraint)
87 { 87 {
88 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", 88 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}",
89 LogHeader, obj1.ID, obj2.ID); 89 LogHeader, obj1.ID, obj2.ID);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 0df4310..777c5cb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -32,6 +32,14 @@ using OMV = OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35
36// A BSPrim can get individual information about its linkedness attached
37// to it through an instance of a subclass of LinksetInfo.
38// Each type of linkset will define the information needed for its type.
39public abstract class BSLinksetInfo
40{
41}
42
35public abstract class BSLinkset 43public abstract class BSLinkset
36{ 44{
37 // private static string LogHeader = "[BULLETSIM LINKSET]"; 45 // private static string LogHeader = "[BULLETSIM LINKSET]";
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index bc9f9be..fe5b5e3 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -32,6 +32,31 @@ using OMV = OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35
36// When a child is linked, the relationship position of the child to the parent
37// is remembered so the child's world position can be recomputed when it is
38// removed from the linkset.
39sealed class BSLinksetCompoundInfo : BSLinksetInfo
40{
41 public OMV.Vector3 OffsetPos;
42 public OMV.Quaternion OffsetRot;
43 public BSLinksetCompoundInfo(OMV.Vector3 p, OMV.Quaternion r)
44 {
45 OffsetPos = p;
46 OffsetRot = r;
47 }
48 public override string ToString()
49 {
50 StringBuilder buff = new StringBuilder();
51 buff.Append("<p=");
52 buff.Append(OffsetPos.ToString());
53 buff.Append(",r=");
54 buff.Append(OffsetRot.ToString());
55 buff.Append(">");
56 return buff.ToString();
57 }
58};
59
35public sealed class BSLinksetCompound : BSLinkset 60public sealed class BSLinksetCompound : BSLinkset
36{ 61{
37 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; 62 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
@@ -44,6 +69,7 @@ public sealed class BSLinksetCompound : BSLinkset
44 // For compound implimented linksets, if there are children, use compound shape for the root. 69 // For compound implimented linksets, if there are children, use compound shape for the root.
45 public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) 70 public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
46 { 71 {
72 // Returning 'unknown' means we don't have a preference.
47 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; 73 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
48 if (IsRoot(requestor) && HasAnyChildren) 74 if (IsRoot(requestor) && HasAnyChildren)
49 { 75 {
@@ -63,10 +89,10 @@ public sealed class BSLinksetCompound : BSLinkset
63 // InternalRefresh(requestor); 89 // InternalRefresh(requestor);
64 } 90 }
65 91
92 // Schedule a refresh to happen after all the other taint processing.
66 private void InternalRefresh(BSPhysObject requestor) 93 private void InternalRefresh(BSPhysObject requestor)
67 { 94 {
68 DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); 95 DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID);
69 // Queue to happen after all the other taint processing
70 PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() 96 PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate()
71 { 97 {
72 if (IsRoot(requestor) && HasAnyChildren) 98 if (IsRoot(requestor) && HasAnyChildren)
@@ -108,7 +134,7 @@ public sealed class BSLinksetCompound : BSLinkset
108 { 134 {
109 // The non-physical children can come back to life. 135 // The non-physical children can come back to life.
110 BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 136 BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
111 // Don't force activation so setting of DISABLE_SIMULATION can stay. 137 // Don't force activation so setting of DISABLE_SIMULATION can stay if used.
112 BulletSimAPI.Activate2(child.PhysBody.ptr, false); 138 BulletSimAPI.Activate2(child.PhysBody.ptr, false);
113 ret = true; 139 ret = true;
114 } 140 }
@@ -146,6 +172,10 @@ public sealed class BSLinksetCompound : BSLinkset
146 172
147 if (!IsRoot(child)) 173 if (!IsRoot(child))
148 { 174 {
175 // Because it is a convenient time, recompute child world position and rotation based on
176 // its position in the linkset.
177 RecomputeChildWorldPosition(child, true);
178
149 // Cause the current shape to be freed and the new one to be built. 179 // Cause the current shape to be freed and the new one to be built.
150 InternalRefresh(LinksetRoot); 180 InternalRefresh(LinksetRoot);
151 ret = true; 181 ret = true;
@@ -154,6 +184,42 @@ public sealed class BSLinksetCompound : BSLinkset
154 return ret; 184 return ret;
155 } 185 }
156 186
187 // When the linkset is built, the child shape is added
188 // to the compound shape relative to the root shape. The linkset then moves around but
189 // this does not move the actual child prim. The child prim's location must be recomputed
190 // based on the location of the root shape.
191 private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime)
192 {
193 BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo;
194 if (lci != null)
195 {
196 if (inTaintTime)
197 {
198 OMV.Vector3 oldPos = child.RawPosition;
199 child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetPos;
200 child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
201 DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
202 child.LocalID, oldPos, lci, child.RawPosition);
203 }
204 else
205 {
206 // TaintedObject is not used here so the raw position is set now and not at taint-time.
207 child.Position = LinksetRoot.RawPosition + lci.OffsetPos;
208 child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
209 }
210 }
211 else
212 {
213 // This happens when children have been added to the linkset but the linkset
214 // has not been constructed yet. So like, at taint time, adding children to a linkset
215 // and then changing properties of the children (makePhysical, for instance)
216 // but the post-print action of actually rebuilding the linkset has not yet happened.
217 // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}",
218 // LogHeader, child.LocalID);
219 DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID);
220 }
221 }
222
157 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', 223 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
158 // this routine will restore the removed constraints. 224 // this routine will restore the removed constraints.
159 // Called at taint-time!! 225 // Called at taint-time!!
@@ -192,8 +258,7 @@ public sealed class BSLinksetCompound : BSLinkset
192 child.LocalID, child.PhysBody.ptr.ToString("X")); 258 child.LocalID, child.PhysBody.ptr.ToString("X"));
193 259
194 // Cause the child's body to be rebuilt and thus restored to normal operation 260 // Cause the child's body to be rebuilt and thus restored to normal operation
195 // TODO: position and rotation must be restored because the child could have moved 261 RecomputeChildWorldPosition(child, false);
196 // based on the linkset.
197 child.ForceBodyShapeRebuild(false); 262 child.ForceBodyShapeRebuild(false);
198 263
199 if (!HasAnyChildren) 264 if (!HasAnyChildren)
@@ -228,43 +293,57 @@ public sealed class BSLinksetCompound : BSLinkset
228 { 293 {
229 if (!IsRoot(cPrim)) 294 if (!IsRoot(cPrim))
230 { 295 {
231 // Each child position and rotation is given relative to the root. 296 // Compute the displacement of the child from the root of the linkset.
232 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); 297 // This info is saved in the child prim so the relationship does not
233 OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; 298 // change over time and the new child position can be computed
234 OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; 299 // when the linkset is being disassembled (the linkset may have moved).
300 BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
301 if (lci == null)
302 {
303 // Each child position and rotation is given relative to the root.
304 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
305 OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
306 OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
307
308 // Save relative position for recomputing child's world position after moving linkset.
309 lci = new BSLinksetCompoundInfo(displacementPos, displacementRot);
310 cPrim.LinksetInfo = lci;
311 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
312 }
235 313
236 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", 314 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
237 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot); 315 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot);
238 316
239 if (cPrim.PhysShape.isNativeShape) 317 if (cPrim.PhysShape.isNativeShape)
240 { 318 {
241 // A native shape is turning into a null collision shape because native 319 // A native shape is turning into a hull collision shape because native
242 // shapes are not shared so we have to hullify it so it will be tracked 320 // shapes are not shared so we have to hullify it so it will be tracked
243 // and freed at the correct time. This also solves the scaling problem 321 // and freed at the correct time. This also solves the scaling problem
244 // (native shapes scaled but hull/meshes are assumed to not be). 322 // (native shapes scaled but hull/meshes are assumed to not be).
323 // TODO: decide of the native shape can just be used in the compound shape.
324 // Use call to CreateGeomNonSpecial().
245 BulletShape saveShape = cPrim.PhysShape; 325 BulletShape saveShape = cPrim.PhysShape;
246 cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape 326 cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
327 // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null);
247 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); 328 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
248 BulletShape newShape = cPrim.PhysShape; 329 BulletShape newShape = cPrim.PhysShape;
249 cPrim.PhysShape = saveShape; 330 cPrim.PhysShape = saveShape;
250 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot); 331 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos , lci.OffsetRot);
251 } 332 }
252 else 333 else
253 { 334 {
254 // For the shared shapes (meshes and hulls), just use the shape in the child. 335 // For the shared shapes (meshes and hulls), just use the shape in the child.
336 // The reference count added here will be decremented when the compound shape
337 // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced).
255 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) 338 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
256 { 339 {
257 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", 340 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
258 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); 341 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
259 } 342 }
260 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); 343 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, lci.OffsetPos , lci.OffsetRot);
261 } 344 }
262 } 345 }
263 346
264 // TODO: need to phantomize the child prims left behind.
265 // Maybe just destroy the children bodies and shapes and have them rebuild on unlink.
266 // Selection/deselection might cause way too many build/destructions esp. for LARGE linksets.
267
268 return false; // 'false' says to move onto the next child in the list 347 return false; // 'false' says to move onto the next child in the list
269 }); 348 });
270 349
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index b05d4ee..d2fc15c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -75,6 +75,7 @@ public abstract class BSPhysObject : PhysicsActor
75 public string TypeName { get; protected set; } 75 public string TypeName { get; protected set; }
76 76
77 public BSLinkset Linkset { get; set; } 77 public BSLinkset Linkset { get; set; }
78 public BSLinksetInfo LinksetInfo { get; set; }
78 79
79 // Return the object mass without calculating it or having side effects 80 // Return the object mass without calculating it or having side effects
80 public abstract float RawMass { get; } 81 public abstract float RawMass { get; }
@@ -253,7 +254,9 @@ public abstract class BSPhysObject : PhysicsActor
253 SubscribedEventsMs = 0; 254 SubscribedEventsMs = 0;
254 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 255 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
255 { 256 {
256 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 257 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
258 if (PhysBody.HasPhysicalBody)
259 CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
257 }); 260 });
258 } 261 }
259 // Return 'true' if the simulator wants collision events 262 // Return 'true' if the simulator wants collision events
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 627393a..d1d100d 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -108,8 +108,8 @@ public sealed class BSPrim : BSPhysObject
108 _mass = CalculateMass(); 108 _mass = CalculateMass();
109 109
110 // No body or shape yet 110 // No body or shape yet
111 PhysBody = new BulletBody(LocalID, IntPtr.Zero); 111 PhysBody = new BulletBody(LocalID);
112 PhysShape = new BulletShape(IntPtr.Zero); 112 PhysShape = new BulletShape();
113 113
114 DetailLog("{0},BSPrim.constructor,call", LocalID); 114 DetailLog("{0},BSPrim.constructor,call", LocalID);
115 // do the actual object creation at taint time 115 // do the actual object creation at taint time
@@ -143,7 +143,9 @@ public sealed class BSPrim : BSPhysObject
143 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 143 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
144 // If there are physical body and shape, release my use of same. 144 // If there are physical body and shape, release my use of same.
145 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); 145 PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null);
146 PhysBody.Clear();
146 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); 147 PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null);
148 PhysShape.Clear();
147 }); 149 });
148 } 150 }
149 151
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 933f573..74b4371 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -149,7 +149,7 @@ public sealed class BSShapeCollection : IDisposable
149 // Called when releasing use of a BSBody. BSShape is handled separately. 149 // Called when releasing use of a BSBody. BSShape is handled separately.
150 public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) 150 public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback )
151 { 151 {
152 if (body.ptr == IntPtr.Zero) 152 if (!body.HasPhysicalBody)
153 return; 153 return;
154 154
155 lock (m_collectionActivityLock) 155 lock (m_collectionActivityLock)
@@ -243,12 +243,12 @@ public sealed class BSShapeCollection : IDisposable
243 // Release the usage of a shape. 243 // Release the usage of a shape.
244 public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) 244 public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
245 { 245 {
246 if (shape.ptr == IntPtr.Zero) 246 if (!shape.HasPhysicalShape)
247 return; 247 return;
248 248
249 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() 249 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate()
250 { 250 {
251 if (shape.ptr != IntPtr.Zero) 251 if (shape.HasPhysicalShape)
252 { 252 {
253 if (shape.isNativeShape) 253 if (shape.isNativeShape)
254 { 254 {
@@ -440,7 +440,7 @@ public sealed class BSShapeCollection : IDisposable
440 } 440 }
441 441
442 // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. 442 // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'.
443 private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) 443 public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
444 { 444 {
445 bool ret = false; 445 bool ret = false;
446 bool haveShape = false; 446 bool haveShape = false;
@@ -573,7 +573,7 @@ public sealed class BSShapeCollection : IDisposable
573 // Native shapes are scaled in Bullet so set the scaling to the size 573 // Native shapes are scaled in Bullet so set the scaling to the size
574 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); 574 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType);
575 } 575 }
576 if (newShape.ptr == IntPtr.Zero) 576 if (!newShape.HasPhysicalShape)
577 { 577 {
578 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 578 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
579 LogHeader, prim.LocalID, shapeType); 579 LogHeader, prim.LocalID, shapeType);
@@ -590,7 +590,7 @@ public sealed class BSShapeCollection : IDisposable
590 // Called at taint-time! 590 // Called at taint-time!
591 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 591 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
592 { 592 {
593 BulletShape newShape = new BulletShape(IntPtr.Zero); 593 BulletShape newShape = new BulletShape();
594 594
595 float lod; 595 float lod;
596 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); 596 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
@@ -860,7 +860,7 @@ public sealed class BSShapeCollection : IDisposable
860 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) 860 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
861 { 861 {
862 // If the shape was successfully created, nothing more to do 862 // If the shape was successfully created, nothing more to do
863 if (newShape.ptr != IntPtr.Zero) 863 if (newShape.HasPhysicalShape)
864 return newShape; 864 return newShape;
865 865
866 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset 866 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
@@ -919,7 +919,7 @@ public sealed class BSShapeCollection : IDisposable
919 bool ret = false; 919 bool ret = false;
920 920
921 // the mesh, hull or native shape must have already been created in Bullet 921 // the mesh, hull or native shape must have already been created in Bullet
922 bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero); 922 bool mustRebuild = !prim.PhysBody.HasPhysicalBody;
923 923
924 // If there is an existing body, verify it's of an acceptable type. 924 // If there is an existing body, verify it's of an acceptable type.
925 // If not a solid object, body is a GhostObject. Otherwise a RigidBody. 925 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
index 83b9c37..2d379bb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
@@ -136,7 +136,7 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys
136 { 136 {
137 if (m_mapInfo != null) 137 if (m_mapInfo != null)
138 { 138 {
139 if (m_mapInfo.terrainBody.ptr != IntPtr.Zero) 139 if (m_mapInfo.terrainBody.HasPhysicalBody)
140 { 140 {
141 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr); 141 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
142 // Frees both the body and the shape. 142 // Frees both the body and the shape.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 83df360..c28d69d 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -151,13 +151,13 @@ public sealed class BSTerrainManager
151 // Release all the terrain structures we might have allocated 151 // Release all the terrain structures we might have allocated
152 public void ReleaseGroundPlaneAndTerrain() 152 public void ReleaseGroundPlaneAndTerrain()
153 { 153 {
154 if (m_groundPlane.ptr != IntPtr.Zero) 154 if (m_groundPlane.HasPhysicalBody)
155 { 155 {
156 if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr)) 156 if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr))
157 { 157 {
158 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr); 158 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr);
159 } 159 }
160 m_groundPlane.ptr = IntPtr.Zero; 160 m_groundPlane.Clear();
161 } 161 }
162 162
163 ReleaseTerrain(); 163 ReleaseTerrain();
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
index 6ce767d..3473006 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
@@ -94,7 +94,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
94 m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, 94 m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
95 indicesCount, indices, verticesCount, vertices), 95 indicesCount, indices, verticesCount, vertices),
96 BSPhysicsShapeType.SHAPE_MESH); 96 BSPhysicsShapeType.SHAPE_MESH);
97 if (m_terrainShape.ptr == IntPtr.Zero) 97 if (!m_terrainShape.HasPhysicalShape)
98 { 98 {
99 // DISASTER!! 99 // DISASTER!!
100 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID); 100 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID);
@@ -107,7 +107,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
107 Quaternion rot = Quaternion.Identity; 107 Quaternion rot = Quaternion.Identity;
108 108
109 m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot)); 109 m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot));
110 if (m_terrainBody.ptr == IntPtr.Zero) 110 if (!m_terrainBody.HasPhysicalBody)
111 { 111 {
112 // DISASTER!! 112 // DISASTER!!
113 physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase); 113 physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
@@ -140,7 +140,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
140 140
141 public override void Dispose() 141 public override void Dispose()
142 { 142 {
143 if (m_terrainBody.ptr != IntPtr.Zero) 143 if (m_terrainBody.HasPhysicalBody)
144 { 144 {
145 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr); 145 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr);
146 // Frees both the body and the shape. 146 // Frees both the body and the shape.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 2671995..1559025 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -53,6 +53,9 @@ public struct BulletSim
53// An allocated Bullet btRigidBody 53// An allocated Bullet btRigidBody
54public struct BulletBody 54public struct BulletBody
55{ 55{
56 public BulletBody(uint id) : this(id, IntPtr.Zero)
57 {
58 }
56 public BulletBody(uint id, IntPtr xx) 59 public BulletBody(uint id, IntPtr xx)
57 { 60 {
58 ID = id; 61 ID = id;
@@ -64,6 +67,13 @@ public struct BulletBody
64 public uint ID; 67 public uint ID;
65 public CollisionFilterGroups collisionGroup; 68 public CollisionFilterGroups collisionGroup;
66 public CollisionFilterGroups collisionMask; 69 public CollisionFilterGroups collisionMask;
70
71 public void Clear()
72 {
73 ptr = IntPtr.Zero;
74 }
75 public bool HasPhysicalBody { get { return ptr != IntPtr.Zero; } }
76
67 public override string ToString() 77 public override string ToString()
68 { 78 {
69 StringBuilder buff = new StringBuilder(); 79 StringBuilder buff = new StringBuilder();
@@ -103,6 +113,13 @@ public struct BulletShape
103 public BSPhysicsShapeType type; 113 public BSPhysicsShapeType type;
104 public System.UInt64 shapeKey; 114 public System.UInt64 shapeKey;
105 public bool isNativeShape; 115 public bool isNativeShape;
116
117 public void Clear()
118 {
119 ptr = IntPtr.Zero;
120 }
121 public bool HasPhysicalShape { get { return ptr != IntPtr.Zero; } }
122
106 public override string ToString() 123 public override string ToString()
107 { 124 {
108 StringBuilder buff = new StringBuilder(); 125 StringBuilder buff = new StringBuilder();
@@ -140,6 +157,12 @@ public struct BulletConstraint
140 ptr = xx; 157 ptr = xx;
141 } 158 }
142 public IntPtr ptr; 159 public IntPtr ptr;
160
161 public void Clear()
162 {
163 ptr = IntPtr.Zero;
164 }
165 public bool HasPhysicalConstraint { get { return ptr != IntPtr.Zero; } }
143} 166}
144 167
145// An allocated HeightMapThing which holds various heightmap info. 168// An allocated HeightMapThing which holds various heightmap info.