Esempio n. 1
0
        public List <MeshPart> PartialPolySeparate(
            CuttingPlane plane,
            HashSet <Vector3> allow_cut
            )
        {
            //Debug.Log("allow_cut");
            //foreach (Vector3 v in allow_cut) Debug.Log(VecStr(v));
            //Debug.Log("missing");

            List <Tuple <HashSet <int>, HashSet <Vector3>, List <int> > > list = new List <Tuple <HashSet <int>, HashSet <Vector3>, List <int> > >();

            AssertMatchingCounts();

            // create index groups
            for (int i = 0; i < indices.Count; i += 3)
            {
                int     i0 = indices[i], i1 = indices[i + 1], i2 = indices[i + 2];
                Vector3 v0 = vertices[i0], v1 = vertices[i1], v2 = vertices[i2];
                bool    ci0 = allow_cut.Contains(v0),
                        ci1 = allow_cut.Contains(v1),
                        ci2 = allow_cut.Contains(v2);
                AddIndices(list, vertices, v0, v1, v2, i0, i1, i2, ci0, ci1, ci2);
            }

            return(list.ConvertAll(set => {
                MeshPart part = new MeshPart(false);

                int doSwap = 0, doStay = 0; // temporary solution (?)

                foreach (int ind in set.Item3)
                {
                    Vector3 point = vertices[ind];
                    if (!allow_cut.Contains(point))
                    {
                        if (plane.IsAbove(point))
                        {
                            doSwap++;
                        }
                        else
                        {
                            doStay++;
                        }
                    }
                    ;
                    if (part.indexMap.ContainsKey(ind))
                    {
                        part.indices.Add(part.indexMap[ind]);
                    }
                    else
                    {
                        part.indexMap.Add(ind, part.vertices.Count);
                        part.indices.Add(part.vertices.Count);
                        part.vertices.Add(point);
                        if (uvs.Count > 0)
                        {
                            part.uvs.Add(uvs[ind]);
                        }
                    }
                }

                if (doSwap > doStay)
                {
                    part.SwapSide();
                }

                part.AssertMatchingCounts();

                return part;
            }));
        }
