BulletSim: parameterize C# HACD hull creation. Add feature of reducing max hull count for simple (non-cut prims) meshes.
parent
128c72a234
commit
f783b9169f
|
@ -142,6 +142,14 @@ public static class BSParam
|
|||
public static float VehicleAngularBankingTimescaleFudge { get; private set; }
|
||||
public static bool VehicleDebuggingEnabled { get; private set; }
|
||||
|
||||
// Convex Hulls
|
||||
public static int CSHullMaxDepthSplit { get; private set; }
|
||||
public static int CSHullMaxDepthSplitForSimpleShapes { get; private set; }
|
||||
public static float CSHullConcavityThresholdPercent { get; private set; }
|
||||
public static float CSHullVolumeConservationThresholdPercent { get; private set; }
|
||||
public static int CSHullMaxVertices { get; private set; }
|
||||
public static float CSHullMaxSkinWidth { get; private set; }
|
||||
|
||||
// Linkset implementation parameters
|
||||
public static float LinksetImplementation { get; private set; }
|
||||
public static bool LinkConstraintUseFrameOffset { get; private set; }
|
||||
|
@ -623,6 +631,31 @@ public static class BSParam
|
|||
(s) => { return GlobalContactBreakingThreshold; },
|
||||
(s,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ),
|
||||
|
||||
new ParameterDefn<int>("CSHullMaxDepthSplit", "CS impl: max depth to split for hull. 1-10 but > 7 is iffy",
|
||||
7,
|
||||
(s) => { return CSHullMaxDepthSplit; },
|
||||
(s,v) => { CSHullMaxDepthSplit = v; } ),
|
||||
new ParameterDefn<int>("CSHullMaxDepthSplitForSimpleShapes", "CS impl: max depth setting for simple prim shapes",
|
||||
2,
|
||||
(s) => { return CSHullMaxDepthSplitForSimpleShapes; },
|
||||
(s,v) => { CSHullMaxDepthSplitForSimpleShapes = v; } ),
|
||||
new ParameterDefn<float>("CSHullConcavityThresholdPercent", "CS impl: concavity threshold percent (0-20)",
|
||||
5f,
|
||||
(s) => { return CSHullConcavityThresholdPercent; },
|
||||
(s,v) => { CSHullConcavityThresholdPercent = v; } ),
|
||||
new ParameterDefn<float>("CSHullVolumeConservationThresholdPercent", "percent volume conservation to collapse hulls (0-30)",
|
||||
5f,
|
||||
(s) => { return CSHullVolumeConservationThresholdPercent; },
|
||||
(s,v) => { CSHullVolumeConservationThresholdPercent = v; } ),
|
||||
new ParameterDefn<int>("CSHullMaxVertices", "CS impl: maximum number of vertices in output hulls. Keep < 50.",
|
||||
32,
|
||||
(s) => { return CSHullMaxVertices; },
|
||||
(s,v) => { CSHullMaxVertices = v; } ),
|
||||
new ParameterDefn<float>("CSHullMaxSkinWidth", "CS impl: skin width to apply to output hulls.",
|
||||
0,
|
||||
(s) => { return CSHullMaxSkinWidth; },
|
||||
(s,v) => { CSHullMaxSkinWidth = v; } ),
|
||||
|
||||
new ParameterDefn<float>("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
|
||||
(float)BSLinkset.LinksetImplementation.Compound,
|
||||
(s) => { return LinksetImplementation; },
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue