Example #1
0
        public CHull canMerge(CHull a, CHull b)
        {
            if (!a.overlap(b)) // if their AABB's (with a little slop) don't overlap, then return.
            {
                return(null);
            }

            CHull ret = null;

            // ok..we are going to combine both meshes into a single mesh
            // and then we are going to compute the concavity...

            VertexPool vc = new VertexPool();

            List <int> indices = new List <int>();

            getMesh(a.mResult, vc, indices);
            getMesh(b.mResult, vc, indices);

            int           vcount   = vc.GetSize();
            List <float3> vertices = vc.GetVertices();
            int           tcount   = indices.Count / 3;

            //don't do anything if hull is empty
            if (tcount == 0)
            {
                vc.Clear();
                return(null);
            }

            HullResult hresult = new HullResult();
            HullDesc   desc    = new HullDesc();

            desc.SetHullFlag(HullFlag.QF_TRIANGLES);
            desc.Vertices = vertices;

            HullError hret = HullUtils.CreateConvexHull(desc, ref hresult);

            if (hret == HullError.QE_OK)
            {
                float combineVolume = Concavity.computeMeshVolume(hresult.OutputVertices, hresult.Indices);
                float sumVolume     = a.mVolume + b.mVolume;

                float percent = (sumVolume * 100) / combineVolume;
                if (percent >= (100.0f - MERGE_PERCENT))
                {
                    ConvexResult cr = new ConvexResult(hresult.OutputVertices, hresult.Indices);
                    ret = new CHull(cr);
                }
            }

            vc.Clear();
            return(ret);
        }
Example #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;
        }
Example #3
0
        public CHull canMerge(CHull a, CHull b)
        {
            if (!a.overlap(b)) // if their AABB's (with a little slop) don't overlap, then return.
                return null;

            CHull ret = null;

            // ok..we are going to combine both meshes into a single mesh
            // and then we are going to compute the concavity...

            VertexPool vc = new VertexPool();

            List<int> indices = new List<int>();

            getMesh(a.mResult, vc, indices);
            getMesh(b.mResult, vc, indices);

            int vcount = vc.GetSize();
            List<float3> vertices = vc.GetVertices();
            int tcount = indices.Count/3;

            //don't do anything if hull is empty
            if (tcount == 0)
            {
                vc.Clear();
                return null;
            }

            HullResult hresult = new HullResult();
            HullDesc desc = new HullDesc();

            desc.SetHullFlag(HullFlag.QF_TRIANGLES);
            desc.Vertices = vertices;

            HullError hret = HullUtils.CreateConvexHull(desc, ref hresult);

            if (hret == HullError.QE_OK)
            {
                float combineVolume = Concavity.computeMeshVolume(hresult.OutputVertices, hresult.Indices);
                float sumVolume = a.mVolume + b.mVolume;

                float percent = (sumVolume*100)/combineVolume;
                if (percent >= (100.0f - MERGE_PERCENT))
                {
                    ConvexResult cr = new ConvexResult(hresult.OutputVertices, hresult.Indices);
                    ret = new CHull(cr);
                }
            }

            vc.Clear();
            return ret;
        }
