diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index 385ed9e9bc..06df85e1e1 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("ShouldUseBulletHACD", "If true, use the Bullet version of HACD", + false, + (s) => { return ShouldUseBulletHACD; }, + (s,v) => { ShouldUseBulletHACD = v; } ), new ParameterDefn("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("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.", - 0, + 0f, (s) => { return CSHullMaxSkinWidth; }, (s,v) => { CSHullMaxSkinWidth = v; } ), + new ParameterDefn("BHullMaxVerticesPerHull", "Bullet impl: max number of vertices per created hull", + 100f, + (s) => { return BHullMaxVerticesPerHull; }, + (s,v) => { BHullMaxVerticesPerHull = v; } ), + new ParameterDefn("BHullMinClusters", "Bullet impl: minimum number of hulls to create per mesh", + 2f, + (s) => { return BHullMinClusters; }, + (s,v) => { BHullMinClusters = v; } ), + new ParameterDefn("BHullCompacityWeight", "Bullet impl: weight factor for how compact to make hulls", + 2f, + (s) => { return BHullCompacityWeight; }, + (s,v) => { BHullCompacityWeight = v; } ), + new ParameterDefn("BHullVolumeWeight", "Bullet impl: weight factor for volume in created hull", + 0.1f, + (s) => { return BHullVolumeWeight; }, + (s,v) => { BHullVolumeWeight = v; } ), + new ParameterDefn("BHullConcavity", "Bullet impl: weight factor for how convex a created hull can be", + 100f, + (s) => { return BHullConcavity; }, + (s,v) => { BHullConcavity = v; } ), + new ParameterDefn("BHullAddExtraDistPoints", "Bullet impl: whether to add extra vertices for long distance vectors", + false, + (s) => { return BHullAddExtraDistPoints; }, + (s,v) => { BHullAddExtraDistPoints = v; } ), + new ParameterDefn("BHullAddNeighboursDistPoints", "Bullet impl: whether to add extra vertices between neighbor hulls", + false, + (s) => { return BHullAddNeighboursDistPoints; }, + (s,v) => { BHullAddNeighboursDistPoints = v; } ), + new ParameterDefn("BHullAddFacesPoints", "Bullet impl: whether to add extra vertices to break up hull faces", + false, + (s) => { return BHullAddFacesPoints; }, + (s,v) => { BHullAddFacesPoints = v; } ), + new ParameterDefn("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin", + false, + (s) => { return BHullShouldAdjustCollisionMargin; }, + (s,v) => { BHullShouldAdjustCollisionMargin = v; } ), + new ParameterDefn("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 9818b054fc..8e05b587aa 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 b6ac23d6a0..bfa69b28b4 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 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,115 +745,152 @@ 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 vertices = meshData.getVertexList(); - - //format conversion from IMesh format to DecompDesc format - List convIndices = new List(); - List convVertices = new List(); - 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]); - } - foreach (OMV.Vector3 vv in vertices) - { - convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); - } + // 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); - 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)) + if (newShape.HasPhysicalShape) { - maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes; + ReferenceShape(newShape); + Meshes.TryGetValue(newHullKey, out meshDesc); } } - - // setup and do convex hull conversion - m_hulls = new List(); - 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) + if (meshDesc.shape.HasPhysicalShape) { - totalVertices += 4; // add four for the vertex count and centroid - totalVertices += cr.HullIndices.Count * 3; // we pass just triangles - } - float[] convHulls = new float[totalVertices]; + 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); - 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) - { - 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; - } + 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); } - // create the hull data structure in Bullet - newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls); + 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) + { + int[] indices = meshData.getIndexListAsInt(); + List vertices = meshData.getVertexList(); - newShape.shapeKey = newHullKey; + //format conversion from IMesh format to DecompDesc format + List convIndices = new List(); + List convVertices = new List(); + for (int ii = 0; ii < indices.GetLength(0); ii++) + { + convIndices.Add(indices[ii]); + } + foreach (OMV.Vector3 vv in vertices) + { + convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); + } + + 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; + } + } + + // setup and do convex hull conversion + m_hulls = new List(); + 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]; + + 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) + { + 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); + } + } + newShape.shapeKey = newHullKey; + } return newShape; } diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll index 5432813a50..618d4bd3e2 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 286d930864..e3b40fba1b 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 dca711603a..491ac22fe1 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 b63feb3ae6..a8ad533e87 100755 Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