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); }
public static Triangle3D[] SplitTriangleWithPlane(Triangle3D triangle, Plane plane, float e, out ClassificationUtil.Classification side) { return(SplitTriangleWithPlane(triangle, plane, e, out side, true)); }
public static void SplitTriangleWithPlane(ref int vertexCount, Vector3[] points, int[] indices, Plane plane, float e, out ClassificationUtil.Classification side, bool cap, out int[] newTris, out Vector3[] newPoints) { ClassificationUtil.Classification[] classes; side = ClassificationUtil.ClassifyPoints(points, plane, out classes, e); if (side != ClassificationUtil.Classification.STRADDLE) { if (cap) { SetEdgeHash(0, 1, classes, points); SetEdgeHash(1, 2, classes, points); SetEdgeHash(2, 0, classes, points); } newTris = null; newPoints = null; return; } int totalVertexCount = vertexCount; //int iA; Vector3 pA; //Vector3 normA; //Vector2 uvA; //Vector4 tA; uint aLength = 0; int[] indicesA = new int[4]; Vector3[] verticesA = new Vector3[4]; //Vector3[] normalsA = new Vector3[4]; //Vector2[] uvsA = new Vector2[4]; //Vector4[] tangentsA = new Vector4[4]; int iB; Vector3 pB; //Vector3 normB; //Vector2 uvB; //Vector4 tB; uint bLength = 0; int[] indicesB = new int[4]; Vector3[] verticesB = new Vector3[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 = triangles; //Triangle3D.Vertex[] points //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]); } 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, pB, plane, e, null); if (isect.status != Intersection.IntersectionType.INTERSECTION) { SplitTriangleWithPlane(ref totalVertexCount, points, indices, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap, out newTris, out newPoints); } indicesA[aLength] = totalVertexCount; indicesB[bLength] = totalVertexCount; totalVertexCount++; verticesA[aLength] = isect.vert; verticesB[bLength] = 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, pB, plane, e, null); if (isect.status != Intersection.IntersectionType.INTERSECTION) { SplitTriangleWithPlane(ref totalVertexCount, points, indices, new Plane(plane.normal, plane.distance + 1.0f), e, out side, cap, out newTris, out newPoints); } indicesA[aLength] = totalVertexCount; indicesB[bLength] = totalVertexCount; totalVertexCount++; verticesA[aLength] = isect.vert; verticesB[bLength] = 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); if (!cVerts.Contains(pB)) { cVerts.Add(pB); } } } for (int i = 0; i < cVerts.Count - 1; i++) { MeshSlicer.debugEdges.Add(new Vector3[] { cVerts[i], cVerts[i + 1] }); } if (aLength > 3 || bLength > 3) { newTris = new int[3 * 3]; newPoints = new Vector3[3 * 3]; } else { newTris = new int[3 * 2]; newPoints = new Vector3[3 * 2]; } newPoints[0] = verticesA[0]; newPoints[1] = verticesA[1]; newPoints[2] = verticesA[2]; newTris[0] = indicesA[0]; newTris[1] = indicesA[1]; newTris[2] = indicesA[2]; newPoints[3] = verticesB[0]; newPoints[4] = verticesB[1]; newPoints[5] = verticesB[2]; newTris[3] = indicesB[0]; newTris[4] = indicesB[1]; newTris[5] = indicesB[2]; if (aLength > 3) { newPoints[6] = verticesA[0]; newPoints[7] = verticesA[2]; newPoints[8] = verticesA[3]; newTris[6] = indicesA[0]; newTris[7] = indicesA[2]; newTris[8] = indicesA[3]; } else if (bLength > 3) { newPoints[6] = verticesB[0]; newPoints[7] = verticesB[2]; newPoints[8] = verticesB[3]; newTris[6] = indicesB[0]; newTris[7] = indicesB[2]; newTris[8] = indicesB[3]; } vertexCount = totalVertexCount; }
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); }