/// <summary> /// /// </summary> /// <param name="polygon">Polygon to triangulate</param> /// <param name="verticesCount">lenght of the vertexList of the mesh that has been sliced - 1</param> public static FinishedPolygon Triangulate(PolygonCreator polygon, int verticesCount) { FinishedPolygon finishedPolygon = new FinishedPolygon(); //polygon creator has outlines and holes; //for each outline we need a seperate polygon to triangulate for (int i = 0; i < polygon.Outlines.Count; i++) { EarClippingPolygon earClipPoly = new EarClippingPolygon(new PolygonMetaData(polygon.Outlines[i])); for (int j = 0; j < polygon.Holes.Count; j++) { if (polygon.Holes[j].Parent == polygon.Outlines[i].ID) { earClipPoly.AddHole(new PolygonMetaData(polygon.Holes[j])); } } //outline is combined with hole(s) if any and is ready to be earclipped //add triangle offset to make up for vertices that are already inside the mesh int triangleOffsetIndex = verticesCount + finishedPolygon.vertices.Count; Earclipping earClipper = new Earclipping(earClipPoly, triangleOffsetIndex); earClipper.ClipEars(); finishedPolygon.triangles.AddRange(earClipper.Triangles); finishedPolygon.uv.AddRange(earClipper.UV); finishedPolygon.vertices.AddRange(earClipper.Vertices); for (int n = 0; n < earClipper.Vertices.Count; n++) { finishedPolygon.normals.Add(polygon.Normal); } } return(finishedPolygon); }
private List <SlicedMesh> GenerateMesh(SlicedMesh original, Plane plane, bool positiveSide, Transform objectTransform) { SlicedMesh slicePositive = new SlicedMesh(); SlicedMesh sliceNegative = new SlicedMesh(); //polygon we use to fill in the sliced surface PolygonCreator polygonPositive = new PolygonCreator(objectTransform, plane.normal * -1); PolygonCreator polygonNegative = new PolygonCreator(objectTransform, plane.normal); bool matPositiveAdded = false, matNegativeAdded = false; //we loop over all submeshes for (int submesh = 0; submesh < original.triangles.Length; submesh++) { int[] originalTriangles = original.triangles[submesh]; setEdge = false; //increase t by 3 because a triangle consist out of 3 vertices; for (int t = 0; t < originalTriangles.Length; t += 3) { //which triangle we need int t1 = t, t2 = t + 1, t3 = t + 2; //Check if vertice is on positive side of the plane bool sideA = plane.GetSide(original.vertices[originalTriangles[t1]]) == positiveSide; bool sideB = plane.GetSide(original.vertices[originalTriangles[t2]]) == positiveSide; bool sideC = plane.GetSide(original.vertices[originalTriangles[t3]]) == positiveSide; //how many vertices are on the positive side of the plane int sideCount = (sideA ? 1 : 0) + (sideB ? 1 : 0) + (sideC ? 1 : 0); //if none of the vertices is located on the positive side if (sideCount == 0) { //add entire triangle to negative side sliceNegative.AddTriangle(submesh, original.vertices[originalTriangles[t1]], original.vertices[originalTriangles[t2]], original.vertices[originalTriangles[t3]], original.normals[originalTriangles[t1]], original.normals[originalTriangles[t2]], original.normals[originalTriangles[t3]], original.uv[originalTriangles[t1]], original.uv[originalTriangles[t2]], original.uv[originalTriangles[t3]]); if (!matNegativeAdded) { matNegativeAdded = true; sliceNegative.materialIndex.Add(submesh); } continue; } //if all the vertices are located on the positive side else if (sideCount == 3) { //add entire triangle to positive side slicePositive.AddTriangle(submesh, original.vertices[originalTriangles[t1]], original.vertices[originalTriangles[t2]], original.vertices[originalTriangles[t3]], original.normals[originalTriangles[t1]], original.normals[originalTriangles[t2]], original.normals[originalTriangles[t3]], original.uv[originalTriangles[t1]], original.uv[originalTriangles[t2]], original.uv[originalTriangles[t3]]); if (!matPositiveAdded) { matPositiveAdded = true; slicePositive.materialIndex.Add(submesh); } continue; } //else a triangle is cut and submesh material must be added to both sides if (!matNegativeAdded) { matNegativeAdded = true; sliceNegative.materialIndex.Add(submesh); } if (!matPositiveAdded) { matPositiveAdded = true; slicePositive.materialIndex.Add(submesh); } //determines which vertex in the triangle is solely located on one side of the plane int singleIndex = sideB == sideC ? 0 : sideA == sideC ? 1 : 2; int indexB = t + ((singleIndex + 1) % 3), indexC = t + ((singleIndex + 2) % 3); singleIndex += t; //calculate which vertices/normals/uv should be used to calculate intersection points Vector3 singleVertex = original.vertices[originalTriangles[singleIndex]], vertexB = original.vertices[originalTriangles[indexB]], //right vertex vertexC = original.vertices[originalTriangles[indexC]]; //left vertex Vector3 singleNormal = original.normals[originalTriangles[singleIndex]], normalB = original.normals[originalTriangles[indexB]], normalC = original.normals[originalTriangles[indexC]]; Vector2 singleUv = original.uv[originalTriangles[singleIndex]], uvB = original.uv[originalTriangles[indexB]], uvC = original.uv[originalTriangles[indexC]]; //calculate new vertices/normals/uv where edge intersects plane float lerpB, lerpC; Vector3 newVertexB = PointOnPlane(plane, singleVertex, vertexB, out lerpB), //new right vertex newVertexC = PointOnPlane(plane, singleVertex, vertexC, out lerpC); //new left vertex Vector3 newNormalB = Vector3.Lerp(singleNormal, normalB, lerpB), //lerp to get the point between the old vertices where the new vertex is located newNormalC = Vector3.Lerp(singleNormal, normalC, lerpC); Vector2 newUvB = Vector2.Lerp(singleUv, uvB, lerpB), newUvC = Vector2.Lerp(singleUv, uvC, lerpC); if (!concave) { //add and edge to "fill" the mesh AddSliceTriangle(submesh, slicePositive, newVertexB, newVertexC, plane.normal * -1, newUvB, newUvC); AddSliceTriangle(submesh, sliceNegative, newVertexB, newVertexC, plane.normal, newUvB, newUvC); } if (sideCount == 1) { //positive data slicePositive.AddTriangle(submesh, singleVertex, newVertexB, newVertexC, singleNormal, newNormalB, newNormalC, singleUv, newUvB, newUvC); //negative data sliceNegative.AddTriangle(submesh, newVertexB, vertexB, vertexC, newNormalB, normalB, normalC, newUvB, uvB, uvC); sliceNegative.AddTriangle(submesh, newVertexB, vertexC, newVertexC, newNormalB, normalC, newNormalC, newUvB, uvC, newUvC); if (concave) { //positive Edge edgePositive = new Edge(newVertexB, newVertexC, plane.normal * -1, newUvB, newUvC); polygonPositive.AddEdge(edgePositive); //negative Edge edgeNegative = new Edge(newVertexC, newVertexB, plane.normal, newUvC, newUvB); polygonNegative.AddEdge(edgeNegative); } continue; } else if (sideCount == 2) { //positive data slicePositive.AddTriangle(submesh, newVertexB, vertexB, vertexC, newNormalB, normalB, normalC, newUvB, uvB, uvC); slicePositive.AddTriangle(submesh, newVertexB, vertexC, newVertexC, newNormalB, normalC, newNormalC, newUvB, uvC, newUvC); //negative data sliceNegative.AddTriangle(submesh, singleVertex, newVertexB, newVertexC, singleNormal, newNormalB, newNormalC, singleUv, newUvB, newUvC); if (concave) { //positive Edge edgePositive = new Edge(newVertexC, newVertexB, plane.normal * -1, newUvC, newUvB); polygonPositive.AddEdge(edgePositive); //negative Edge edgeNegative = new Edge(newVertexB, newVertexC, plane.normal, newUvB, newUvC); polygonNegative.AddEdge(edgeNegative); } continue; } } } if (concave) { //build polygons polygonPositive.ConnectEdges(); polygonNegative.ConnectEdges(); //build meshdata for polygons FinishedPolygon polygonPositiveFinished = Triangulation.Triangulate(polygonPositive, slicePositive.VertexCount); FinishedPolygon polygonNegativeFinished = Triangulation.Triangulate(polygonNegative, sliceNegative.VertexCount); //add meshdata to slices slicePositive.AddPolygon(polygonPositiveFinished); sliceNegative.AddPolygon(polygonNegativeFinished); } slicePositive.FillArray(correctData); sliceNegative.FillArray(correctData); return(new List <SlicedMesh>() { slicePositive, sliceNegative }); }