aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
diff options
context:
space:
mode:
authorRobert Adams2012-11-02 09:53:41 -0700
committerRobert Adams2012-11-03 21:15:30 -0700
commitb0eccd5044b1a20b995a62d6fb76fdd73b712f9a (patch)
tree877464740b99169d2e8f38bc8c75a33b37e9d475 /OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
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.
Diffstat (limited to '')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs152
1 files changed, 117 insertions, 35 deletions
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)