From 59135c9a31875dc514b3ea2fe14021571807701d Mon Sep 17 00:00:00 2001
From: Robert Adams
Date: Tue, 9 Apr 2013 16:32:54 -0700
Subject: BulletSim: add Bullet HACD library invocation. Turned off by default
 as not totally debugged. Updated DLLs and SOs with more debugged HACD library
 code.

---
 OpenSim/Region/Physics/BulletSPlugin/BSParam.cs    |  53 ++++-
 OpenSim/Region/Physics/BulletSPlugin/BSScene.cs    |   1 +
 .../Physics/BulletSPlugin/BSShapeCollection.cs     | 223 ++++++++++++---------
 bin/lib32/BulletSim.dll                            | Bin 570880 -> 1008640 bytes
 bin/lib32/libBulletSim.so                          | Bin 1762207 -> 2093987 bytes
 bin/lib64/BulletSim.dll                            | Bin 721920 -> 1140224 bytes
 bin/lib64/libBulletSim.so                          | Bin 1920169 -> 2258808 bytes
 7 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
     public static bool ShouldForceSimplePrimMeshing { get; private set; }   // if a cube or sphere, let Bullet do internal shapes
     public static bool ShouldUseHullsForPhysicalObjects { get; private set; }   // 'true' if should create hulls for physical objects
     public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
+    public static bool ShouldUseBulletHACD { get; set; }
 
     public static float TerrainImplementation { get; private set; }
     public static int TerrainMeshMagnification { get; private set; }
@@ -149,6 +150,15 @@ public static class BSParam
     public static float CSHullVolumeConservationThresholdPercent { get; private set; }
     public static int CSHullMaxVertices { get; private set; }
     public static float CSHullMaxSkinWidth { get; private set; }
+	public static float BHullMaxVerticesPerHull { get; private set; }		// 100
+	public static float BHullMinClusters { get; private set; }				// 2
+	public static float BHullCompacityWeight { get; private set; }			// 0.1
+	public static float BHullVolumeWeight { get; private set; }				// 0.0
+	public static float BHullConcavity { get; private set; }				    // 100
+	public static bool BHullAddExtraDistPoints { get; private set; }		// false
+	public static bool BHullAddNeighboursDistPoints { get; private set; }	// false
+	public static bool BHullAddFacesPoints { get; private set; }			// false
+	public static bool BHullShouldAdjustCollisionMargin { get; private set; }	// false
 
     // Linkset implementation parameters
     public static float LinksetImplementation { get; private set; }
@@ -325,6 +335,10 @@ public static class BSParam
             true,
             (s) => { return ShouldRemoveZeroWidthTriangles; },
             (s,v) => { ShouldRemoveZeroWidthTriangles = v; } ),
+        new ParameterDefn<bool>("ShouldUseBulletHACD", "If true, use the Bullet version of HACD",
+            false,
+            (s) => { return ShouldUseBulletHACD; },
+            (s,v) => { ShouldUseBulletHACD = v; } ),
 
         new ParameterDefn<int>("CrossingFailuresBeforeOutOfBounds", "How forgiving we are about getting into adjactent regions",
             5,
@@ -663,10 +677,47 @@ public static class BSParam
             (s) => { return CSHullMaxVertices; },
             (s,v) => { CSHullMaxVertices = v; } ),
 	    new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.",
-            0,
+            0f,
             (s) => { return CSHullMaxSkinWidth; },
             (s,v) => { CSHullMaxSkinWidth = v; } ),
 
