Ejemplo n.º 1
0
    // No locking here because this is done when we know physics is not simulating
    private void CreateGeomHull()
    {
        float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
        ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod);
        // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey);

        // if the hull hasn't changed, don't rebuild it
        if (newHullKey == _hullKey) return;

        // Since we're recreating new, get rid of any previously generated shape
        if (_hullKey != 0)
        {
            // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
            BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
            _hullKey = 0;
            _hulls.Clear();
            BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
            _mesh = null;   // the mesh cannot match either
            _meshKey = 0;
        }

        _hullKey = newHullKey;
        if (_meshKey != _hullKey)
        {
            // if the underlying mesh has changed, rebuild it
            CreateGeomMesh();
        }

        int[] indices = _mesh.getIndexListAsInt();
        List<OMV.Vector3> vertices = _mesh.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
        _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 = _hulls.Count;
        int totalVertices = 1;          // include one for the count of the hulls
        foreach (ConvexResult cr in _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 _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 definition in Bullet
        // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount);
        BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls);
        _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
        // meshes are already scaled by the meshmerizer
        _scale = new OMV.Vector3(1f, 1f, 1f);
        return;
    }
Ejemplo n.º 2
0
        public int process(DecompDesc desc)
        {
            int ret = 0;

            MAXDEPTH        = (int)desc.mDepth;
            CONCAVE_PERCENT = desc.mCpercent;
            MERGE_PERCENT   = desc.mPpercent;

            ConvexDecomposition.calcConvexDecomposition(desc.mVertices, desc.mIndices, ConvexDecompResult, 0f, 0,
                                                        MAXDEPTH, CONCAVE_PERCENT, MERGE_PERCENT);

            while (combineHulls()) // keep combinging hulls until I can't combine any more...
            {
                ;
            }

            int i;

            for (i = 0; i < mChulls.Count; i++)
            {
                CHull cr = mChulls[i];

                // before we hand it back to the application, we need to regenerate the hull based on the
                // limits given by the user.

                ConvexResult c = cr.mResult; // the high resolution hull...

                HullResult result = new HullResult();
                HullDesc   hdesc  = new HullDesc();

                hdesc.SetHullFlag(HullFlag.QF_TRIANGLES);

                hdesc.Vertices    = c.HullVertices;
                hdesc.MaxVertices = desc.mMaxVertices; // maximum number of vertices allowed in the output

                if (desc.mSkinWidth != 0f)
                {
                    hdesc.SkinWidth = desc.mSkinWidth;
                    hdesc.SetHullFlag(HullFlag.QF_SKIN_WIDTH); // do skin width computation.
                }

                HullError ret2 = HullUtils.CreateConvexHull(hdesc, ref result);

                if (ret2 == HullError.QE_OK)
                {
                    ConvexResult r = new ConvexResult(result.OutputVertices, result.Indices)
                    {
                        mHullVolume =
                            Concavity.computeMeshVolume(result.OutputVertices, result.Indices)
                    };

                    // the volume of the hull.

                    // compute the best fit OBB
                    //computeBestFitOBB(result.mNumOutputVertices, result.mOutputVertices, sizeof(float) * 3, r.mOBBSides, r.mOBBTransform);

                    //r.mOBBVolume = r.mOBBSides[0] * r.mOBBSides[1] * r.mOBBSides[2]; // compute the OBB volume.

                    //fm_getTranslation(r.mOBBTransform, r.mOBBCenter); // get the translation component of the 4x4 matrix.

                    //fm_matrixToQuat(r.mOBBTransform, r.mOBBOrientation); // extract the orientation as a quaternion.

                    //r.mSphereRadius = computeBoundingSphere(result.mNumOutputVertices, result.mOutputVertices, r.mSphereCenter);
                    //r.mSphereVolume = fm_sphereVolume(r.mSphereRadius);

                    mCallback(r);
                }

                result = null;
                cr.Dispose();
            }

            ret = mChulls.Count;

            mChulls.Clear();

            return(ret);
        }
