BulletSim: parameterize C# HACD hull creation. Add feature of reducing max hull count for simple (non-cut prims) meshes.

This commit is contained in:
Robert Adams
2013-03-22 16:50:56 -07:00
parent 128c72a234
commit f783b9169f
2 changed files with 74 additions and 14 deletions

View File

@@ -447,17 +447,10 @@ public sealed class BSShapeCollection : IDisposable
// If the prim attributes are simple, this could be a simple Bullet native shape
if (!haveShape
&& nativeShapePossible
&& pbs != null
&& !pbs.SculptEntry
&& nativeShapePossible
&& ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim)
|| (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
&& pbs.ProfileHollow == 0
&& pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
&& pbs.PathBegin == 0 && pbs.PathEnd == 0
&& pbs.PathTaperX == 0 && pbs.PathTaperY == 0
&& pbs.PathScaleX == 100 && pbs.PathScaleY == 100
&& pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
&& ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) )
{
// Get the scale of any existing shape so we can see if the new shape is same native type and same size.
OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
@@ -508,6 +501,18 @@ public sealed class BSShapeCollection : IDisposable
return ret;
}
// return 'true' if this shape description does not include any cutting or twisting.
private bool PrimHasNoCuts(PrimitiveBaseShape pbs)
{
return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
&& pbs.ProfileHollow == 0
&& pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
&& pbs.PathBegin == 0 && pbs.PathEnd == 0
&& pbs.PathTaperX == 0 && pbs.PathTaperY == 0
&& pbs.PathScaleX == 100 && pbs.PathScaleY == 100
&& pbs.PathShearX == 0 && pbs.PathShearY == 0;
}
// return 'true' if the prim's shape was changed.
public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
{
@@ -518,7 +523,7 @@ public sealed class BSShapeCollection : IDisposable
if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
{
// Update prim.BSShape to reference a hull of this shape.
ret = GetReferenceToHull(prim,shapeCallback);
ret = GetReferenceToHull(prim, shapeCallback);
if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
}
@@ -697,6 +702,7 @@ public sealed class BSShapeCollection : IDisposable
// See that hull shape exists in the physical world and update prim.BSShape.
// We could be creating the hull because scale changed or whatever.
// Return 'true' if a new hull was built. Otherwise, returning a shared hull instance.
private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
{
BulletShape newShape;
@@ -715,6 +721,7 @@ public sealed class BSShapeCollection : IDisposable
DereferenceShape(prim.PhysShape, shapeCallback);
newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
// It might not have been created if we're waiting for an asset.
newShape = VerifyMeshCreated(newShape, prim);
ReferenceShape(newShape);
@@ -733,14 +740,14 @@ public sealed class BSShapeCollection : IDisposable
HullDesc hullDesc;
if (Hulls.TryGetValue(newHullKey, out hullDesc))
{
// If the hull shape already is created, just use it.
// If the hull shape already has been created, just use the one shared instance.
newShape = hullDesc.shape.Clone();
}
else
{
// Build a new hull in the physical world
// Pass true for physicalness as this creates some sort of bounding box which we don't need
IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false);
// 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)
{
@@ -759,15 +766,35 @@ public sealed class BSShapeCollection : IDisposable
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<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: