diff options
author | Robert Adams | 2012-11-02 09:53:41 -0700 |
---|---|---|
committer | Robert Adams | 2012-11-03 21:15:30 -0700 |
commit | b0eccd5044b1a20b995a62d6fb76fdd73b712f9a (patch) | |
tree | 877464740b99169d2e8f38bc8c75a33b37e9d475 /OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | |
parent | BulletSim: Add RawPosition and RawOrientation to BSPhysObject and rename Mass... (diff) | |
download | opensim-SC_OLD-b0eccd5044b1a20b995a62d6fb76fdd73b712f9a.zip opensim-SC_OLD-b0eccd5044b1a20b995a62d6fb76fdd73b712f9a.tar.gz opensim-SC_OLD-b0eccd5044b1a20b995a62d6fb76fdd73b712f9a.tar.bz2 opensim-SC_OLD-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 'OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 152 |
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) |