Пример #1
0
        public static void GenIntersection(
            CuttingPlane plane,
            Vector3 a, Vector3 b, Vector3 c,
            RingGenerator rings
            )
        {
            // find intersection vertices
            Vector3 e = plane.Intersection(a, c, Vector2.zero, Vector2.zero, 0).Item1,
                    d = plane.Intersection(b, c, Vector2.zero, Vector2.zero, 0).Item1;

            // if e == d, the three vertices lie in a line,
            //   and thus do not make up a triangle
            if (e == d)
            {
                return;

                // not sure if this is nescessary
                throw MeshUtilsException.ZeroAreaTriangle();
            }

            // find proper direction for ring
            Vector3 tri_nor = Vector3.Cross(c - a, c - b);
            bool    dir     = Vector3.Dot(e - d, Vector3.Cross(plane.normal, tri_nor)) > 0;

            // add connected pair in ring generator
            rings.AddConnected(dir?e:d, dir?d:e);
        }
Пример #2
0
        public static CuttingPlane InLocalSpace(Vector3 normal, Vector3 pointInPlane, Transform transform)
        {
            CuttingPlane worldSpace = new CuttingPlane(
                transform.worldToLocalMatrix.transpose * normal,
                transform.TransformPoint(pointInPlane),
                null
                );

            return(new CuttingPlane(normal, pointInPlane, worldSpace));
        }
Пример #3
0
        public CuttingPlane ToLocalSpace(Transform transform)
        {
            CuttingPlane worldSpace = ToWorldSpace();

            return(new CuttingPlane(
                       transform.localToWorldMatrix.transpose * worldSpace.normal,
                       transform.InverseTransformPoint(worldSpace.pointInPlane),
                       worldSpace
                       ));
        }
Пример #4
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
                });
            }
        }
Пример #5
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");
     }
     //}
 }
Пример #6
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>());
                }
            }
        }
Пример #7
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;
            }));
        }
Пример #8
0
 private CuttingPlane(Vector3 normal, Vector3 pointInPlane, CuttingPlane worldSpace) : base(normal, pointInPlane)
 {
     this.worldSpace = worldSpace;
 }
Пример #9
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));
        }
Пример #10
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));
        }
Пример #11
0
        public static void GenPartialTriangles(
            CuttingPlane plane,
            MeshPart part,
            Vector3 a, Vector3 b, Vector3 c,
            Vector2 txa, Vector2 txb, Vector2 txc,
            int i_a, int i_b, int i_c,
            HashSet <Vector3> allow_cut,
            bool addUVs
            )
        {
            // find intersection vertices / uvs
            var es = plane.Intersection(a, c, txa, txc, 0);
            var ds = plane.Intersection(b, c, txb, txc, 0);

            Vector3 e = es.Item1, d = ds.Item1;
            Vector2 txe = es.Item2, txd = ds.Item2;

            // if e == d, the three vertices lie in a line,
            //   and thus do not make up a triangle
            if (e == d)
            {
                return;

                // not sure if this is nescessary
                throw MeshUtilsException.ZeroAreaTriangle();
            }

            if (
                !allow_cut.Contains(e) &&
                !allow_cut.Contains(d)
                )
            {
                // triangle must not be cut
                part.indices.Add(part.indexMap[i_a]);
                part.indices.Add(part.indexMap[i_b]);
                part.indices.Add(part.indexMap[i_c]);
                return;
            }

            // new indices
            int i0 = part.vertices.Count, i1 = part.vertices.Count + 2;

            // add new vertices and uvs
            part.vertices.Add(d);
            part.vertices.Add(e);
            part.vertices.Add(d);
            part.vertices.Add(e);
            if (addUVs)
            {
                part.uvs.Add(txd);
                part.uvs.Add(txe);
                part.uvs.Add(txd);
                part.uvs.Add(txe);
            }

            // generate triangles ...

            // add a,d,e
            part.indices.Add(part.indexMap[i_a]);
            part.indices.Add(i0);
            part.indices.Add(i0 + 1);
            // add a,b,d
            part.indices.Add(part.indexMap[i_a]);
            part.indices.Add(part.indexMap[i_b]);
            part.indices.Add(i0);
            // add e,d,c
            part.indices.Add(i1 + 1);
            part.indices.Add(i1);
            part.indices.Add(part.indexMap[i_c]);
        }
Пример #12
0
        // ------------------------------------------------------------
        // Generate single triangle for an intersecting triangle a,b,c
        // It is assumed that a is on the positive half plane
        // ------------------------------------------------------------
        public static void GenTriangle(
            CuttingPlane plane,
            MeshPart pos,
            Vector3 a, Vector3 b, Vector3 c,
            Vector2 txa, Vector2 txb, Vector2 txc,
            Vector3 na, Vector3 nb, Vector3 nc,
            int i_a, int i_b, int i_c,
            RingGenerator rings,
            bool addUVs,
            bool addNormals,
            float shift
            )
        {
            // find intersection vertices / uvs
            var es = plane.Intersection(c, a, txa, txc, nc, na, shift);
            var ds = plane.Intersection(b, a, txb, txc, nb, na, shift);

            Vector3 e = es.Item1, d = ds.Item1;
            Vector2 txe = es.Item2, txd = ds.Item2;
            Vector3 ne = es.Item3, nd = ds.Item3;

            // if e == d, the three vertices lie in a line,
            //   and thus do not make up a triangle
            if (e == d)
            {
                return;

                // not sure if this is nescessary
                throw MeshUtilsException.ZeroAreaTriangle();
            }

            // new indices
            int i0 = pos.vertices.Count;

            // add connected pair in ring generator

            // find proper direction for ring
            Vector3 tri_nor = Vector3.Cross(c - a, c - b);
            bool    dir     = Vector3.Dot(e - d, Vector3.Cross(plane.normal, tri_nor)) > 0;

            rings.AddConnected(dir?e:d, dir?d:e);

            // add new vertices and uvs
            pos.vertices.Add(d);
            pos.vertices.Add(e);
            if (addUVs)
            {
                pos.uvs.Add(txd);
                pos.uvs.Add(txe);
            }
            if (addNormals)
            {
                pos.normals.Add(nd);
                pos.normals.Add(ne);
            }

            // add a,d,e to positive indicies
            pos.indices.Add(pos.indexMap[i_a]);
            pos.indices.Add(i0);
            pos.indices.Add(i0 + 1);
        }
Пример #13
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));
        }