public static GameObject Update(this GameObject go, Element element, UnityEngine.Material material) { var goMeshFilter = go.GetComponent <MeshFilter>(); var goRenderer = go.GetComponent <MeshRenderer>(); goRenderer.material = material; var goMesh = goMeshFilter.mesh; goMesh.Clear(); // var o = element.Transform.Origin.ToUnityVector3(); var verts = new List <UnityEngine.Vector3>(); var tris = new List <int>(); if (element is IGeometry3D) { var tess = (IGeometry3D)element; var mesh = new Elements.Geometry.Mesh(); tess.Geometry[0].Tessellate(ref mesh); verts.AddRange(mesh.Vertices.ToArray().ToUnityVertices(element.Transform)); tris.AddRange(mesh.Indices.Select(idx => (int)idx)); } goMesh.vertices = verts.ToArray(); goMesh.triangles = tris.ToArray(); goMesh.RecalculateNormals(); return(go); }
public static GameObject ToGameObject(this Element element, GameObject parent, UnityEngine.Material material) { var go = new GameObject($"hypar_{element.Id}"); var goMeshFilter = go.AddComponent <MeshFilter>(); var goRenderer = go.AddComponent <MeshRenderer>(); goRenderer.material = material; var goMesh = new UnityEngine.Mesh(); goMeshFilter.mesh = goMesh; go.transform.SetParent(parent.transform, false); var verts = new List <UnityEngine.Vector3>(); var tris = new List <int>(); if (element is IGeometry3D) { var geo = (IGeometry3D)element; var mesh = new Elements.Geometry.Mesh(); geo.Geometry[0].Tessellate(ref mesh); verts.AddRange(mesh.Vertices.ToArray().ToUnityVertices(element.Transform)); tris.AddRange(mesh.Indices.Select(idx => (int)idx)); } goMesh.vertices = verts.ToArray(); goMesh.triangles = tris.ToArray(); goMesh.RecalculateNormals(); return(go); }
private void GetRenderDataForElement(IElement e, Gltf gltf, Dictionary <string, int> materials, List <Vector3> lines) { if (e is IGeometry3D) { var geo = e as IGeometry3D; Elements.Geometry.Mesh mesh = null; foreach (var solid in geo.Geometry) { foreach (var edge in solid.Edges.Values) { if (e.Transform != null) { lines.AddRange(new[] { e.Transform.OfVector(edge.Left.Vertex.Point), e.Transform.OfVector(edge.Right.Vertex.Point) }); } else { lines.AddRange(new[] { edge.Left.Vertex.Point, edge.Right.Vertex.Point }); } } mesh = new Elements.Geometry.Mesh(); solid.Tessellate(ref mesh); gltf.AddTriangleMesh(e.Id + "_mesh", _buffer, mesh.Vertices.ToArray(), mesh.Normals.ToArray(), mesh.Indices.ToArray(), mesh.VMin, mesh.VMax, mesh.NMin, mesh.NMax, mesh.IMin, mesh.IMax, materials[solid.Material.Name], null, e.Transform); } } if (e is IAggregateElement) { var ae = (IAggregateElement)e; if (ae.Elements.Count > 0) { foreach (var esub in ae.Elements) { GetRenderDataForElement(esub, gltf, materials, lines); } } } }
public static Elements.Geometry.Mesh ToMesh(this MeshData vMesh) { var mesh = new Elements.Geometry.Mesh(); var vertices = new List <Vertex>(); for (int i = 0; i < vMesh.points.length; i++) { var pt = (vMesh.points[i] as Array <double>).ToVector3(); var normal = (vMesh.normals[i] as Array <double>).ToVector3(); var vertex = new Vertex(pt, normal); vertices.Add(vertex); mesh.AddVertex(vertex); } Console.WriteLine(vertices.Count); for (int i = 0; i < vMesh.faces.length; i++) { var face = vMesh.faces[i] as Array <int>; mesh.AddTriangle(vertices[face[2]], vertices[face[1]], vertices[face[0]]); } return(mesh); }
/// <summary> /// Generates a Roof from a DXF Polyline and supplied elevation and thickness values. /// </summary> /// <param name="model">The input model.</param> /// <param name="input">The arguments to the execution.</param> /// <returns>A RoofByDXFOutputs instance containing computed results and the model with any new elements.</returns> public static RoofByDXFOutputs Execute(Dictionary <string, Model> inputModels, RoofByDXFInputs input) { DxfFile dxfFile; using (FileStream fs = new FileStream(input.DXF.LocalFilePath, FileMode.Open)) { dxfFile = DxfFile.Load(fs); } var polygons = new List <Polygon>(); foreach (DxfEntity entity in dxfFile.Entities) { if (entity.EntityType != DxfEntityType.LwPolyline) { continue; } var pline = (DxfLwPolyline)entity; if (pline.IsClosed == false) { continue; } var vertices = pline.Vertices.ToList(); var verts = new List <Vector3>(); vertices.ForEach(v => verts.Add(new Vector3(v.X, v.Y))); polygons.Add(new Polygon(verts)); } if (polygons.Count == 0) { throw new ArgumentException("No LWPolylines found in DXF."); } var highPoint = input.RoofElevation + input.RoofThickness; polygons = polygons.OrderByDescending(p => Math.Abs(p.Area())).ToList(); var polygon = polygons.First().IsClockWise() ? polygons.First().Reversed() : polygons.First(); polygon = polygon.TransformedPolygon(new Transform(0.0, 0.0, highPoint)); var underBoundary = polygon.TransformedPolygon(new Transform(0.0, 0.0, input.RoofThickness * -1.0)); var ePoints = polygon.Vertices.ToList(); var uPoints = underBoundary.Vertices.ToList(); var topSide = polygon.ToMesh(true); var underSide = underBoundary.ToMesh(false); var sideTriangles = new List <Elements.Geometry.Triangle>(); for (var i = 0; i < ePoints.Count; i++) { sideTriangles.Add(new Elements.Geometry.Triangle(new Vertex(ePoints[i]), new Vertex(uPoints[i]), new Vertex(uPoints[(i + 1) % uPoints.Count]))); sideTriangles.Add(new Elements.Geometry.Triangle(new Vertex(ePoints[i]), new Vertex(uPoints[(i + 1) % uPoints.Count]), new Vertex(ePoints[(i + 1) % ePoints.Count]))); } // Create an aggregated list of Triangles representing the Roof envelope. var envTriangles = new List <Elements.Geometry.Triangle>(); topSide.Triangles.ForEach(t => envTriangles.Add(t)); underSide.Triangles.ForEach(t => envTriangles.Add(t)); sideTriangles.ForEach(t => envTriangles.Add(t)); // Create an aggregated list of Vertices representing the Roof envelope. var enVertices = new List <Vertex>(); envTriangles.ForEach(t => enVertices.AddRange(t.Vertices)); // Construct the roof envelope in Elements.Geometry.mesh form. var Envelope = new Elements.Geometry.Mesh(); envTriangles.ForEach(t => Envelope.AddTriangle(t)); enVertices.ForEach(v => Envelope.AddVertex(v)); Envelope.ComputeNormals(); // Construct serializable topside mesh var triangles = new List <triangles>(); var indices = new List <vertices>(); var tsIV = topSide.ToIndexedVertices(); tsIV.triangles.ForEach(t => triangles.Add(new triangles(t))); tsIV.vertices.ForEach(v => indices.Add(new vertices(v.index, v.isBoundary, v.position))); var topside = new Elements.Mesh(triangles, indices); // Construct serializable underside mesh triangles.Clear(); indices.Clear(); var usIV = underSide.ToIndexedVertices(); usIV.triangles.ForEach(t => triangles.Add(new triangles(t))); usIV.vertices.ForEach(v => indices.Add(new vertices(v.index, v.isBoundary, v.position))); var underside = new Elements.Mesh(triangles, indices); // Construct serializable envelope mesh triangles.Clear(); indices.Clear(); var enIV = Envelope.ToIndexedVertices(); enIV.triangles.ForEach(t => triangles.Add(new triangles(t))); enIV.vertices.ForEach(v => indices.Add(new vertices(v.index, v.isBoundary, v.position))); var envelope = new Elements.Mesh(triangles, indices); var roof = new Roof( envelope, topside, underside, underBoundary, input.RoofElevation, highPoint, input.RoofThickness, polygon.Area(), new Transform(), BuiltInMaterials.Concrete, null, false, Guid.NewGuid(), "Roof"); var output = new RoofByDXFOutputs(polygon.Area()); output.Model.AddElement(new MeshElement(Envelope, BuiltInMaterials.Concrete)); output.Model.AddElement(roof); return(output); }
internal static void ToGlb(this Solid solid, string path) { var gltf = new Gltf(); var asset = new Asset(); asset.Version = "2.0"; asset.Generator = "hypar-gltf"; gltf.Asset = asset; var root = new Node(); root.Translation = new[] { 0.0f, 0.0f, 0.0f }; root.Scale = new[] { 1.0f, 1.0f, 1.0f }; // Set Z up by rotating -90d around the X Axis var q = new Quaternion(new Vector3(1, 0, 0), -Math.PI / 2); root.Rotation = new[] { (float)q.X, (float)q.Y, (float)q.Z, (float)q.W }; gltf.Nodes = new[] { root }; gltf.Scene = 0; var scene = new Scene(); scene.Nodes = new[] { 0 }; gltf.Scenes = new[] { scene }; gltf.ExtensionsUsed = new[] { "KHR_materials_pbrSpecularGlossiness" }; var materials = gltf.AddMaterials(new[] { BuiltInMaterials.Default, BuiltInMaterials.Edges, BuiltInMaterials.EdgesHighlighted }); var buffer = new List <byte>(); var mesh = new Elements.Geometry.Mesh(); solid.Tessellate(ref mesh); gltf.AddTriangleMesh("mesh", buffer, mesh.Vertices.ToArray(), mesh.Normals.ToArray(), mesh.Indices.ToArray(), mesh.VertexColors.ToArray(), mesh.VMin, mesh.VMax, mesh.NMin, mesh.NMax, mesh.CMin, mesh.CMax, mesh.IMin, mesh.IMax, materials[BuiltInMaterials.Default.Name], null, null); var edgeCount = 0; var vertices = new List <Vector3>(); var verticesHighlighted = new List <Vector3>(); foreach (var e in solid.Edges.Values) { if (e.Left.Loop == null || e.Right.Loop == null) { verticesHighlighted.AddRange(new[] { e.Left.Vertex.Point, e.Right.Vertex.Point }); } else { vertices.AddRange(new[] { e.Left.Vertex.Point, e.Right.Vertex.Point }); } edgeCount++; } if (vertices.Count > 0) { // Draw standard edges var vBuff = vertices.ToArray().ToArray(); var vCount = vertices.Count; // var indices = Enumerable.Range(0, vCount).Select(i => (ushort)i).ToArray(); var indices = new List <ushort>(); for (var i = 0; i < vertices.Count; i += 2) { indices.Add((ushort)i); indices.Add((ushort)(i + 1)); } var bbox = new BBox3(vertices.ToArray()); gltf.AddLineLoop($"edge_{edgeCount}", buffer, vBuff, indices.ToArray(), bbox.Min.ToArray(), bbox.Max.ToArray(), 0, (ushort)(vCount - 1), materials[BuiltInMaterials.Edges.Name], MeshPrimitive.ModeEnum.LINES, null); } if (verticesHighlighted.Count > 0) { // Draw highlighted edges var vBuff = vertices.ToArray().ToArray(); var vCount = vertices.Count; var indices = new List <ushort>(); for (var i = 0; i < vertices.Count; i += 2) { indices.Add((ushort)i); indices.Add((ushort)(i + 1)); } var bbox = new BBox3(vertices.ToArray()); gltf.AddLineLoop($"edge_{edgeCount}", buffer, vBuff, indices.ToArray(), bbox.Min.ToArray(), bbox.Max.ToArray(), 0, (ushort)(vCount - 1), materials[BuiltInMaterials.EdgesHighlighted.Name], MeshPrimitive.ModeEnum.LINES, null); } var buff = new glTFLoader.Schema.Buffer(); buff.ByteLength = buffer.Count; gltf.Buffers = new[] { buff }; if (File.Exists(path)) { File.Delete(path); } gltf.SaveBinaryModel(buffer.ToArray(), path); }
private static void GetRenderDataForElement(IElement e, Gltf gltf, Dictionary <string, int> materials, List <Vector3> lines, List <byte> buffer) { if (e is IGeometry3D) { var geo = e as IGeometry3D; Elements.Geometry.Mesh mesh = null; foreach (var solid in geo.Geometry) { foreach (var edge in solid.Edges.Values) { if (e.Transform != null) { lines.AddRange(new[] { e.Transform.OfPoint(edge.Left.Vertex.Point), e.Transform.OfPoint(edge.Right.Vertex.Point) }); } else { lines.AddRange(new[] { edge.Left.Vertex.Point, edge.Right.Vertex.Point }); } } mesh = new Elements.Geometry.Mesh(); solid.Tessellate(ref mesh); double[] vertexBuffer; double[] normalBuffer; ushort[] indexBuffer; float[] colorBuffer; double[] vmin; double[] vmax; double[] nmin; double[] nmax; float[] cmin; float[] cmax; ushort imin; ushort imax; mesh.GetBuffers(out vertexBuffer, out indexBuffer, out normalBuffer, out colorBuffer, out vmax, out vmin, out nmin, out nmax, out cmin, out cmax, out imin, out imax); gltf.AddTriangleMesh(e.Id + "_mesh", buffer, vertexBuffer, normalBuffer, indexBuffer, colorBuffer, vmin, vmax, nmin, nmax, imin, imax, materials[solid.Material.Name], cmin, cmax, null, e.Transform); } } if (e is ITessellate) { var geo = (ITessellate)e; var mesh = new Elements.Geometry.Mesh(); geo.Tessellate(ref mesh); double[] vertexBuffer; double[] normalBuffer; ushort[] indexBuffer; float[] colorBuffer; double[] vmin; double[] vmax; double[] nmin; double[] nmax; float[] cmin; float[] cmax; ushort imin; ushort imax; mesh.GetBuffers(out vertexBuffer, out indexBuffer, out normalBuffer, out colorBuffer, out vmax, out vmin, out nmin, out nmax, out cmin, out cmax, out imin, out imax); gltf.AddTriangleMesh(e.Id + "_mesh", buffer, vertexBuffer, normalBuffer, indexBuffer, colorBuffer, vmin, vmax, nmin, nmax, imin, imax, materials[((IMaterial)e).Material.Name], cmin, cmax, null, e.Transform); } if (e is IAggregateElement) { var ae = (IAggregateElement)e; if (ae.Elements.Count > 0) { foreach (var esub in ae.Elements) { GetRenderDataForElement(esub, gltf, materials, lines, buffer); } } } }
private static void ProcessSolid(Solid solid, Transform t, string id, string materialName, ref Gltf gltf, ref Dictionary <string, int> materials, ref List <List <Vector3> > lines, ref List <byte> buffer, List <BufferView> bufferViews, List <Accessor> accessors) { Elements.Geometry.Mesh mesh = null; var currLines = lines.Last(); foreach (var edge in solid.Edges.Values) { // Check if we'll overrun the index size // for the current line array. If so, // create a new line array. if (currLines.Count + 2 > ushort.MaxValue) { // Console.WriteLine($"Creating new line array at {currLines.Count}."); currLines = new List <Vector3>(); lines.Add(currLines); } if (t != null) { currLines.AddRange(new[] { t.OfPoint(edge.Left.Vertex.Point), t.OfPoint(edge.Right.Vertex.Point) }); } else { currLines.AddRange(new[] { edge.Left.Vertex.Point, edge.Right.Vertex.Point }); } } // var sw = new Stopwatch(); // sw.Start(); mesh = new Elements.Geometry.Mesh(); solid.Tessellate(ref mesh); // sw.Stop(); // Console.WriteLine($"glTF:\t\t{sw.Elapsed} for tessellating the solid."); // sw.Reset(); // sw.Start(); byte[] vertexBuffer; byte[] normalBuffer; byte[] indexBuffer; byte[] colorBuffer; double[] vmin; double[] vmax; double[] nmin; double[] nmax; float[] cmin; float[] cmax; ushort imin; ushort imax; mesh.GetBuffers(out vertexBuffer, out indexBuffer, out normalBuffer, out colorBuffer, out vmax, out vmin, out nmin, out nmax, out cmin, out cmax, out imin, out imax); // sw.Stop(); // Console.WriteLine($"glTF:\t\t{sw.Elapsed} for getting the mesh buffers."); // sw.Reset(); // sw.Start(); gltf.AddTriangleMesh(id + "_mesh", buffer, bufferViews, accessors, vertexBuffer, normalBuffer, indexBuffer, colorBuffer, vmin, vmax, nmin, nmax, imin, imax, materials[materialName], cmin, cmax, null, t); // sw.Stop(); // Console.WriteLine($"glTF:\t\t{sw.Elapsed} for adding a triangle mesh."); // sw.Reset(); }
private static void GetRenderDataForElement(IElement e, Gltf gltf, Dictionary <string, int> materials, List <List <Vector3> > lines, List <byte> buffer, List <BufferView> bufferViews, List <Accessor> accessors) { // var sw = new Stopwatch(); // sw.Start(); if (e is IAggregateElements) { var ae = (IAggregateElements)e; if (ae.Elements.Count > 0) { for (var i = 0; i < ae.Elements.Count; i++) { var esub = ae.Elements[i]; GetRenderDataForElement(esub, gltf, materials, lines, buffer, bufferViews, accessors); } } } // sw.Stop(); // Console.WriteLine($"glTF:\t{sw.Elapsed} for processing aggregates"); // sw.Reset(); // sw.Start(); var materialName = BuiltInMaterials.Default.Name; if (e is IElementType <StructuralFramingType> ) { // Get the material from the framing type's material. materialName = ((IElementType <StructuralFramingType>)e).ElementType.Material.Name; } if (e is IElementType <WallType> ) { // Get the material from the first layer of the wall. materialName = ((IElementType <WallType>)e).ElementType.MaterialLayers[0].Material.Name; } if (e is IElementType <FloorType> ) { // Get the material from the first layer of the floor. materialName = ((IElementType <FloorType>)e).ElementType.MaterialLayers[0].Material.Name; } if (e is IMaterial) { // Get the material from the material property. materialName = ((IMaterial)e).Material.Name; } // sw.Stop(); // Console.WriteLine($"glTF:\t{sw.Elapsed} for getting the material name."); // sw.Reset(); // sw.Start(); Solid solid = null; if (e is ISolid) { // Element already has a solid representation. var geo = e as ISolid; solid = geo.GetUpdatedSolid(); } // sw.Stop(); // Console.WriteLine($"glTF:\t{sw.Elapsed} for updating element solids."); // sw.Reset(); // sw.Start(); if (solid != null) { ProcessSolid(solid, e.Transform, e.Id.ToString(), materialName, ref gltf, ref materials, ref lines, ref buffer, bufferViews, accessors); } // sw.Stop(); // Console.WriteLine($"glTF:\t{sw.Elapsed} for processing element solids."); // sw.Reset(); if (e is ITessellate) { var geo = (ITessellate)e; var mesh = new Elements.Geometry.Mesh(); geo.Tessellate(ref mesh); byte[] vertexBuffer; byte[] normalBuffer; byte[] indexBuffer; byte[] colorBuffer; double[] vmin; double[] vmax; double[] nmin; double[] nmax; float[] cmin; float[] cmax; ushort imin; ushort imax; mesh.GetBuffers(out vertexBuffer, out indexBuffer, out normalBuffer, out colorBuffer, out vmax, out vmin, out nmin, out nmax, out cmin, out cmax, out imin, out imax); gltf.AddTriangleMesh(e.Id + "_mesh", buffer, bufferViews, accessors, vertexBuffer, normalBuffer, indexBuffer, colorBuffer, vmin, vmax, nmin, nmax, imin, imax, materials[materialName], cmin, cmax, null, e.Transform); } }
internal static void ToGlb(this Solid solid, string path) { var gltf = new Gltf(); var asset = new Asset(); asset.Version = "2.0"; asset.Generator = "hypar-gltf"; gltf.Asset = asset; var root = new Node(); root.Translation = new[] { 0.0f, 0.0f, 0.0f }; root.Scale = new[] { 1.0f, 1.0f, 1.0f }; // Set Z up by rotating -90d around the X Axis var q = new Quaternion(new Vector3(1, 0, 0), -Math.PI / 2); root.Rotation = new[] { (float)q.X, (float)q.Y, (float)q.Z, (float)q.W }; gltf.Nodes = new[] { root }; gltf.Scene = 0; var scene = new Scene(); scene.Nodes = new[] { 0 }; gltf.Scenes = new[] { scene }; gltf.ExtensionsUsed = new[] { "KHR_materials_pbrSpecularGlossiness" }; var materials = gltf.AddMaterials(new[] { BuiltInMaterials.Default, BuiltInMaterials.Edges, BuiltInMaterials.EdgesHighlighted }); var buffer = new List <byte>(); var mesh = new Elements.Geometry.Mesh(); solid.Tessellate(ref mesh); byte[] vertexBuffer; byte[] normalBuffer; byte[] indexBuffer; byte[] colorBuffer; double[] vmin; double[] vmax; double[] nmin; double[] nmax; float[] cmin; float[] cmax; ushort imin; ushort imax; mesh.GetBuffers(out vertexBuffer, out indexBuffer, out normalBuffer, out colorBuffer, out vmax, out vmin, out nmin, out nmax, out cmin, out cmax, out imin, out imax); var bufferViews = new List <BufferView>(); var accessors = new List <Accessor>(); gltf.AddTriangleMesh("mesh", buffer, bufferViews, accessors, vertexBuffer, normalBuffer, indexBuffer, colorBuffer, vmin, vmax, nmin, nmax, imin, imax, materials[BuiltInMaterials.Default.Name], cmin, cmax, null, null); var edgeCount = 0; var vertices = new List <Vector3>(); var verticesHighlighted = new List <Vector3>(); foreach (var e in solid.Edges.Values) { if (e.Left.Loop == null || e.Right.Loop == null) { verticesHighlighted.AddRange(new[] { e.Left.Vertex.Point, e.Right.Vertex.Point }); } else { vertices.AddRange(new[] { e.Left.Vertex.Point, e.Right.Vertex.Point }); } edgeCount++; } if (vertices.Count > 0) { // Draw standard edges AddLines(100000, vertices.ToArray(), gltf, materials[BuiltInMaterials.Edges.Name], buffer, bufferViews, accessors); } if (verticesHighlighted.Count > 0) { // Draw highlighted edges AddLines(100001, verticesHighlighted.ToArray(), gltf, materials[BuiltInMaterials.EdgesHighlighted.Name], buffer, bufferViews, accessors); } var buff = new glTFLoader.Schema.Buffer(); buff.ByteLength = buffer.Count; gltf.Buffers = new[] { buff }; gltf.BufferViews = bufferViews.ToArray(); gltf.Accessors = accessors.ToArray(); if (File.Exists(path)) { File.Delete(path); } gltf.SaveBinaryModel(buffer.ToArray(), path); }
private static void GetRenderDataForElement(Element e, Gltf gltf, Dictionary <string, int> materials, List <byte> buffer, List <BufferView> bufferViews, List <Accessor> accessors, List <glTFLoader.Schema.Mesh> meshes, List <glTFLoader.Schema.Node> nodes, Dictionary <Guid, List <int> > meshElementMap, List <Vector3> lines, bool drawEdges) { var materialName = BuiltInMaterials.Default.Name; int meshId = -1; if (e is GeometricElement) { var geom = (GeometricElement)e; materialName = geom.Material.Name; geom.UpdateRepresentations(); if (geom.Representation != null) { foreach (var solidOp in geom.Representation.SolidOperations) { if (solidOp.Solid != null) { meshId = ProcessSolid(solidOp.Solid, e.Id.ToString(), materialName, ref gltf, ref materials, ref buffer, bufferViews, accessors, meshes, lines, geom.IsElementDefinition ? false : drawEdges, geom.Transform); if (!meshElementMap.ContainsKey(e.Id)) { meshElementMap.Add(e.Id, new List <int>()); } meshElementMap[e.Id].Add(meshId); if (!geom.IsElementDefinition) { CreateNodeForMesh(gltf, meshId, nodes, geom.Transform); } } } } } if (e is ElementInstance) { var i = (ElementInstance)e; // Lookup the corresponding mesh in the map. AddInstanceMesh(gltf, nodes, meshElementMap[i.BaseDefinition.Id], i.Transform); if (drawEdges) { // Get the edges for the solid var geom = i.BaseDefinition; if (geom.Representation != null) { foreach (var solidOp in geom.Representation.SolidOperations) { if (solidOp.Solid != null) { foreach (var edge in solidOp.Solid.Edges.Values) { lines.AddRange(new[] { i.Transform.OfVector(edge.Left.Vertex.Point), i.Transform.OfVector(edge.Right.Vertex.Point) }); } } } } } } if (e is ModelCurve) { var mc = (ModelCurve)e; AddLines(GetNextId(), mc.Curve.RenderVertices(), gltf, materials[mc.Material.Name], buffer, bufferViews, accessors, meshes, nodes, true, mc.Transform); } if (e is ModelPoints) { var mp = (ModelPoints)e; if (mp.Locations.Count != 0) { AddPoints(GetNextId(), mp.Locations, gltf, materials[mp.Material.Name], buffer, bufferViews, accessors, meshes, nodes, mp.Transform); } } if (e is ITessellate) { var geo = (ITessellate)e; var mesh = new Elements.Geometry.Mesh(); geo.Tessellate(ref mesh); if (mesh == null) { return; } byte[] vertexBuffer; byte[] normalBuffer; byte[] indexBuffer; byte[] colorBuffer; byte[] uvBuffer; double[] vmin; double[] vmax; double[] nmin; double[] nmax; float[] cmin; float[] cmax; ushort imin; ushort imax; double[] uvmin; double[] uvmax; mesh.GetBuffers(out vertexBuffer, out indexBuffer, out normalBuffer, out colorBuffer, out uvBuffer, out vmax, out vmin, out nmin, out nmax, out cmin, out cmax, out imin, out imax, out uvmax, out uvmin); // TODO(Ian): Remove this cast to GeometricElement when we // consolidate mesh under geometric representations. meshId = gltf.AddTriangleMesh(e.Id + "_mesh", buffer, bufferViews, accessors, vertexBuffer, normalBuffer, indexBuffer, colorBuffer, uvBuffer, vmin, vmax, nmin, nmax, imin, imax, uvmax, uvmin, materials[materialName], cmin, cmax, null, meshes); if (!meshElementMap.ContainsKey(e.Id)) { meshElementMap.Add(e.Id, new List <int>()); } meshElementMap[e.Id].Add(meshId); var geom = (GeometricElement)e; if (!geom.IsElementDefinition) { CreateNodeForMesh(gltf, meshId, nodes, geom.Transform); } } }
/// <summary> /// Creates a Roof from a supplied Polygon sketch and a supplied elevation. /// </summary> /// <param name="model">The input model.</param> /// <param name="input">The arguments to the execution.</param> /// <returns>A RoofBySketchOutputs instance containing computed results and the model with any new elements.</returns> public static RoofBySketchOutputs Execute(Dictionary <string, Model> inputModels, RoofBySketchInputs input) { var topSide = new Elements.Geometry.Mesh(); var area = 0.0; foreach (var triangle in input.Mesh.Triangles) { var a = topSide.AddVertex(triangle.Vertices[0].Position); var b = topSide.AddVertex(triangle.Vertices[1].Position); var c = topSide.AddVertex(triangle.Vertices[2].Position); var triAng = new Elements.Geometry.Triangle(a, b, c); topSide.AddTriangle(triAng); area += triAng.Area(); } topSide.ComputeNormals(); // Find the Mesh's lowest point and use the // roof thickness to the set the Roof's underside elevation. var vertices = input.Mesh.Vertices.ToList(); vertices = vertices.OrderBy(v => v.Position.Z).ToList(); var elevation = vertices.First().Position.Z - input.Thickness; // Find the topSide Mesh's perimeter points and use them to // construct a Mesh representing the underside of the Roof. var perimeter = topSide.EdgesPerimeters().First(); var ePoints = new List <Vector3>(); perimeter.ForEach(e => ePoints.AddRange(e.Points())); ePoints = ePoints.Distinct().ToList(); var uPoints = new List <Vector3>(); ePoints.ForEach(p => uPoints.Add(new Vector3(p.X, p.Y, elevation))); var underBoundary = new Polygon(uPoints); var underSide = underBoundary.ToMesh(false); // Use the topSide Mesh's edgePoints and the lower Mesh's underPoints // to construct a series of triangles forming the sides of the Roof. var sideTriangles = new List <Elements.Geometry.Triangle>(); for (var i = 0; i < ePoints.Count; i++) { sideTriangles.Add( new Elements.Geometry.Triangle(new Vertex(ePoints[i]), new Vertex(uPoints[i]), new Vertex(uPoints[(i + 1) % uPoints.Count]))); sideTriangles.Add( new Elements.Geometry.Triangle(new Vertex(ePoints[i]), new Vertex(uPoints[(i + 1) % uPoints.Count]), new Vertex(ePoints[(i + 1) % ePoints.Count]))); } // Construct the roof envelope in Elements.Geometry.mesh form. // We add vertices individually by position so that we don't affect // the original vertices of hte individual faces var Envelope = new Elements.Geometry.Mesh(); foreach (var t in topSide.Triangles) { var a = Envelope.AddVertex(t.Vertices[0].Position); var b = Envelope.AddVertex(t.Vertices[1].Position); var c = Envelope.AddVertex(t.Vertices[2].Position); Envelope.AddTriangle(new Triangle(a, b, c)); } foreach (var t in underSide.Triangles) { var a = Envelope.AddVertex(t.Vertices[0].Position); var b = Envelope.AddVertex(t.Vertices[1].Position); var c = Envelope.AddVertex(t.Vertices[2].Position); Envelope.AddTriangle(new Triangle(a, b, c)); } foreach (var t in sideTriangles) { var a = Envelope.AddVertex(t.Vertices[0].Position); var b = Envelope.AddVertex(t.Vertices[1].Position); var c = Envelope.AddVertex(t.Vertices[2].Position); Envelope.AddTriangle(new Triangle(a, b, c)); } // enVertices.ToList().ForEach(v => Envelope.AddVertex(v)); // envTriangles.ToList().ForEach(t => Envelope.AddTriangle(t)); Envelope.ComputeNormals(); //Record roof high point from topSide mesh. var highPoint = topSide.Points().OrderByDescending(p => p.Z).First().Z; // // code for when debugging the function. // var envelope = MakeEnvelope(); // var topside = MakeTopside(); // var underside = MakeUnderside(); // var underBoundary = Polygon.Rectangle(20.0, 20.0); // var elevation = 10.0; // var highPoint = 15.0; // var area = 100.0; var roof = new Roof( Envelope, topSide, underSide, underBoundary, elevation, highPoint, input.Thickness, area, new Transform(), BuiltInMaterials.Concrete, null, false, Guid.NewGuid(), "Roof"); var output = new RoofBySketchOutputs(area); output.Model.AddElement(new MeshElement(Envelope, BuiltInMaterials.Concrete)); output.Model.AddElement(roof); return(output); }