private static int ProcessSolid(Solid solid, string id, string materialName, ref Gltf gltf, ref Dictionary <string, int> materials, ref List <byte> buffer, List <BufferView> bufferViews, List <Accessor> accessors, List <glTFLoader.Schema.Mesh> meshes, List <Vector3> lines, bool drawEdges, Transform t = null) { 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; solid.Tessellate(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); if (drawEdges) { foreach (var edge in solid.Edges.Values) { if (t != null) { lines.AddRange(new[] { t.OfVector(edge.Left.Vertex.Point), t.OfVector(edge.Right.Vertex.Point) }); } else { lines.AddRange(new[] { edge.Left.Vertex.Point, edge.Right.Vertex.Point }); } } } return(gltf.AddTriangleMesh(id + "_mesh", buffer, bufferViews, accessors, vertexBuffer, normalBuffer, indexBuffer, colorBuffer, uvBuffer, vmin, vmax, nmin, nmax, imin, imax, uvmin, uvmax, materials[materialName], cmin, cmax, null, meshes)); }
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); } } } }
private void GetRenderDataForElement(Element e, Gltf gltf, Dictionary <string, int> materials) { if (e is ITessellateMesh) { var mp = e as ITessellateMesh; var mesh = mp.Mesh(); Transform transform = null; if (e.Transform != null) { transform = e.Transform; } gltf.AddTriangleMesh(e.Id + "_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[e.Material.Name], null, transform); } if (e is ITessellateCurves) { var cp = e as ITessellateCurves; var curves = cp.Curves(); var counter = 0; foreach (var c in curves) { var vBuff = c.ToArray(); var indices = Enumerable.Range(0, c.Count).Select(i => (ushort)i).ToArray(); var bbox = new BBox3(c); gltf.AddLineLoop($"{e.Id}_curve_{counter}", _buffer, vBuff, indices, bbox.Min.ToArray(), bbox.Max.ToArray(), 0, (ushort)(c.Count - 1), materials[BuiltInMaterials.Black.Name], e.Transform); } } if (e.SubElements.Count > 0) { foreach (var esub in e.SubElements) { GetRenderDataForElement(esub, gltf, materials); } } }
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); } } }