From f783b9169fbc0544ec6c634900cb34bf48c6b2a9 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 22 Mar 2013 16:50:56 -0700 Subject: BulletSim: parameterize C# HACD hull creation. Add feature of reducing max hull count for simple (non-cut prims) meshes. --- .../Physics/BulletSPlugin/BSShapeCollection.cs | 55 ++++++++++++++++------ 1 file changed, 41 insertions(+), 14 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index b16bc10..457f204 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -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(); 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: -- cgit v1.1 From 953090fd62c2f8647d0e04bc3890a04a7076dbad Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Sat, 23 Mar 2013 11:00:52 -0700 Subject: BulletSim: fix possible race condition where an prim's asset can be requested quicker than the asset fetcher returns and thus falsely reporting that an asset was not fetched and defaulting the assset to a bounding box. --- .../Physics/BulletSPlugin/BSShapeCollection.cs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs') diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 457f204..a6e20a8 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -930,11 +930,15 @@ public sealed class BSShapeCollection : IDisposable return newShape; // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset - if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) + if (prim.BaseShape.SculptEntry + && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed + && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting + && prim.BaseShape.SculptTexture != OMV.UUID.Zero + ) { - DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lastFailed={1}", prim.LocalID, prim.LastAssetBuildFailed); - // This will prevent looping through this code as we keep trying to get the failed shape - prim.LastAssetBuildFailed = true; + DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID); + // Multiple requestors will know we're waiting for this asset + prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting; BSPhysObject xprim = prim; Util.FireAndForget(delegate @@ -945,7 +949,7 @@ public sealed class BSShapeCollection : IDisposable BSPhysObject yprim = xprim; // probably not necessary, but, just in case. assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) { - bool assetFound = false; // DEBUG DEBUG + bool assetFound = false; string mismatchIDs = String.Empty; // DEBUG DEBUG if (asset != null && yprim.BaseShape.SculptEntry) { @@ -963,6 +967,10 @@ public sealed class BSShapeCollection : IDisposable mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID; } } + if (assetFound) + yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched; + else + yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}", yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs ); @@ -970,6 +978,7 @@ public sealed class BSShapeCollection : IDisposable } else { + xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}", LogHeader, PhysicsScene.Name); } @@ -977,7 +986,7 @@ public sealed class BSShapeCollection : IDisposable } else { - if (prim.LastAssetBuildFailed) + if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed) { PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", LogHeader, prim.LocalID, prim.BaseShape.SculptTexture); -- cgit v1.1