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

// 20131224 not used            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 void getMesh(ConvexResult cr, VertexPool vc, List <int> indices)
        {
            List <int> src = cr.HullIndices;

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

                float3 p1 = cr.HullVertices[i1];
                float3 p2 = cr.HullVertices[i2];
                float3 p3 = cr.HullVertices[i3];

                i1 = vc.getIndex(p1);
                i2 = vc.getIndex(p2);
                i3 = vc.getIndex(p3);
            }
        }
        public CHull(ConvexResult result)
        {
            mResult = new ConvexResult(result);
            mVolume = Concavity.computeMeshVolume(result.HullVertices, result.HullIndices);

            mDiagonal = getBoundingRegion(result.HullVertices, mMin, mMax);

            float dx = mMax[0] - mMin[0];
            float dy = mMax[1] - mMin[1];
            float dz = mMax[2] - mMin[2];

            dx *= 0.1f; // inflate 1/10th on each edge
            dy *= 0.1f; // inflate 1/10th on each edge
            dz *= 0.1f; // inflate 1/10th on each edge

            mMin[0] -= dx;
            mMin[1] -= dy;
            mMin[2] -= dz;

            mMax[0] += dx;
            mMax[1] += dy;
            mMax[2] += dz;
        }
Example #4
0
        public CHull(ConvexResult result)
        {
            mResult = new ConvexResult(result);
            mVolume = Concavity.computeMeshVolume(result.HullVertices, result.HullIndices);

            mDiagonal = getBoundingRegion(result.HullVertices, mMin, mMax);

            float dx = mMax[0] - mMin[0];
            float dy = mMax[1] - mMin[1];
            float dz = mMax[2] - mMin[2];

            dx *= 0.1f; // inflate 1/10th on each edge
            dy *= 0.1f; // inflate 1/10th on each edge
            dz *= 0.1f; // inflate 1/10th on each edge

            mMin[0] -= dx;
            mMin[1] -= dy;
            mMin[2] -= dz;

            mMax[0] += dx;
            mMax[1] += dy;
            mMax[2] += dz;
        }
        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();
        }
 public void Dispose()
 {
     mResult = null;
 }
        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);

                    r.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 void getMesh(ConvexResult cr, VertexPool vc, List<int> indices)
        {
            List<int> src = cr.HullIndices;

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

                float3 p1 = cr.HullVertices[i1];
                float3 p2 = cr.HullVertices[i2];
                float3 p3 = cr.HullVertices[i3];

                i1 = vc.getIndex(p1);
                i2 = vc.getIndex(p2);
                i3 = vc.getIndex(p3);
            }
        }
 public void ConvexDecompResult(ConvexResult result)
 {
     CHull ch = new CHull(result);
     mChulls.Add(ch);
 }
 public ConvexResult(ConvexResult r)
 {
     HullVertices = new List<float3>(r.HullVertices);
     HullIndices = new List<int>(r.HullIndices);
 }
Example #11
0
 public void Dispose()
 {
     mResult = null;
 }
Example #12
0
        public void ConvexDecompResult(ConvexResult result)
        {
            CHull ch = new CHull(result);

            mChulls.Add(ch);
        }
Example #13
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);

                    r.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 #14
0
 // Callback from convex hull creater with a newly created hull.
 // Just add it to our collection of hulls for this shape.
 void HullReturn(ConvexResult result)
 {
     m_hulls.Add(result);
     return;
 }
        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);

            // 20131224 not used            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;
        }
 public ConvexResult(ConvexResult r)
 {
     HullVertices = new List <float3>(r.HullVertices);
     HullIndices  = new List <int>(r.HullIndices);
 }
Example #17
0
        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();
        }