aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs')
-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)