Ejemplo n.º 1
0
        public HacdConvexHull[] DecomposeToConvexHulls(ulong meshHash, bool useCache, List <float3> convVertices, List <int> convIndices)
        {
            if (convIndices.Count % 3 != 0)
            {
                throw new InvalidOperationException("Number of indicies must be divisble by 3");
            }

            if (IsCacheCandidate(useCache, convVertices.Count))
            {
                //try cache
                try
                {
                    HacdConvexHull[] cachedHulls;
                    if (MeshingStage.HullCache.TryGetHulls(meshHash, out cachedHulls))
                    {
                        return(cachedHulls);
                    }
                }
                catch (Exception e)
                {
                    m_log.ErrorFormat("[InWorldz.PhysX.RatcliffACD] Failure retrieving HACD hulls from cache: {0}: {1}", e, e.Message);
                }
            }

            ConvexBuilder builder = new ConvexBuilder(HullReturn);

            m_hulls = new List <ConvexResult>();

            DecompDesc dcomp = new DecompDesc();

            dcomp.mIndices  = convIndices;
            dcomp.mVertices = convVertices;

            builder.process(dcomp);

            var retHulls = new HacdConvexHull[m_hulls.Count];

            for (int i = 0; i < m_hulls.Count; i++)
            {
                ConvexResult hull = m_hulls[i];

                float[] rawVerts = null;
                if (IsCacheCandidate(useCache, convVertices.Count))
                {
                    rawVerts = new float[hull.HullVertices.Count * 3];
                }

                PhysX.Math.Vector3[] hullVerts = new PhysX.Math.Vector3[hull.HullVertices.Count];
                for (int j = 0; j < hull.HullVertices.Count; j++)
                {
                    hullVerts[j] = new PhysX.Math.Vector3(hull.HullVertices[j].x, hull.HullVertices[j].y, hull.HullVertices[j].z);

                    if (rawVerts != null)
                    {
                        rawVerts[j * 3 + 0] = hull.HullVertices[j].x;
                        rawVerts[j * 3 + 1] = hull.HullVertices[j].y;
                        rawVerts[j * 3 + 2] = hull.HullVertices[j].z;
                    }
                }

                retHulls[i] = new HacdConvexHull {
                    Indicies  = hull.HullIndices.ToArray(),
                    Vertices  = hullVerts,
                    _rawVerts = rawVerts,
                };
            }

            //store in cache for later
            if (IsCacheCandidate(useCache, convVertices.Count))
            {
                try
                {
                    MeshingStage.HullCache.CacheHulls(meshHash, retHulls);
                }
                catch (Exception e)
                {
                    m_log.ErrorFormat("[InWorldz.PhysX.RatcliffACD] Failure storing HACD results in cache: {0}: {1}", e, e.Message);
                }
            }

            return(retHulls);
        }
Ejemplo n.º 2
0
        private BulletShape CreatePhysicalHull(string objName, ulong newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
        {
            IntPtr   hullPtr;
            HullDesc hullDesc;

            if (Hulls.TryGetValue(newHullKey, out hullDesc))
            {
                // If the hull shape already is created, just use it.
                hullPtr = hullDesc.ptr;
            }
            else
            {
                // Build a new hull in the physical world
                // Pass false for physicalness as this creates some sort of bounding box which we don't need
                IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);

                int[] indices = meshData.getIndexListAsInt();
                List <OMV.Vector3> vertices = meshData.getVertexList();

                //format conversion from IMesh format to DecompDesc format
                List <int>    convIndices  = new List <int>();
                List <float3> convVertices = new List <float3>();
                for (int ii = 0; ii < indices.GetLength(0); ii++)
                {
                    convIndices.Add(indices[ii]);
                }
                foreach (OMV.Vector3 vv in vertices)
                {
                    convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
                }

                // setup and do convex hull conversion
                m_hulls = new List <ConvexResult>();
                DecompDesc dcomp = new DecompDesc();
                dcomp.mIndices  = convIndices;
                dcomp.mVertices = convVertices;
                ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
                // create the hull into the _hulls variable
                convexBuilder.process(dcomp);

                // Convert the vertices and indices for passing to unmanaged.
                // The hull information is passed as a large floating point array.
                // The format is:
                //  convHulls[0] = number of hulls
                //  convHulls[1] = number of vertices in first hull
                //  convHulls[2] = hull centroid X coordinate
                //  convHulls[3] = hull centroid Y coordinate
                //  convHulls[4] = hull centroid Z coordinate
                //  convHulls[5] = first hull vertex X
                //  convHulls[6] = first hull vertex Y
                //  convHulls[7] = first hull vertex Z
                //  convHulls[8] = second hull vertex X
                //  ...
                //  convHulls[n] = number of vertices in second hull
                //  convHulls[n+1] = second hull centroid X coordinate
                //  ...
                //
                // TODO: is is very inefficient. Someday change the convex hull generator to return
                //   data structures that do not need to be converted in order to pass to Bullet.
                //   And maybe put the values directly into pinned memory rather than marshaling.
                int hullCount     = m_hulls.Count;
                int totalVertices = 1;      // include one for the count of the hulls
                foreach (ConvexResult cr in m_hulls)
                {
                    totalVertices += 4;                        // add four for the vertex count and centroid
                    totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
                }
                float[] convHulls = new float[totalVertices];

                convHulls[0] = (float)hullCount;
                int jj = 1;
                foreach (ConvexResult cr in m_hulls)
                {
                    // copy vertices for index access
                    float3[] verts = new float3[cr.HullVertices.Count];
                    int      kk    = 0;
                    foreach (float3 ff in cr.HullVertices)
                    {
                        verts[kk++] = ff;
                    }

                    // add to the array one hull's worth of data
                    convHulls[jj++] = cr.HullIndices.Count;
                    convHulls[jj++] = 0f; // centroid x,y,z
                    convHulls[jj++] = 0f;
                    convHulls[jj++] = 0f;
                    foreach (int ind in cr.HullIndices)
                    {
                        convHulls[jj++] = verts[ind].x;
                        convHulls[jj++] = verts[ind].y;
                        convHulls[jj++] = verts[ind].z;
                    }
                }
                // create the hull data structure in Bullet
                hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls);
            }

            BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL);

            newShape.shapeKey = newHullKey;

            return(newShape);   // 'true' means a new shape has been added to this prim
        }
