public Mesh ToMesh(Facing facing = Facing.Normal, GlobalSurfaceType surfaceType = GlobalSurfaceType.Normal) { Mesh mesh = new Mesh(); ToMesh(mesh, facing, surfaceType); return(mesh); }
public void ToMesh(Mesh mesh, Facing facing = Facing.Normal, GlobalSurfaceType surfaceType = GlobalSurfaceType.Normal) { var indexByVertexKey = new Dictionary <Vertex, SortedDictionary <VertexKey, int> >(); var trigs = new List <int>(); var verts = new List <Vector3>(); var norms = new List <Vector3>(); var meshuv = new List <Vector2>(); var vertexKeyComparer = new VertexKeyComparer(); int MeshVertex(Halfedge e, Vector3 normal) { if (!indexByVertexKey.TryGetValue(e.vertex, out SortedDictionary <VertexKey, int> indices)) { indices = new SortedDictionary <VertexKey, int>(vertexKeyComparer); indexByVertexKey[e.vertex] = indices; } VertexKey key = new VertexKey(normal, GetUV(e)); if (!indices.TryGetValue(key, out int index)) { index = verts.Count; verts.Add(e.vertex.p); norms.Add(normal); meshuv.Add(GetUV(e)); indices.Add(key, index); } return(index); } int MeshVertexEdgeNormal(Halfedge e) { return(MeshVertex(e, GetNormal(e))); } if (surfaceType == GlobalSurfaceType.AutoSmoothAll || surfaceType == GlobalSurfaceType.SplitTriangleAll) { // No vertex duplication. foreach (Face f in faces) { List <Halfedge> edges = f.edges; int p1 = 0; int p2 = edges.Count - 1; while (p2 - p1 > 1) { trigs.Add(edges[p1].vertex.index); trigs.Add(edges[p1 + 1].vertex.index); trigs.Add(edges[p2].vertex.index); p1++; if (p2 - p1 <= 1) { break; } trigs.Add(edges[p1].vertex.index); trigs.Add(edges[p2 - 1].vertex.index); trigs.Add(edges[p2].vertex.index); p2--; } } mesh.vertices = vertices.Select(v => v.p).ToArray(); mesh.triangles = trigs.ToArray(); } else { foreach (Face f in faces) { FaceType faceType = GetFaceType(f); List <Halfedge> edges = f.edges; if (surfaceType == GlobalSurfaceType.HardPolygonAll || faceType == FaceType.Polygonal) { Vector3 normal = f.CalculateNormal(); int p1 = 0; int p2 = edges.Count - 1; while (p2 - p1 > 1) { trigs.Add(MeshVertex(edges[p1], normal)); trigs.Add(MeshVertex(edges[p1 + 1], normal)); trigs.Add(MeshVertex(edges[p2], normal)); p1++; if (p2 - p1 <= 1) { break; } trigs.Add(MeshVertex(edges[p1], normal)); trigs.Add(MeshVertex(edges[p2 - 1], normal)); trigs.Add(MeshVertex(edges[p2], normal)); p2--; } } else if (surfaceType == GlobalSurfaceType.HardTriangleAll || faceType == FaceType.Triangular) { int p1 = 0; int p2 = edges.Count - 1; while (p2 - p1 > 1) { Vector3 normal1 = Vector3.Cross(edges[p1 + 1].vertex.p - edges[p1].vertex.p, edges[p2].vertex.p - edges[p1].vertex.p).normalized; trigs.Add(MeshVertex(edges[p1], normal1)); trigs.Add(MeshVertex(edges[p1 + 1], normal1)); trigs.Add(MeshVertex(edges[p2], normal1)); p1++; if (p2 - p1 <= 1) { break; } Vector3 normal2 = Vector3.Cross(edges[p2 - 1].vertex.p - edges[p1].vertex.p, edges[p2].vertex.p - edges[p1].vertex.p).normalized; trigs.Add(MeshVertex(edges[p1], normal2)); trigs.Add(MeshVertex(edges[p2 - 1], normal2)); trigs.Add(MeshVertex(edges[p2], normal2)); p2--; } } else if (faceType == FaceType.Smooth) { int p1 = 0; int p2 = edges.Count - 1; while (p2 - p1 > 1) { trigs.Add(MeshVertexEdgeNormal(edges[p1])); trigs.Add(MeshVertexEdgeNormal(edges[p1 + 1])); trigs.Add(MeshVertexEdgeNormal(edges[p2])); p1++; if (p2 - p1 <= 1) { break; } trigs.Add(MeshVertexEdgeNormal(edges[p1])); trigs.Add(MeshVertexEdgeNormal(edges[p2 - 1])); trigs.Add(MeshVertexEdgeNormal(edges[p2])); p2--; } } else if (faceType == FaceType.Directinal1 || faceType == FaceType.Directinal2) { if (edges.Count > 4) { throw new Exception("Directional smooth can only apply to quad or triangle faces!"); } Vector3[] localNormals = edges.Select((e, i) => CalculateDirectionalNormal(e, faceType, i, edges.Count)).ToArray(); if (edges.Count == 4) { trigs.Add(MeshVertex(edges[0], localNormals[0])); trigs.Add(MeshVertex(edges[1], localNormals[1])); trigs.Add(MeshVertex(edges[3], localNormals[3])); trigs.Add(MeshVertex(edges[1], localNormals[1])); trigs.Add(MeshVertex(edges[2], localNormals[2])); trigs.Add(MeshVertex(edges[3], localNormals[3])); } else { trigs.Add(MeshVertex(edges[0], localNormals[0])); trigs.Add(MeshVertex(edges[1], localNormals[1])); trigs.Add(MeshVertex(edges[2], localNormals[2])); } } } mesh.vertices = verts.ToArray(); mesh.triangles = trigs.ToArray(); mesh.normals = norms.ToArray(); mesh.uv = meshuv.ToArray(); } if (facing != Facing.Normal || surfaceType == GlobalSurfaceType.SplitTriangleAll) { // Extra processing through mesh builder. MeshBuilder meshBuilder = new MeshBuilder(mesh); if (facing == Facing.Flipped) { meshBuilder.Invert(); } else if (facing == Facing.TwoSided) { meshBuilder.AddOtherSide(); } if (surfaceType == GlobalSurfaceType.SplitTriangleAll) { meshBuilder.SplitAllTriangles(); } meshBuilder.ToMesh(mesh); } // Finalize the mesh. if (surfaceType == GlobalSurfaceType.AutoSmoothAll) { mesh.RecalculateNormals(); } mesh.RecalculateBounds(); }