Example #1
0
        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));
        }
Example #2
0
        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);
                    }
                }
            }
        }
Example #3
0
        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);
                }
            }
        }
Example #4
0
        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);
        }
Example #5
0
        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);
                    }
                }
            }
        }
Example #6
0
        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();
        }
Example #7
0
        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);
            }
        }
Example #8
0
        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);
        }
Example #9
0
        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);
                }
            }
        }