Ejemplo n.º 3
0
        public int process(DecompDesc desc)
        {
            int ret = 0;

            MAXDEPTH = (int) desc.mDepth;
            CONCAVE_PERCENT = desc.mCpercent;
            MERGE_PERCENT = desc.mPpercent;

            ConvexDecomposition.calcConvexDecomposition(desc.mVertices, desc.mIndices, ConvexDecompResult, 0f, 0,
                                                        MAXDEPTH, CONCAVE_PERCENT, MERGE_PERCENT);

            while (combineHulls()) // keep combinging hulls until I can't combine any more...
                ;

            int i;
            for (i = 0; i < mChulls.Count; i++)
            {
                CHull cr = mChulls[i];

                // before we hand it back to the application, we need to regenerate the hull based on the
                // limits given by the user.

                ConvexResult c = cr.mResult; // the high resolution hull...

                HullResult result = new HullResult();
                HullDesc hdesc = new HullDesc();

                hdesc.SetHullFlag(HullFlag.QF_TRIANGLES);

                hdesc.Vertices = c.HullVertices;
                hdesc.MaxVertices = desc.mMaxVertices; // maximum number of vertices allowed in the output

                if (desc.mSkinWidth != 0f)
                {
                    hdesc.SkinWidth = desc.mSkinWidth;
                    hdesc.SetHullFlag(HullFlag.QF_SKIN_WIDTH); // do skin width computation.
                }

                HullError ret2 = HullUtils.CreateConvexHull(hdesc, ref result);

                if (ret2 == HullError.QE_OK)
                {
                    ConvexResult r = new ConvexResult(result.OutputVertices, result.Indices)
                                         {
                                             mHullVolume =
                                                 Concavity.computeMeshVolume(result.OutputVertices, result.Indices)
                                         };

                    // the volume of the hull.

                    // compute the best fit OBB
                    //computeBestFitOBB(result.mNumOutputVertices, result.mOutputVertices, sizeof(float) * 3, r.mOBBSides, r.mOBBTransform);

                    //r.mOBBVolume = r.mOBBSides[0] * r.mOBBSides[1] * r.mOBBSides[2]; // compute the OBB volume.

                    //fm_getTranslation(r.mOBBTransform, r.mOBBCenter); // get the translation component of the 4x4 matrix.

                    //fm_matrixToQuat(r.mOBBTransform, r.mOBBOrientation); // extract the orientation as a quaternion.

                    //r.mSphereRadius = computeBoundingSphere(result.mNumOutputVertices, result.mOutputVertices, r.mSphereCenter);
                    //r.mSphereVolume = fm_sphereVolume(r.mSphereRadius);

                    mCallback(r);
                }

                result = null;
                cr.Dispose();
            }

            ret = mChulls.Count;

            mChulls.Clear();

            return ret;
        }
Ejemplo n.º 4
0
    private void GenerateHullMesh ()
    {
        float[] convHulls;
        _hullKey = (ulong)_pbs.GetHashCode();
        if(_hullMeshDictionary.TryGetValue(_hullKey, out convHulls))
        {
            // create the hull definition in Bullet
            // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount);
            BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, (int)convHulls[0], convHulls);
            _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
            // Let the object be scaled by Bullet (the mesh was created as a unit mesh)
            _scale = _size;
            return;
        }
        int[] indices = _mesh.getIndexListAsInt();
        List<OMV.Vector3> vertices = _mesh.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
        _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 = _hulls.Count;
        int totalVertices = 1;          // include one for the count of the hulls
        foreach(ConvexResult cr in _hulls)
        {
            totalVertices += 4;                         // add four for the vertex count and centroid
            totalVertices += cr.HullIndices.Count * 3;  // we pass just triangles
        }
        convHulls = new float[totalVertices];

        convHulls[0] = (float)hullCount;
        int jj = 1;
        foreach(ConvexResult cr in _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 definition in Bullet
        // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount);
        BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls);
        _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
        // Let the object be scaled by Bullet (the mesh was created as a unit mesh)
        _scale = _size;
    }