+	    new ParameterDefn<float>("BHullMaxVerticesPerHull", "Bullet impl: max number of vertices per created hull",
+            100f,
+            (s) => { return BHullMaxVerticesPerHull; },
+            (s,v) => { BHullMaxVerticesPerHull = v; } ),
+	    new ParameterDefn<float>("BHullMinClusters", "Bullet impl: minimum number of hulls to create per mesh",
+            2f,
+            (s) => { return BHullMinClusters; },
+            (s,v) => { BHullMinClusters = v; } ),
+	    new ParameterDefn<float>("BHullCompacityWeight", "Bullet impl: weight factor for how compact to make hulls",
+            2f,
+            (s) => { return BHullCompacityWeight; },
+            (s,v) => { BHullCompacityWeight = v; } ),
+	    new ParameterDefn<float>("BHullVolumeWeight", "Bullet impl: weight factor for volume in created hull",
+            0.1f,
+            (s) => { return BHullVolumeWeight; },
+            (s,v) => { BHullVolumeWeight = v; } ),
+	    new ParameterDefn<float>("BHullConcavity", "Bullet impl: weight factor for how convex a created hull can be",
+            100f,
+            (s) => { return BHullConcavity; },
+            (s,v) => { BHullConcavity = v; } ),
+	    new ParameterDefn<bool>("BHullAddExtraDistPoints", "Bullet impl: whether to add extra vertices for long distance vectors",
+            false,
+            (s) => { return BHullAddExtraDistPoints; },
+            (s,v) => { BHullAddExtraDistPoints = v; } ),
+	    new ParameterDefn<bool>("BHullAddNeighboursDistPoints", "Bullet impl: whether to add extra vertices between neighbor hulls",
+            false,
+            (s) => { return BHullAddNeighboursDistPoints; },
+            (s,v) => { BHullAddNeighboursDistPoints = v; } ),
+	    new ParameterDefn<bool>("BHullAddFacesPoints", "Bullet impl: whether to add extra vertices to break up hull faces",
+            false,
+            (s) => { return BHullAddFacesPoints; },
+            (s,v) => { BHullAddFacesPoints = v; } ),
+	    new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin",
+            false,
+            (s) => { return BHullShouldAdjustCollisionMargin; },
+            (s,v) => { BHullShouldAdjustCollisionMargin = v; } ),
+
 	    new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
             (float)BSLinkset.LinksetImplementation.Compound,
             (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
                 break;
             case "bulletxna":
                 ret = new BSAPIXNA(engineName, this);
+                BSParam.ShouldUseBulletHACD = false;
                 break;
         }
 
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
         // Remove usage of the previous shape.
         DereferenceShape(prim.PhysShape, shapeCallback);
 
-        newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
+        newShape = CreatePhysicalHull(prim, newHullKey, prim.BaseShape, prim.Size, lod);
         // It might not have been created if we're waiting for an asset.
         newShape = VerifyMeshCreated(newShape, prim);
 
@@ -731,7 +731,7 @@ public sealed class BSShapeCollection : IDisposable
     }
 
     List<ConvexResult> m_hulls;
