internal bool TryGetCachedShape(ulong meshHash, OpenSim.Framework.PrimitiveBaseShape shape, bool isDynamic, out PhysicsShape phyShape)
        {
            ShapeCache cache = FindCorrespondingCache(ShapeDeterminer.FindBestShape(shape, isDynamic));

            if (cache != null)
            {
                return(cache.TryGetShape(meshHash, out phyShape));
            }

            phyShape = null;
            return(false);
        }
Exemple #2
0
            public void Execute(MeshingStage meshingStage)
            {
                //short circuit null shapes
                if (Shape.PreferredPhysicsShape == OpenMetaverse.PhysicsShapeType.None)
                {
                    this.CompletedDelegate(PhysicsShape.Null);
                    return;
                }

                ulong meshHash = Shape.GetMeshKey(Size, MeshingStage.SCULPT_MESH_LOD);

                //check to see if we have this shape in the cache
                PhysicsShape phyShape;

                if (meshingStage.TryGetCachedShape(meshHash, Shape, IsDynamic, out phyShape))
                {
                    phyShape.AddRef();

                    //we are done here, call back to caller
                    this.CompletedDelegate(phyShape);

                    return;
                }

                int meshingBegan = Environment.TickCount;

                var bestShape = ShapeDeterminer.FindBestShape(Shape, IsDynamic);

                //first try to extract serialized shapes
                if (!TryExtractSerializedShapes(meshingStage, meshHash, bestShape))
                {
                    //failure, generate
                    GenerateShapes(meshingStage, meshHash, bestShape);
                }

                if (Settings.Instance.InstrumentMeshing)
                {
                    m_log.InfoFormat("[STATS]: PHYSX_MESHING_TIME,{0},{1}", bestShape, Environment.TickCount - meshingBegan);
                }
            }
        private List <PhysX.ConvexMeshGeometry> GenerateComplexPhysXShape(ulong meshHash, string primName, PrimitiveBaseShape shape, OpenMetaverse.Vector3 size,
                                                                          float LOD, bool isDynamic)
        {
            //create the mesh and do not prescale it. the ACD algorithm can then cache the output hulls and
            //scale as appropriate
            MeshingResult result = _mesher.CreateMesh(primName, shape, size, LOD, ShapeType.DecomposedConvexHulls, false);

            if (result == null)
            {
                return(null);
            }

            HacdConvexHull[] hulls = null;

            if (result.ResultType == ShapeType.TriMesh)
            {
                IMesh mesh = result.TriMesh;
                if (mesh == null)
                {
                    return(null);
                }

                //Debugging.VrmlGenerator.SaveToVrmlFile("lastMesh.wrl", mesh.getVertexListAsArray(), mesh.getTriangleList());

                switch (ShapeDeterminer.FindBestAcdAlgorithm(shape))
                {
                case ShapeDeterminer.AcdAlgorithm.HACD:
                    hulls = DecomposeWithHACD(shape, LOD, mesh);
                    break;

                case ShapeDeterminer.AcdAlgorithm.RATCLIFF:
                    hulls = DecomposeWithRatcliff(shape, LOD, mesh);
                    break;

                default:
                    throw new PhysxSdkException("GenerateComplexPhysXShape(): Specified ACD algorithm does not exist");
                }

                if (hulls == null)
                {
                    return(null);
                }
            }
            else if (result.ResultType == ShapeType.DecomposedConvexHulls)
            {
                hulls = new HacdConvexHull[result.ConvexVerts.Count];

                for (int i = 0; i < result.ConvexVerts.Count; i++)
                {
                    hulls[i] = new HacdConvexHull {
                        Vertices = new PhysX.Math.Vector3[result.ConvexVerts[i].Count]
                    };
                    for (int j = 0; j < result.ConvexVerts[i].Count; j++)
                    {
                        var vert = result.ConvexVerts[i][j];
                        hulls[i].Vertices[j] = new PhysX.Math.Vector3(vert.X, vert.Y, vert.Z);
                    }
                }
            }
            else
            {
                return(null);
            }

            HacdConvexHull.Scale(size, hulls);

            List <PhysX.ConvexMeshGeometry> ret = new List <PhysX.ConvexMeshGeometry>();

            try
            {
                foreach (HacdConvexHull hull in hulls)
                {
                    PhysX.ConvexMeshDesc convexMeshDesc = new PhysX.ConvexMeshDesc()
                    {
                        Flags = PhysX.ConvexFlag.InflateConvex
                    };

                    if (hull.Indicies == null)
                    {
                        convexMeshDesc.Flags |= PhysX.ConvexFlag.ComputeConvex;
                    }

                    convexMeshDesc.SetPositions(hull.Vertices);
                    if (hull.Indicies != null)
                    {
                        convexMeshDesc.SetTriangles(hull.Indicies);
                    }

                    if (!convexMeshDesc.IsValid())
                    {
                        throw new PhysxSdkException("GenerateComplexPhysXShape: Convex mesh description is invalid");
                    }

                    using (MemoryStream ms = new MemoryStream())
                    {
                        if (!_cooking.CookConvexMesh(convexMeshDesc, ms))
                        {
                            throw new PhysxSdkException("GenerateComplexPhysXShape: CookConvexMesh() failed");
                        }

                        ms.Position = 0;

                        PhysX.ConvexMesh         convexMesh      = _scene.Physics.CreateConvexMesh(ms);
                        PhysX.ConvexMeshGeometry convexShapeGeom = new PhysX.ConvexMeshGeometry(convexMesh);
                        ret.Add(convexShapeGeom);
                    }
                }
            }
            catch (Exception e)
            {
                m_log.WarnFormat("[InWorldz.PhysxPhysics] Unable to create convex hullset for shape: {0}", e);

                result = _mesher.CreateMesh(primName, shape, size, LOD, ShapeType.SingleConvex, true);
                if (result == null)
                {
                    m_log.WarnFormat("[InWorldz.PhysxPhysics] Fallback hull generation failed, giving up", e);
                    return(null);
                }

                //direct convex available?
                if (result.ResultType == ShapeType.SingleConvex)
                {
                    if (!TryGenerateFallbackHullFromHullData(ret, e, result.SingleConvex))
                    {
                        return(null);
                    }
                }
                else if (result.ResultType == ShapeType.TriMesh)
                {
                    IMesh mesh = result.TriMesh;
                    if (mesh == null)
                    {
                        m_log.WarnFormat("[InWorldz.PhysxPhysics] Fallback hull generation failed, giving up", e);
                        return(null);
                    }

                    if (!TryGenerateFallbackHullFromTrimesh(ret, e, mesh))
                    {
                        return(null);
                    }
                }
            }

            return(ret);
        }