aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs53
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs1
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs223
3 files changed, 183 insertions, 94 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 385ed9e..06df85e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -86,6 +86,7 @@ public static class BSParam
86 public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes 86 public static bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes
87 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects 87 public static bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects
88 public static bool ShouldRemoveZeroWidthTriangles { get; private set; } 88 public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
89 public static bool ShouldUseBulletHACD { get; set; }
89 90
90 public static float TerrainImplementation { get; private set; } 91 public static float TerrainImplementation { get; private set; }
91 public static int TerrainMeshMagnification { get; private set; } 92 public static int TerrainMeshMagnification { get; private set; }
@@ -149,6 +150,15 @@ public static class BSParam
149 public static float CSHullVolumeConservationThresholdPercent { get; private set; } 150 public static float CSHullVolumeConservationThresholdPercent { get; private set; }
150 public static int CSHullMaxVertices { get; private set; } 151 public static int CSHullMaxVertices { get; private set; }
151 public static float CSHullMaxSkinWidth { get; private set; } 152 public static float CSHullMaxSkinWidth { get; private set; }
153 public static float BHullMaxVerticesPerHull { get; private set; } // 100
154 public static float BHullMinClusters { get; private set; } // 2
155 public static float BHullCompacityWeight { get; private set; } // 0.1
156 public static float BHullVolumeWeight { get; private set; } // 0.0
157 public static float BHullConcavity { get; private set; } // 100
158 public static bool BHullAddExtraDistPoints { get; private set; } // false
159 public static bool BHullAddNeighboursDistPoints { get; private set; } // false
160 public static bool BHullAddFacesPoints { get; private set; } // false
161 public static bool BHullShouldAdjustCollisionMargin { get; private set; } // false
152 162
153 // Linkset implementation parameters 163 // Linkset implementation parameters
154 public static float LinksetImplementation { get; private set; } 164 public static float LinksetImplementation { get; private set; }
@@ -325,6 +335,10 @@ public static class BSParam
325 true, 335 true,
326 (s) => { return ShouldRemoveZeroWidthTriangles; }, 336 (s) => { return ShouldRemoveZeroWidthTriangles; },
327 (s,v) => { ShouldRemoveZeroWidthTriangles = v; } ), 337 (s,v) => { ShouldRemoveZeroWidthTriangles = v; } ),
338 new ParameterDefn<bool>("ShouldUseBulletHACD", "If true, use the Bullet version of HACD",
339 false,
340 (s) => { return ShouldUseBulletHACD; },
341 (s,v) => { ShouldUseBulletHACD = v; } ),
328 342
329 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions", 343 new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
330 5, 344 5,
@@ -663,10 +677,47 @@ public static class BSParam
663 (s) => { return CSHullMaxVertices; }, 677 (s) => { return CSHullMaxVertices; },
664 (s,v) => { CSHullMaxVertices = v; } ), 678 (s,v) => { CSHullMaxVertices = v; } ),
665 new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.", 679 new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.",
666 0, 680 0f,
667 (s) => { return CSHullMaxSkinWidth; }, 681 (s) => { return CSHullMaxSkinWidth; },
668 (s,v) => { CSHullMaxSkinWidth = v; } ), 682 (s,v) => { CSHullMaxSkinWidth = v; } ),
669 683
684 new ParameterDefn<float>("BHullMaxVerticesPerHull", "Bullet impl: max number of vertices per created hull",
685 100f,
686 (s) => { return BHullMaxVerticesPerHull; },
687 (s,v) => { BHullMaxVerticesPerHull = v; } ),
688 new ParameterDefn<float>("BHullMinClusters", "Bullet impl: minimum number of hulls to create per mesh",
689 2f,
690 (s) => { return BHullMinClusters; },
691 (s,v) => { BHullMinClusters = v; } ),
692 new ParameterDefn<float>("BHullCompacityWeight", "Bullet impl: weight factor for how compact to make hulls",
693 2f,
694 (s) => { return BHullCompacityWeight; },
695 (s,v) => { BHullCompacityWeight = v; } ),
696 new ParameterDefn<float>("BHullVolumeWeight", "Bullet impl: weight factor for volume in created hull",
697 0.1f,
698 (s) => { return BHullVolumeWeight; },
699 (s,v) => { BHullVolumeWeight = v; } ),
700 new ParameterDefn<float>("BHullConcavity", "Bullet impl: weight factor for how convex a created hull can be",
701 100f,
702 (s) => { return BHullConcavity; },
703 (s,v) => { BHullConcavity = v; } ),
704 new ParameterDefn<bool>("BHullAddExtraDistPoints", "Bullet impl: whether to add extra vertices for long distance vectors",
705 false,
706 (s) => { return BHullAddExtraDistPoints; },
707 (s,v) => { BHullAddExtraDistPoints = v; } ),
708 new ParameterDefn<bool>("BHullAddNeighboursDistPoints", "Bullet impl: whether to add extra vertices between neighbor hulls",
709 false,
710 (s) => { return BHullAddNeighboursDistPoints; },
711 (s,v) => { BHullAddNeighboursDistPoints = v; } ),
712 new ParameterDefn<bool>("BHullAddFacesPoints", "Bullet impl: whether to add extra vertices to break up hull faces",
713 false,
714 (s) => { return BHullAddFacesPoints; },
715 (s,v) => { BHullAddFacesPoints = v; } ),
716 new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin",
717 false,
718 (s) => { return BHullShouldAdjustCollisionMargin; },
719 (s,v) => { BHullShouldAdjustCollisionMargin = v; } ),
720
670 new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", 721 new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
671 (float)BSLinkset.LinksetImplementation.Compound, 722 (float)BSLinkset.LinksetImplementation.Compound,
672 (s) => { return LinksetImplementation; }, 723 (s) => { return LinksetImplementation; },
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 9818b05..8e05b58 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -316,6 +316,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
316 break; 316 break;
317 case "bulletxna": 317 case "bulletxna":
318 ret = new BSAPIXNA(engineName, this); 318 ret = new BSAPIXNA(engineName, this);
319 BSParam.ShouldUseBulletHACD = false;
319 break; 320 break;
320 } 321 }
321 322
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index b6ac23d..bfa69b2 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -720,7 +720,7 @@ public sealed class BSShapeCollection : IDisposable
720 // Remove usage of the previous shape. 720 // Remove usage of the previous shape.
721 DereferenceShape(prim.PhysShape, shapeCallback); 721 DereferenceShape(prim.PhysShape, shapeCallback);
722 722
723 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); 723 newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod);
724 // It might not have been created if we're waiting for an asset. 724 // It might not have been created if we're waiting for an asset.
725 newShape = VerifyMeshCreated(newShape, prim); 725 newShape = VerifyMeshCreated(newShape, prim);
726 726
@@ -731,7 +731,7 @@ public sealed class BSShapeCollection : IDisposable
731 } 731 }
732 732
733 List<ConvexResult> m_hulls; 733 List<ConvexResult> m_hulls;
734 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 734 private BulletShape CreatePhysicalHull(BSPhysObject prim, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
735 { 735 {
736 736
737 BulletShape newShape = new BulletShape(); 737 BulletShape newShape = new BulletShape();
@@ -745,116 +745,153 @@ public sealed class BSShapeCollection : IDisposable
745 } 745 }
746 else 746 else
747 { 747 {
748 // Build a new hull in the physical world. 748 if (BSParam.ShouldUseBulletHACD)
749 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
750 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
751 if (meshData != null)
752 { 749 {
753 750 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
754 int[] indices = meshData.getIndexListAsInt(); 751 MeshDesc meshDesc;
755 List<OMV.Vector3> vertices = meshData.getVertexList(); 752 if (!Meshes.TryGetValue(newHullKey, out meshDesc))
756
757 //format conversion from IMesh format to DecompDesc format
758 List<int> convIndices = new List<int>();
759 List<float3> convVertices = new List<float3>();
760 for (int ii = 0; ii < indices.GetLength(0); ii++)
761 { 753 {
762 convIndices.Add(indices[ii]); 754 // That's odd because the mesh should have been created before the hull
755 // but, since it doesn't exist, create it.
756 newShape = CreatePhysicalMesh(prim, newHullKey, prim.BaseShape, prim.Size, lod);
757 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,noMeshBuiltNew,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
758
759 if (newShape.HasPhysicalShape)
760 {
761 ReferenceShape(newShape);
762 Meshes.TryGetValue(newHullKey, out meshDesc);
763 }
763 } 764 }
764 foreach (OMV.Vector3 vv in vertices) 765 if (meshDesc.shape.HasPhysicalShape)
765 { 766 {
766 convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); 767 HACDParams parms;
768 parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
769 parms.minClusters = BSParam.BHullMinClusters;
770 parms.compacityWeight = BSParam.BHullCompacityWeight;
771 parms.volumeWeight = BSParam.BHullVolumeWeight;
772 parms.concavity = BSParam.BHullConcavity;
773 parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
774 parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
775 parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
776 parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
777
778 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
779 newShape = PhysicsScene.PE.BuildHullShapeFromMesh(PhysicsScene.World, meshDesc.shape, parms);
780 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
767 } 781 }
768 782 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
769 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit; 783 }
770 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes) 784 if (!newShape.HasPhysicalShape)
785 {
786 // Build a new hull in the physical world.
787 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
788 IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
789 if (meshData != null)
771 { 790 {
772 // Simple primitive shapes we know are convex so they are better implemented with 791 int[] indices = meshData.getIndexListAsInt();
773 // fewer hulls. 792 List<OMV.Vector3> vertices = meshData.getVertexList();
774 // Check for simple shape (prim without cuts) and reduce split parameter if so. 793
775 if (PrimHasNoCuts(pbs)) 794 //format conversion from IMesh format to DecompDesc format
795 List<int> convIndices = new List<int>();
796 List<float3> convVertices = new List<float3>();
797 for (int ii = 0; ii < indices.GetLength(0); ii++)
776 { 798 {
777 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes; 799 convIndices.Add(indices[ii]);
800 }
801 foreach (OMV.Vector3 vv in vertices)
802 {
803 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
778 } 804 }
779 }
780 805
781 // setup and do convex hull conversion 806 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
782 m_hulls = new List<ConvexResult>(); 807 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
783 DecompDesc dcomp = new DecompDesc(); 808 {
784 dcomp.mIndices = convIndices; 809 // Simple primitive shapes we know are convex so they are better implemented with
785 dcomp.mVertices = convVertices; 810 // fewer hulls.
786 dcomp.mDepth = maxDepthSplit; 811 // Check for simple shape (prim without cuts) and reduce split parameter if so.
787 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent; 812 if (PrimHasNoCuts(pbs))
788 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent; 813 {
789 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices; 814 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
790 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth; 815 }
791 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); 816 }
792 // create the hull into the _hulls variable
793 convexBuilder.process(dcomp);
794
795 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
796 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
797
798 // Convert the vertices and indices for passing to unmanaged.
799 // The hull information is passed as a large floating point array.
800 // The format is:
801 // convHulls[0] = number of hulls
802 // convHulls[1] = number of vertices in first hull
803 // convHulls[2] = hull centroid X coordinate
804 // convHulls[3] = hull centroid Y coordinate
805 // convHulls[4] = hull centroid Z coordinate
806 // convHulls[5] = first hull vertex X
807 // convHulls[6] = first hull vertex Y
808 // convHulls[7] = first hull vertex Z
809 // convHulls[8] = second hull vertex X
810 // ...
811 // convHulls[n] = number of vertices in second hull
812 // convHulls[n+1] = second hull centroid X coordinate
813 // ...
814 //
815 // TODO: is is very inefficient. Someday change the convex hull generator to return
816 // data structures that do not need to be converted in order to pass to Bullet.
817 // And maybe put the values directly into pinned memory rather than marshaling.
818 int hullCount = m_hulls.Count;
819 int totalVertices = 1; // include one for the count of the hulls
820 foreach (ConvexResult cr in m_hulls)
821 {
822 totalVertices += 4; // add four for the vertex count and centroid
823 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
824 }
825 float[] convHulls = new float[totalVertices];
826 817
827 convHulls[0] = (float)hullCount; 818 // setup and do convex hull conversion
828 int jj = 1; 819 m_hulls = new List<ConvexResult>();
829 foreach (ConvexResult cr in m_hulls) 820 DecompDesc dcomp = new DecompDesc();
830 { 821 dcomp.mIndices = convIndices;
831 // copy vertices for index access 822 dcomp.mVertices = convVertices;
832 float3[] verts = new float3[cr.HullVertices.Count]; 823 dcomp.mDepth = maxDepthSplit;
833 int kk = 0; 824 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
834 foreach (float3 ff in cr.HullVertices) 825 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
826 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
827 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
828 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
829 // create the hull into the _hulls variable
830 convexBuilder.process(dcomp);
831
832 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
833 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
834
835 // Convert the vertices and indices for passing to unmanaged.
836 // The hull information is passed as a large floating point array.
837 // The format is:
838 // convHulls[0] = number of hulls
839 // convHulls[1] = number of vertices in first hull
840 // convHulls[2] = hull centroid X coordinate
841 // convHulls[3] = hull centroid Y coordinate
842 // convHulls[4] = hull centroid Z coordinate
843 // convHulls[5] = first hull vertex X
844 // convHulls[6] = first hull vertex Y
845 // convHulls[7] = first hull vertex Z
846 // convHulls[8] = second hull vertex X
847 // ...
848 // convHulls[n] = number of vertices in second hull
849 // convHulls[n+1] = second hull centroid X coordinate
850 // ...
851 //
852 // TODO: is is very inefficient. Someday change the convex hull generator to return
853 // data structures that do not need to be converted in order to pass to Bullet.
854 // And maybe put the values directly into pinned memory rather than marshaling.
855 int hullCount = m_hulls.Count;
856 int totalVertices = 1; // include one for the count of the hulls
857 foreach (ConvexResult cr in m_hulls)
835 { 858 {
836 verts[kk++] = ff; 859 totalVertices += 4; // add four for the vertex count and centroid
860 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
837 } 861 }
862 float[] convHulls = new float[totalVertices];
838 863
839 // add to the array one hull's worth of data 864 convHulls[0] = (float)hullCount;
840 convHulls[jj++] = cr.HullIndices.Count; 865 int jj = 1;
841 convHulls[jj++] = 0f; // centroid x,y,z 866 foreach (ConvexResult cr in m_hulls)
842 convHulls[jj++] = 0f;
843 convHulls[jj++] = 0f;
844 foreach (int ind in cr.HullIndices)
845 { 867 {
846 convHulls[jj++] = verts[ind].x; 868 // copy vertices for index access
847 convHulls[jj++] = verts[ind].y; 869 float3[] verts = new float3[cr.HullVertices.Count];
848 convHulls[jj++] = verts[ind].z; 870 int kk = 0;
871 foreach (float3 ff in cr.HullVertices)
872 {
873 verts[kk++] = ff;
874 }
875
876 // add to the array one hull's worth of data
877 convHulls[jj++] = cr.HullIndices.Count;
878 convHulls[jj++] = 0f; // centroid x,y,z
879 convHulls[jj++] = 0f;
880 convHulls[jj++] = 0f;
881 foreach (int ind in cr.HullIndices)
882 {
883 convHulls[jj++] = verts[ind].x;
884 convHulls[jj++] = verts[ind].y;
885 convHulls[jj++] = verts[ind].z;
886 }
849 } 887 }
888 // create the hull data structure in Bullet
889 newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
850 } 890 }
851 // create the hull data structure in Bullet
852 newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
853 } 891 }
892 newShape.shapeKey = newHullKey;
854 } 893 }
855 894
856 newShape.shapeKey = newHullKey;
857
858 return newShape; 895 return newShape;
859 } 896 }
860 897