Example #4
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);
        }
        public static void calcConvexDecomposition(List<float3> vertices, List<int> indices, ConvexDecompositionCallback callback, float masterVolume, int depth,
            int maxDepth, float concavePercent, float mergePercent)
        {
            float4 plane = new float4();
            bool split = false;

            if (depth < maxDepth)
            {
                float volume = 0f;
                float c = Concavity.computeConcavity(vertices, indices, ref plane, ref volume);

                if (depth == 0)
                {
                    masterVolume = volume;
                }

                float percent = (c * 100.0f) / masterVolume;

                if (percent > concavePercent) // if great than 5% of the total volume is concave, go ahead and keep splitting.
                {
                    split = true;
                }
            }

            if (depth >= maxDepth || !split)
            {
                HullResult result = new HullResult();
                HullDesc desc = new HullDesc();

                desc.SetHullFlag(HullFlag.QF_TRIANGLES);

                desc.Vertices = vertices;

                HullError ret = HullUtils.CreateConvexHull(desc, ref result);

                if (ret == HullError.QE_OK)
                {
                    ConvexResult r = new ConvexResult(result.OutputVertices, result.Indices);
                    callback(r);
                }

                return;
            }

            List<int> ifront = new List<int>();
            List<int> iback = new List<int>();

            VertexPool vfront = new VertexPool();
            VertexPool vback = new VertexPool();

            // ok..now we are going to 'split' all of the input triangles against this plane!
            for (int i = 0; i < indices.Count / 3; i++)
            {
                int i1 = indices[i * 3 + 0];
                int i2 = indices[i * 3 + 1];
                int i3 = indices[i * 3 + 2];

                FaceTri t = new FaceTri(vertices, i1, i2, i3);

                float3[] front = new float3[4];
                float3[] back = new float3[4];

                int fcount = 0;
                int bcount = 0;

                PlaneTriResult result = PlaneTri.planeTriIntersection(plane, t, 0.00001f, ref front, out fcount, ref back, out bcount);

                if (fcount > 4 || bcount > 4)
                {
                    result = PlaneTri.planeTriIntersection(plane, t, 0.00001f, ref front, out fcount, ref back, out bcount);
                }

                switch (result)
                {
                    case PlaneTriResult.PTR_FRONT:
                        Debug.Assert(fcount == 3);
                        addTri(vfront, ifront, front[0], front[1], front[2]);
                        break;
                    case PlaneTriResult.PTR_BACK:
                        Debug.Assert(bcount == 3);
                        addTri(vback, iback, back[0], back[1], back[2]);
                        break;
                    case PlaneTriResult.PTR_SPLIT:
                        Debug.Assert(fcount >= 3 && fcount <= 4);
                        Debug.Assert(bcount >= 3 && bcount <= 4);

                        addTri(vfront, ifront, front[0], front[1], front[2]);
                        addTri(vback, iback, back[0], back[1], back[2]);

                        if (fcount == 4)
                        {
                            addTri(vfront, ifront, front[0], front[2], front[3]);
                        }

                        if (bcount == 4)
                        {
                            addTri(vback, iback, back[0], back[2], back[3]);
                        }

                        break;
                }
            }

            // ok... here we recursively call
            if (ifront.Count > 0)
            {
            // 20131224 not used                int vcount = vfront.GetSize();
                List<float3> vertices2 = vfront.GetVertices();
                for (int i = 0; i < vertices2.Count; i++)
                    vertices2[i] = new float3(vertices2[i]);
            // 20131224 not used                int tcount = ifront.Count / 3;

                calcConvexDecomposition(vertices2, ifront, callback, masterVolume, depth + 1, maxDepth, concavePercent, mergePercent);
            }

            ifront.Clear();
            vfront.Clear();

            if (iback.Count > 0)
            {
            // 20131224 not used                int vcount = vback.GetSize();
                List<float3> vertices2 = vback.GetVertices();
            // 20131224 not used                int tcount = iback.Count / 3;

                calcConvexDecomposition(vertices2, iback, callback, masterVolume, depth + 1, maxDepth, concavePercent, mergePercent);
            }

            iback.Clear();
            vback.Clear();
        }
