aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs158
1 files changed, 103 insertions, 55 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 05c147d..220fbbc 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -447,17 +447,10 @@ public sealed class BSShapeCollection : IDisposable
447 447
448 // If the prim attributes are simple, this could be a simple Bullet native shape 448 // If the prim attributes are simple, this could be a simple Bullet native shape
449 if (!haveShape 449 if (!haveShape
450 && nativeShapePossible
450 && pbs != null 451 && pbs != null
451 && !pbs.SculptEntry 452 && !pbs.SculptEntry
452 && nativeShapePossible 453 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) )
453 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim)
454 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
455 && pbs.ProfileHollow == 0
456 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
457 && pbs.PathBegin == 0 && pbs.PathEnd == 0
458 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
459 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
460 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
461 { 454 {
462 // Get the scale of any existing shape so we can see if the new shape is same native type and same size. 455 // Get the scale of any existing shape so we can see if the new shape is same native type and same size.
463 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; 456 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
@@ -508,6 +501,18 @@ public sealed class BSShapeCollection : IDisposable
508 return ret; 501 return ret;
509 } 502 }
510 503
504 // return 'true' if this shape description does not include any cutting or twisting.
505 private bool PrimHasNoCuts(PrimitiveBaseShape pbs)
506 {
507 return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
508 && pbs.ProfileHollow == 0
509 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
510 && pbs.PathBegin == 0 && pbs.PathEnd == 0
511 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
512 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
513 && pbs.PathShearX == 0 && pbs.PathShearY == 0;
514 }
515
511 // return 'true' if the prim's shape was changed. 516 // return 'true' if the prim's shape was changed.
512 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 517 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
513 { 518 {
@@ -518,7 +523,7 @@ public sealed class BSShapeCollection : IDisposable
518 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) 523 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
519 { 524 {
520 // Update prim.BSShape to reference a hull of this shape. 525 // Update prim.BSShape to reference a hull of this shape.
521 ret = GetReferenceToHull(prim,shapeCallback); 526 ret = GetReferenceToHull(prim, shapeCallback);
522 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", 527 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
523 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); 528 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
524 } 529 }
@@ -699,6 +704,7 @@ public sealed class BSShapeCollection : IDisposable
699 704
700 // See that hull shape exists in the physical world and update prim.BSShape. 705 // See that hull shape exists in the physical world and update prim.BSShape.
701 // We could be creating the hull because scale changed or whatever. 706 // We could be creating the hull because scale changed or whatever.
707 // Return 'true' if a new hull was built. Otherwise, returning a shared hull instance.
702 private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 708 private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
703 { 709 {
704 BulletShape newShape; 710 BulletShape newShape;
@@ -717,6 +723,7 @@ public sealed class BSShapeCollection : IDisposable
717 DereferenceShape(prim.PhysShape, shapeCallback); 723 DereferenceShape(prim.PhysShape, shapeCallback);
718 724
719 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); 725 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
726 // It might not have been created if we're waiting for an asset.
720 newShape = VerifyMeshCreated(newShape, prim); 727 newShape = VerifyMeshCreated(newShape, prim);
721 728
722 ReferenceShape(newShape); 729 ReferenceShape(newShape);
@@ -735,13 +742,13 @@ public sealed class BSShapeCollection : IDisposable
735 HullDesc hullDesc; 742 HullDesc hullDesc;
736 if (Hulls.TryGetValue(newHullKey, out hullDesc)) 743 if (Hulls.TryGetValue(newHullKey, out hullDesc))
737 { 744 {
738 // If the hull shape already is created, just use it. 745 // If the hull shape already has been created, just use the one shared instance.
739 newShape = hullDesc.shape.Clone(); 746 newShape = hullDesc.shape.Clone();
740 } 747 }
741 else 748 else
742 { 749 {
743 // Build a new hull in the physical world 750 // Build a new hull in the physical world.
744 // Pass true for physicalness as this creates some sort of bounding box which we don't need 751 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
745 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false); 752 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
746 if (meshData != null) 753 if (meshData != null)
747 { 754 {
@@ -761,15 +768,35 @@ public sealed class BSShapeCollection : IDisposable
761 convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); 768 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
762 } 769 }
763 770
771 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
772 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
773 {
774 // Simple primitive shapes we know are convex so they are better implemented with
775 // fewer hulls.
776 // Check for simple shape (prim without cuts) and reduce split parameter if so.
777 if (PrimHasNoCuts(pbs))
778 {
779 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
780 }
781 }
782
764 // setup and do convex hull conversion 783 // setup and do convex hull conversion
765 m_hulls = new List<ConvexResult>(); 784 m_hulls = new List<ConvexResult>();
766 DecompDesc dcomp = new DecompDesc(); 785 DecompDesc dcomp = new DecompDesc();
767 dcomp.mIndices = convIndices; 786 dcomp.mIndices = convIndices;
768 dcomp.mVertices = convVertices; 787 dcomp.mVertices = convVertices;
788 dcomp.mDepth = maxDepthSplit;
789 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
790 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
791 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
792 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
769 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); 793 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
770 // create the hull into the _hulls variable 794 // create the hull into the _hulls variable
771 convexBuilder.process(dcomp); 795 convexBuilder.process(dcomp);
772 796
797 DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
798 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
799
773 // Convert the vertices and indices for passing to unmanaged. 800 // Convert the vertices and indices for passing to unmanaged.
774 // The hull information is passed as a large floating point array. 801 // The hull information is passed as a large floating point array.
775 // The format is: 802 // The format is:
@@ -904,58 +931,79 @@ public sealed class BSShapeCollection : IDisposable
904 if (newShape.HasPhysicalShape) 931 if (newShape.HasPhysicalShape)
905 return newShape; 932 return newShape;
906 933
907 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset 934 // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been
908 if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) 935 // fetched but we end up here again, the meshing of the asset must have failed.
936 // Prevent trying to keep fetching the mesh by declaring failure.
937 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
938 {
939 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
940 PhysicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}",
941 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
942 }
943 else
909 { 944 {
910 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lastFailed={1}", prim.LocalID, prim.LastAssetBuildFailed); 945 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
911 // This will prevent looping through this code as we keep trying to get the failed shape 946 if (prim.BaseShape.SculptEntry
912 prim.LastAssetBuildFailed = true; 947 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed
948 && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting
949 && prim.BaseShape.SculptTexture != OMV.UUID.Zero
950 )
951 {
952 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID);
953 // Multiple requestors will know we're waiting for this asset
954 prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting;
913 955
914 BSPhysObject xprim = prim; 956 BSPhysObject xprim = prim;
915 Util.FireAndForget(delegate 957 Util.FireAndForget(delegate
916 {
917 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
918 if (assetProvider != null)
919 { 958 {
920 BSPhysObject yprim = xprim; // probably not necessary, but, just in case. 959 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
921 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) 960 if (assetProvider != null)
922 { 961 {
923 bool assetFound = false; // DEBUG DEBUG 962 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
924 string mismatchIDs = String.Empty; // DEBUG DEBUG 963 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
925 if (asset != null && yprim.BaseShape.SculptEntry)
926 { 964 {
927 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID) 965 bool assetFound = false;
966 string mismatchIDs = String.Empty; // DEBUG DEBUG
967 if (asset != null && yprim.BaseShape.SculptEntry)
928 { 968 {
929 yprim.BaseShape.SculptData = asset.Data; 969 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
930 // This will cause the prim to see that the filler shape is not the right 970 {
931 // one and try again to build the object. 971 yprim.BaseShape.SculptData = asset.Data;
932 // No race condition with the normal shape setting since the rebuild is at taint time. 972 // This will cause the prim to see that the filler shape is not the right
933 yprim.ForceBodyShapeRebuild(false /* inTaintTime */); 973 // one and try again to build the object.
934 assetFound = true; 974 // No race condition with the normal shape setting since the rebuild is at taint time.
975 yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
976 assetFound = true;
977 }
978 else
979 {
980 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
981 }
935 } 982 }
983 if (assetFound)
984 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched;
936 else 985 else
937 { 986 yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
938 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID; 987 DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
939 } 988 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
940 }
941 DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
942 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
943 989
944 }); 990 });
945 } 991 }
946 else 992 else
947 { 993 {
948 PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}", 994 xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed;
949 LogHeader, PhysicsScene.Name); 995 PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
950 } 996 LogHeader, PhysicsScene.Name);
951 }); 997 }
952 } 998 });
953 else 999 }
954 { 1000 else
955 if (prim.LastAssetBuildFailed)
956 { 1001 {
957 PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", 1002 if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed)
958 LogHeader, prim.LocalID, prim.BaseShape.SculptTexture); 1003 {
1004 PhysicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}",
1005 LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture);
1006 }
959 } 1007 }
960 } 1008 }
961 1009