Ejemplo n.º 5
0
        private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
        {
            BulletShape newShape = new BulletShape();
            // 20131224 not used        IntPtr hullPtr = IntPtr.Zero;

            HullDesc hullDesc;
            if (Hulls.TryGetValue(newHullKey, out hullDesc))
            {
            // 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 prevents the creation of bounding box which is not needed
            IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true /* isPhysical */);
            if (meshData != null)
            {

                int[] indices = meshData.getIndexListAsInt();
                float[] vertices = meshData.getVertexListAsFloat();

                //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.Length; ii++)
                {
                    convIndices.Add(indices[ii]);
                }
                for(int ii = 0; ii < vertices.Length; ii += 3)
                {
                    convVertices.Add(new float3(vertices[ii], vertices[ii + 1], vertices[ii+2]));
                }

                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<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);

                DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
                                    BSScene.DetailLogZero, newHullKey, indices.Length, vertices.Length / 3, 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;
        }
Ejemplo n.º 6
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.º 7
0
    private BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, System.UInt64 newHullKey,
                                            PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
    {
        BulletShape newShape = new BulletShape();

        IMesh meshData = null;
        List<List<OMV.Vector3>> allHulls = null;
        lock (physicsScene.mesher)
        {
            // Pass true for physicalness as this prevents the creation of bounding box which is not needed
            meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);

            // If we should use the asset's hull info, fetch it out of the locked mesher
            if (meshData != null && BSParam.ShouldUseAssetHulls)
            {
                Meshmerizer realMesher = physicsScene.mesher as Meshmerizer;
                if (realMesher != null)
                {
                    allHulls = realMesher.GetConvexHulls(size);
                }
                if (allHulls == null)
                {
                    physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,noAssetHull", prim.LocalID);
                }
            }
        }

        // If there is hull data in the mesh asset, build the hull from that
        if (allHulls != null && BSParam.ShouldUseAssetHulls)
        {
            int hullCount = allHulls.Count;
            int totalVertices = 1;      // include one for the count of the hulls
            // Using the structure described for HACD hulls, create the memory sturcture
            //     to pass the hull data to the creater.
            foreach (List<OMV.Vector3> hullVerts in allHulls)
            {
                totalVertices += 4;                     // add four for the vertex count and centroid
                totalVertices += hullVerts.Count * 3;   // one vertex is three dimensions
            }
            float[] convHulls = new float[totalVertices];

            convHulls[0] = (float)hullCount;
            int jj = 1;
            foreach (List<OMV.Vector3> hullVerts in allHulls)
            {
                convHulls[jj + 0] = hullVerts.Count;
                convHulls[jj + 1] = 0f;   // centroid x,y,z
                convHulls[jj + 2] = 0f;
                convHulls[jj + 3] = 0f;
                jj += 4;
                foreach (OMV.Vector3 oneVert in hullVerts)
                {
                    convHulls[jj + 0] = oneVert.X;
                    convHulls[jj + 1] = oneVert.Y;
                    convHulls[jj + 2] = oneVert.Z;
                    jj += 3;
                }
            }

            // create the hull data structure in Bullet
            newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);

            physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,assetHulls,hulls={1},totVert={2},shape={3}",
                                        prim.LocalID, hullCount, totalVertices, newShape);
        }

        // If no hull specified in the asset and we should use Bullet's HACD approximation...
        if (!newShape.HasPhysicalShape && 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,bulletHACD,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,shape={1}", prim.LocalID, newShape);

                // Now done with the mesh shape.
                meshShape.Dereference(physicsScene);
            }
            physicsScene.DetailLog("{0},BSShapeHull.CreatePhysicalHull,bulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
        }

        // If no other hull specifications, use our HACD hull approximation.
        if (!newShape.HasPhysicalShape && 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;
    }
Ejemplo n.º 8
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;
        }