Example #1
0
        private void AddComponentsToMesh(gltf.Mesh targetMesh, ShapeComponentIds osgGeom, int materialIndex)
        {
            gltf.MeshPrimitive       thisPrimitive = new gltf.MeshPrimitive();
            Dictionary <string, int> att           = new Dictionary <string, int>();

            att.Add("NORMAL", osgGeom.NormalsAccessorId);
            att.Add("POSITION", osgGeom.VerticesAccessorId);
            thisPrimitive.Attributes = att;
            thisPrimitive.Indices    = osgGeom.IndicesAccessorId;
            thisPrimitive.Material   = materialIndex;
            thisPrimitive.Mode       = gltf.MeshPrimitive.ModeEnum.TRIANGLES;


            int initSize = targetMesh.Primitives != null
                ? targetMesh.Primitives.Length
                : 0;

            if (initSize == 0)
            {
                targetMesh.Primitives = new gltf.MeshPrimitive[] { thisPrimitive };
            }
            else
            {
                var concat = targetMesh.Primitives.ToList();
                concat.Add(thisPrimitive);
                targetMesh.Primitives = concat.ToArray();
            }
        }
        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);
        }