diff options
author | Robert Adams | 2013-05-23 14:40:16 -0700 |
---|---|---|
committer | Robert Adams | 2013-05-23 14:40:16 -0700 |
commit | 29b3b44fab46a44f911e582ab284025086cf3692 (patch) | |
tree | a3a3f808490695c6aa979b88c8394f39a4404c79 | |
parent | BulletSim: correct errors caused by misspelled INI parameter spec. (diff) | |
download | opensim-SC_OLD-29b3b44fab46a44f911e582ab284025086cf3692.zip opensim-SC_OLD-29b3b44fab46a44f911e582ab284025086cf3692.tar.gz opensim-SC_OLD-29b3b44fab46a44f911e582ab284025086cf3692.tar.bz2 opensim-SC_OLD-29b3b44fab46a44f911e582ab284025086cf3692.tar.xz |
BulletSim: add locking around Meshmerizer use to eliminate possible race
condition when extracting the convex hulls.
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | 302 |
1 files changed, 157 insertions, 145 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index 6729d6b..48f1394 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs | |||
@@ -441,10 +441,14 @@ public class BSShapeMesh : BSShape | |||
441 | { | 441 | { |
442 | BulletShape newShape = new BulletShape(); | 442 | BulletShape newShape = new BulletShape(); |
443 | 443 | ||
444 | IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, | 444 | IMesh meshData = null; |
445 | false, // say it is not physical so a bounding box is not built | 445 | lock (physicsScene.mesher) |
446 | false // do not cache the mesh and do not use previously built versions | 446 | { |
447 | ); | 447 | meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, |
448 | false, // say it is not physical so a bounding box is not built | ||
449 | false // do not cache the mesh and do not use previously built versions | ||
450 | ); | ||
451 | } | ||
448 | 452 | ||
449 | if (meshData != null) | 453 | if (meshData != null) |
450 | { | 454 | { |
@@ -576,55 +580,67 @@ public class BSShapeHull : BSShape | |||
576 | BulletShape newShape = new BulletShape(); | 580 | BulletShape newShape = new BulletShape(); |
577 | newShape.shapeKey = newHullKey; | 581 | newShape.shapeKey = newHullKey; |
578 | 582 | ||
579 | // Pass true for physicalness as this prevents the creation of bounding box which is not needed | 583 | IMesh meshData = null; |
580 | IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */); | 584 | List<List<OMV.Vector3>> allHulls = null; |
581 | 585 | lock (physicsScene.mesher) | |
582 | // If there is hull data in the mesh asset, build the hull from that | ||
583 | if (meshData != null && BSParam.ShouldUseAssetHulls) | ||
584 | { | 586 | { |
585 | Meshmerizer realMesher = physicsScene.mesher as Meshmerizer; | 587 | // Pass true for physicalness as this prevents the creation of bounding box which is not needed |
586 | if (realMesher != null) | 588 | meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */); |
589 | |||
590 | // If we should use the asset's hull info, fetch it out of the locked mesher | ||
591 | if (meshData != null && BSParam.ShouldUseAssetHulls) | ||
587 | { | 592 | { |
588 | List<List<OMV.Vector3>> allHulls = realMesher.GetConvexHulls(size); | 593 | Meshmerizer realMesher = physicsScene.mesher as Meshmerizer; |
589 | if (allHulls != null) | 594 | if (realMesher != null) |
590 | { | 595 | { |
591 | int hullCount = allHulls.Count; | 596 | allHulls = realMesher.GetConvexHulls(size); |
592 | int totalVertices = 1; // include one for the count of the hulls | 597 | } |
593 | // Using the structure described for HACD hulls, create the memory sturcture | 598 | if (allHulls == null) |
594 | // to pass the hull data to the creater. | 599 | { |
595 | foreach (List<OMV.Vector3> hullVerts in allHulls) | 600 | physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,noAssetHull", prim.LocalID); |
596 | { | 601 | } |
597 | totalVertices += 4; // add four for the vertex count and centroid | 602 | } |
598 | totalVertices += hullVerts.Count * 3; // one vertex is three dimensions | 603 | } |
599 | } | ||
600 | float[] convHulls = new float[totalVertices]; | ||
601 | |||
602 | convHulls[0] = (float)hullCount; | ||
603 | int jj = 1; | ||
604 | foreach (List<OMV.Vector3> hullVerts in allHulls) | ||
605 | { | ||
606 | convHulls[jj + 0] = hullVerts.Count; | ||
607 | convHulls[jj + 1] = 0f; // centroid x,y,z | ||
608 | convHulls[jj + 2] = 0f; | ||
609 | convHulls[jj + 3] = 0f; | ||
610 | jj += 4; | ||
611 | foreach (OMV.Vector3 oneVert in hullVerts) | ||
612 | { | ||
613 | convHulls[jj + 0] = oneVert.X; | ||
614 | convHulls[jj + 1] = oneVert.Y; | ||
615 | convHulls[jj + 2] = oneVert.Z; | ||
616 | jj += 3; | ||
617 | } | ||
618 | } | ||
619 | 604 | ||
620 | // create the hull data structure in Bullet | 605 | // If there is hull data in the mesh asset, build the hull from that |
621 | newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls); | 606 | if (allHulls != null && BSParam.ShouldUseAssetHulls) |
607 | { | ||
608 | int hullCount = allHulls.Count; | ||
609 | int totalVertices = 1; // include one for the count of the hulls | ||
610 | // Using the structure described for HACD hulls, create the memory sturcture | ||
611 | // to pass the hull data to the creater. | ||
612 | foreach (List<OMV.Vector3> hullVerts in allHulls) | ||
613 | { | ||
614 | totalVertices += 4; // add four for the vertex count and centroid | ||
615 | totalVertices += hullVerts.Count * 3; // one vertex is three dimensions | ||
616 | } | ||
617 | float[] convHulls = new float[totalVertices]; | ||
622 | 618 | ||
623 | physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,hulls={1},totVert={2},shape={3}", | 619 | convHulls[0] = (float)hullCount; |
624 | prim.LocalID, hullCount, totalVertices, newShape); | 620 | int jj = 1; |
621 | foreach (List<OMV.Vector3> hullVerts in allHulls) | ||
622 | { | ||
623 | convHulls[jj + 0] = hullVerts.Count; | ||
624 | convHulls[jj + 1] = 0f; // centroid x,y,z | ||
625 | convHulls[jj + 2] = 0f; | ||
626 | convHulls[jj + 3] = 0f; | ||
627 | jj += 4; | ||
628 | foreach (OMV.Vector3 oneVert in hullVerts) | ||
629 | { | ||
630 | convHulls[jj + 0] = oneVert.X; | ||
631 | convHulls[jj + 1] = oneVert.Y; | ||
632 | convHulls[jj + 2] = oneVert.Z; | ||
633 | jj += 3; | ||
625 | } | 634 | } |
626 | } | 635 | } |
636 | |||
637 | // create the hull data structure in Bullet | ||
638 | newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls); | ||
639 | |||
640 | physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,hulls={1},totVert={2},shape={3}", | ||
641 | prim.LocalID, hullCount, totalVertices, newShape); | ||
627 | } | 642 | } |
643 | |||
628 | // If no hull specified in the asset and we should use Bullet's HACD approximation... | 644 | // If no hull specified in the asset and we should use Bullet's HACD approximation... |
629 | if (!newShape.HasPhysicalShape && BSParam.ShouldUseBulletHACD) | 645 | if (!newShape.HasPhysicalShape && BSParam.ShouldUseBulletHACD) |
630 | { | 646 | { |
@@ -655,120 +671,116 @@ public class BSShapeHull : BSShape | |||
655 | } | 671 | } |
656 | physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape); | 672 | physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape); |
657 | } | 673 | } |
658 | // If no hull specified, use our HACD hull approximation. | 674 | |
659 | if (!newShape.HasPhysicalShape) | 675 | // If no other hull specifications, use our HACD hull approximation. |
676 | if (!newShape.HasPhysicalShape && meshData != null) | ||
660 | { | 677 | { |
661 | // Build a new hull in the physical world using the C# HACD algorigthm. | 678 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched) |
662 | if (meshData != null) | ||
663 | { | 679 | { |
664 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched) | 680 | // Release the fetched asset data once it has been used. |
665 | { | 681 | pbs.SculptData = new byte[0]; |
666 | // Release the fetched asset data once it has been used. | 682 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown; |
667 | pbs.SculptData = new byte[0]; | 683 | } |
668 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown; | ||
669 | } | ||
670 | 684 | ||
671 | int[] indices = meshData.getIndexListAsInt(); | 685 | int[] indices = meshData.getIndexListAsInt(); |
672 | List<OMV.Vector3> vertices = meshData.getVertexList(); | 686 | List<OMV.Vector3> vertices = meshData.getVertexList(); |
673 | 687 | ||
674 | //format conversion from IMesh format to DecompDesc format | 688 | //format conversion from IMesh format to DecompDesc format |
675 | List<int> convIndices = new List<int>(); | 689 | List<int> convIndices = new List<int>(); |
676 | List<float3> convVertices = new List<float3>(); | 690 | List<float3> convVertices = new List<float3>(); |
677 | for (int ii = 0; ii < indices.GetLength(0); ii++) | 691 | for (int ii = 0; ii < indices.GetLength(0); ii++) |
678 | { | 692 | { |
679 | convIndices.Add(indices[ii]); | 693 | convIndices.Add(indices[ii]); |
680 | } | 694 | } |
681 | foreach (OMV.Vector3 vv in vertices) | 695 | foreach (OMV.Vector3 vv in vertices) |
682 | { | 696 | { |
683 | convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); | 697 | convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); |
684 | } | 698 | } |
685 | 699 | ||
686 | uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit; | 700 | uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit; |
687 | if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes) | 701 | if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes) |
702 | { | ||
703 | // Simple primitive shapes we know are convex so they are better implemented with | ||
704 | // fewer hulls. | ||
705 | // Check for simple shape (prim without cuts) and reduce split parameter if so. | ||
706 | if (BSShapeCollection.PrimHasNoCuts(pbs)) | ||
688 | { | 707 | { |
689 | // Simple primitive shapes we know are convex so they are better implemented with | 708 | maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes; |
690 | // fewer hulls. | ||
691 | // Check for simple shape (prim without cuts) and reduce split parameter if so. | ||
692 | if (BSShapeCollection.PrimHasNoCuts(pbs)) | ||
693 | { | ||
694 | maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes; | ||
695 | } | ||
696 | } | 709 | } |
710 | } | ||
711 | |||
712 | // setup and do convex hull conversion | ||
713 | m_hulls = new List<ConvexResult>(); | ||
714 | DecompDesc dcomp = new DecompDesc(); | ||
715 | dcomp.mIndices = convIndices; | ||
716 | dcomp.mVertices = convVertices; | ||
717 | dcomp.mDepth = maxDepthSplit; | ||
718 | dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent; | ||
719 | dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent; | ||
720 | dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices; | ||
721 | dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth; | ||
722 | ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); | ||
723 | // create the hull into the _hulls variable | ||
724 | convexBuilder.process(dcomp); | ||
725 | |||
726 | physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}", | ||
727 | BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count); | ||
728 | |||
729 | // Convert the vertices and indices for passing to unmanaged. | ||
730 | // The hull information is passed as a large floating point array. | ||
731 | // The format is: | ||
732 | // convHulls[0] = number of hulls | ||
733 | // convHulls[1] = number of vertices in first hull | ||
734 | // convHulls[2] = hull centroid X coordinate | ||
735 | // convHulls[3] = hull centroid Y coordinate | ||
736 | // convHulls[4] = hull centroid Z coordinate | ||
737 | // convHulls[5] = first hull vertex X | ||
738 | // convHulls[6] = first hull vertex Y | ||
739 | // convHulls[7] = first hull vertex Z | ||
740 | // convHulls[8] = second hull vertex X | ||
741 | // ... | ||
742 | // convHulls[n] = number of vertices in second hull | ||
743 | // convHulls[n+1] = second hull centroid X coordinate | ||
744 | // ... | ||
745 | // | ||
746 | // TODO: is is very inefficient. Someday change the convex hull generator to return | ||
747 | // data structures that do not need to be converted in order to pass to Bullet. | ||
748 | // And maybe put the values directly into pinned memory rather than marshaling. | ||
749 | int hullCount = m_hulls.Count; | ||
750 | int totalVertices = 1; // include one for the count of the hulls | ||
751 | foreach (ConvexResult cr in m_hulls) | ||
752 | { | ||
753 | totalVertices += 4; // add four for the vertex count and centroid | ||
754 | totalVertices += cr.HullIndices.Count * 3; // we pass just triangles | ||
755 | } | ||
756 | float[] convHulls = new float[totalVertices]; | ||
697 | 757 | ||
698 | // setup and do convex hull conversion | 758 | convHulls[0] = (float)hullCount; |
699 | m_hulls = new List<ConvexResult>(); | 759 | int jj = 1; |
700 | DecompDesc dcomp = new DecompDesc(); | 760 | foreach (ConvexResult cr in m_hulls) |
701 | dcomp.mIndices = convIndices; | 761 | { |
702 | dcomp.mVertices = convVertices; | 762 | // copy vertices for index access |
703 | dcomp.mDepth = maxDepthSplit; | 763 | float3[] verts = new float3[cr.HullVertices.Count]; |
704 | dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent; | 764 | int kk = 0; |
705 | dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent; | 765 | foreach (float3 ff in cr.HullVertices) |
706 | dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices; | ||
707 | dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth; | ||
708 | ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); | ||
709 | // create the hull into the _hulls variable | ||
710 | convexBuilder.process(dcomp); | ||
711 | |||
712 | physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}", | ||
713 | BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count); | ||
714 | |||
715 | // Convert the vertices and indices for passing to unmanaged. | ||
716 | // The hull information is passed as a large floating point array. | ||
717 | // The format is: | ||
718 | // convHulls[0] = number of hulls | ||
719 | // convHulls[1] = number of vertices in first hull | ||
720 | // convHulls[2] = hull centroid X coordinate | ||
721 | // convHulls[3] = hull centroid Y coordinate | ||
722 | // convHulls[4] = hull centroid Z coordinate | ||
723 | // convHulls[5] = first hull vertex X | ||
724 | // convHulls[6] = first hull vertex Y | ||
725 | // convHulls[7] = first hull vertex Z | ||
726 | // convHulls[8] = second hull vertex X | ||
727 | // ... | ||
728 | // convHulls[n] = number of vertices in second hull | ||
729 | // convHulls[n+1] = second hull centroid X coordinate | ||
730 | // ... | ||
731 | // | ||
732 | // TODO: is is very inefficient. Someday change the convex hull generator to return | ||
733 | // data structures that do not need to be converted in order to pass to Bullet. | ||
734 | // And maybe put the values directly into pinned memory rather than marshaling. | ||
735 | int hullCount = m_hulls.Count; | ||
736 | int totalVertices = 1; // include one for the count of the hulls | ||
737 | foreach (ConvexResult cr in m_hulls) | ||
738 | { | 766 | { |
739 | totalVertices += 4; // add four for the vertex count and centroid | 767 | verts[kk++] = ff; |
740 | totalVertices += cr.HullIndices.Count * 3; // we pass just triangles | ||
741 | } | 768 | } |
742 | float[] convHulls = new float[totalVertices]; | ||
743 | 769 | ||
744 | convHulls[0] = (float)hullCount; | 770 | // add to the array one hull's worth of data |
745 | int jj = 1; | 771 | convHulls[jj++] = cr.HullIndices.Count; |
746 | foreach (ConvexResult cr in m_hulls) | 772 | convHulls[jj++] = 0f; // centroid x,y,z |
773 | convHulls[jj++] = 0f; | ||
774 | convHulls[jj++] = 0f; | ||
775 | foreach (int ind in cr.HullIndices) | ||
747 | { | 776 | { |
748 | // copy vertices for index access | 777 | convHulls[jj++] = verts[ind].x; |
749 | float3[] verts = new float3[cr.HullVertices.Count]; | 778 | convHulls[jj++] = verts[ind].y; |
750 | int kk = 0; | 779 | convHulls[jj++] = verts[ind].z; |
751 | foreach (float3 ff in cr.HullVertices) | ||
752 | { | ||
753 | verts[kk++] = ff; | ||
754 | } | ||
755 | |||
756 | // add to the array one hull's worth of data | ||
757 | convHulls[jj++] = cr.HullIndices.Count; | ||
758 | convHulls[jj++] = 0f; // centroid x,y,z | ||
759 | convHulls[jj++] = 0f; | ||
760 | convHulls[jj++] = 0f; | ||
761 | foreach (int ind in cr.HullIndices) | ||
762 | { | ||
763 | convHulls[jj++] = verts[ind].x; | ||
764 | convHulls[jj++] = verts[ind].y; | ||
765 | convHulls[jj++] = verts[ind].z; | ||
766 | } | ||
767 | } | 780 | } |
768 | // create the hull data structure in Bullet | ||
769 | newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls); | ||
770 | } | 781 | } |
771 | newShape.shapeKey = newHullKey; | 782 | // create the hull data structure in Bullet |
783 | newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls); | ||
772 | } | 784 | } |
773 | return newShape; | 785 | return newShape; |
774 | } | 786 | } |