Example #6
0
        // compute's how 'concave' this object is and returns the total volume of the
        // convex hull as well as the volume of the 'concavity' which was found.
        public static float computeConcavity(List <float3> vertices, List <int> indices, ref float4 plane,
                                             ref float volume)
        {
            float cret = 0f;

            volume = 1f;

            HullResult result = new HullResult();
            HullDesc   desc   = new HullDesc {
                MaxFaces = 256, MaxVertices = 256
            };

            desc.SetHullFlag(HullFlag.QF_TRIANGLES);
            desc.Vertices = vertices;

            HullError ret = HullUtils.CreateConvexHull(desc, ref result);

            if (ret == HullError.QE_OK)
            {
                volume = computeMeshVolume2(result.OutputVertices, result.Indices);

                // ok..now..for each triangle on the original mesh..
                // we extrude the points to the nearest point on the hull.
                List <CTri> tris = new List <CTri>();

                for (int i = 0; i < result.Indices.Count / 3; i++)
                {
                    int i1 = result.Indices[i * 3 + 0];
                    int i2 = result.Indices[i * 3 + 1];
                    int i3 = result.Indices[i * 3 + 2];

                    float3 p1 = result.OutputVertices[i1];
                    float3 p2 = result.OutputVertices[i2];
                    float3 p3 = result.OutputVertices[i3];

                    CTri t = new CTri(p1, p2, p3, i1, i2, i3);
                    tris.Add(t);
                }

                // we have not pre-computed the plane equation for each triangle in the convex hull..
                float totalVolume = 0;

                List <CTri> ftris      = new List <CTri>(); // 'feature' triangles.
                List <CTri> input_mesh = new List <CTri>();

                for (int i = 0; i < indices.Count / 3; i++)
                {
                    int i1 = indices[i * 3 + 0];
                    int i2 = indices[i * 3 + 1];
                    int i3 = indices[i * 3 + 2];

                    float3 p1 = vertices[i1];
                    float3 p2 = vertices[i2];
                    float3 p3 = vertices[i3];

                    CTri t = new CTri(p1, p2, p3, i1, i2, i3);
                    input_mesh.Add(t);
                }

                for (int i = 0; i < indices.Count / 3; i++)
                {
                    int i1 = indices[i * 3 + 0];
                    int i2 = indices[i * 3 + 1];
                    int i3 = indices[i * 3 + 2];

                    float3 p1 = vertices[i1];
                    float3 p2 = vertices[i2];
                    float3 p3 = vertices[i3];

                    CTri t = new CTri(p1, p2, p3, i1, i2, i3);

                    featureMatch(t, tris, input_mesh);

                    if (t.mConcavity > 0.05f)
                    {
                        float v = t.getVolume();
                        totalVolume += v;
                        ftris.Add(t);
                    }
                }

                SplitPlane.computeSplitPlane(vertices, indices, ref plane);
                cret = totalVolume;
            }

            return(cret);
        }
        public static void calcConvexDecomposition(List <float3> vertices, List <int> indices,
                                                   ConvexDecompositionCallback callback, float masterVolume, int depth,
                                                   int maxDepth, float concavePercent, float mergePercent)
        {
            float4 plane = new float4();
            bool   split = false;

            if (depth < maxDepth)
            {
                float volume = 0f;
                float c      = Concavity.computeConcavity(vertices, indices, ref plane, ref volume);

                if (depth == 0)
                {
                    masterVolume = volume;
                }

                float percent = (c * 100.0f) / masterVolume;

                if (percent > concavePercent)
                // if great than 5% of the total volume is concave, go ahead and keep splitting.
                {
                    split = true;
                }
            }

            if (depth >= maxDepth || !split)
            {
                HullResult result = new HullResult();
                HullDesc   desc   = new HullDesc();

                desc.SetHullFlag(HullFlag.QF_TRIANGLES);

                desc.Vertices = vertices;

                HullError ret = HullUtils.CreateConvexHull(desc, ref result);

                if (ret == HullError.QE_OK)
                {
                    ConvexResult r = new ConvexResult(result.OutputVertices, result.Indices);
                    callback(r);
                }

                return;
            }

            List <int> ifront = new List <int>();
            List <int> iback  = new List <int>();

            VertexPool vfront = new VertexPool();
            VertexPool vback  = new VertexPool();

            // ok..now we are going to 'split' all of the input triangles against this plane!
            for (int i = 0; i < indices.Count / 3; i++)
            {
                int i1 = indices[i * 3 + 0];
                int i2 = indices[i * 3 + 1];
                int i3 = indices[i * 3 + 2];

                FaceTri t = new FaceTri(vertices, i1, i2, i3);

                float3[] front = new float3[4];
                float3[] back  = new float3[4];

                int fcount = 0;
                int bcount = 0;

                PlaneTriResult result = PlaneTri.planeTriIntersection(plane, t, 0.00001f, ref front, out fcount,
                                                                      ref back, out bcount);

                if (fcount > 4 || bcount > 4)
                {
                    result = PlaneTri.planeTriIntersection(plane, t, 0.00001f, ref front, out fcount, ref back,
                                                           out bcount);
                }

                switch (result)
                {
                case PlaneTriResult.PTR_FRONT:
                    Debug.Assert(fcount == 3);
                    addTri(vfront, ifront, front[0], front[1], front[2]);
                    break;

                case PlaneTriResult.PTR_BACK:
                    Debug.Assert(bcount == 3);
                    addTri(vback, iback, back[0], back[1], back[2]);
                    break;

                case PlaneTriResult.PTR_SPLIT:
                    Debug.Assert(fcount >= 3 && fcount <= 4);
                    Debug.Assert(bcount >= 3 && bcount <= 4);

                    addTri(vfront, ifront, front[0], front[1], front[2]);
                    addTri(vback, iback, back[0], back[1], back[2]);

                    if (fcount == 4)
                    {
                        addTri(vfront, ifront, front[0], front[2], front[3]);
                    }

                    if (bcount == 4)
                    {
                        addTri(vback, iback, back[0], back[2], back[3]);
                    }

                    break;
                }
            }

            // ok... here we recursively call
            if (ifront.Count > 0)
            {
                int           vcount    = vfront.GetSize();
                List <float3> vertices2 = vfront.GetVertices();
                for (int i = 0; i < vertices2.Count; i++)
                {
                    vertices2[i] = new float3(vertices2[i]);
                }
                int tcount = ifront.Count / 3;

                calcConvexDecomposition(vertices2, ifront, callback, masterVolume, depth + 1, maxDepth, concavePercent,
                                        mergePercent);
            }

            ifront.Clear();
            vfront.Clear();

            if (iback.Count > 0)
            {
                int           vcount    = vback.GetSize();
                List <float3> vertices2 = vback.GetVertices();
                int           tcount    = iback.Count / 3;

                calcConvexDecomposition(vertices2, iback, callback, masterVolume, depth + 1, maxDepth, concavePercent,
                                        mergePercent);
            }

            iback.Clear();
            vback.Clear();
        }
