/// <summary> /// Create a ruled loft between sections. /// </summary> /// <param name="sections"></param> public static Mesh Loft(IList <Polygon> sections) { var mesh = new Elements.Geometry.Mesh(); for (var i = 0; i < sections.Count; i++) { var p1 = sections[i]; var p2 = i == sections.Count - 1 ? sections[0] : sections[i + 1]; for (var j = 0; j < p1.Vertices.Length; j++) { var j1 = j == p1.Vertices.Length - 1 ? 0 : j + 1; var v1 = p1.Vertices[j]; var v2 = p1.Vertices[j1]; var v3 = p2.Vertices[j1]; var v4 = p2.Vertices[j]; mesh.AddQuad(new [] { v1, v2, v3, v4 }); } } return(mesh); }
public static RenderData DrawMesh(Elements.Geometry.Mesh mesh, ref Outline outline, DisplayStyle displayStyle) { var min = new XYZ(double.MaxValue, double.MaxValue, double.MaxValue); var max = new XYZ(double.MinValue, double.MinValue, double.MinValue); var numVertices = mesh.Triangles.Count * 3; var numPrimitives = mesh.Triangles.Count; var pType = PrimitiveType.TriangleList; var numIndices = GetPrimitiveSize(pType) * numPrimitives; VertexFormatBits vertexFormatBits; switch (displayStyle) { case DisplayStyle.HLR: case DisplayStyle.FlatColors: vertexFormatBits = VertexFormatBits.PositionColored; break; default: vertexFormatBits = VertexFormatBits.PositionNormalColored; break; } var vertexFormat = new VertexFormat(vertexFormatBits); var vBuffer = new VertexBuffer(GetVertexSize(vertexFormatBits) * numVertices); var iBuffer = new IndexBuffer(numIndices); vBuffer.Map(GetVertexSize(vertexFormatBits) * numVertices); iBuffer.Map(numIndices); var verticesFlat = new List <VertexPositionColored>(); var vertices = new List <VertexPositionNormalColored>(); var triangles = new List <IndexTriangle>(); // We duplicate the vertices on each triangle so that // we can get the correct number of face normals. foreach (var t in mesh.Triangles) { foreach (var v in t.Vertices) { var pos = v.Position.ToXYZFeet(); outline.AddPoint(pos); switch (vertexFormatBits) { case VertexFormatBits.PositionColored: var color = displayStyle == DisplayStyle.HLR ? new ColorWithTransparency(255, 255, 255, 0) : v.Color.ToColorWithTransparency(); verticesFlat.Add(new VertexPositionColored(pos, color)); break; default: vertices.Add(new VertexPositionNormalColored(pos, t.Normal.ToXYZ(), v.Color.ToColorWithTransparency())); break; } if (pos.X < min.X && pos.Y < min.Y && pos.Z < min.Z) { min = pos; } if (pos.X > min.X && pos.Y > min.Y && pos.Z > min.Z) { max = pos; } } triangles.Add(new IndexTriangle(t.Vertices[0].Index, t.Vertices[1].Index, t.Vertices[2].Index)); } switch (displayStyle) { case DisplayStyle.HLR: case DisplayStyle.FlatColors: var pc = vBuffer.GetVertexStreamPositionColored(); pc.AddVertices(verticesFlat); break; default: var pnc = vBuffer.GetVertexStreamPositionNormalColored(); pnc.AddVertices(vertices); break; } var iPos = iBuffer.GetIndexStreamTriangle(); iPos.AddTriangles(triangles); vBuffer.Unmap(); iBuffer.Unmap(); var effect = new EffectInstance(vertexFormatBits); // There is no reason why this should work. // In other situations, 255 is the 'full' component. // In the case of hidden line rendering, 0, 0, 0 makes white. // if (displayStyle == DisplayStyle.HLR) // { // var color = new ColorWithTransparency(0, 0, 0, 0); // effect.SetColor(color.GetColor()); // effect.SetAmbientColor(color.GetColor()); // effect.SetDiffuseColor(color.GetColor()); // } // Create a render data for reuse // on non-update calls. var renderData = new RenderData() { VertexBuffer = vBuffer, VertexCount = numVertices, IndexBuffer = iBuffer, IndexCount = numIndices, VertexFormat = vertexFormat, Effect = effect, PrimitiveType = pType, PrimitiveCount = numPrimitives }; if (displayStyle != DisplayStyle.Wireframe && numPrimitives > 0) { DrawContext.FlushBuffer(vBuffer, numVertices, iBuffer, numIndices, vertexFormat, effect, pType, 0, numPrimitives); } return(renderData); }
private static List <RenderData> DrawExecution(ILogger logger, string workflowId, string executionId, Outline outline, DisplayStyle displayStyle) { // Read the workflow from disk var execPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), $".hypar/workflows/{workflowId}/{executionId}/model.json"); if (!File.Exists(execPath)) { logger.Debug("The execution path {Path} could not be found. Perhaps the workflow was deleted from the cache.", execPath); return(null); } var errors = new List <string>(); var model = Elements.Model.FromJson(File.ReadAllText(execPath), errors); foreach (var error in errors) { logger.Debug("{Error}", error); } var geoms = model.AllElementsOfType <Elements.GeometricElement>(); var instances = model.AllElementsOfType <Elements.ElementInstance>(); logger.Debug("Found {ElementCount} elements.", geoms.Count()); if (geoms.Count() == 0) { return(null); } var meshes = new List <Elements.Geometry.Mesh>(); var edgeSet = new List <List <Elements.Geometry.Line> >(); var edges = new List <Elements.Geometry.Line>(); edgeSet.Add(edges); // Draw the meshes and edges in batches. Arbitrarily large meshes // will overun the max value of ushorts causing data // not to show up. var meshBatchSize = 500; var edgeBatchSize = 1000; var mesh = new Elements.Geometry.Mesh(); var count = 0; foreach (var geom in geoms) { if (geom.Representation == null || geom.Representation.SolidOperations.Count() == 0) { continue; } foreach (var solidOp in geom.Representation.SolidOperations) { solidOp.Solid.Tessellate(ref mesh, geom.Transform, geom.Material.Color); foreach (var e in solidOp.Solid.Edges.Values) { edges.Add(new Elements.Geometry.Line(geom.Transform.OfPoint(e.Left.Vertex.Point), geom.Transform.OfPoint(e.Right.Vertex.Point))); if (edges.Count >= edgeBatchSize) { edgeSet.Add(edges); edges = new List <Elements.Geometry.Line>(); } } } count++; if (count > meshBatchSize) { meshes.Add(mesh); mesh = new Elements.Geometry.Mesh(); count = 0; } } foreach (var instance in instances) { if (instance.BaseDefinition.Representation == null || instance.BaseDefinition.Representation.SolidOperations.Count() == 0) { continue; } foreach (var solidOp in instance.BaseDefinition.Representation.SolidOperations) { solidOp.Solid.Tessellate(ref mesh, instance.Transform, instance.BaseDefinition.Material.Color); foreach (var e in solidOp.Solid.Edges.Values) { edges.Add(new Elements.Geometry.Line(instance.Transform.OfPoint(e.Left.Vertex.Point), instance.Transform.OfPoint(e.Right.Vertex.Point))); if (edges.Count >= edgeBatchSize) { edgeSet.Add(edges); edges = new List <Elements.Geometry.Line>(); } } } count++; if (count > meshBatchSize) { meshes.Add(mesh); mesh = new Elements.Geometry.Mesh(); count = 0; } } meshes.Add(mesh); edgeSet.Add(edges); var renderDatas = new List <RenderData>(); logger.Debug("There are {MeshCount} meshes to be drawn.", meshes.Count); foreach (var subMesh in meshes) { try { if (displayStyle != DisplayStyle.Wireframe) { renderDatas.Add(DrawMesh(subMesh, ref outline, displayStyle)); } } catch (Exception ex) { logger.Debug(ex.Message); } } if (displayStyle != DisplayStyle.Shading) { foreach (var e in edgeSet) { renderDatas.Add(DrawEdges(e)); } } return(renderDatas); }