Beispiel #1
0
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            if (!_isDone)
            {
                _poly.Add(GetMousePoint());
            }
        }

        if (Input.GetMouseButtonDown(1))
        {
            if (!_isDone)
            {
                _hole.Add(GetMousePoint());
            }
        }

        if (Input.GetKeyDown(KeyCode.Return) || Input.GetKeyDown(KeyCode.KeypadEnter))
        {
            if (_poly.Count >= 3 && _hole.Count >= 3)
            {
                _isDone = true;
                _full   = Triangulator.RemoveHoles(_poly, _hole);
                _tris   = Triangulator.TriangulatePolygon(_full, new Vector3(0f, 0f, -1f));
            }
        }

        if (Input.GetKeyDown(KeyCode.T))
        {
            showTris = !showTris;
        }

        if (Input.GetKeyDown(KeyCode.C) && (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)))
        {
            _isDone = false;

            _poly.Clear();
            _hole.Clear();

            if (_tris != null)
            {
                _tris.Clear();
            }
        }
    }
Beispiel #2
0
    public static bool SliceMultiTriangleMesh(GameObject meshGO, Vector3 cutStartPos, Vector3 cutEndPos,
                                              Material material, bool makePiecesDrop = true, bool log = true)
    {
        // TODO: it might make sense to check in advance somehow if anything is going to be affected
        // by the cut, even if we don't actually do anything if it's not.

        var cutNormal = CalculateCutNormal(cutStartPos, cutEndPos, log);

        staticCutNormal = cutNormal;

        var meshTransform = meshGO.transform;

        TransformCutToObjectSpace(ref cutStartPos, ref cutEndPos, ref cutNormal, meshTransform);

        var mesh = meshGO.GetComponent <MeshFilter>().sharedMesh;

        var vertsAboveCut   = new List <Vector3>();
        var normalsAboveCut = new List <Vector3>();

        var vertsBelowCut   = new List <Vector3>();
        var normalsBelowCut = new List <Vector3>();

        var atLeastOneTriangleWasCut = false;

        var meshVertices  = mesh.vertices;
        var meshTriangles = mesh.triangles;
        var meshNormals   = mesh.normals;

        //TODO - how long will it be? Can we pre-calc?
        var cutEdges = new List <Edge>();

        for (int triStartIndex = 0; triStartIndex < meshTriangles.Length; triStartIndex += 3)
        {
            var intersection = CalculateIntersections(meshVertices, meshTriangles, meshNormals, triStartIndex,
                                                      cutStartPos, cutNormal, log);
            if (intersection.type == CutType.None)
            {
                if (IsTriAboveCut(meshVertices, meshTriangles, triStartIndex, cutStartPos, cutNormal, log))
                {
                    CopyVertsAndNormals(meshVertices, meshTriangles, meshNormals, triStartIndex, vertsAboveCut, normalsAboveCut);
                }
                else
                {
                    CopyVertsAndNormals(meshVertices, meshTriangles, meshNormals, triStartIndex, vertsBelowCut, normalsBelowCut);
                }
            }
            else
            {
                atLeastOneTriangleWasCut = true;
                CutTriangleAndCopyVertsAndNormals(mesh, intersection, cutStartPos, cutNormal,
                                                  vertsAboveCut, normalsAboveCut,
                                                  vertsBelowCut, normalsBelowCut,
                                                  cutEdges, log);
            }
        }

        // Create cut surfaces

        // So what should happen:
        // cutFacePolys = ConnectEdges(cutEdges).
        // if more than one polygon found:
        // - collect "is a hole in" relationships
        // - iter through and remove all the holes
        // now do the thing.

        if (atLeastOneTriangleWasCut)
        {
            var cutFacePolys = ConnectEdges(cutEdges);
            var isHole       = new bool[cutFacePolys.Count];

            if (cutFacePolys.Count > 1)
            {
                var holes = FindHolesIn(cutFacePolys);
                foreach (var hole in holes)
                {
                    cutFacePolys[hole.outerPolyIndex] = Triangulator.RemoveHoles(cutFacePolys[hole.outerPolyIndex],
                                                                                 cutFacePolys[hole.holePolyIndex]);
                    isHole[hole.holePolyIndex] = true;
                }
            }

            var foundAtLeastOneFace = false;

            for (int polyIndex = 0; polyIndex < cutFacePolys.Count; ++polyIndex)
            {
                if (!isHole[polyIndex] && cutFacePolys[polyIndex].Count > 2)
                {
                    var face     = Triangulator.TriangulatePolygon(cutFacePolys[polyIndex], -cutNormal);
                    var triCount = face.Count;
                    if (triCount > 0 && triCount % 3 == 0)
                    {
                        foundAtLeastOneFace = true;
                        for (int i = triCount - 1; i >= 0; --i)
                        {
                            vertsBelowCut.Add(face[i]);
                            normalsAboveCut.Add(-cutNormal);
                            normalsBelowCut.Add(cutNormal);
                        }
                        vertsAboveCut.AddRange(face);
                    }
                }
            }

            if (!foundAtLeastOneFace)
            {
                return(false);
            }
        }

        if (atLeastOneTriangleWasCut)
        {
            var meshAbove = BuildMesh(vertsAboveCut, normalsAboveCut, log);
            var meshBelow = BuildMesh(vertsBelowCut, normalsBelowCut, log);

            var goAbove = BuildGO(meshAbove, string.Format("{0}_above", meshGO.name), meshTransform, material, cutNormal, true, makePiecesDrop, log);
            var goBelow = BuildGO(meshBelow, string.Format("{0}_below", meshGO.name), meshTransform, material, cutNormal, false, makePiecesDrop, log);
        }

        return(atLeastOneTriangleWasCut);
    }