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.cs296
1 files changed, 181 insertions, 115 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 861ffe7..d3ba273 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -117,7 +117,7 @@ public class BSShapeCollection : IDisposable
117 117
118 // Track another user of a body 118 // Track another user of a body
119 // We presume the caller has allocated the body. 119 // We presume the caller has allocated the body.
120 // Bodies only have one user so the reference count is either 1 or 0. 120 // Bodies only have one user so the body is just put into the world if not already there.
121 public void ReferenceBody(BulletBody body, bool inTaintTime) 121 public void ReferenceBody(BulletBody body, bool inTaintTime)
122 { 122 {
123 lock (m_collectionActivityLock) 123 lock (m_collectionActivityLock)
@@ -241,26 +241,32 @@ public class BSShapeCollection : IDisposable
241 241
242 BSScene.TaintCallback dereferenceOperation = delegate() 242 BSScene.TaintCallback dereferenceOperation = delegate()
243 { 243 {
244 switch (shape.type) 244 if (shape.ptr != IntPtr.Zero)
245 { 245 {
246 case ShapeData.PhysicsShapeType.SHAPE_HULL: 246 if (shape.isNativeShape)
247 DereferenceHull(shape, shapeCallback); 247 {
248 break;
249 case ShapeData.PhysicsShapeType.SHAPE_MESH:
250 DereferenceMesh(shape, shapeCallback);
251 break;
252 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
253 break;
254 default:
255 // Native shapes are not tracked and are released immediately 248 // Native shapes are not tracked and are released immediately
256 if (shape.ptr != IntPtr.Zero & shape.isNativeShape) 249 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
250 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime);
251 if (shapeCallback != null) shapeCallback(shape);
252 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
253 }
254 else
255 {
256 switch (shape.type)
257 { 257 {
258 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", 258 case ShapeData.PhysicsShapeType.SHAPE_HULL:
259 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); 259 DereferenceHull(shape, shapeCallback);
260 if (shapeCallback != null) shapeCallback(shape); 260 break;
261 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); 261 case ShapeData.PhysicsShapeType.SHAPE_MESH:
262 DereferenceMesh(shape, shapeCallback);
263 break;
264 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
265 break;
266 default:
267 break;
262 } 268 }
263 break; 269 }
264 } 270 }
265 }; 271 };
266 if (inTaintTime) 272 if (inTaintTime)
@@ -405,7 +411,6 @@ public class BSShapeCollection : IDisposable
405 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, 411 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey,
406 ShapeDestructionCallback shapeCallback) 412 ShapeDestructionCallback shapeCallback)
407 { 413 {
408 BulletShape newShape;
409 414
410 shapeData.Type = shapeType; 415 shapeData.Type = shapeType;
411 // Bullet native objects are scaled by the Bullet engine so pass the size in 416 // Bullet native objects are scaled by the Bullet engine so pass the size in
@@ -415,27 +420,35 @@ public class BSShapeCollection : IDisposable
415 // release any previous shape 420 // release any previous shape
416 DereferenceShape(prim.BSShape, true, shapeCallback); 421 DereferenceShape(prim.BSShape, true, shapeCallback);
417 422
423 BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey);
424
425 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
426 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
427 shapeData.ID, newShape, shapeData.Scale);
428
429 prim.BSShape = newShape;
430 return true;
431 }
432
433 private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType,
434 ShapeData shapeData, ShapeData.FixedShapeKey shapeKey)
435 {
436 BulletShape newShape;
437
418 if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 438 if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
419 { 439 {
420 newShape = new BulletShape( 440 newShape = new BulletShape(
421 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale), 441 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1.0f, 1.0f, shapeData.Scale),
422 shapeType); 442 shapeType);
423 newShape.shapeKey = (System.UInt64)shapeKey;
424 newShape.isNativeShape = true;
425 } 443 }
426 else 444 else
427 { 445 {
428 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType); 446 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
429 newShape.shapeKey = (System.UInt64)shapeKey;
430 newShape.isNativeShape = true;
431 } 447 }
448 newShape.shapeKey = (System.UInt64)shapeKey;
449 newShape.isNativeShape = true;
432 450
433 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. 451 return newShape;
434 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
435 shapeData.ID, newShape, shapeData.Scale);
436
437 prim.BSShape = newShape;
438 return true;
439 } 452 }
440 453
441 // Builds a mesh shape in the physical world and updates prim.BSShape. 454 // Builds a mesh shape in the physical world and updates prim.BSShape.
@@ -461,6 +474,8 @@ public class BSShapeCollection : IDisposable
461 DereferenceShape(prim.BSShape, true, shapeCallback); 474 DereferenceShape(prim.BSShape, true, shapeCallback);
462 475
463 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); 476 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod);
477 // Take evasive action if the mesh was not constructed.
478 newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs);
464 479
465 ReferenceShape(newShape); 480 ReferenceShape(newShape);
466 481
@@ -474,7 +489,7 @@ public class BSShapeCollection : IDisposable
474 private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 489 private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
475 { 490 {
476 IMesh meshData = null; 491 IMesh meshData = null;
477 IntPtr meshPtr; 492 IntPtr meshPtr = IntPtr.Zero;
478 MeshDesc meshDesc; 493 MeshDesc meshDesc;
479 if (Meshes.TryGetValue(newMeshKey, out meshDesc)) 494 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
480 { 495 {
@@ -486,23 +501,26 @@ public class BSShapeCollection : IDisposable
486 // Pass false for physicalness as this creates some sort of bounding box which we don't need 501 // Pass false for physicalness as this creates some sort of bounding box which we don't need
487 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); 502 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
488 503
489 int[] indices = meshData.getIndexListAsInt(); 504 if (meshData != null)
490 List<OMV.Vector3> vertices = meshData.getVertexList();
491
492 float[] verticesAsFloats = new float[vertices.Count * 3];
493 int vi = 0;
494 foreach (OMV.Vector3 vv in vertices)
495 { 505 {
496 verticesAsFloats[vi++] = vv.X; 506 int[] indices = meshData.getIndexListAsInt();
497 verticesAsFloats[vi++] = vv.Y; 507 List<OMV.Vector3> vertices = meshData.getVertexList();
498 verticesAsFloats[vi++] = vv.Z;
499 }
500 508
501 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", 509 float[] verticesAsFloats = new float[vertices.Count * 3];
502 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); 510 int vi = 0;
511 foreach (OMV.Vector3 vv in vertices)
512 {
513 verticesAsFloats[vi++] = vv.X;
514 verticesAsFloats[vi++] = vv.Y;
515 verticesAsFloats[vi++] = vv.Z;
516 }
517
518 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
519 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
503 520
504 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, 521 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
505 indices.GetLength(0), indices, vertices.Count, verticesAsFloats); 522 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
523 }
506 } 524 }
507 BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); 525 BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH);
508 newShape.shapeKey = newMeshKey; 526 newShape.shapeKey = newMeshKey;
@@ -531,6 +549,7 @@ public class BSShapeCollection : IDisposable
531 DereferenceShape(prim.BSShape, true, shapeCallback); 549 DereferenceShape(prim.BSShape, true, shapeCallback);
532 550
533 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); 551 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);
552 newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs);
534 553
535 ReferenceShape(newShape); 554 ReferenceShape(newShape);
536 555
@@ -544,7 +563,7 @@ public class BSShapeCollection : IDisposable
544 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 563 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
545 { 564 {
546 565
547 IntPtr hullPtr; 566 IntPtr hullPtr = IntPtr.Zero;
548 HullDesc hullDesc; 567 HullDesc hullDesc;
549 if (Hulls.TryGetValue(newHullKey, out hullDesc)) 568 if (Hulls.TryGetValue(newHullKey, out hullDesc))
550 { 569 {
@@ -556,86 +575,89 @@ public class BSShapeCollection : IDisposable
556 // Build a new hull in the physical world 575 // Build a new hull in the physical world
557 // Pass false for physicalness as this creates some sort of bounding box which we don't need 576 // Pass false for physicalness as this creates some sort of bounding box which we don't need
558 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); 577 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
559 578 if (meshData != null)
560 int[] indices = meshData.getIndexListAsInt();
561 List<OMV.Vector3> vertices = meshData.getVertexList();
562
563 //format conversion from IMesh format to DecompDesc format
564 List<int> convIndices = new List<int>();
565 List<float3> convVertices = new List<float3>();
566 for (int ii = 0; ii < indices.GetLength(0); ii++)
567 {
568 convIndices.Add(indices[ii]);
569 }
570 foreach (OMV.Vector3 vv in vertices)
571 { 579 {
572 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
573 }
574 580
575 // setup and do convex hull conversion 581 int[] indices = meshData.getIndexListAsInt();
576 m_hulls = new List<ConvexResult>(); 582 List<OMV.Vector3> vertices = meshData.getVertexList();
577 DecompDesc dcomp = new DecompDesc();
578 dcomp.mIndices = convIndices;
579 dcomp.mVertices = convVertices;
580 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
581 // create the hull into the _hulls variable
582 convexBuilder.process(dcomp);
583
584 // Convert the vertices and indices for passing to unmanaged.
585 // The hull information is passed as a large floating point array.
586 // The format is:
587 // convHulls[0] = number of hulls
588 // convHulls[1] = number of vertices in first hull
589 // convHulls[2] = hull centroid X coordinate
590 // convHulls[3] = hull centroid Y coordinate
591 // convHulls[4] = hull centroid Z coordinate
592 // convHulls[5] = first hull vertex X
593 // convHulls[6] = first hull vertex Y
594 // convHulls[7] = first hull vertex Z
595 // convHulls[8] = second hull vertex X
596 // ...
597 // convHulls[n] = number of vertices in second hull
598 // convHulls[n+1] = second hull centroid X coordinate
599 // ...
600 //
601 // TODO: is is very inefficient. Someday change the convex hull generator to return
602 // data structures that do not need to be converted in order to pass to Bullet.
603 // And maybe put the values directly into pinned memory rather than marshaling.
604 int hullCount = m_hulls.Count;
605 int totalVertices = 1; // include one for the count of the hulls
606 foreach (ConvexResult cr in m_hulls)
607 {
608 totalVertices += 4; // add four for the vertex count and centroid
609 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
610 }
611 float[] convHulls = new float[totalVertices];
612 583
613 convHulls[0] = (float)hullCount; 584 //format conversion from IMesh format to DecompDesc format
614 int jj = 1; 585 List<int> convIndices = new List<int>();
615 foreach (ConvexResult cr in m_hulls) 586 List<float3> convVertices = new List<float3>();
616 { 587 for (int ii = 0; ii < indices.GetLength(0); ii++)
617 // copy vertices for index access
618 float3[] verts = new float3[cr.HullVertices.Count];
619 int kk = 0;
620 foreach (float3 ff in cr.HullVertices)
621 { 588 {
622 verts[kk++] = ff; 589 convIndices.Add(indices[ii]);
590 }
591 foreach (OMV.Vector3 vv in vertices)
592 {
593 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
623 } 594 }
624 595
625 // add to the array one hull's worth of data 596 // setup and do convex hull conversion
626 convHulls[jj++] = cr.HullIndices.Count; 597 m_hulls = new List<ConvexResult>();
627 convHulls[jj++] = 0f; // centroid x,y,z 598 DecompDesc dcomp = new DecompDesc();
628 convHulls[jj++] = 0f; 599 dcomp.mIndices = convIndices;
629 convHulls[jj++] = 0f; 600 dcomp.mVertices = convVertices;
630 foreach (int ind in cr.HullIndices) 601 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
602 // create the hull into the _hulls variable
603 convexBuilder.process(dcomp);
604
605 // Convert the vertices and indices for passing to unmanaged.
606 // The hull information is passed as a large floating point array.
607 // The format is:
608 // convHulls[0] = number of hulls
609 // convHulls[1] = number of vertices in first hull
610 // convHulls[2] = hull centroid X coordinate
611 // convHulls[3] = hull centroid Y coordinate
612 // convHulls[4] = hull centroid Z coordinate
613 // convHulls[5] = first hull vertex X
614 // convHulls[6] = first hull vertex Y
615 // convHulls[7] = first hull vertex Z
616 // convHulls[8] = second hull vertex X
617 // ...
618 // convHulls[n] = number of vertices in second hull
619 // convHulls[n+1] = second hull centroid X coordinate
620 // ...
621 //
622 // TODO: is is very inefficient. Someday change the convex hull generator to return
623 // data structures that do not need to be converted in order to pass to Bullet.
624 // And maybe put the values directly into pinned memory rather than marshaling.
625 int hullCount = m_hulls.Count;
626 int totalVertices = 1; // include one for the count of the hulls
627 foreach (ConvexResult cr in m_hulls)
631 { 628 {
632 convHulls[jj++] = verts[ind].x; 629 totalVertices += 4; // add four for the vertex count and centroid
633 convHulls[jj++] = verts[ind].y; 630 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
634 convHulls[jj++] = verts[ind].z; 631 }
632 float[] convHulls = new float[totalVertices];
633
634 convHulls[0] = (float)hullCount;
635 int jj = 1;
636 foreach (ConvexResult cr in m_hulls)
637 {
638 // copy vertices for index access
639 float3[] verts = new float3[cr.HullVertices.Count];
640 int kk = 0;
641 foreach (float3 ff in cr.HullVertices)
642 {
643 verts[kk++] = ff;
644 }
645
646 // add to the array one hull's worth of data
647 convHulls[jj++] = cr.HullIndices.Count;
648 convHulls[jj++] = 0f; // centroid x,y,z
649 convHulls[jj++] = 0f;
650 convHulls[jj++] = 0f;
651 foreach (int ind in cr.HullIndices)
652 {
653 convHulls[jj++] = verts[ind].x;
654 convHulls[jj++] = verts[ind].y;
655 convHulls[jj++] = verts[ind].z;
656 }
635 } 657 }
658 // create the hull data structure in Bullet
659 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls);
636 } 660 }
637 // create the hull data structure in Bullet
638 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls);
639 } 661 }
640 662
641 BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); 663 BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL);
@@ -676,6 +698,50 @@ public class BSShapeCollection : IDisposable
676 return ComputeShapeKey(shapeData, pbs, out lod); 698 return ComputeShapeKey(shapeData, pbs, out lod);
677 } 699 }
678 700
701 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs)
702 {
703 // If the shape was successfully created, nothing more to do
704 if (newShape.ptr != IntPtr.Zero)
705 return newShape;
706
707 // The most common reason for failure is that an underlying asset is not available
708
709 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
710 if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero)
711 {
712 prim.LastAssetBuildFailed = true;
713 BSPhysObject xprim = prim;
714 Util.FireAndForget(delegate
715 {
716 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
717 if (assetProvider != null)
718 {
719 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
720 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
721 {
722 if (!yprim.BaseShape.SculptEntry)
723 return;
724 if (yprim.BaseShape.SculptTexture.ToString() != asset.ID)
725 return;
726
727 yprim.BaseShape.SculptData = new byte[asset.Data.Length];
728 asset.Data.CopyTo(yprim.BaseShape.SculptData, 0);
729 // This will cause the prim to see that the filler shape is not the right
730 // one and try again to build the object.
731 yprim.ForceBodyShapeRebuild(false);
732
733 });
734 }
735 });
736 }
737
738 // While we figure out the real problem, stick a simple native shape on the object.
739 BulletShape fillinShape =
740 BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_SPHERE, shapeData, ShapeData.FixedShapeKey.KEY_SPHERE);
741
742 return fillinShape;
743 }
744
679 // Create a body object in Bullet. 745 // Create a body object in Bullet.
680 // Updates prim.BSBody with the information about the new body if one is created. 746 // Updates prim.BSBody with the information about the new body if one is created.
681 // Returns 'true' if an object was actually created. 747 // Returns 'true' if an object was actually created.