public static Mesh Stitch(Polygons bottomLoop, double bottomHeight, Polygons topLoop, double topHeight, double scaling = 1000) { // only a bottom if (bottomLoop?.Count > 0 && (topLoop == null || topLoop.Count == 0)) { // if there is no top than we need to create a top return(CreateTop(bottomLoop, bottomHeight, scaling)); } // only a top if ((bottomLoop == null || bottomLoop.Count == 0) && topLoop.Count > 0) { // if there is no bottom than we need to create bottom return(CreateBottom(topLoop, topHeight, scaling)); } // simple bottom and top if (bottomLoop.Count == 1 && topLoop.Count == 1 && bottomLoop[0].Count == topLoop[0].Count) { var mesh = CreateSimpleWall(bottomLoop[0], bottomHeight * 1000, topLoop[0], topHeight * 1000); mesh.Transform(Matrix4X4.CreateScale(1 / scaling)); return(mesh); } var all = new Polygons(); all.AddRange(bottomLoop); all.AddRange(topLoop); all = all.GetCorrectedWinding(); var bevelLoop = all.CreateVertexStorage().TriangulateFaces(); for (var i = 0; i < bevelLoop.Vertices.Count; i++) { bevelLoop.Vertices[i] = bevelLoop.Vertices[i] + new Vector3Float(0, 0, 16); } return(bevelLoop); }
public static Mesh Extrude(this IVertexSource vertexSource, double zHeight) { Polygons polygons = vertexSource.CreatePolygons(); // ensure good winding and consistent shapes polygons = polygons.GetCorrectedWinding(); // convert the data back to PathStorage vertexSource = polygons.CreateVertexStorage(); CachedTesselator teselatedSource = new CachedTesselator(); Mesh mesh = vertexSource.TriangulateFaces(teselatedSource); int numIndicies = teselatedSource.IndicesCache.Count; mesh.Translate(new Vector3(0, 0, zHeight)); // then the outside edge for (int i = 0; i < numIndicies; i += 3) { Vector2 v0 = teselatedSource.VerticesCache[teselatedSource.IndicesCache[i + 0].Index].Position; Vector2 v1 = teselatedSource.VerticesCache[teselatedSource.IndicesCache[i + 1].Index].Position; Vector2 v2 = teselatedSource.VerticesCache[teselatedSource.IndicesCache[i + 2].Index].Position; if (v0 == v1 || v1 == v2 || v2 == v0) { continue; } var bottomVertex0 = new Vector3(v0, 0); var bottomVertex1 = new Vector3(v1, 0); var bottomVertex2 = new Vector3(v2, 0); var topVertex0 = new Vector3(v0, zHeight); var topVertex1 = new Vector3(v1, zHeight); var topVertex2 = new Vector3(v2, zHeight); if (teselatedSource.IndicesCache[i + 0].IsEdge) { mesh.CreateFace(new Vector3[] { bottomVertex0, bottomVertex1, topVertex1, topVertex0 }); } if (teselatedSource.IndicesCache[i + 1].IsEdge) { mesh.CreateFace(new Vector3[] { bottomVertex1, bottomVertex2, topVertex2, topVertex1 }); } if (teselatedSource.IndicesCache[i + 2].IsEdge) { mesh.CreateFace(new Vector3[] { bottomVertex2, bottomVertex0, topVertex0, topVertex2 }); } } // then the bottom for (int i = 0; i < numIndicies; i += 3) { Vector2 v0 = teselatedSource.VerticesCache[teselatedSource.IndicesCache[i + 0].Index].Position; Vector2 v1 = teselatedSource.VerticesCache[teselatedSource.IndicesCache[i + 1].Index].Position; Vector2 v2 = teselatedSource.VerticesCache[teselatedSource.IndicesCache[i + 2].Index].Position; if (v0 == v1 || v1 == v2 || v2 == v0) { continue; } mesh.CreateFace(new Vector3[] { new Vector3(v2, 0), new Vector3(v1, 0), new Vector3(v0, 0) }); } mesh.CleanAndMerge(); return(mesh); }