Esempio n. 2
0
        public static CutResult Run(
            GameObject target,
            CuttingPlane plane,
            CutParams param
            )
        {
            CuttingPlane cutting_plane = plane.ToLocalSpace(target.transform);

            Mesh          mesh = target.GetComponent <MeshFilter>().mesh;
            MeshPart      pos = new MeshPart(true), neg = new MeshPart(false);
            RingGenerator pos_rings = new RingGenerator(), neg_rings = new RingGenerator();

            Vector2[] uvs       = mesh.uv;
            Vector3[] vertices  = mesh.vertices;
            Vector3[] normals   = mesh.normals;
            int[]     triangles = mesh.triangles;

            bool addUVs     = uvs.Length > 0 && param.innerTextureCoord != null,
                 addNormals = normals.Length > 0;

            // removed indices
            HashSet <int> removed = new HashSet <int>();

            // divide mesh in half by vertices
            int i = -1;

            foreach (Vector3 vertex in vertices)
            {
                i++;
                float dist = cutting_plane.Distance(vertex);
                if (dist < param.seperationDistance)
                {
                    removed.Add(i);
                    continue;
                }
                if (cutting_plane.IsAbove(vertex))
                {
                    pos.indexMap.Add(i, pos.vertices.Count);
                    pos.vertices.Add(vertex);
                    if (addUVs)
                    {
                        pos.uvs.Add(uvs[i]);
                    }
                    if (addNormals)
                    {
                        pos.normals.Add(normals[i]);
                    }
                }
                else
                {
                    neg.indexMap.Add(i, neg.vertices.Count);
                    neg.vertices.Add(vertex);
                    if (addUVs)
                    {
                        neg.uvs.Add(uvs[i]);
                    }
                    if (addNormals)
                    {
                        pos.normals.Add(normals[i]);
                    }
                }
            }

            // if either vertex list is empty and no vertices were removed, the knife plane didn't collide
            if (pos.vertices.Count == 0 || neg.vertices.Count == 0)
            {
                if (!param.allowSingleResult)
                {
                    return(null);
                }
            }

            // put triangles in correct mesh
            for (i = 0; i < triangles.Length; i += 3)
            {
                // find orignal indices
                int i_a = triangles[i],
                    i_b = triangles[i + 1],
                    i_c = triangles[i + 2];

                // find if these were removed in cut
                bool r_a = removed.Contains(i_a),
                     r_b = removed.Contains(i_b),
                     r_c = removed.Contains(i_c);

                // if all are removed, ignore triangle
                if (r_a && r_b && r_c)
                {
                    continue;
                }

                // find original verticies
                Vector3 a = vertices[i_a],
                        b = vertices[i_b],
                        c = vertices[i_c];

                Vector2 txa, txb, txc;

                // find original uvs
                if (uvs.Length > 0)
                {
                    txa = uvs[i_a];
                    txb = uvs[i_b];
                    txc = uvs[i_c];
                }
                else
                {
                    txa = txb = txc = Vector2.zero;
                }

                // find original normals
                Vector3 na, nb, nc;
                if (addNormals)
                {
                    na = normals[i_a];
                    nb = normals[i_b];
                    nc = normals[i_c];
                }
                else
                {
                    na = nb = nc = Vector3.zero;
                }

                // seperation check
                bool aAbove = cutting_plane.IsAbove(a),
                     bAbove = cutting_plane.IsAbove(b),
                     cAbove = cutting_plane.IsAbove(c);

                if (!r_a && !r_b && !r_c)
                {
                    // all available
                    if (aAbove && bAbove && cAbove)
                    {
                        // triangle above plane
                        pos.indices.Add(pos.indexMap[i_a]);
                        pos.indices.Add(pos.indexMap[i_b]);
                        pos.indices.Add(pos.indexMap[i_c]);
                    }
                    else if (!aAbove && !bAbove && !cAbove)
                    {
                        // triangle below plane
                        neg.indices.Add(neg.indexMap[i_a]);
                        neg.indices.Add(neg.indexMap[i_b]);
                        neg.indices.Add(neg.indexMap[i_c]);
                    }
                    else
                    {
                        // triangle crosses plane
                        if (aAbove == bAbove)
                        {
                            // a, b, c
                            GenTwoTriangles(
                                cutting_plane,
                                aAbove ? pos : neg,
                                a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c,
                                aAbove ? pos_rings : neg_rings,
                                addUVs,
                                addNormals,
                                -param.seperationDistance
                                );
                            GenTriangle(
                                cutting_plane,
                                cAbove ? pos : neg,
                                c, a, b, txc, txa, txb, nc, na, nb, i_c, i_a, i_b,
                                cAbove ? pos_rings : neg_rings,
                                addUVs,
                                addNormals,
                                param.seperationDistance
                                );
                        }
                        else if (aAbove == cAbove)
                        {
                            // c, a, b
                            GenTwoTriangles(
                                cutting_plane,
                                aAbove ? pos : neg,
                                c, a, b, txc, txa, txb, nc, na, nb, i_c, i_a, i_b,
                                aAbove ? pos_rings : neg_rings,
                                addUVs,
                                addNormals,
                                -param.seperationDistance
                                );
                            GenTriangle(
                                cutting_plane,
                                bAbove ? pos : neg,
                                b, c, a, txb, txc, txa, nb, nc, na, i_b, i_c, i_a,
                                bAbove ? pos_rings : neg_rings,
                                addUVs,
                                addNormals,
                                param.seperationDistance
                                );
                        }
                        else if (bAbove == cAbove)
                        {
                            // b, c, a
                            GenTwoTriangles(
                                cutting_plane,
                                bAbove ? pos : neg,
                                b, c, a, txb, txc, txa, nb, nc, na, i_b, i_c, i_a,
                                bAbove ? pos_rings : neg_rings,
                                addUVs,
                                addNormals,
                                -param.seperationDistance
                                );
                            GenTriangle(
                                cutting_plane,
                                aAbove ? pos : neg,
                                a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c,
                                aAbove ? pos_rings : neg_rings,
                                addUVs,
                                addNormals,
                                param.seperationDistance
                                );
                        }
                    }
                }
                else if (!r_a && !r_b)
                {
                    // a and b available
                    if (aAbove != bAbove)
                    {
                        GenTriangle(
                            cutting_plane,
                            aAbove ? pos : neg,
                            a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c,
                            aAbove ? pos_rings : neg_rings,
                            addUVs,
                            addNormals,
                            param.seperationDistance
                            );
                        GenTriangle(
                            cutting_plane,
                            bAbove ? pos : neg,
                            b, c, a, txb, txc, txa, nb, nc, na, i_b, i_c, i_a,
                            bAbove ? pos_rings : neg_rings,
                            addUVs,
                            addNormals,
                            param.seperationDistance
                            );
                    }
                    else
                    {
                        GenTwoTriangles(
                            cutting_plane,
                            aAbove ? pos : neg,
                            a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c,
                            aAbove ? pos_rings : neg_rings,
                            addUVs,
                            addNormals,
                            -param.seperationDistance
                            );
                    }
                }
                else if (!r_a && !r_c)
                {
                    // a and c available
                    if (aAbove != cAbove)
                    {
                        GenTriangle(
                            cutting_plane,
                            aAbove ? pos : neg,
                            a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c,
                            aAbove ? pos_rings : neg_rings,
                            addUVs,
                            addNormals,
                            param.seperationDistance
                            );
                        GenTriangle(
                            cutting_plane,
                            cAbove ? pos : neg,
                            c, a, b, txc, txa, txb, nc, na, nb, i_c, i_a, i_b,
                            cAbove ? pos_rings : neg_rings,
                            addUVs,
                            addNormals,
                            param.seperationDistance
                            );
                    }
                    else
                    {
                        GenTwoTriangles(
                            cutting_plane,
                            aAbove ? pos : neg,
                            c, a, b, txc, txa, txb, nc, na, nb, i_c, i_a, i_b,
                            aAbove ? pos_rings : neg_rings,
                            addUVs,
                            addNormals,
                            -param.seperationDistance
                            );
                    }
                }
                else if (!r_b && !r_c)
                {
                    // b and c available
                    if (bAbove != cAbove)
                    {
                        GenTriangle(
                            cutting_plane,
                            bAbove ? pos : neg,
                            b, c, a, txb, txc, txa, nb, nc, na, i_b, i_c, i_a,
                            bAbove ? pos_rings : neg_rings,
                            addUVs,
                            addNormals,
                            param.seperationDistance
                            );
                        GenTriangle(
                            cutting_plane,
                            cAbove ? pos : neg,
                            c, a, b, txc, txa, txb, nc, na, nb, i_c, i_a, i_b,
                            cAbove ? pos_rings : neg_rings,
                            addUVs,
                            addNormals,
                            param.seperationDistance
                            );
                    }
                    else
                    {
                        GenTwoTriangles(
                            cutting_plane,
                            bAbove ? pos : neg,
                            b, c, a, txb, txc, txa, nb, nc, na, i_b, i_c, i_a,
                            bAbove ? pos_rings : neg_rings,
                            addUVs,
                            addNormals,
                            -param.seperationDistance
                            );
                    }
                }
                else if (!r_a)
                {
                    // a available
                    GenTriangle(
                        cutting_plane,
                        aAbove ? pos : neg,
                        a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c,
                        aAbove ? pos_rings : neg_rings,
                        addUVs,
                        addNormals,
                        param.seperationDistance
                        );
                }
                else if (!r_b)
                {
                    // b available
                    GenTriangle(
                        cutting_plane,
                        bAbove ? pos : neg,
                        b, c, a, txb, txc, txa, nb, nc, na, i_b, i_c, i_a,
                        bAbove ? pos_rings : neg_rings,
                        addUVs,
                        addNormals,
                        param.seperationDistance
                        );
                }
                else
                {
                    // c available
                    GenTriangle(
                        cutting_plane,
                        cAbove ? pos : neg,
                        c, a, b, txc, txa, txb, nc, na, nb, i_c, i_a, i_b,
                        cAbove ? pos_rings : neg_rings,
                        addUVs,
                        addNormals,
                        param.seperationDistance
                        );
                }
            }

            List <Ring> pos_ring_res = pos_rings.GetRings(param.selfConnectRings, param.ignorePartialRings);
            List <Ring> neg_ring_res = neg_rings.GetRings(param.selfConnectRings, param.ignorePartialRings);

            List <Ring> pos_analysis = param.hiearchyAnalysis ? Hierarchy.Analyse(pos_ring_res, cutting_plane.normal) : pos_ring_res;
            List <Ring> neg_analysis = param.hiearchyAnalysis ? Hierarchy.Analyse(neg_ring_res, cutting_plane.normal) : neg_ring_res;

            Vector2?innerUV = addUVs ? param.innerTextureCoord : null;

            // generate seperation meshing
            foreach (var ring in pos_analysis)
            {
                GenerateRingMesh(ring, pos, cutting_plane.normal, innerUV);
            }
            foreach (var ring in neg_analysis)
            {
                GenerateRingMesh(ring, neg, cutting_plane.normal, innerUV);
            }

            List <MeshPart> resParts = new List <MeshPart>();

            if (pos.vertices.Count > 0)
            {
                resParts.Add(pos);
            }
            if (neg.vertices.Count > 0)
            {
                resParts.Add(neg);
            }

            if (resParts.Count < 2 && !param.allowSingleResult)
            {
                return(null);
            }

            return(new CutResult(target, resParts, cutting_plane.ToWorldSpace().normal, new List <Ring>(), false));
        }
