public static bool CutTriangleMesh(Mesh[] outputMeshes, Mesh sourceMesh, Plane cuttingPlane, Transform transform, Transform rotation, bool cap) { float epsilon = 0.00001f; debugPolyLoop = new List <Vector3>(); debugEdgePoints = new List <Vector3>(); debugEdges = new List <Vector3[]>(); debugLoopEdgePoints = new List <Vector3[]>(); int vertCount = sourceMesh.vertexCount; Vector3[] verts = sourceMesh.vertices; Triangle3D.Vertex[] allVerts = new Triangle3D.Vertex[vertCount]; for (int i = 0; i < vertCount; i++) { allVerts[i] = new Triangle3D.Vertex(transform.TransformPoint(verts[i])); } List <Triangle3D.Vertex> allVertList = new List <Triangle3D.Vertex>(); Vector2[] originalUVs = sourceMesh.uv; Vector3[] originalNormals = sourceMesh.normals; Vector4[] originalTangents = sourceMesh.tangents; int triCount = sourceMesh.triangles.Length / 3; Triangle3D[] originalTriangles = new Triangle3D[triCount]; int offset = 0; for (int j = 0; j < sourceMesh.subMeshCount; j++) { uint triOffset = 0; int[] subMeshIndices = sourceMesh.GetTriangles(j); int subMeshTriCount = subMeshIndices.Length / 3; for (int i = 0; i < subMeshTriCount; i++) { int idx0 = subMeshIndices[triOffset + 0]; int idx1 = subMeshIndices[triOffset + 1]; int idx2 = subMeshIndices[triOffset + 2]; originalTriangles[offset++] = new Triangle3D(allVertList, new Triangle3D.Vertex[] { allVerts[idx0], allVerts[idx1], allVerts[idx2] }, new Vector3[] { originalNormals[idx0], originalNormals[idx1], originalNormals[idx2] }, new Vector2[] { originalUVs[idx0], originalUVs[idx1], originalUVs[idx2] }, new Vector4[] { originalTangents[idx0], originalTangents[idx1], originalTangents[idx2] }, new int[] { subMeshIndices[triOffset + 0], subMeshIndices[triOffset + 1], subMeshIndices[triOffset + 2] }, j); triOffset += 3; } } if (originalTriangles.Length > 0) { int processedTriCount = 0; Triangle3D[] processedTris = new Triangle3D[originalTriangles.Length * 3]; ClassificationUtil.Classification prevSide = ClassificationUtil.Classification.UNDEFINED; foreach (Triangle3D originalTriangle in originalTriangles) { ClassificationUtil.Classification side; Triangle3D[] splitTriangles = TriangleUtil.SplitTriangleWithPlane(originalTriangle, cuttingPlane, epsilon, out side, cap); if (prevSide != ClassificationUtil.Classification.UNDEFINED && prevSide != side) { } prevSide = side; if (splitTriangles != null) { // Triangle was cut foreach (Triangle3D splitTriangle in splitTriangles) { processedTris[processedTriCount] = splitTriangle; processedTriCount++; } } else { // Triangle was not cut processedTris[processedTriCount] = originalTriangle; processedTriCount++; } } int triangleBucketACount = 0; int triangleBucketBCount = 0; Triangle3D[] triangleBucketA = new Triangle3D[processedTriCount]; Triangle3D[] triangleBucketB = new Triangle3D[processedTriCount]; for (int i = 0; i < processedTriCount; i++) { ClassificationUtil.Classification[] classes; ClassificationUtil.Classification triClass = ClassificationUtil.ClassifyPoints(processedTris[i].pos, cuttingPlane, out classes, epsilon); if (triClass == ClassificationUtil.Classification.FRONT) { triangleBucketA[triangleBucketACount++] = processedTris[i]; } else if (triClass == ClassificationUtil.Classification.BACK) { triangleBucketB[triangleBucketBCount++] = processedTris[i]; } } if (triangleBucketACount == 0 || triangleBucketBCount == 0) { return(false); } List <Triangle3D> totalCapTriBucket = new List <Triangle3D>(); List <Triangle3D.Vertex> totalCapVertBucket = new List <Triangle3D.Vertex>(); while (cap && debugEdges.Count > 2) { List <Triangle3D> capTriBucket = new List <Triangle3D>(); List <Triangle3D.Vertex> capVertBucket = new List <Triangle3D.Vertex>(); Triangle3D.Vertex[] sortedVerts = GetPolyLoop(ref debugEdges); if (sortedVerts != null) { CapMesh(out capTriBucket, out capVertBucket, sortedVerts, transform, rotation, totalCapTriBucket.Count); } if (capVertBucket.Count > 2) { for (int i = 0; i < capVertBucket.Count - 1; i++) { Debug.DrawLine(transform.TransformPoint(capVertBucket[i].pos), transform.TransformPoint(capVertBucket[i + 1].pos)); } Debug.DrawLine(transform.TransformPoint(capVertBucket[capVertBucket.Count - 1].pos), transform.TransformPoint(capVertBucket[0].pos)); } totalCapTriBucket.AddRange(capTriBucket); totalCapVertBucket.AddRange(capVertBucket); } if (triangleBucketACount > 0) { SortMesh(outputMeshes[0], triangleBucketA, triangleBucketACount, transform, totalCapTriBucket, totalCapVertBucket, false); } if (triangleBucketBCount > 0) { SortMesh(outputMeshes[1], triangleBucketB, triangleBucketBCount, transform, totalCapTriBucket, totalCapVertBucket, true); } return(true); } else { Debug.Log("source geometry empty"); return(false); } }
public static bool CutTriangleMeshFast(Mesh[] outputMeshes, Mesh sourceMesh, Transform objectTransform, Transform planeTransform, bool cap) { float epsilon = 0.00001f; hashCheck = new Dictionary <Vector3, int>(); debugPolyLoop = new List <Vector3>(); debugEdgePoints = new List <Vector3>(); debugEdges = new List <Vector3[]>(); debugLoopEdgePoints = new List <Vector3[]>(); int originalVertexCount = sourceMesh.vertexCount; Vector3[] originalVertices = sourceMesh.vertices; int originalIndexCount = sourceMesh.triangles.Length; int[] originalIndices = sourceMesh.triangles; Vector3 centre = objectTransform.transform.InverseTransformPoint(planeTransform.position); Vector3 up = objectTransform.transform.InverseTransformDirection(planeTransform.up); Plane cuttingPlane = new Plane(up, centre); int totalIndexCount = originalIndexCount; int totalVertexCount = originalVertexCount; int indexBufferCountA = 0; int vertexBufferCountA = 0; Vector3[] vertexBufferA = new Vector3[totalVertexCount * 10]; int[] indexBufferA = new int[originalIndexCount * 10]; int indexBufferCountB = 0; int vertexBufferCountB = 0; Vector3[] vertexBufferB = new Vector3[totalVertexCount * 10]; int[] indexBufferB = new int[originalIndexCount * 10]; Vector3[] points = new Vector3[3]; int[] triIndices = new int[3]; for (int i = 0; i < totalIndexCount; i += 3) { triIndices[0] = originalIndices[i]; triIndices[1] = originalIndices[i + 1]; triIndices[2] = originalIndices[i + 2]; points[0] = originalVertices[triIndices[0]]; points[1] = originalVertices[triIndices[1]]; points[2] = originalVertices[triIndices[2]]; int[] newTris; Vector3[] newPoints; ClassificationUtil.Classification side; TriangleUtil.SplitTriangleWithPlane( ref totalVertexCount, points, triIndices, cuttingPlane, epsilon, out side, cap, out newTris, out newPoints); // Slice the triangle then classify which side it's on if (newTris != null) { for (int j = 0; j < newTris.Length; j += 3) { ClassificationUtil.Classification[] classes; ClassificationUtil.Classification triClass = ClassificationUtil.ClassifyPoints( new Vector3[] { newPoints[j + 0], newPoints[j + 1], newPoints[j + 2] }, cuttingPlane, out classes, epsilon); //Debug.DrawLine(newPoints[j + 0], newPoints[j + 1]); //Debug.DrawLine(newPoints[j + 1], newPoints[j + 2]); //Debug.DrawLine(newPoints[j + 2], newPoints[j + 0]); if (triClass == ClassificationUtil.Classification.FRONT) { indexBufferA[indexBufferCountA++] = newTris[j + 0]; indexBufferA[indexBufferCountA++] = newTris[j + 1]; indexBufferA[indexBufferCountA++] = newTris[j + 2]; vertexBufferA[vertexBufferCountA++] = newPoints[j + 0]; vertexBufferA[vertexBufferCountA++] = newPoints[j + 1]; vertexBufferA[vertexBufferCountA++] = newPoints[j + 2]; } else if (triClass == ClassificationUtil.Classification.BACK) { indexBufferB[indexBufferCountB++] = newTris[j + 0]; indexBufferB[indexBufferCountB++] = newTris[j + 1]; indexBufferB[indexBufferCountB++] = newTris[j + 2]; vertexBufferB[vertexBufferCountB++] = newPoints[j + 0]; vertexBufferB[vertexBufferCountB++] = newPoints[j + 1]; vertexBufferB[vertexBufferCountB++] = newPoints[j + 2]; } } } else { ClassificationUtil.Classification[] classes; ClassificationUtil.Classification triClass = ClassificationUtil.ClassifyPoints( new Vector3[] { points[0], points[1], points[2] }, cuttingPlane, out classes, epsilon); //Debug.DrawLine(points[0], points[1], Color.red); //Debug.DrawLine(points[1], points[2], Color.red); //Debug.DrawLine(points[2], points[0], Color.red); if (triClass == ClassificationUtil.Classification.FRONT) { indexBufferA[indexBufferCountA++] = triIndices[0]; indexBufferA[indexBufferCountA++] = triIndices[1]; indexBufferA[indexBufferCountA++] = triIndices[2]; vertexBufferA[vertexBufferCountA++] = points[0]; vertexBufferA[vertexBufferCountA++] = points[1]; vertexBufferA[vertexBufferCountA++] = points[2]; } else if (triClass == ClassificationUtil.Classification.BACK) { indexBufferB[indexBufferCountB++] = triIndices[0]; indexBufferB[indexBufferCountB++] = triIndices[1]; indexBufferB[indexBufferCountB++] = triIndices[2]; vertexBufferB[vertexBufferCountB++] = points[0]; vertexBufferB[vertexBufferCountB++] = points[1]; vertexBufferB[vertexBufferCountB++] = points[2]; } } } if (indexBufferCountA > 0) { SortMesh(outputMeshes[0], indexBufferA, vertexBufferA, indexBufferCountA, false); } if (indexBufferCountB > 0) { SortMesh(outputMeshes[1], indexBufferB, vertexBufferB, indexBufferCountB, true); } return(true); }