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);
        }
Exemple #2
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;
        }
Exemple #3
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)
            {
                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();
        }
        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();
        }