diff options
Diffstat (limited to '')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 158 |
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 | ||