Esempio n. 3
0
        public static CutResult Run(
            GameObject target,
            CuttingPlane plane,
            CutParams param
            )
        {
            CuttingPlane cutting_plane = plane.ToLocalSpace(target.transform);

            Mesh          mesh = target.GetComponent <MeshFilter>().mesh;
            MeshPart      pos = new MeshPart(true), neg = new MeshPart(false);
            RingGenerator rings = new RingGenerator();

            //DateTime start = DateTime.Now;

            Vector2[] uvs       = mesh.uv;
            Vector3[] vertices  = mesh.vertices;
            Vector3[] normals   = mesh.normals;
            int[]     triangles = mesh.triangles;

            bool addUVs     = uvs.Length > 0 && param.innerTextureCoord != null,
                 addNormals = normals.Length > 0;

            // divide mesh in half by vertices
            int i = 0;

            foreach (Vector3 vertex in vertices)
            {
                if (cutting_plane.IsAbove(vertex))
                {
                    pos.indexMap.Add(i, pos.vertices.Count);
                    pos.vertices.Add(vertex);
                    if (addUVs)
                    {
                        pos.uvs.Add(uvs[i]);
                    }
                    if (addNormals)
                    {
                        pos.normals.Add(normals[i]);
                    }
                }
                else
                {
                    neg.indexMap.Add(i, neg.vertices.Count);
                    neg.vertices.Add(vertex);
                    if (addUVs)
                    {
                        neg.uvs.Add(uvs[i]);
                    }
                    if (addNormals)
                    {
                        neg.normals.Add(normals[i]);
                    }
                }
                i++;
            }

            //Debug.Log((DateTime.Now-start).TotalMilliseconds+" elapsed (1)");
            //start = DateTime.Now;

            // if either vertex list is empty the knife plane didn't collide
            if (pos.vertices.Count == 0 || neg.vertices.Count == 0)
            {
                if (!param.allowSingleResult)
                {
                    return(null);
                }
            }

            // put triangles in correct mesh
            for (i = 0; i < triangles.Length; i += 3)
            {
                // find orignal indices
                int i_a = triangles[i],
                    i_b = triangles[i + 1],
                    i_c = triangles[i + 2];

                // find original verticies
                Vector3 a = vertices[i_a],
                        b = vertices[i_b],
                        c = vertices[i_c];

                // find original uvs
                Vector2 txa, txb, txc;
                if (addUVs)
                {
                    txa = uvs[i_a];
                    txb = uvs[i_b];
                    txc = uvs[i_c];
                }
                else
                {
                    txa = txb = txc = Vector3.zero;
                }

                // find original normals
                Vector3 na, nb, nc;
                if (addNormals)
                {
                    na = normals[i_a];
                    nb = normals[i_b];
                    nc = normals[i_c];
                }
                else
                {
                    na = nb = nc = Vector3.zero;
                }

                // seperation check
                bool aAbove = cutting_plane.IsAbove(a),
                     bAbove = cutting_plane.IsAbove(b),
                     cAbove = cutting_plane.IsAbove(c);

                if (aAbove && bAbove && cAbove)
                {
                    // triangle above plane
                    pos.indices.Add(pos.indexMap[i_a]);
                    pos.indices.Add(pos.indexMap[i_b]);
                    pos.indices.Add(pos.indexMap[i_c]);
                }
                else if (!aAbove && !bAbove && !cAbove)
                {
                    // triangle below plane
                    neg.indices.Add(neg.indexMap[i_a]);
                    neg.indices.Add(neg.indexMap[i_b]);
                    neg.indices.Add(neg.indexMap[i_c]);
                }
                else
                {
                    // triangle crosses plane
                    // call Util.GenTriangles
                    if (aAbove == bAbove)
                    {
                        // a, b, c
                        GenTriangles(
                            cutting_plane,
                            aAbove ? pos : neg,
                            !aAbove ? pos : neg,
                            a, b, c, txa, txb, txc, na, nb, nc, i_a, i_b, i_c,
                            rings,
                            addUVs,
                            addNormals
                            );
                    }
                    else if (aAbove == cAbove)
                    {
                        // c, a, b
                        GenTriangles(
                            cutting_plane,
                            aAbove ? pos : neg,
                            !aAbove ? pos : neg,
                            c, a, b, txc, txa, txb, na, nb, nc, i_c, i_a, i_b,
                            rings,
                            addUVs,
                            addNormals
                            );
                    }
                    else if (bAbove == cAbove)
                    {
                        // b, c, a (use bAbove)
                        GenTriangles(
                            cutting_plane,
                            bAbove ? pos : neg,
                            !bAbove ? pos : neg,
                            b, c, a, txb, txc, txa, na, nb, nc, i_b, i_c, i_a,
                            rings,
                            addUVs,
                            addNormals
                            );
                    }
                }
            }

            //Debug.Log((DateTime.Now-start).TotalMilliseconds+" elapsed (2)");
            //start = DateTime.Now;

            List <Ring> ringOut = rings.GetRings(param.selfConnectRings, param.ignorePartialRings);

            List <Ring> analysis = param.hiearchyAnalysis ? Hierarchy.Analyse(ringOut, cutting_plane.normal) : ringOut;

            Vector2?innerUV = addUVs ? param.innerTextureCoord : null;

            // generate seperation meshing
            foreach (var ring in analysis)
            {
                GenerateRingMesh(ring, pos, cutting_plane.normal, innerUV, addNormals);
                GenerateRingMesh(ring, neg, cutting_plane.normal, innerUV, addNormals);
            }

            //Debug.Log((DateTime.Now-start).TotalMilliseconds+" elapsed (3)");
            //start = DateTime.Now;

            return(new CutResult(target, cutting_plane.ToWorldSpace().normal, ringOut, pos, neg));
        }
