public static void SortMesh(Mesh targetMesh, Triangle3D[] triangleBucket, int triangleBucketCount, Transform objectTransform, List <Triangle3D> capTriBucket, List <Triangle3D.Vertex> capVertBucket, bool flip) { Dictionary <int, int> vertCache = new Dictionary <int, int>(triangleBucketCount * 3); Triangle3D.Vertex vert = null; int vertexBucketCount = 0; Vector3[] vertexBucket = new Vector3[triangleBucketCount * 3]; for (int i = 0; i < triangleBucketCount; i++) { Triangle3D triangle = triangleBucket[i]; for (int j = 0; j < triangle.vertices.Length; j++) { vert = triangle.vertices[j]; int code = vert.GetHashCode(); if (!vertCache.ContainsKey(code)) { vertCache[code] = vertexBucketCount; triangle.vertices[j] = vert; triangle.indices[j] = vertexBucketCount; vertexBucket[vertexBucketCount] = objectTransform.InverseTransformPoint(vert.pos); vertexBucketCount++; } else { triangle.indices[j] = vertCache[code]; } } } int triWithCapCount = triangleBucketCount + capTriBucket.Count; int vertWithCapCount = vertexBucketCount + capVertBucket.Count; Array.Resize <Triangle3D>(ref triangleBucket, triangleBucketCount + capTriBucket.Count); Array.Resize <Vector3>(ref vertexBucket, vertexBucketCount + capVertBucket.Count); int triOff = 0; for (int i = triangleBucketCount; i < triWithCapCount; i++) { triangleBucket[i] = new Triangle3D(capTriBucket[triOff++], vertexBucketCount, flip); } int vertOff = 0; for (int i = vertexBucketCount; i < vertWithCapCount; i++) { vertexBucket[i] = capVertBucket[vertOff++].pos; } CreateNewMesh(targetMesh, triangleBucket, vertexBucket); }
public static SplitMesh GrabMeshOutline(Mesh mesh, Plane cuttingPlane, Transform transform, Transform rotation) { debugPolyLoop = new List<Vector3>(); debugEdgePoints = new List<Vector3>(); debugEdges = new List<Vector3[]>(); debugLoopEdgePoints = new List<Vector3[]>(); int vertCount = mesh.vertexCount; Vector3[] verts = mesh.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 = mesh.uv; Vector3[] originalNormals = mesh.normals; Vector4[] originalTangents = mesh.tangents; int triCount = mesh.triangles.Length / 3; Triangle3D[] originalTriangles = new Triangle3D[triCount]; int offset = 0; for (int j = 0; j < mesh.subMeshCount; j++) { uint triOffset = 0; int[] subMeshIndices = mesh.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]; if (originalTriangles.Length <= offset) { Debug.Log("Error"); } 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, float.Epsilon, out side); 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, float.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 null; } List<Triangle3D> totalCapTriBucket = new List<Triangle3D>(); List<Triangle3D.Vertex> totalCapVertBucket = new List<Triangle3D.Vertex>(); List<List<Triangle3D.Vertex>> capVertGroups = new List<List<Triangle3D.Vertex>>(); while (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 false 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)); } #endif totalCapTriBucket.AddRange(capTriBucket); totalCapVertBucket.AddRange(capVertBucket); capVertGroups.Add(capVertBucket); } Vector3[] vertexBucket = new Vector3[totalCapVertBucket.Count]; for (int i = 0; i < totalCapVertBucket.Count; i++) { vertexBucket[i] = transform.TransformPoint(totalCapVertBucket[i].pos); } return new SplitMesh(new List<Vector3>(vertexBucket), totalCapTriBucket, capVertGroups); } else { Debug.LogError("Source geometry empty"); return null; } }
public static bool CutTriangleMeshOneSide(Mesh outputMeshes, Mesh sourceMesh, Plane cuttingPlane, Transform transform, Transform rotation, bool frontSide, 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 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>(); //int[] originalIndices = sourceMesh.triangles; 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) { foreach (Triangle3D splitTriangle in splitTriangles) { processedTris[processedTriCount] = splitTriangle; processedTriCount++; } } else { processedTris[processedTriCount] = originalTriangle; processedTriCount++; } } //if (!cut) //{ // CloneMesh(sourceMesh, outputMeshes); // return false; //} int triangleBucketCount = 0; Triangle3D[] triangleBucket = 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 && frontSide) { triangleBucket[triangleBucketCount++] = processedTris[i]; } else if (triClass == ClassificationUtil.Classification.BACK && !frontSide) { triangleBucket[triangleBucketCount++] = processedTris[i]; } } if (triangleBucketCount == 0) { outputMeshes.Clear(); 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); } totalCapTriBucket.AddRange(capTriBucket); totalCapVertBucket.AddRange(capVertBucket); } if (triangleBucketCount > 0) { SortMesh(outputMeshes, triangleBucket, triangleBucketCount, transform, totalCapTriBucket, totalCapVertBucket, !frontSide); } return true; } else { return false; } }
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 Triangle3D[] SplitTriangleWithPlane(Triangle3D triangle, Plane plane, float e, out ClassificationUtil.Classification side, bool cap) { ClassificationUtil.Classification[] classes; side = ClassificationUtil.ClassifyTriangle(triangle, plane, out classes, e); if(side != ClassificationUtil.Classification.STRADDLE) { if(cap) { SetEdge(0, 1, classes, triangle.pos); SetEdge(1, 2, classes, triangle.pos); SetEdge(2, 0, classes, triangle.pos); } return null; } //int iA; Triangle3D.Vertex pA; Vector3 normA; Vector2 uvA; //Vector4 tA; uint aLength = 0; int[] indicesA = new int[4]; Triangle3D.Vertex[] verticesA = new Triangle3D.Vertex[4]; Vector3[] normalsA = new Vector3[4]; Vector2[] uvsA = new Vector2[4]; Vector4[] tangentsA = new Vector4[4]; int iB; Triangle3D.Vertex pB; Vector3 normB; Vector2 uvB; Vector4 tB; uint bLength = 0; int[] indicesB = new int[4]; Triangle3D.Vertex[] verticesB = new Triangle3D.Vertex[4]; Vector3[] normalsB = new Vector3[4]; Vector2[] uvsB = new Vector2[4]; Vector4[] tangentsB = new Vector4[4]; float sideA; float sideB; Intersection isect; Vector2 newUV; List<Vector3> cVerts = new List<Vector3> (); int[] indices = new int[] { triangle.idxV0, triangle.idxV1, triangle.idxV2 }; Triangle3D.Vertex[] points = new Triangle3D.Vertex[] { triangle.v0, triangle.v1, triangle.v2 }; Vector3[] normals = new Vector3[] { triangle.nv0, triangle.nv1, triangle.nv2 }; Vector2[] uvs = new Vector2[] { triangle.uv0, triangle.uv1, triangle.uv2 }; Vector4[] tangents = new Vector4[] { triangle.tv0, triangle.tv1, triangle.tv2 }; float[] distance = new float[3]; for(int i = 0; i < points.Length; i++) { distance[i] = plane.GetDistanceToPoint(points[i].pos); } for(int i = 0; i < points.Length; i++) { int j = (i + 1) % points.Length; //iA = indices[i]; iB = indices[j]; pA = points[i]; pB = points[j]; uvA = uvs[i]; uvB = uvs[j]; normA = normals[i]; normB = normals[j]; //tA = tangents[i]; tB = tangents[j]; sideA = distance[i]; sideB = distance[j]; if(sideB > e) { if(sideA < -e) { isect = Intersection.LinePlane(pA.pos, pB.pos, plane, e, null); if(isect.status != Intersection.IntersectionType.INTERSECTION) { plane.distance += Mathf.Epsilon; return SplitTriangleWithPlane(triangle, new Plane (plane.normal, plane.distance + 1.0f), e, out side, cap); } // New vertex was created int newIndex = triangle.meshVertices.Count; triangle.meshVertices.Add(new Triangle3D.Vertex (isect.vert)); indicesA[aLength] = newIndex; indicesB[bLength] = newIndex; verticesA[aLength] = new Triangle3D.Vertex (isect.vert); verticesB[bLength] = new Triangle3D.Vertex (isect.vert); newUV = InterpolateUV(uvA, uvB, isect.alpha); uvsA[aLength] = newUV; uvsB[bLength] = newUV; tangentsA[aLength] = tB; tangentsB[bLength] = tB; normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha); normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha); aLength++; bLength++; if(!cVerts.Contains(isect.vert)) { cVerts.Add(isect.vert); } } indicesA[aLength] = iB; verticesA[aLength] = pB; uvsA[aLength] = uvB; normalsA[aLength] = normB; tangentsA[aLength] = tB; aLength++; } else if(sideB < -e) { if(sideA > e) { isect = Intersection.LinePlane(pA.pos, pB.pos, plane, e, null); if(isect.status != Intersection.IntersectionType.INTERSECTION) { return SplitTriangleWithPlane(triangle, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap); } // New vertex was created int newIndex = triangle.meshVertices.Count; triangle.meshVertices.Add(new Triangle3D.Vertex (isect.vert)); indicesA[aLength] = newIndex; indicesB[bLength] = newIndex; verticesA[aLength] = new Triangle3D.Vertex (isect.vert); verticesB[bLength] = new Triangle3D.Vertex (isect.vert); newUV = InterpolateUV(uvA, uvB, isect.alpha); uvsA[aLength] = newUV; uvsB[bLength] = newUV; tangentsA[aLength] = tB; tangentsB[bLength] = tB; normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha); normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha); aLength++; bLength++; if(!cVerts.Contains(isect.vert)) { cVerts.Add(isect.vert); } } indicesB[bLength] = iB; verticesB[bLength] = pB; uvsB[bLength] = uvB; normalsB[bLength] = normB; tangentsB[bLength] = tB; bLength++; } else { indicesA[aLength] = iB; verticesA[aLength] = pB; uvsA[aLength] = uvB; normalsA[aLength] = normB; tangentsA[aLength] = tB; aLength++; indicesB[bLength] = iB; verticesB[bLength] = pB; uvsB[bLength] = uvB; normalsB[bLength] = normB; tangentsB[bLength] = tB; bLength++; cVerts.Add(pB.pos); if(!cVerts.Contains(pB.pos)) { cVerts.Add(pB.pos); } } } for(int i = 0; i < cVerts.Count - 1; i++) { MeshSlicer.debugEdges.Add(new Vector3[] { cVerts[i], cVerts[i + 1] }); } Triangle3D[] tris; if(aLength > 3 || bLength > 3) { tris = new Triangle3D[3]; } else { tris = new Triangle3D[2]; } tris[0] = new Triangle3D (triangle.meshVertices, new Triangle3D.Vertex[] { verticesA[0], verticesA[1], verticesA[2] }, new Vector3[] { normalsA[0], normalsA[1], normalsA[2] }, new Vector2[] { uvsA[0], uvsA[1], uvsA[2] }, new Vector4[] { tangentsA[0], tangentsA[1], tangentsA[2] }, new int[] { indicesA[0], indicesA[1], indicesA[2] }, triangle.subMeshGroup); tris[1] = new Triangle3D (triangle.meshVertices, new Triangle3D.Vertex[] { verticesB[0], verticesB[1], verticesB[2] }, new Vector3[] { normalsB[0], normalsB[1], normalsB[2] }, new Vector2[] { uvsB[0], uvsB[1], uvsB[2] }, new Vector4[] { tangentsB[0], tangentsB[1], tangentsB[2] }, new int[] { indicesB[0], indicesB[1], indicesB[2] }, triangle.subMeshGroup); if(aLength > 3) { tris[2] = new Triangle3D (triangle.meshVertices, new Triangle3D.Vertex[] { verticesA[0], verticesA[2], verticesA[3] }, new Vector3[] { normalsA[0], normalsA[2], normalsA[3] }, new Vector2[] { uvsA[0], uvsA[2], uvsA[3] }, new Vector4[] { tangentsA[0], tangentsA[2], tangentsA[3] }, new int[] { indicesA[0], indicesA[2], indicesA[3] }, triangle.subMeshGroup); } else if(bLength > 3) { tris[2] = new Triangle3D (triangle.meshVertices, new Triangle3D.Vertex[] { verticesB[0], verticesB[2], verticesB[3] }, new Vector3[] { normalsB[0], normalsB[2], normalsB[3] }, new Vector2[] { uvsB[0], uvsB[2], uvsB[3] }, new Vector4[] { tangentsB[0], tangentsB[2], tangentsB[3] }, new int[] { indicesB[0], indicesB[2], indicesB[3] }, triangle.subMeshGroup); } return tris; }
public static Triangle3D[] SplitTriangleWithPlane(Triangle3D triangle, Plane plane, float e, out ClassificationUtil.Classification side, bool cap) { ClassificationUtil.Classification[] classes; side = ClassificationUtil.ClassifyTriangle(triangle, plane, out classes, e); if (side != ClassificationUtil.Classification.STRADDLE) { if (cap) { SetEdge(0, 1, classes, triangle.pos); SetEdge(1, 2, classes, triangle.pos); SetEdge(2, 0, classes, triangle.pos); } return(null); } //int iA; Triangle3D.Vertex pA; Vector3 normA; Vector2 uvA; //Vector4 tA; uint aLength = 0; int[] indicesA = new int[4]; Triangle3D.Vertex[] verticesA = new Triangle3D.Vertex[4]; Vector3[] normalsA = new Vector3[4]; Vector2[] uvsA = new Vector2[4]; Vector4[] tangentsA = new Vector4[4]; int iB; Triangle3D.Vertex pB; Vector3 normB; Vector2 uvB; Vector4 tB; uint bLength = 0; int[] indicesB = new int[4]; Triangle3D.Vertex[] verticesB = new Triangle3D.Vertex[4]; Vector3[] normalsB = new Vector3[4]; Vector2[] uvsB = new Vector2[4]; Vector4[] tangentsB = new Vector4[4]; float sideA; float sideB; Intersection isect; Vector2 newUV; List <Vector3> cVerts = new List <Vector3> (); int[] indices = new int[] { triangle.idxV0, triangle.idxV1, triangle.idxV2 }; Triangle3D.Vertex[] points = new Triangle3D.Vertex[] { triangle.v0, triangle.v1, triangle.v2 }; Vector3[] normals = new Vector3[] { triangle.nv0, triangle.nv1, triangle.nv2 }; Vector2[] uvs = new Vector2[] { triangle.uv0, triangle.uv1, triangle.uv2 }; Vector4[] tangents = new Vector4[] { triangle.tv0, triangle.tv1, triangle.tv2 }; float[] distance = new float[3]; for (int i = 0; i < points.Length; i++) { distance[i] = plane.GetDistanceToPoint(points[i].pos); } for (int i = 0; i < points.Length; i++) { int j = (i + 1) % points.Length; //iA = indices[i]; iB = indices[j]; pA = points[i]; pB = points[j]; uvA = uvs[i]; uvB = uvs[j]; normA = normals[i]; normB = normals[j]; //tA = tangents[i]; tB = tangents[j]; sideA = distance[i]; sideB = distance[j]; if (sideB > e) { if (sideA < -e) { isect = Intersection.LinePlane(pA.pos, pB.pos, plane, e, null); if (isect.status != Intersection.IntersectionType.INTERSECTION) { plane.distance += Mathf.Epsilon; return(SplitTriangleWithPlane(triangle, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap)); } // New vertex was created int newIndex = triangle.meshVertices.Count; triangle.meshVertices.Add(new Triangle3D.Vertex(isect.vert)); indicesA[aLength] = newIndex; indicesB[bLength] = newIndex; verticesA[aLength] = new Triangle3D.Vertex(isect.vert); verticesB[bLength] = new Triangle3D.Vertex(isect.vert); newUV = InterpolateUV(uvA, uvB, isect.alpha); uvsA[aLength] = newUV; uvsB[bLength] = newUV; tangentsA[aLength] = tB; tangentsB[bLength] = tB; normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha); normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha); aLength++; bLength++; if (!cVerts.Contains(isect.vert)) { cVerts.Add(isect.vert); } } indicesA[aLength] = iB; verticesA[aLength] = pB; uvsA[aLength] = uvB; normalsA[aLength] = normB; tangentsA[aLength] = tB; aLength++; } else if (sideB < -e) { if (sideA > e) { isect = Intersection.LinePlane(pA.pos, pB.pos, plane, e, null); if (isect.status != Intersection.IntersectionType.INTERSECTION) { return(SplitTriangleWithPlane(triangle, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap)); } // New vertex was created int newIndex = triangle.meshVertices.Count; triangle.meshVertices.Add(new Triangle3D.Vertex(isect.vert)); indicesA[aLength] = newIndex; indicesB[bLength] = newIndex; verticesA[aLength] = new Triangle3D.Vertex(isect.vert); verticesB[bLength] = new Triangle3D.Vertex(isect.vert); newUV = InterpolateUV(uvA, uvB, isect.alpha); uvsA[aLength] = newUV; uvsB[bLength] = newUV; tangentsA[aLength] = tB; tangentsB[bLength] = tB; normalsA[aLength] = Vector3.Lerp(normA, normB, isect.alpha); normalsB[bLength] = Vector3.Lerp(normA, normB, isect.alpha); aLength++; bLength++; if (!cVerts.Contains(isect.vert)) { cVerts.Add(isect.vert); } } indicesB[bLength] = iB; verticesB[bLength] = pB; uvsB[bLength] = uvB; normalsB[bLength] = normB; tangentsB[bLength] = tB; bLength++; } else { indicesA[aLength] = iB; verticesA[aLength] = pB; uvsA[aLength] = uvB; normalsA[aLength] = normB; tangentsA[aLength] = tB; aLength++; indicesB[bLength] = iB; verticesB[bLength] = pB; uvsB[bLength] = uvB; normalsB[bLength] = normB; tangentsB[bLength] = tB; bLength++; cVerts.Add(pB.pos); if (!cVerts.Contains(pB.pos)) { cVerts.Add(pB.pos); } } } for (int i = 0; i < cVerts.Count - 1; i++) { MeshSlicer.debugEdges.Add(new Vector3[] { cVerts[i], cVerts[i + 1] }); } Triangle3D[] tris; if (aLength > 3 || bLength > 3) { tris = new Triangle3D[3]; } else { tris = new Triangle3D[2]; } tris[0] = new Triangle3D(triangle.meshVertices, new Triangle3D.Vertex[] { verticesA[0], verticesA[1], verticesA[2] }, new Vector3[] { normalsA[0], normalsA[1], normalsA[2] }, new Vector2[] { uvsA[0], uvsA[1], uvsA[2] }, new Vector4[] { tangentsA[0], tangentsA[1], tangentsA[2] }, new int[] { indicesA[0], indicesA[1], indicesA[2] }, triangle.subMeshGroup); tris[1] = new Triangle3D(triangle.meshVertices, new Triangle3D.Vertex[] { verticesB[0], verticesB[1], verticesB[2] }, new Vector3[] { normalsB[0], normalsB[1], normalsB[2] }, new Vector2[] { uvsB[0], uvsB[1], uvsB[2] }, new Vector4[] { tangentsB[0], tangentsB[1], tangentsB[2] }, new int[] { indicesB[0], indicesB[1], indicesB[2] }, triangle.subMeshGroup); if (aLength > 3) { tris[2] = new Triangle3D(triangle.meshVertices, new Triangle3D.Vertex[] { verticesA[0], verticesA[2], verticesA[3] }, new Vector3[] { normalsA[0], normalsA[2], normalsA[3] }, new Vector2[] { uvsA[0], uvsA[2], uvsA[3] }, new Vector4[] { tangentsA[0], tangentsA[2], tangentsA[3] }, new int[] { indicesA[0], indicesA[2], indicesA[3] }, triangle.subMeshGroup); } else if (bLength > 3) { tris[2] = new Triangle3D(triangle.meshVertices, new Triangle3D.Vertex[] { verticesB[0], verticesB[2], verticesB[3] }, new Vector3[] { normalsB[0], normalsB[2], normalsB[3] }, new Vector2[] { uvsB[0], uvsB[2], uvsB[3] }, new Vector4[] { tangentsB[0], tangentsB[2], tangentsB[3] }, new int[] { indicesB[0], indicesB[2], indicesB[3] }, triangle.subMeshGroup); } return(tris); }