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();
        }
Ejemplo n.º 2
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();
        }
Ejemplo n.º 3
0
        public static PlaneTriResult planeTriIntersection(float4 plane, FaceTri triangle, float epsilon, ref float3[] front, out int fcount, ref float3[] back, out int bcount)
        {
            fcount = 0;
            bcount = 0;

            // get the three vertices of the triangle.
            float3 p1 = triangle.P1;
            float3 p2 = triangle.P2;
            float3 p3 = triangle.P3;

            PlaneTriResult r1 = getSidePlane(p1, plane, epsilon); // compute the side of the plane each vertex is on
            PlaneTriResult r2 = getSidePlane(p2, plane, epsilon);
            PlaneTriResult r3 = getSidePlane(p3, plane, epsilon);

            if (r1 == r2 && r1 == r3) // if all three vertices are on the same side of the plane.
            {
                if (r1 == PlaneTriResult.PTR_FRONT) // if all three are in front of the plane, then copy to the 'front' output triangle.
                {
                    add(p1, front, ref fcount);
                    add(p2, front, ref fcount);
                    add(p3, front, ref fcount);
                }
                else
                {
                    add(p1, back, ref bcount); // if all three are in 'back' then copy to the 'back' output triangle.
                    add(p2, back, ref bcount);
                    add(p3, back, ref bcount);
                }
                return r1; // if all three points are on the same side of the plane return result
            }

            // ok.. we need to split the triangle at the plane.

            // First test ray segment P1 to P2
            if (r1 == r2) // if these are both on the same side...
            {
                if (r1 == PlaneTriResult.PTR_FRONT)
                {
                    add(p1, front, ref fcount);
                    add(p2, front, ref fcount);
                }
                else
                {
                    add(p1, back, ref bcount);
                    add(p2, back, ref bcount);
                }
            }
            else
            {
                float3 split = new float3();
                intersect(p1, p2, split, plane);

                if (r1 == PlaneTriResult.PTR_FRONT)
                {

                    add(p1, front, ref fcount);
                    add(split, front, ref fcount);

                    add(split, back, ref bcount);
                    add(p2, back, ref bcount);

                }
                else
                {
                    add(p1, back, ref bcount);
                    add(split, back, ref bcount);

                    add(split, front, ref fcount);
                    add(p2, front, ref fcount);
                }

            }

            // Next test ray segment P2 to P3
            if (r2 == r3) // if these are both on the same side...
            {
                if (r3 == PlaneTriResult.PTR_FRONT)
                {
                    add(p3, front, ref fcount);
                }
                else
                {
                    add(p3, back, ref bcount);
                }
            }
            else
            {
                float3 split = new float3(); // split the point
                intersect(p2, p3, split, plane);

                if (r3 == PlaneTriResult.PTR_FRONT)
                {
                    add(split, front, ref fcount);
                    add(split, back, ref bcount);

                    add(p3, front, ref fcount);
                }
                else
                {
                    add(split, front, ref fcount);
                    add(split, back, ref bcount);

                    add(p3, back, ref bcount);
                }
            }

            // Next test ray segment P3 to P1
            if (r3 != r1) // if these are both on the same side...
            {
                float3 split = new float3(); // split the point
                intersect(p3, p1, split, plane);

                if (r1 == PlaneTriResult.PTR_FRONT)
                {
                    add(split, front, ref fcount);
                    add(split, back, ref bcount);
                }
                else
                {
                    add(split, front, ref fcount);
                    add(split, back, ref bcount);
                }
            }

            return PlaneTriResult.PTR_SPLIT;
        }
Ejemplo n.º 4
0
        public static PlaneTriResult planeTriIntersection(float4 plane, FaceTri triangle, float epsilon,
                                                          ref float3[] front, out int fcount, ref float3[] back,
                                                          out int bcount)
        {
            fcount = 0;
            bcount = 0;

            // get the three vertices of the triangle.
            float3 p1 = triangle.P1;
            float3 p2 = triangle.P2;
            float3 p3 = triangle.P3;

            PlaneTriResult r1 = getSidePlane(p1, plane, epsilon); // compute the side of the plane each vertex is on
            PlaneTriResult r2 = getSidePlane(p2, plane, epsilon);
            PlaneTriResult r3 = getSidePlane(p3, plane, epsilon);

            if (r1 == r2 && r1 == r3) // if all three vertices are on the same side of the plane.
            {
                if (r1 == PlaneTriResult.PTR_FRONT)
                // if all three are in front of the plane, then copy to the 'front' output triangle.
                {
                    add(p1, front, ref fcount);
                    add(p2, front, ref fcount);
                    add(p3, front, ref fcount);
                }
                else
                {
                    add(p1, back, ref bcount); // if all three are in 'back' then copy to the 'back' output triangle.
                    add(p2, back, ref bcount);
                    add(p3, back, ref bcount);
                }
                return(r1); // if all three points are on the same side of the plane return result
            }

            // ok.. we need to split the triangle at the plane.

            // First test ray segment P1 to P2
            if (r1 == r2) // if these are both on the same side...
            {
                if (r1 == PlaneTriResult.PTR_FRONT)
                {
                    add(p1, front, ref fcount);
                    add(p2, front, ref fcount);
                }
                else
                {
                    add(p1, back, ref bcount);
                    add(p2, back, ref bcount);
                }
            }
            else
            {
                float3 split = new float3();
                intersect(p1, p2, split, plane);

                if (r1 == PlaneTriResult.PTR_FRONT)
                {
                    add(p1, front, ref fcount);
                    add(split, front, ref fcount);

                    add(split, back, ref bcount);
                    add(p2, back, ref bcount);
                }
                else
                {
                    add(p1, back, ref bcount);
                    add(split, back, ref bcount);

                    add(split, front, ref fcount);
                    add(p2, front, ref fcount);
                }
            }

            // Next test ray segment P2 to P3
            if (r2 == r3) // if these are both on the same side...
            {
                if (r3 == PlaneTriResult.PTR_FRONT)
                {
                    add(p3, front, ref fcount);
                }
                else
                {
                    add(p3, back, ref bcount);
                }
            }
            else
            {
                float3 split = new float3(); // split the point
                intersect(p2, p3, split, plane);

                if (r3 == PlaneTriResult.PTR_FRONT)
                {
                    add(split, front, ref fcount);
                    add(split, back, ref bcount);

                    add(p3, front, ref fcount);
                }
                else
                {
                    add(split, front, ref fcount);
                    add(split, back, ref bcount);

                    add(p3, back, ref bcount);
                }
            }

            // Next test ray segment P3 to P1
            if (r3 != r1)                    // if these are both on the same side...
            {
                float3 split = new float3(); // split the point
                intersect(p3, p1, split, plane);

                if (r1 == PlaneTriResult.PTR_FRONT)
                {
                    add(split, front, ref fcount);
                    add(split, back, ref bcount);
                }
                else
                {
                    add(split, front, ref fcount);
                    add(split, back, ref bcount);
                }
            }

            return(PlaneTriResult.PTR_SPLIT);
        }