Esempio n. 4
0
        public static CutResult Run(
            GameObject target,
            CuttingPlane plane,
            CutParams param
            )
        {
            CuttingPlane cutting_plane = plane.ToLocalSpace(target.transform);
            Mesh         mesh          = target.GetComponent <MeshFilter>().mesh;

            MeshPart part = new MeshPart(false);

            Vector2[] uvs       = mesh.uv;
            Vector3[] vertices  = mesh.vertices;
            int[]     triangles = mesh.triangles;

            //
            // First we find the rings that are eligable for cutting
            //

            RingGenerator rings = new RingGenerator();

            int i;

            for (i = 0; i < triangles.Length; i += 3)
            {
                // find orignal indices
                int i_a = triangles[i],
                    i_b = triangles[i + 1],
                    i_c = triangles[i + 2];

                // find original verticies
                Vector3 a = vertices[i_a],
                        b = vertices[i_b],
                        c = vertices[i_c];

                // seperation check
                bool aAbove = cutting_plane.IsAbove(a),
                     bAbove = cutting_plane.IsAbove(b),
                     cAbove = cutting_plane.IsAbove(c);

                if (aAbove == bAbove && aAbove == cAbove)
                {
                    continue;
                }

                if (aAbove == bAbove)
                {
                    // a, b, c
                    GenIntersection(
                        cutting_plane,
                        a, b, c,
                        rings
                        );
                }
                else if (aAbove == cAbove)
                {
                    // c, a, b
                    GenIntersection(
                        cutting_plane,
                        c, a, b,
                        rings
                        );
                }
                else if (bAbove == cAbove)
                {
                    // b, c, a
                    GenIntersection(
                        cutting_plane,
                        b, c, a,
                        rings
                        );
                }
            }

            Vector3 point = target.transform.InverseTransformPoint(param.originPoint);

            List <Ring> resulting_rings = new List <Ring>();

            foreach (Ring ring in rings.GetRings(param.selfConnectRings, param.ignorePartialRings))
            {
                Vector3 vec = ring.FurthestVectorToRingPerimeter(point);
                vec = target.transform.TransformVector(vec);
                // Debug.DrawRay(param.originPoint,vec,Color.blue,10);
                float mag = vec.magnitude;
                Debug.Log(mag);
                if (mag < param.maxCutDistance)
                {
                    resulting_rings.Add(ring);
                }
            }

            if (resulting_rings.Count == 0)
            {
                return(null);
            }

            // Debug.Log(resulting_rings.Count);

            HashSet <Vector3> allow_cut = new HashSet <Vector3>();

            foreach (Ring ring in resulting_rings)
            {
                foreach (Vector3 v in ring.verts)
                {
                    allow_cut.Add(v);
                }
            }

            //
            // Start of cutting
            //

            bool addUVs = uvs.Length > 0 && param.innerTextureCoord != null;

            // transfer vertices into MeshPart
            i = 0;
            foreach (Vector3 vertex in vertices)
            {
                part.indexMap.Add(i, part.vertices.Count);
                part.vertices.Add(vertex);
                if (addUVs)
                {
                    part.uvs.Add(uvs[i]);
                }
                i++;
            }

            // process triangles
            for (i = 0; i < triangles.Length; i += 3)
            {
                // find orignal indices
                int i_a = triangles[i],
                    i_b = triangles[i + 1],
                    i_c = triangles[i + 2];

                // find original verticies
                Vector3 a = vertices[i_a],
                        b = vertices[i_b],
                        c = vertices[i_c];

                Vector2 txa, txb, txc;

                // find original uvs
                if (uvs.Length > 0)
                {
                    txa = uvs[i_a];
                    txb = uvs[i_b];
                    txc = uvs[i_c];
                }
                else
                {
                    txa = txb = txc = Vector2.zero;
                }

                // seperation check
                bool aAbove = cutting_plane.IsAbove(a),
                     bAbove = cutting_plane.IsAbove(b),
                     cAbove = cutting_plane.IsAbove(c);

                if (aAbove == bAbove && aAbove == cAbove)
                {
                    // triangle on one side of plane
                    part.indices.Add(part.indexMap[i_a]);
                    part.indices.Add(part.indexMap[i_b]);
                    part.indices.Add(part.indexMap[i_c]);
                }
                else
                {
                    // triangle crosses plane
                    if (aAbove == bAbove)
                    {
                        // a, b, c
                        GenPartialTriangles(
                            cutting_plane,
                            part,
                            a, b, c, txa, txb, txc, i_a, i_b, i_c,
                            allow_cut,
                            addUVs
                            );
                    }
                    else if (aAbove == cAbove)
                    {
                        // c, a, b
                        GenPartialTriangles(
                            cutting_plane,
                            part,
                            c, a, b, txc, txa, txb, i_c, i_a, i_b,
                            allow_cut,
                            addUVs
                            );
                    }
                    else if (bAbove == cAbove)
                    {
                        // b, c, a
                        GenPartialTriangles(
                            cutting_plane,
                            part,
                            b, c, a, txb, txc, txa, i_b, i_c, i_a,
                            allow_cut,
                            addUVs
                            );
                    }
                }
            }

            List <Ring> analysis = param.hiearchyAnalysis ? Hierarchy.Analyse(resulting_rings, cutting_plane.normal) : resulting_rings;

            List <MeshPart> parts = part.PartialPolySeparate(cutting_plane, allow_cut);

            if (parts.Count < 2 && !param.allowSingleResult)
            {
                return(null);
            }

            // generate seperation meshing
            if (parts.Count > 0)
            {
                foreach (var ring in analysis)
                {
                    foreach (var resPart in parts)
                    {
                        GenerateRingMesh(ring, resPart, cutting_plane.normal, param.innerTextureCoord);
                    }
                }
            }

            return(new CutResult(target, parts, cutting_plane.ToWorldSpace().normal, resulting_rings, true));
        }