-    private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
+    private BulletShape CreatePhysicalHull(BSPhysObject prim, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
     {
 
         BulletShape newShape = new BulletShape();
@@ -745,116 +745,153 @@ public sealed class BSShapeCollection : IDisposable
         }
         else
         {
-            // Build a new hull in the physical world.
-            // Pass true for physicalness as this prevents the creation of bounding box which is not needed
-            IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
-            if (meshData != null)
+            if (BSParam.ShouldUseBulletHACD)
             {
-
-                int[] indices = meshData.getIndexListAsInt();
-                List<OMV.Vector3> vertices = meshData.getVertexList();
-
-                //format conversion from IMesh format to DecompDesc format
-                List<int> convIndices = new List<int>();
-                List<float3> convVertices = new List<float3>();
-                for (int ii = 0; ii < indices.GetLength(0); ii++)
+                DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
+                MeshDesc meshDesc;
+                if (!Meshes.TryGetValue(newHullKey, out meshDesc))
                 {
-                    convIndices.Add(indices[ii]);
+                    // That's odd because the mesh should have been created before the hull
+                    //     but, since it doesn't exist, create it.
+                    newShape = CreatePhysicalMesh(prim, newHullKey, prim.BaseShape, prim.Size, lod);
+                    DetailLog("{0},BSShapeCollection.CreatePhysicalHull,noMeshBuiltNew,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
+
+                    if (newShape.HasPhysicalShape)
+                    {
+                        ReferenceShape(newShape);
+                        Meshes.TryGetValue(newHullKey, out meshDesc);
+                    }
                 }
-                foreach (OMV.Vector3 vv in vertices)
+                if (meshDesc.shape.HasPhysicalShape)
                 {
-                    convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
+                    HACDParams parms;
+                    parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
+                    parms.minClusters = BSParam.BHullMinClusters;
+                    parms.compacityWeight = BSParam.BHullCompacityWeight;
+                    parms.volumeWeight = BSParam.BHullVolumeWeight;
+                    parms.concavity = BSParam.BHullConcavity;
+                	parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
+                	parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
+                	parms.addFacesPoints =  BSParam.NumericBool(BSParam.BHullAddFacesPoints);
+                    parms.shouldAdjustCollisionMargin =  BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
+
+                    DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
+                    newShape = PhysicsScene.PE.BuildHullShapeFromMesh(PhysicsScene.World, meshDesc.shape, parms);
+                    DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
                 }
-
-                uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
-                if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
+                DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
+            }
+            if (!newShape.HasPhysicalShape)
+            {
+                // Build a new hull in the physical world.
+                // Pass true for physicalness as this prevents the creation of bounding box which is not needed
+                IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
+                if (meshData != null)
                 {
-                    // Simple primitive shapes we know are convex so they are better implemented with
-                    //    fewer hulls.
-                    // Check for simple shape (prim without cuts) and reduce split parameter if so.
-                    if (PrimHasNoCuts(pbs))
+                    int[] indices = meshData.getIndexListAsInt();
+                    List<OMV.Vector3> vertices = meshData.getVertexList();
+
+                    //format conversion from IMesh format to DecompDesc format
+                    List<int> convIndices = new List<int>();
+                    List<float3> convVertices = new List<float3>();
+                    for (int ii = 0; ii < indices.GetLength(0); ii++)
                     {
-                        maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
+                        convIndices.Add(indices[ii]);
+                    }
+                    foreach (OMV.Vector3 vv in vertices)
+                    {
+                        convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
                     }
-                }
 
-                // setup and do convex hull conversion
-                m_hulls = new List<ConvexResult>();
-                DecompDesc dcomp = new DecompDesc();
-                dcomp.mIndices = convIndices;
-                dcomp.mVertices = convVertices;
-                dcomp.mDepth = maxDepthSplit;
-                dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
-                dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
-                dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
-                dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
-                ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
-                // create the hull into the _hulls variable
-                convexBuilder.process(dcomp);
-
-                DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
-                                    BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
-
-                // Convert the vertices and indices for passing to unmanaged.
-                // The hull information is passed as a large floating point array.
-                // The format is:
-                //  convHulls[0] = number of hulls
-                //  convHulls[1] = number of vertices in first hull
-                //  convHulls[2] = hull centroid X coordinate
-                //  convHulls[3] = hull centroid Y coordinate
-                //  convHulls[4] = hull centroid Z coordinate
-                //  convHulls[5] = first hull vertex X
-                //  convHulls[6] = first hull vertex Y
-                //  convHulls[7] = first hull vertex Z
-                //  convHulls[8] = second hull vertex X
-                //  ...
-                //  convHulls[n] = number of vertices in second hull
-                //  convHulls[n+1] = second hull centroid X coordinate
-                //  ...
-                //
-                // TODO: is is very inefficient. Someday change the convex hull generator to return
-                //   data structures that do not need to be converted in order to pass to Bullet.
-                //   And maybe put the values directly into pinned memory rather than marshaling.
-                int hullCount = m_hulls.Count;
-                int totalVertices = 1;          // include one for the count of the hulls
-                foreach (ConvexResult cr in m_hulls)
-                {
-                    totalVertices += 4;                         // add four for the vertex count and centroid
-                    totalVertices += cr.HullIndices.Count * 3;  // we pass just triangles
-                }
-                float[] convHulls = new float[totalVertices];
+                    uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
+                    if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
+                    {
+                        // Simple primitive shapes we know are convex so they are better implemented with
+                        //    fewer hulls.
+                        // Check for simple shape (prim without cuts) and reduce split parameter if so.
+                        if (PrimHasNoCuts(pbs))
+                        {
+                            maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
+                        }
+                    }
 
-                convHulls[0] = (float)hullCount;
-                int jj = 1;
-                foreach (ConvexResult cr in m_hulls)
-                {
-                    // copy vertices for index access
-                    float3[] verts = new float3[cr.HullVertices.Count];
-                    int kk = 0;
-                    foreach (float3 ff in cr.HullVertices)
+                    // setup and do convex hull conversion
+                    m_hulls = new List<ConvexResult>();
+                    DecompDesc dcomp = new DecompDesc();
+                    dcomp.mIndices = convIndices;
+                    dcomp.mVertices = convVertices;
+                    dcomp.mDepth = maxDepthSplit;
+                    dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
+                    dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
+                    dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
+                    dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
+                    ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
+                    // create the hull into the _hulls variable
+                    convexBuilder.process(dcomp);
+
+                    DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
+                                        BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
+
+                    // Convert the vertices and indices for passing to unmanaged.
+                    // The hull information is passed as a large floating point array.
+                    // The format is:
+                    //  convHulls[0] = number of hulls
+                    //  convHulls[1] = number of vertices in first hull
+                    //  convHulls[2] = hull centroid X coordinate
+                    //  convHulls[3] = hull centroid Y coordinate
+                    //  convHulls[4] = hull centroid Z coordinate
+                    //  convHulls[5] = first hull vertex X
+                    //  convHulls[6] = first hull vertex Y
+                    //  convHulls[7] = first hull vertex Z
+                    //  convHulls[8] = second hull vertex X
+                    //  ...
+                    //  convHulls[n] = number of vertices in second hull
+                    //  convHulls[n+1] = second hull centroid X coordinate
+                    //  ...
+                    //
+                    // TODO: is is very inefficient. Someday change the convex hull generator to return
+                    //   data structures that do not need to be converted in order to pass to Bullet.
+                    //   And maybe put the values directly into pinned memory rather than marshaling.
+                    int hullCount = m_hulls.Count;
+                    int totalVertices = 1;          // include one for the count of the hulls
+                    foreach (ConvexResult cr in m_hulls)
                     {
-                        verts[kk++] = ff;
+                        totalVertices += 4;                         // add four for the vertex count and centroid
+                        totalVertices += cr.HullIndices.Count * 3;  // we pass just triangles
                     }
+                    float[] convHulls = new float[totalVertices];
 
-                    // add to the array one hull's worth of data
-                    convHulls[jj++] = cr.HullIndices.Count;
-                    convHulls[jj++] = 0f;   // centroid x,y,z
-                    convHulls[jj++] = 0f;
-                    convHulls[jj++] = 0f;
-                    foreach (int ind in cr.HullIndices)
+                    convHulls[0] = (float)hullCount;
+                    int jj = 1;
+                    foreach (ConvexResult cr in m_hulls)
                     {
-                        convHulls[jj++] = verts[ind].x;
-                        convHulls[jj++] = verts[ind].y;
-                        convHulls[jj++] = verts[ind].z;
+                        // copy vertices for index access
+                        float3[] verts = new float3[cr.HullVertices.Count];
+                        int kk = 0;
+                        foreach (float3 ff in cr.HullVertices)
+                        {
+                            verts[kk++] = ff;
+                        }
+
+                        // add to the array one hull's worth of data
+                        convHulls[jj++] = cr.HullIndices.Count;
+                        convHulls[jj++] = 0f;   // centroid x,y,z
+                        convHulls[jj++] = 0f;
+                        convHulls[jj++] = 0f;
+                        foreach (int ind in cr.HullIndices)
+                        {
+                            convHulls[jj++] = verts[ind].x;
+                            convHulls[jj++] = verts[ind].y;
+                            convHulls[jj++] = verts[ind].z;
+                        }
                     }
+                    // create the hull data structure in Bullet
+                    newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
                 }
-                // create the hull data structure in Bullet
-                newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
             }
+            newShape.shapeKey = newHullKey;
         }
 
-        newShape.shapeKey = newHullKey;
-
         return newShape;
     }
 
diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll
index 5432813..618d4bd 100755
Binary files a/bin/lib32/BulletSim.dll and b/bin/lib32/BulletSim.dll differ
diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so
index 286d930..e3b40fb 100755
Binary files a/bin/lib32/libBulletSim.so and b/bin/lib32/libBulletSim.so differ
diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll
index dca7116..491ac22 100755
Binary files a/bin/lib64/BulletSim.dll and b/bin/lib64/BulletSim.dll differ
diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so
index b63feb3..a8ad533 100755
Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ
-- 
cgit v1.1