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(); } } }
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); }