Exemple #1
0
        List <GameObject> IterativeCut(GameObject obj, int count)
        {
            CutParams param = new CutParams(false, false, false, false, Vector3.zero, float.PositiveInfinity, 0, Vector3.zero);

            try {
                CutResult res = API.PerformCut(obj, CuttingPlane.RandomInWorldSpace(obj.transform.position), param);
                res.DestroyObject();
                if (res == null)
                {
                    return(new List <GameObject>());
                }
                if (count > 1)
                {
                    List <GameObject> ret = new List <GameObject>();
                    foreach (CutObj robj in res.Results)
                    {
                        ret.AddRange(
                            IterativeCut(
                                robj
                                .CopyParent()
                                .CopyMaterial()
                                .CopyVelocity()
                                .WithDriftVelocity(0.2f)
                                .Instantiate(),
                                count - 1
                                )
                            );
                    }
                    return(ret);
                }
                else
                {
                    return(res.ConvertAll(
                               robj =>
                               robj
                               .CopyParent()
                               .CopyMaterial()
                               .WithCollider()
                               .WithRenderer()
                               .CopyVelocity()
                               .WithDriftVelocity(0.2f)
                               .Instantiate()
                               ));
                }
            } catch (MeshUtilsException e) {
                Debug.LogWarning(e);
                obj.AddComponent <Rigidbody>();
                obj.AddComponent <MeshRenderer>();
                obj.AddComponent <MeshCollider>();
                return(new List <GameObject>()
                {
                    obj
                });
            }
        }
Exemple #2
0
 void Test()
 {
     //for (int i = 0; i < 10; i++) {
     foreach (GameObject obj in objs)
     {
         Debug.Log(obj);
         DateTime     start = DateTime.Now;
         CutParams    p     = new CutParams(false, false, false, false, Vector3.zero, 0.2f, 0, Vector2.zero);
         CuttingPlane pl    = CuttingPlane.InWorldSpace(obj.transform.up, obj.transform.position);
         if (GapAlgorithm.Run(obj, pl, p) == null)
         {
             throw new Exception("test failed");
         }
         Debug.Log((DateTime.Now - start).TotalMilliseconds + " elapsed");
     }
     //}
 }
Exemple #3
0
        public void OnCollisionEnter(Collision col)
        {
            if (ignoreColliders.Contains(col.collider))
            {
                ignoreColliders.Remove(col.collider);
                return;
            }

            Cuttable cuttable;

            if (!col.gameObject.TryGetComponent <Cuttable>(out cuttable))
            {
                return;
            }

            Vector3 cutDir = directionsAreNormals
                ? TransformNormal(cutDirection, transform)
                : transform.TransformDirection(cutDirection);

            float relVel = (col.relativeVelocity - Vector3.Project(col.relativeVelocity, cutDir)).magnitude;

            // Debug.Log("vel: "+relVel);
            // Debug.DrawRay(col.GetContact(0).point,col.relativeVelocity-Vector3.Project(col.relativeVelocity,cutDir)/relVel,Color.blue,1);

            if (minimumVelocity > relVel)
            {
                return;
            }

            Vector3 dir = omnidirectionalMode
                ? -col.relativeVelocity
                : cutDir;

            Vector3 edge = directionsAreNormals
                ? TransformNormal(edgeDirection, transform)
                : transform.TransformDirection(edgeDirection);

            Vector3 angleProjection = Vector3.ProjectOnPlane(gameObject.GetComponentInParent <Rigidbody>().velocity, edge);

            // Debug.Log("angle: "+Vector3.Angle(angleProjection,cutDir));

            // if (Vector3.Angle(angleProjection,cutDir) > 70) Debug.Break();

            // Debug.DrawRay(col.GetContact(0).point,angleProjection,Color.red,1);
            // Debug.DrawRay(col.GetContact(0).point,cutDir,Color.green,1);
            // Debug.DrawRay(col.GetContact(0).point,-col.relativeVelocity,Color.blue,1);

            if (Vector3.Angle(angleProjection, cutDir) > maxAngle)
            {
                return;
            }

            Vector3 normal = Vector3.Cross(dir, edge).normalized;

            Vector3 pointInPlane = useContactPoint
                ? col.GetContact(0).point
                : transform.position;

            CuttingPlane plane = CuttingPlane.InWorldSpace(normal, pointInPlane);
            CutParams    param = new CutParams(
                cuttable.checkForHoles,
                true,
                cuttable.closeOpenSurfaces,
                cuttable.allowOpenSurfaces,
                Vector3.zero, float.PositiveInfinity, 0,
                cuttable.innerTextureCoordinate
                );

            CutResult result = PerformCut(col.gameObject, plane, param);

            if (result != null)
            {
                if (cuttable.polySeparate)
                {
                    result.PolySeparate();
                }
                result.DestroyObject();
                foreach (CutObj res in result.Results)
                {
                    GameObject resObj = res
                                        .UseDefaults()
                                        .WithDriftVelocity(driftVelocity)
                                        .WithSeperationDistance(seperationDistance)
                                        .WithRingWidth(cuttable.highlightWidth)
                                        .WithRingColor(cuttable.highLightColor)
                                        .FallbackToColor(new Color(1, 0.1f, 0.1f))
                                        .Instantiate();
                    cuttable.CopyTo(resObj);
                    ignoreColliders.Add(resObj.GetComponent <Collider>());
                }
            }
        }
Exemple #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      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));
        }
Exemple #5
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));
        }
Exemple #6
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));
        }