Example #8
0
        // compute's how 'concave' this object is and returns the total volume of the
        // convex hull as well as the volume of the 'concavity' which was found.
        public static float computeConcavity(List<float3> vertices, List<int> indices, ref float4 plane, ref float volume)
        {
            float cret = 0f;
            volume = 1f;

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

            desc.MaxFaces = 256;
            desc.MaxVertices = 256;
            desc.SetHullFlag(HullFlag.QF_TRIANGLES);
            desc.Vertices = vertices;

            HullError ret = HullUtils.CreateConvexHull(desc, ref result);

            if (ret == HullError.QE_OK)
            {
                volume = computeMeshVolume2(result.OutputVertices, result.Indices);

                // ok..now..for each triangle on the original mesh..
                // we extrude the points to the nearest point on the hull.
                List<CTri> tris = new List<CTri>();

                for (int i = 0; i < result.Indices.Count / 3; i++)
                {
                    int i1 = result.Indices[i * 3 + 0];
                    int i2 = result.Indices[i * 3 + 1];
                    int i3 = result.Indices[i * 3 + 2];

                    float3 p1 = result.OutputVertices[i1];
                    float3 p2 = result.OutputVertices[i2];
                    float3 p3 = result.OutputVertices[i3];

                    CTri t = new CTri(p1, p2, p3, i1, i2, i3);
                    tris.Add(t);
                }

                // we have not pre-computed the plane equation for each triangle in the convex hull..
                float totalVolume = 0;

                List<CTri> ftris = new List<CTri>(); // 'feature' triangles.
                List<CTri> input_mesh = new List<CTri>();

                for (int i = 0; i < indices.Count / 3; i++)
                {
                    int i1 = indices[i * 3 + 0];
                    int i2 = indices[i * 3 + 1];
                    int i3 = indices[i * 3 + 2];

                    float3 p1 = vertices[i1];
                    float3 p2 = vertices[i2];
                    float3 p3 = vertices[i3];

                    CTri t = new CTri(p1, p2, p3, i1, i2, i3);
                    input_mesh.Add(t);
                }

                for (int i = 0; i < indices.Count / 3; i++)
                {
                    int i1 = indices[i * 3 + 0];
                    int i2 = indices[i * 3 + 1];
                    int i3 = indices[i * 3 + 2];

                    float3 p1 = vertices[i1];
                    float3 p2 = vertices[i2];
                    float3 p3 = vertices[i3];

                    CTri t = new CTri(p1, p2, p3, i1, i2, i3);

                    featureMatch(t, tris, input_mesh);

                    if (t.mConcavity > 0.05f)
                    {
                        float v = t.getVolume();
                        totalVolume += v;
                        ftris.Add(t);
                    }
                }

                SplitPlane.computeSplitPlane(vertices, indices, ref plane);
                cret = totalVolume;
            }

            return cret;
        }