Ejemplo n.º 3
0
    private BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, System.UInt64 newHullKey,
                                           PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
    {
        BulletShape newShape = new BulletShape();
        IntPtr      hullPtr  = IntPtr.Zero;

        if (BSParam.ShouldUseBulletHACD)
        {
            // Build the hull shape from an existing mesh shape.
            // The mesh should have already been created in Bullet.
            physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
            BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);

            if (meshShape.physShapeInfo.HasPhysicalShape)
            {
                HACDParams parms;
                parms.maxVerticesPerHull          = BSParam.BHullMaxVerticesPerHull;
                parms.minClusters                 = BSParam.BHullMinClusters;
                parms.compacityWeight             = BSParam.BHullCompacityWeight;
                parms.volumeWeight                = BSParam.BHullVolumeWeight;
                parms.concavity                   = BSParam.BHullConcavity;
                parms.addExtraDistPoints          = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
                parms.addNeighboursDistPoints     = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
                parms.addFacesPoints              = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
                parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);

                physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
                newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
                physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);

                // Now done with the mesh shape.
                meshShape.Dereference(physicsScene);
            }
            physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
        }
        if (!newShape.HasPhysicalShape)
        {
            // Build a new hull in the physical world using the C# HACD algorigthm.
            // Pass true for physicalness as this prevents the creation of bounding box which is not needed
            IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
            if (meshData != null)
            {
                if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched)
                {
                    // Release the fetched asset data once it has been used.
                    pbs.SculptData      = new byte[0];
                    prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Unknown;
                }

                int[] indices = meshData.getIndexListAsInt();
                List <OMV.Vector3> vertices = meshData.getVertexList();

                //format conversion from IMesh format to DecompDesc format
                List <int>    convIndices  = new List <int>();
                List <float3> convVertices = new List <float3>();
                for (int ii = 0; ii < indices.GetLength(0); ii++)
                {
                    convIndices.Add(indices[ii]);
                }
                foreach (OMV.Vector3 vv in vertices)
                {
                    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 (BSShapeCollection.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);

                physicsScene.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:
                //  convHulls[0] = number of hulls
                //  convHulls[1] = number of vertices in first hull
                //  convHulls[2] = hull centroid X coordinate
                //  convHulls[3] = hull centroid Y coordinate
                //  convHulls[4] = hull centroid Z coordinate
                //  convHulls[5] = first hull vertex X
                //  convHulls[6] = first hull vertex Y
                //  convHulls[7] = first hull vertex Z
                //  convHulls[8] = second hull vertex X
                //  ...
                //  convHulls[n] = number of vertices in second hull
                //  convHulls[n+1] = second hull centroid X coordinate
                //  ...
                //
                // TODO: is is very inefficient. Someday change the convex hull generator to return
                //   data structures that do not need to be converted in order to pass to Bullet.
                //   And maybe put the values directly into pinned memory rather than marshaling.
                int hullCount     = m_hulls.Count;
                int totalVertices = 1;          // include one for the count of the hulls
                foreach (ConvexResult cr in m_hulls)
                {
                    totalVertices += 4;                         // add four for the vertex count and centroid
                    totalVertices += cr.HullIndices.Count * 3;  // we pass just triangles
                }
                float[] convHulls = new float[totalVertices];

                convHulls[0] = (float)hullCount;
                int jj = 1;
                foreach (ConvexResult cr in m_hulls)
                {
                    // copy vertices for index access
                    float3[] verts = new float3[cr.HullVertices.Count];
                    int      kk    = 0;
                    foreach (float3 ff in cr.HullVertices)
                    {
                        verts[kk++] = ff;
                    }

                    // add to the array one hull's worth of data
                    convHulls[jj++] = cr.HullIndices.Count;
                    convHulls[jj++] = 0f;   // centroid x,y,z
                    convHulls[jj++] = 0f;
                    convHulls[jj++] = 0f;
                    foreach (int ind in cr.HullIndices)
                    {
                        convHulls[jj++] = verts[ind].x;
                        convHulls[jj++] = verts[ind].y;
                        convHulls[jj++] = verts[ind].z;
                    }
                }
                // create the hull data structure in Bullet
                newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
            }
            newShape.shapeKey = newHullKey;
        }
        return(newShape);
    }