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 RenderData ProcessPrimitive(ILogger logger, glTFLoader.Schema.MeshPrimitive primitive, Gltf gltf, byte[][] buffers, DisplayStyle displayStyle, Outline outline, Transform transform) { if (primitive.Mode != MeshPrimitive.ModeEnum.TRIANGLES) { logger.Debug("The selected primitive mode is not supported."); return(null); } var indexAccessor = gltf.Accessors[(int)primitive.Indices]; var positionAccessor = gltf.Accessors[primitive.Attributes["POSITION"]]; var normalAccessor = gltf.Accessors[primitive.Attributes["NORMAL"]]; var hasColor = primitive.Attributes.ContainsKey("COLOR_0"); var indexBufferView = gltf.BufferViews[(int)indexAccessor.BufferView]; var positionBufferView = gltf.BufferViews[(int)positionAccessor.BufferView]; var normalBufferView = gltf.BufferViews[(int)normalAccessor.BufferView]; var indices = new List <int>(); for (var i = indexBufferView.ByteOffset; i < indexBufferView.ByteOffset + indexBufferView.ByteLength; i += indexBufferView.ByteStride ?? sizeof(ushort)) { var index = BitConverter.ToUInt16(buffers[indexBufferView.Buffer], i); indices.Add(index); } var floatSize = sizeof(float); var positions = new List <XYZ>(); for (var i = positionBufferView.ByteOffset; i < positionBufferView.ByteOffset + positionBufferView.ByteLength; i += positionBufferView.ByteStride ?? (floatSize * 3)) { // Read x, y, z values var x = BitConverter.ToSingle(buffers[positionBufferView.Buffer], i); var y = BitConverter.ToSingle(buffers[positionBufferView.Buffer], i + floatSize); var z = BitConverter.ToSingle(buffers[positionBufferView.Buffer], i + floatSize * 2); var pt = new XYZ(Elements.Units.MetersToFeet(x), Elements.Units.MetersToFeet(y), Elements.Units.MetersToFeet(z)); if (transform != null) { pt = transform.OfPoint(pt); } outline.AddPoint(pt); positions.Add(pt); } var normals = new List <XYZ>(); for (var i = normalBufferView.ByteOffset; i < normalBufferView.ByteOffset + normalBufferView.ByteLength; i += normalBufferView.ByteStride ?? (floatSize * 3)) { // Read x, y, z values var x = BitConverter.ToSingle(buffers[normalBufferView.Buffer], i); var y = BitConverter.ToSingle(buffers[normalBufferView.Buffer], i + floatSize); var z = BitConverter.ToSingle(buffers[normalBufferView.Buffer], i + floatSize * 2); var n = new XYZ(x, y, z); if (transform != null) { n = transform.OfVector(n); } normals.Add(n); } var colors = new List <ColorWithTransparency>(); if (hasColor) { var colorAccessor = gltf.Accessors[primitive.Attributes["COLOR_0"]]; var colorBufferView = gltf.BufferViews[(int)colorAccessor.BufferView]; for (var i = colorBufferView.ByteOffset; i < colorBufferView.ByteOffset + colorBufferView.ByteLength; i += colorBufferView.ByteStride ?? (floatSize * 3)) { // Read x, y, z values var r = BitConverter.ToSingle(buffers[colorBufferView.Buffer], i); var g = BitConverter.ToSingle(buffers[colorBufferView.Buffer], i + floatSize); var b = BitConverter.ToSingle(buffers[colorBufferView.Buffer], i + floatSize * 2); colors.Add(displayStyle == DisplayStyle.HLR ? new ColorWithTransparency(255, 255, 255, 0) : new ColorWithTransparency((uint)(r * 255), (uint)(g * 255), (uint)(b * 255), 0)); } } // The number of vertices will be the same as the length of the indices // because we'll duplicate vertices at every position. var numVertices = indices.Count; var pType = PrimitiveType.TriangleList; var numPrimitives = indices.Count / 3; 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>(); ColorWithTransparency color = null; if (displayStyle == DisplayStyle.HLR) { color = new ColorWithTransparency(255, 255, 255, 0); } else if (primitive.Material != null) { var material = gltf.Materials[(int)primitive.Material]; var r = (uint)(material.PbrMetallicRoughness.BaseColorFactor[0] * 255); var g = (uint)(material.PbrMetallicRoughness.BaseColorFactor[1] * 255); var b = (uint)(material.PbrMetallicRoughness.BaseColorFactor[2] * 255); var a = (uint)(material.PbrMetallicRoughness.BaseColorFactor[3] * 255); color = new ColorWithTransparency(r, g, b, a); } for (var i = 0; i < indices.Count; i += 3) { var ia = indices[i]; var ib = indices[i + 1]; var ic = indices[i + 2]; var a = positions[ia]; var b = positions[ib]; var c = positions[ic]; var na = normals[ia]; var nb = normals[ib]; var nc = normals[ic]; switch (vertexFormatBits) { case VertexFormatBits.PositionColored: if (hasColor) { color = colors[ia]; } verticesFlat.Add(new VertexPositionColored(a, hasColor ? colors[ia] : color)); verticesFlat.Add(new VertexPositionColored(b, hasColor ? colors[ib] : color)); verticesFlat.Add(new VertexPositionColored(c, hasColor ? colors[ic] : color)); break; default: if (hasColor) { color = colors[ia]; } vertices.Add(new VertexPositionNormalColored(a, na, hasColor ? colors[ia] : color)); vertices.Add(new VertexPositionNormalColored(b, nb, hasColor ? colors[ib] : color)); vertices.Add(new VertexPositionNormalColored(c, nc, hasColor ? colors[ic] : color)); break; } triangles.Add(new IndexTriangle(i, i + 1, i + 2)); } 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); 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); }