void Update() { if (Input.GetMouseButtonUp(0)) { MeasureIt.Count("Clicks"); MeasureIt.End("Time between Clicks (s)"); MeasureIt.Begin("Time between Clicks (s)"); Ray r = Camera.main.ScreenPointToRay(Input.mousePosition); transform.position = r.GetPoint(-Camera.main.transform.position.z); } transform.Rotate(new Vector3(20, 20, 20) * Time.deltaTime); }
public void AddTriangle(int triangleID, int id0, int id1, Vector3 v0, Vector3 v1) { #if PROFILING MeasureIt.Begin("AddTriangle"); #endif // we need to compute position hash to make sure we find all (duplicated) vertices with different edges int hash0, hash1; lsHash.Hash(v0, v1, out hash0, out hash1); // filter out points with similar positions if (hash0 == hash1) { #if PROFILING MeasureIt.End("AddTriangle"); #endif return; } MidPoint midPoint; if (midPoints.TryGetValue(hash0, out midPoint)) { if (midPoint.idNext == Int32.MaxValue && midPoint.idPrev != hash1) { midPoint.idNext = hash1; } else if (midPoint.idPrev == Int32.MaxValue && midPoint.idNext != hash1) { midPoint.idPrev = hash1; } midPoints[hash0] = midPoint; } else { midPoints.Add(hash0, new MidPoint { id = hash0, vertexId = id0, idNext = hash1, idPrev = Int32.MaxValue /*, position = v0*/ }); } if (midPoints.TryGetValue(hash1, out midPoint)) { if (midPoint.idNext == Int32.MaxValue && midPoint.idPrev != hash0) { midPoint.idNext = hash0; } else if (midPoint.idPrev == Int32.MaxValue && midPoint.idNext != hash0) { midPoint.idPrev = hash0; } midPoints[hash1] = midPoint; } else { midPoints.Add(hash1, new MidPoint { id = hash1, vertexId = id1, idPrev = hash0, idNext = Int32.MaxValue /*, position = v1*/ }); } MidPointsCount = midPoints.Count; #if PROFILING MeasureIt.End("AddTriangle"); #endif }
float Cut(ExploderMesh mesh, ExploderTransform meshTransform, Plane plane, bool triangulateHoles, bool allowOpenMesh, ref List <ExploderMesh> meshes) { var stopWatch = new Stopwatch(); stopWatch.Start(); #if PROFILING MeasureIt.Begin("CutAllocations"); #endif // cache mesh data var trianglesNum = mesh.triangles.Length; var verticesNum = mesh.vertices.Length; var meshTriangles = mesh.triangles; var meshTangents = mesh.tangents; var meshColors = mesh.colors32; var meshVertices = mesh.vertices; var meshNormals = mesh.normals; var meshUV = mesh.uv; var useMeshTangents = meshTangents != null && meshTangents.Length > 0; var useVertexColors = meshColors != null && meshColors.Length > 0; var useNormals = meshNormals != null && meshNormals.Length > 0; // preallocate buffers AllocateBuffers(trianglesNum, verticesNum, useMeshTangents, useVertexColors); ExploderMesh mesh0, mesh1; #if PROFILING MeasureIt.End("CutAllocations"); MeasureIt.Begin("CutCycleFirstPass"); #endif // first pass - find complete triangles on both sides of the plane for (int i = 0; i < trianglesNum; i += 3) { // get triangle points var v0 = meshVertices[meshTriangles[i]]; var v1 = meshVertices[meshTriangles[i + 1]]; var v2 = meshVertices[meshTriangles[i + 2]]; var side0 = plane.GetSideFix(ref v0); var side1 = plane.GetSideFix(ref v1); var side2 = plane.GetSideFix(ref v2); meshVertices[meshTriangles[i]] = v0; meshVertices[meshTriangles[i + 1]] = v1; meshVertices[meshTriangles[i + 2]] = v2; // Utils.Log(plane.Pnt + " " + v0 + " " + v1 + " " + " " + v2); // all points on one side if (side0 == side1 && side1 == side2) { var idx = side0 ? 0 : 1; if (meshTriangles[i] >= triCache.Length) { ExploderUtils.Log("TriCacheError " + meshTriangles[i] + " " + triCache.Length + " " + meshVertices.Length); } if (triCache[meshTriangles[i]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i]]); uvs[idx].Add(meshUV[meshTriangles[i]]); if (useNormals) { normals[idx].Add(meshNormals[meshTriangles[i]]); } if (useMeshTangents) { tangents[idx].Add(meshTangents[meshTriangles[i]]); } if (useVertexColors) { vertexColors[idx].Add(meshColors[meshTriangles[i]]); } centroid[idx] += meshVertices[meshTriangles[i]]; triCache[meshTriangles[i]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i]] - 1); } if (triCache[meshTriangles[i + 1]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i + 1]]); uvs[idx].Add(meshUV[meshTriangles[i + 1]]); if (useNormals) { normals[idx].Add(meshNormals[meshTriangles[i + 1]]); } if (useMeshTangents) { tangents[idx].Add(meshTangents[meshTriangles[i + 1]]); } if (useVertexColors) { vertexColors[idx].Add(meshColors[meshTriangles[i + 1]]); } centroid[idx] += meshVertices[meshTriangles[i + 1]]; triCache[meshTriangles[i + 1]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i + 1]] - 1); } if (triCache[meshTriangles[i + 2]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i + 2]]); uvs[idx].Add(meshUV[meshTriangles[i + 2]]); if (useNormals) { normals[idx].Add(meshNormals[meshTriangles[i + 2]]); } if (useMeshTangents) { tangents[idx].Add(meshTangents[meshTriangles[i + 2]]); } if (useVertexColors) { vertexColors[idx].Add(meshColors[meshTriangles[i + 2]]); } centroid[idx] += meshVertices[meshTriangles[i + 2]]; triCache[meshTriangles[i + 2]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i + 2]] - 1); } } else { // intersection triangles add to list and process it in second pass cutTris.Add(i); } } if (vertices[0].Count == 0) { centroid[0] = meshVertices[0]; } else { centroid[0] /= vertices[0].Count; } if (vertices[1].Count == 0) { centroid[1] = meshVertices[1]; } else { centroid[1] /= vertices[1].Count; } // UnityEngine.Debug.LogFormat("cut: {0} -- {1}, normal: {2}, tris: {3}", vertices[0].Count, vertices[1].Count, plane.Normal, cutTris.Count); #if PROFILING MeasureIt.End("CutCycleFirstPass"); MeasureIt.Begin("CutCycleSecondPass"); #endif if (cutTris.Count < 1) { stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } AllocateContours(cutTris.Count); // second pass - cut intersecting triangles in half foreach (var cutTri in cutTris) { var triangle = new Triangle { ids = new[] { meshTriangles[cutTri + 0], meshTriangles[cutTri + 1], meshTriangles[cutTri + 2] }, pos = new[] { meshVertices[meshTriangles[cutTri + 0]], meshVertices[meshTriangles[cutTri + 1]], meshVertices[meshTriangles[cutTri + 2]] }, normal = useNormals ? new[] { meshNormals[meshTriangles[cutTri + 0]], meshNormals[meshTriangles[cutTri + 1]], meshNormals[meshTriangles[cutTri + 2]] } : new[] { Vector3.zero, Vector3.zero, Vector3.zero }, uvs = new[] { meshUV[meshTriangles[cutTri + 0]], meshUV[meshTriangles[cutTri + 1]], meshUV[meshTriangles[cutTri + 2]] }, tangents = useMeshTangents ? new[] { meshTangents[meshTriangles[cutTri + 0]], meshTangents[meshTriangles[cutTri + 1]], meshTangents[meshTriangles[cutTri + 2]] } : new [] { Vector4.zero, Vector4.zero, Vector4.zero }, colors = useVertexColors ? new[] { meshColors[meshTriangles[cutTri + 0]], meshColors[meshTriangles[cutTri + 1]], meshColors[meshTriangles[cutTri + 2]] } : new Color32[] { Color.white, Color.white, Color.white }, }; // check points with a plane var side0 = plane.GetSide(triangle.pos[0]); var side1 = plane.GetSide(triangle.pos[1]); var side2 = plane.GetSide(triangle.pos[2]); float t0, t1; Vector3 s0 = Vector3.zero, s1 = Vector3.zero; var idxLeft = side0 ? 0 : 1; var idxRight = 1 - idxLeft; if (side0 == side1) { var a = plane.IntersectSegment(triangle.pos[2], triangle.pos[0], out t0, ref s0); var b = plane.IntersectSegment(triangle.pos[2], triangle.pos[1], out t1, ref s1); ExploderUtils.Assert(a && b, "!!!!!!!!!!!!!!!"); // left side ... 2 triangles var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[2], triangle.ids[0], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[2], triangle.ids[1], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.tangents[0], triangle.colors[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v1Left = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.tangents[1], triangle.colors[1], triangle.ids[1], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); // Triangle (s0, v0, s1) triangles[idxLeft].Add(s0Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s1Left); // Triangle (s1, v0, v1) triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(v1Left); // right side ... 1 triangle var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[2], triangle.ids[0], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[2], triangle.ids[1], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var v2Right = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.tangents[2], triangle.colors[2], triangle.ids[2], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); // Triangle (v2, s0, s1) triangles[idxRight].Add(v2Right); triangles[idxRight].Add(s0Right); triangles[idxRight].Add(s1Right); // buffer intersection vertices for triangulation if (triangulateHoles) { if (idxLeft == 0) { contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1); } else { contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1); } } } else if (side0 == side2) { var a = plane.IntersectSegment(triangle.pos[1], triangle.pos[0], out t0, ref s1); var b = plane.IntersectSegment(triangle.pos[1], triangle.pos[2], out t1, ref s0); ExploderUtils.Assert(a && b, "!!!!!!!!!!!!!"); // left side ... 2 triangles var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[1], triangle.ids[2], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[1], triangle.ids[0], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.tangents[0], triangle.colors[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v2Left = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.tangents[2], triangle.colors[2], triangle.ids[2], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); // Triangle (v2, s1, s0) triangles[idxLeft].Add(v2Left); triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(s0Left); // Triangle (v2, v0, s1) triangles[idxLeft].Add(v2Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s1Left); // right side ... 1 triangle var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[1], triangle.ids[2], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[1], triangle.ids[0], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var v1Right = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.tangents[1], triangle.colors[1], triangle.ids[1], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); // Triangle (s0, s1, v1) triangles[idxRight].Add(s0Right); triangles[idxRight].Add(s1Right); triangles[idxRight].Add(v1Right); // buffer intersection vertices for triangulation if (triangulateHoles) { if (idxLeft == 0) { contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1); } else { contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1); } } } else { var a = plane.IntersectSegment(triangle.pos[0], triangle.pos[1], out t0, ref s0); var b = plane.IntersectSegment(triangle.pos[0], triangle.pos[2], out t1, ref s1); ExploderUtils.Assert(a && b, "!!!!!!!!!!!!!"); // right side ... 2 triangles var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[0], triangle.ids[1], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[0], triangle.ids[2], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var v1Right = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.tangents[1], triangle.colors[1], triangle.ids[1], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); var v2Right = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.tangents[2], triangle.colors[2], triangle.ids[2], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight], tangents[idxRight], vertexColors[idxRight], useMeshTangents, useVertexColors, useNormals); // Triangle (v2, s1, v1) triangles[idxRight].Add(v2Right); triangles[idxRight].Add(s1Right); triangles[idxRight].Add(v1Right); // Triangle (s1, s0, v1) triangles[idxRight].Add(s1Right); triangles[idxRight].Add(s0Right); triangles[idxRight].Add(v1Right); // left side ... 1 triangle var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[0], triangle.ids[1], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[0], triangle.ids[2], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.tangents[0], triangle.colors[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft], tangents[idxLeft], vertexColors[idxLeft], useMeshTangents, useVertexColors, useNormals); // Triangle (s1, v0, s0) triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s0Left); // buffer intersection vertices for triangulation if (triangulateHoles) { if (idxLeft == 0) { contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1); } else { contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1); } } } } #if PROFILING MeasureIt.End("CutCycleSecondPass"); #endif if (triangulateHoles) { #if PROFILING MeasureIt.Begin("FindContours"); #endif contour.FindContours(); if (contour.contour.Count == 0 || contour.contour[0].Count < 3) { // triangulateHoles = false; if (allowOpenMesh) { triangulateHoles = false; } else { stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } } #if PROFILING MeasureIt.End("FindContours"); #endif } List <int>[] trianglesCut = null; var centroid0 = Vector3.zero; var centroid1 = Vector3.zero; var min0 = Vector3.zero; var max0 = Vector3.zero; var min1 = Vector3.zero; var max1 = Vector3.zero; ExploderMesh.CalculateCentroid(vertices[0], ref centroid0, ref min0, ref max0); ExploderMesh.CalculateCentroid(vertices[1], ref centroid1, ref min1, ref max1); if (triangulateHoles) { #if PROFILING MeasureIt.Begin("Triangulate"); #endif trianglesCut = new List <int>[2] { new List <int>(contour.MidPointsCount), new List <int>(contour.MidPointsCount) }; Triangulate(contour.contour, plane, vertices, normals, uvs, tangents, vertexColors, trianglesCut, true, useMeshTangents, useVertexColors, useNormals); #if PROFILING MeasureIt.End("Triangulate"); #endif } if (vertices[0].Count > 3 && vertices[1].Count > 3) { #if PROFILING MeasureIt.Begin("CutEndCopyBack"); #endif mesh0 = new ExploderMesh(); mesh1 = new ExploderMesh(); var verticesArray0 = vertices[0].ToArray(); var verticesArray1 = vertices[1].ToArray(); mesh0.vertices = verticesArray0; mesh0.uv = uvs[0].ToArray(); mesh1.vertices = verticesArray1; mesh1.uv = uvs[1].ToArray(); if (useNormals) { mesh0.normals = normals[0].ToArray(); mesh1.normals = normals[1].ToArray(); } if (useMeshTangents) { mesh0.tangents = tangents[0].ToArray(); mesh1.tangents = tangents[1].ToArray(); } if (useVertexColors) { mesh0.colors32 = vertexColors[0].ToArray(); mesh1.colors32 = vertexColors[1].ToArray(); } if (trianglesCut != null && trianglesCut[0].Count > 3) { triangles[0].AddRange(trianglesCut[0]); triangles[1].AddRange(trianglesCut[1]); } mesh0.triangles = triangles[0].ToArray(); mesh1.triangles = triangles[1].ToArray(); mesh0.centroid = centroid0; mesh0.min = min0; mesh0.max = max0; mesh1.centroid = centroid1; mesh1.min = min1; mesh1.max = max1; #if PROFILING MeasureIt.End("CutEndCopyBack"); #endif meshes = new List <ExploderMesh> { mesh0, mesh1 }; stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } stopWatch.Stop(); // UnityEngine.Debug.Log("Empty cut! " + vertices[0].Count + " " + vertices[1].Count); return(stopWatch.ElapsedMilliseconds); }
private float Cut(Mesh mesh, Transform meshTransform, Utils.Plane plane, bool triangulateHoles, bool fixPivot, bool getContourList, bool dontCut, Vector4 crossSection, out Mesh mesh0, out Mesh mesh1, out Vector3 centroid0, out Vector3 centroid1, out ContourData intersectionData) { var stopWatch = new Stopwatch(); stopWatch.Start(); #if PROFILING MeasureIt.Begin("CutAllocations"); #endif // cache mesh data var trianglesNum = mesh.triangles.Length; var verticesNum = mesh.vertices.Length; var meshTriangles = mesh.triangles; var meshVertices = mesh.vertices; var meshNormals = mesh.normals; var meshUV = mesh.uv; this.crossSectionUV = crossSection; // preallocate buffers AllocateBuffers(trianglesNum, verticesNum); #if PROFILING MeasureIt.End("CutAllocations"); MeasureIt.Begin("CutCycleFirstPass"); #endif // inverse transform cutting plane plane.InverseTransform(meshTransform); // first pass - find complete triangles on both sides of the plane for (var i = 0; i < trianglesNum; i += 3) { // get triangle points var v0 = meshVertices[meshTriangles[i]]; var v1 = meshVertices[meshTriangles[i + 1]]; var v2 = meshVertices[meshTriangles[i + 2]]; var side0 = plane.GetSideFix(ref v0); var side1 = plane.GetSideFix(ref v1); var side2 = plane.GetSideFix(ref v2); meshVertices[meshTriangles[i]] = v0; meshVertices[meshTriangles[i + 1]] = v1; meshVertices[meshTriangles[i + 2]] = v2; // all points on one side if (side0 == side1 && side1 == side2) { var idx = side0 ? 0 : 1; if (triCache[meshTriangles[i]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i]]); normals[idx].Add(meshNormals[meshTriangles[i]]); uvs[idx].Add(meshUV[meshTriangles[i]]); centroid[idx] += meshVertices[meshTriangles[i]]; triCache[meshTriangles[i]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i]] - 1); } if (triCache[meshTriangles[i + 1]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i + 1]]); normals[idx].Add(meshNormals[meshTriangles[i + 1]]); uvs[idx].Add(meshUV[meshTriangles[i + 1]]); centroid[idx] += meshVertices[meshTriangles[i + 1]]; triCache[meshTriangles[i + 1]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i + 1]] - 1); } if (triCache[meshTriangles[i + 2]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i + 2]]); normals[idx].Add(meshNormals[meshTriangles[i + 2]]); uvs[idx].Add(meshUV[meshTriangles[i + 2]]); centroid[idx] += meshVertices[meshTriangles[i + 2]]; triCache[meshTriangles[i + 2]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i + 2]] - 1); } } else { // intersection triangles add to list and process it in second pass cutTris.Add(i); } } if (vertices[0].Count == 0) { centroid[0] = meshVertices[0]; } else { centroid[0] /= vertices[0].Count; } if (vertices[1].Count == 0) { centroid[1] = meshVertices[1]; } else { centroid[1] /= vertices[1].Count; } #if PROFILING MeasureIt.End("CutCycleFirstPass"); MeasureIt.Begin("CutCycleSecondPass"); #endif mesh0 = null; mesh1 = null; centroid0 = centroid[0]; centroid1 = centroid[1]; intersectionData = null; if (cutTris.Count < 1) { stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } AllocateContours(cutTris.Count); // second pass - cut intersecting triangles in half foreach (var cutTri in cutTris) { var triangle = new Triangle { ids = new[] { meshTriangles[cutTri + 0], meshTriangles[cutTri + 1], meshTriangles[cutTri + 2] }, pos = new[] { meshVertices[meshTriangles[cutTri + 0]], meshVertices[meshTriangles[cutTri + 1]], meshVertices[meshTriangles[cutTri + 2]] }, normal = new[] { meshNormals[meshTriangles[cutTri + 0]], meshNormals[meshTriangles[cutTri + 1]], meshNormals[meshTriangles[cutTri + 2]] }, uvs = new[] { meshUV[meshTriangles[cutTri + 0]], meshUV[meshTriangles[cutTri + 1]], meshUV[meshTriangles[cutTri + 2]] } }; // check points with a plane var side0 = plane.GetSide(triangle.pos[0]); var side1 = plane.GetSide(triangle.pos[1]); var side2 = plane.GetSide(triangle.pos[2]); float t0, t1; Vector3 s0, s1; var idxLeft = side0 ? 0 : 1; var idxRight = 1 - idxLeft; if (side0 == side1) { var a = plane.IntersectSegment(triangle.pos[2], triangle.pos[0], out t0, out s0); var b = plane.IntersectSegment(triangle.pos[2], triangle.pos[1], out t1, out s1); MeshUtils.Assert(a && b, "!!!!!!!!!!!!!!!"); // left side ... 2 triangles var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[2], triangle.ids[0], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]); var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[2], triangle.ids[1], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]); var v1Left = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.ids[1], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]); // Triangle (s0, v0, s1) triangles[idxLeft].Add(s0Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s1Left); // Triangle (s1, v0, v1) triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(v1Left); // right side ... 1 triangle var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[2], triangle.ids[0], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]); var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[2], triangle.ids[1], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]); var v2Right = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.ids[2], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]); // Triangle (v2, s0, s1) triangles[idxRight].Add(v2Right); triangles[idxRight].Add(s0Right); triangles[idxRight].Add(s1Right); // buffer intersection vertices for triangulation if (triangulateHoles) { if (idxLeft == 0) { contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1); } else { contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1); } } } else if (side0 == side2) { var a = plane.IntersectSegment(triangle.pos[1], triangle.pos[0], out t0, out s1); var b = plane.IntersectSegment(triangle.pos[1], triangle.pos[2], out t1, out s0); MeshUtils.Assert(a && b, "!!!!!!!!!!!!!"); // left side ... 2 triangles var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[1], triangle.ids[2], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]); var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[1], triangle.ids[0], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]); var v2Left = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.ids[2], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]); // Triangle (v2, s1, s0) triangles[idxLeft].Add(v2Left); triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(s0Left); // Triangle (v2, v0, s1) triangles[idxLeft].Add(v2Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s1Left); // right side ... 1 triangle var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[1], triangle.ids[2], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]); var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[1], triangle.ids[0], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]); var v1Right = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.ids[1], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]); // Triangle (s0, s1, v1) triangles[idxRight].Add(s0Right); triangles[idxRight].Add(s1Right); triangles[idxRight].Add(v1Right); // buffer intersection vertices for triangulation if (triangulateHoles) { if (idxLeft == 0) { contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1); } else { contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1); } } } else { var a = plane.IntersectSegment(triangle.pos[0], triangle.pos[1], out t0, out s0); var b = plane.IntersectSegment(triangle.pos[0], triangle.pos[2], out t1, out s1); MeshUtils.Assert(a && b, "!!!!!!!!!!!!!"); // right side ... 2 triangles var s0Right = AddIntersectionPoint(s0, triangle, triangle.ids[0], triangle.ids[1], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]); var s1Right = AddIntersectionPoint(s1, triangle, triangle.ids[0], triangle.ids[2], cutVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]); var v1Right = AddTrianglePoint(triangle.pos[1], triangle.normal[1], triangle.uvs[1], triangle.ids[1], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]); var v2Right = AddTrianglePoint(triangle.pos[2], triangle.normal[2], triangle.uvs[2], triangle.ids[2], triCache, cornerVertCache[idxRight], vertices[idxRight], normals[idxRight], uvs[idxRight]); // Triangle (v2, s1, v1) triangles[idxRight].Add(v2Right); triangles[idxRight].Add(s1Right); triangles[idxRight].Add(v1Right); // Triangle (s1, s0, v1) triangles[idxRight].Add(s1Right); triangles[idxRight].Add(s0Right); triangles[idxRight].Add(v1Right); // left side ... 1 triangle var s0Left = AddIntersectionPoint(s0, triangle, triangle.ids[0], triangle.ids[1], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]); var s1Left = AddIntersectionPoint(s1, triangle, triangle.ids[0], triangle.ids[2], cutVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.normal[0], triangle.uvs[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft], normals[idxLeft], uvs[idxLeft]); // Triangle (s1, v0, s0) triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s0Left); // buffer intersection vertices for triangulation if (triangulateHoles) { if (idxLeft == 0) { contour.AddTriangle(cutTri, s0Left, s1Left, s0, s1); } else { contour.AddTriangle(cutTri, s0Right, s1Right, s0, s1); } } } } #if PROFILING MeasureIt.End("CutCycleSecondPass"); #endif if (triangulateHoles || getContourList) { #if PROFILING MeasureIt.Begin("FindContours"); #endif contour.FindContours(); #if PROFILING MeasureIt.End("FindContours"); #endif } List <int>[] trianglesCut = null; if (triangulateHoles) { #if PROFILING MeasureIt.Begin("Triangulate"); #endif trianglesCut = new List <int>[2] { new List <int>(contour.MidPointsCount), new List <int>(contour.MidPointsCount) }; Triangulate(contour.contour, plane, vertices, normals, uvs, trianglesCut, true); #if PROFILING MeasureIt.End("Triangulate"); #endif } intersectionData = null; if (getContourList) { #if PROFILING MeasureIt.Begin("GetContourList"); #endif List <Vector3[]> contoursList = null; GetContourList(contour.contour, vertices[0], out contoursList); intersectionData = new ContourData(contoursList, meshTransform); #if PROFILING MeasureIt.End("GetContourList"); #endif } centroid0 = centroid[0]; centroid1 = centroid[1]; if (dontCut) { MeshUtils.Assert(intersectionData != null, "F**k"); MeshUtils.Assert(getContourList != false, "Fuck2"); mesh0 = null; mesh1 = null; return(stopWatch.ElapsedMilliseconds); } if (vertices[0].Count > 0 && vertices[1].Count > 0) { #if PROFILING MeasureIt.Begin("CutEndCopyBack"); #endif mesh0 = new Mesh(); mesh1 = new Mesh(); var verticesArray0 = vertices[0].ToArray(); var verticesArray1 = vertices[1].ToArray(); #if PROFILING MeasureIt.Begin("FixPivot"); #endif if (fixPivot) { MeshUtils.CenterPivot(verticesArray0, centroid[0]); MeshUtils.CenterPivot(verticesArray1, centroid[1]); } #if PROFILING MeasureIt.End("FixPivot"); #endif mesh0.vertices = verticesArray0; mesh0.normals = normals[0].ToArray(); mesh0.uv = uvs[0].ToArray(); mesh1.vertices = verticesArray1; mesh1.normals = normals[1].ToArray(); mesh1.uv = uvs[1].ToArray(); if (triangulateHoles && trianglesCut[0].Count > 0) { mesh0.subMeshCount = 2; mesh0.SetTriangles(triangles[0].ToArray(), 0); mesh0.SetTriangles(trianglesCut[0].ToArray(), 1); mesh1.subMeshCount = 2; mesh1.SetTriangles(triangles[1].ToArray(), 0); mesh1.SetTriangles(trianglesCut[1].ToArray(), 1); } else { mesh0.triangles = triangles[0].ToArray(); mesh1.triangles = triangles[1].ToArray(); } #if PROFILING MeasureIt.End("CutEndCopyBack"); #endif stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } mesh0 = null; mesh1 = null; stopWatch.Stop(); // UnityEngine.Debug.Log("Empty cut! " + vertices[0].Count + " " + vertices[1].Count); return(stopWatch.ElapsedMilliseconds); }
/// <summary> /// cut mesh by plane /// </summary> /// <param name="spriteMesh">mesh to cut</param> /// <param name="meshTransform">transformation of the mesh</param> /// <param name="line2D">cutting plane</param> /// <returns>processing time</returns> public float Cut(SpriteMesh spriteMesh, Transform meshTransform, Math.Line2D line2D, ref List <CutterMesh> meshes) { var stopWatch = new Stopwatch(); stopWatch.Start(); #if PROFILING MeasureIt.Begin("CutAllocations"); #endif // cache mesh data var trianglesNum = spriteMesh.triangles.Length; var verticesNum = spriteMesh.vertices.Length; var meshTriangles = spriteMesh.triangles; var meshVertices = spriteMesh.vertices; // preallocate buffers AllocateBuffers(trianglesNum, verticesNum); CutterMesh mesh0, mesh1; #if PROFILING MeasureIt.End("CutAllocations"); MeasureIt.Begin("CutCycleFirstPass"); #endif // inverse transform cutting plane // line2D.InverseTransform(meshTransform); // first pass - find complete triangles on both sides of the plane for (int i = 0; i < trianglesNum; i += 3) { // get triangle points var v0 = meshVertices[meshTriangles[i]]; var v1 = meshVertices[meshTriangles[i + 1]]; var v2 = meshVertices[meshTriangles[i + 2]]; var side0 = line2D.GetSideFix(ref v0); var side1 = line2D.GetSideFix(ref v1); var side2 = line2D.GetSideFix(ref v2); meshVertices[meshTriangles[i]] = v0; meshVertices[meshTriangles[i + 1]] = v1; meshVertices[meshTriangles[i + 2]] = v2; // Utils.Log(plane.Pnt + " " + v0 + " " + v1 + " " + " " + v2); // all points on one side if (side0 == side1 && side1 == side2) { var idx = side0 ? 0 : 1; if (meshTriangles[i] >= triCache.Length) { Exploder2DUtils.Log("TriCacheError " + meshTriangles[i] + " " + triCache.Length + " " + meshVertices.Length); } if (triCache[meshTriangles[i]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i]]); centroid[idx] += meshVertices[meshTriangles[i]]; triCache[meshTriangles[i]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i]] - 1); } if (triCache[meshTriangles[i + 1]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i + 1]]); centroid[idx] += meshVertices[meshTriangles[i + 1]]; triCache[meshTriangles[i + 1]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i + 1]] - 1); } if (triCache[meshTriangles[i + 2]] == 0) { triangles[idx].Add(triCounter[idx]); vertices[idx].Add(meshVertices[meshTriangles[i + 2]]); centroid[idx] += meshVertices[meshTriangles[i + 2]]; triCache[meshTriangles[i + 2]] = triCounter[idx] + 1; triCounter[idx]++; } else { triangles[idx].Add(triCache[meshTriangles[i + 2]] - 1); } } else { // intersection triangles add to list and process it in second pass cutTris.Add(i); } } if (vertices[0].Count == 0) { centroid[0] = meshVertices[0]; } else { centroid[0] /= vertices[0].Count; } if (vertices[1].Count == 0) { centroid[1] = meshVertices[1]; } else { centroid[1] /= vertices[1].Count; } #if PROFILING MeasureIt.End("CutCycleFirstPass"); MeasureIt.Begin("CutCycleSecondPass"); #endif mesh0.centroidLocal = centroid[0]; mesh1.centroidLocal = centroid[1]; mesh0.mesh = null; mesh1.mesh = null; if (cutTris.Count < 1) { stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } AllocateContours(cutTris.Count); // second pass - cut intersecting triangles in half foreach (var cutTri in cutTris) { var triangle = new Triangle { ids = new[] { meshTriangles[cutTri + 0], meshTriangles[cutTri + 1], meshTriangles[cutTri + 2] }, pos = new[] { meshVertices[meshTriangles[cutTri + 0]], meshVertices[meshTriangles[cutTri + 1]], meshVertices[meshTriangles[cutTri + 2]] }, }; // check points with a plane var side0 = line2D.GetSide(triangle.pos[0]); var side1 = line2D.GetSide(triangle.pos[1]); var side2 = line2D.GetSide(triangle.pos[2]); float t0, t1; Vector2 s0 = Vector2.zero, s1 = Vector2.zero; var idxLeft = side0 ? 0 : 1; var idxRight = 1 - idxLeft; if (side0 == side1) { var a = line2D.IntersectSegment(triangle.pos[2], triangle.pos[0], out t0, ref s0); var b = line2D.IntersectSegment(triangle.pos[2], triangle.pos[1], out t1, ref s1); Exploder2DUtils.Assert(a && b, "!!!!!!!!!!!!!!!"); // left side ... 2 triangles var s0Left = AddIntersectionPoint(s0, triangle.ids[2], triangle.ids[0], cutVertCache[idxLeft], vertices[idxLeft]); var s1Left = AddIntersectionPoint(s1, triangle.ids[2], triangle.ids[1], cutVertCache[idxLeft], vertices[idxLeft]); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft]); var v1Left = AddTrianglePoint(triangle.pos[1], triangle.ids[1], triCache, cornerVertCache[idxLeft], vertices[idxLeft]); // Triangle (s0, v0, s1) triangles[idxLeft].Add(s0Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s1Left); // Triangle (s1, v0, v1) triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(v1Left); // right side ... 1 triangle var s0Right = AddIntersectionPoint(s0, triangle.ids[2], triangle.ids[0], cutVertCache[idxRight], vertices[idxRight]); var s1Right = AddIntersectionPoint(s1, triangle.ids[2], triangle.ids[1], cutVertCache[idxRight], vertices[idxRight]); var v2Right = AddTrianglePoint(triangle.pos[2], triangle.ids[2], triCache, cornerVertCache[idxRight], vertices[idxRight]); // Triangle (v2, s0, s1) triangles[idxRight].Add(v2Right); triangles[idxRight].Add(s0Right); triangles[idxRight].Add(s1Right); } else if (side0 == side2) { var a = line2D.IntersectSegment(triangle.pos[1], triangle.pos[0], out t0, ref s1); var b = line2D.IntersectSegment(triangle.pos[1], triangle.pos[2], out t1, ref s0); Exploder2DUtils.Assert(a && b, "!!!!!!!!!!!!!"); // left side ... 2 triangles var s0Left = AddIntersectionPoint(s0, triangle.ids[1], triangle.ids[2], cutVertCache[idxLeft], vertices[idxLeft]); var s1Left = AddIntersectionPoint(s1, triangle.ids[1], triangle.ids[0], cutVertCache[idxLeft], vertices[idxLeft]); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft]); var v2Left = AddTrianglePoint(triangle.pos[2], triangle.ids[2], triCache, cornerVertCache[idxLeft], vertices[idxLeft]); // Triangle (v2, s1, s0) triangles[idxLeft].Add(v2Left); triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(s0Left); // Triangle (v2, v0, s1) triangles[idxLeft].Add(v2Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s1Left); // right side ... 1 triangle var s0Right = AddIntersectionPoint(s0, triangle.ids[1], triangle.ids[2], cutVertCache[idxRight], vertices[idxRight]); var s1Right = AddIntersectionPoint(s1, triangle.ids[1], triangle.ids[0], cutVertCache[idxRight], vertices[idxRight]); var v1Right = AddTrianglePoint(triangle.pos[1], triangle.ids[1], triCache, cornerVertCache[idxRight], vertices[idxRight]); // Triangle (s0, s1, v1) triangles[idxRight].Add(s0Right); triangles[idxRight].Add(s1Right); triangles[idxRight].Add(v1Right); } else { var a = line2D.IntersectSegment(triangle.pos[0], triangle.pos[1], out t0, ref s0); var b = line2D.IntersectSegment(triangle.pos[0], triangle.pos[2], out t1, ref s1); Exploder2DUtils.Assert(a && b, "!!!!!!!!!!!!!"); // right side ... 2 triangles var s0Right = AddIntersectionPoint(s0, triangle.ids[0], triangle.ids[1], cutVertCache[idxRight], vertices[idxRight]); var s1Right = AddIntersectionPoint(s1, triangle.ids[0], triangle.ids[2], cutVertCache[idxRight], vertices[idxRight]); var v1Right = AddTrianglePoint(triangle.pos[1], triangle.ids[1], triCache, cornerVertCache[idxRight], vertices[idxRight]); var v2Right = AddTrianglePoint(triangle.pos[2], triangle.ids[2], triCache, cornerVertCache[idxRight], vertices[idxRight]); // Triangle (v2, s1, v1) triangles[idxRight].Add(v2Right); triangles[idxRight].Add(s1Right); triangles[idxRight].Add(v1Right); // Triangle (s1, s0, v1) triangles[idxRight].Add(s1Right); triangles[idxRight].Add(s0Right); triangles[idxRight].Add(v1Right); // left side ... 1 triangle var s0Left = AddIntersectionPoint(s0, triangle.ids[0], triangle.ids[1], cutVertCache[idxLeft], vertices[idxLeft]); var s1Left = AddIntersectionPoint(s1, triangle.ids[0], triangle.ids[2], cutVertCache[idxLeft], vertices[idxLeft]); var v0Left = AddTrianglePoint(triangle.pos[0], triangle.ids[0], triCache, cornerVertCache[idxLeft], vertices[idxLeft]); // Triangle (s1, v0, s0) triangles[idxLeft].Add(s1Left); triangles[idxLeft].Add(v0Left); triangles[idxLeft].Add(s0Left); } } #if PROFILING MeasureIt.End("CutCycleSecondPass"); #endif List <int>[] trianglesCut = null; if (vertices[0].Count > 3 && vertices[1].Count > 3) { #if PROFILING MeasureIt.Begin("CutEndCopyBack"); #endif mesh0.mesh = new SpriteMesh(); mesh1.mesh = new SpriteMesh(); var verticesArray0 = vertices[0].ToArray(); var verticesArray1 = vertices[1].ToArray(); mesh0.mesh.vertices = verticesArray0; mesh1.mesh.vertices = verticesArray1; if (trianglesCut != null && trianglesCut[0].Count > 3) { triangles[0].AddRange(trianglesCut[0]); triangles[1].AddRange(trianglesCut[1]); } mesh0.mesh.triangles = triangles[0].ToArray(); mesh1.mesh.triangles = triangles[1].ToArray(); mesh0.centroidLocal = Vector2.zero; mesh1.centroidLocal = Vector2.zero; foreach (var p in vertices[0]) { mesh0.centroidLocal += p; } mesh0.centroidLocal /= vertices[0].Count; foreach (var p in vertices[1]) { mesh1.centroidLocal += p; } mesh1.centroidLocal /= vertices[1].Count; #if PROFILING MeasureIt.End("CutEndCopyBack"); #endif meshes = new List <CutterMesh> { mesh0, mesh1 }; stopWatch.Stop(); return(stopWatch.ElapsedMilliseconds); } stopWatch.Stop(); // UnityEngine.Debug.Log("Empty cut! " + vertices[0].Count + " " + vertices[1].Count); return(stopWatch.ElapsedMilliseconds); }