Exemplo n.º 1
0
        public Task <Mesh> GetMeshAsync(int meshIndex)
        {
            GltfLoader.Schema.Mesh mesh = gltf.Meshes[meshIndex];

            Span <byte>           indexBuffer     = Span <byte> .Empty;
            GraphicsBuffer <byte>?indexBufferView = null;
            bool is32bitIndex = false;

            if (mesh.Primitives[0].Indices.HasValue)
            {
                indexBuffer     = GetIndexBuffer(mesh, out int stride);
                is32bitIndex    = stride == sizeof(int);
                indexBufferView = GraphicsBuffer.New(GraphicsDevice, indexBuffer, stride, ResourceFlags.IndexBuffer).DisposeBy(GraphicsDevice);
            }

            GraphicsBuffer[] vertexBufferViews = GetVertexBufferViews(mesh, indexBuffer, is32bitIndex);

            int materialIndex = 0;

            if (mesh.Primitives[0].Material.HasValue)
            {
                materialIndex = mesh.Primitives[0].Material ?? throw new Exception();
            }

            Node node = gltf.Nodes.First(n => n.Mesh == meshIndex);

            float[] matrix = node.Matrix;

            Matrix4x4 worldMatrix = Matrix4x4.Transpose(new Matrix4x4(
                                                            matrix[0], matrix[1], matrix[2], matrix[3],
                                                            matrix[4], matrix[5], matrix[6], matrix[7],
                                                            matrix[8], matrix[9], matrix[10], matrix[11],
                                                            matrix[12], matrix[13], matrix[14], matrix[15]));

            float[] s = node.Scale;
            float[] r = node.Rotation;
            float[] t = node.Translation;

            Vector3    scale       = new Vector3(s[0], s[1], s[2]);
            Quaternion rotation    = new Quaternion(r[0], r[1], r[2], r[3]);
            Vector3    translation = new Vector3(t[0], t[1], t[2]);

            worldMatrix *= Matrix4x4.CreateScale(scale)
                           * Matrix4x4.CreateFromQuaternion(rotation)
                           * Matrix4x4.CreateTranslation(translation);

            MeshDraw meshDraw = new MeshDraw
            {
                IndexBufferView   = indexBufferView,
                VertexBufferViews = vertexBufferViews
            };

            return(Task.FromResult(new Mesh(meshDraw)
            {
                MaterialIndex = materialIndex, WorldMatrix = worldMatrix
            }));
        }
Exemplo n.º 2
0
        private Span <byte> GetIndexBuffer(GltfLoader.Schema.Mesh mesh, out int stride)
        {
            int      indicesIndex = mesh.Primitives[0].Indices ?? throw new Exception();
            Accessor accessor     = gltf.Accessors[indicesIndex];

            int        bufferViewIndex = accessor.BufferView ?? throw new Exception();
            BufferView bufferView      = gltf.BufferViews[bufferViewIndex];

            int offset = bufferView.ByteOffset + accessor.ByteOffset;

            stride = accessor.ComponentType switch
            {
                Accessor.GltfComponentType.UnsignedShort => GetCountOfAccessorType(accessor.Type) * sizeof(ushort),
                Accessor.GltfComponentType.UnsignedInt => GetCountOfAccessorType(accessor.Type) * sizeof(uint),
                _ => throw new NotSupportedException("This component type is not supported.")
            };

            return(buffers[bufferView.Buffer].AsSpan(offset, stride * accessor.Count));
        }
Exemplo n.º 3
0
        private GraphicsBuffer[] GetVertexBufferViews(GltfLoader.Schema.Mesh mesh, Span <byte> indexBuffer = default, bool is32bitIndex = false)
        {
            GraphicsBuffer[] vertexBufferViews = new GraphicsBuffer[4];

            Dictionary <string, int> attributes = mesh.Primitives[0].Attributes;

            bool hasPosition  = attributes.TryGetValue("POSITION", out int positionIndex);
            bool hasNormal    = attributes.TryGetValue("NORMAL", out int normalIndex);
            bool hasTangent   = attributes.TryGetValue("TANGENT", out int tangentIndex);
            bool hasTexCoord0 = attributes.TryGetValue("TEXCOORD_0", out int texCoord0Index);

            if (hasPosition)
            {
                Span <byte> positionBuffer = GetVertexBuffer(positionIndex, out int positionStride);
                vertexBufferViews[0] = GraphicsBuffer.New(GraphicsDevice, positionBuffer, positionStride, ResourceFlags.VertexBuffer).DisposeBy(GraphicsDevice);

                if (hasNormal)
                {
                    Span <byte> normalBuffer = GetVertexBuffer(normalIndex, out int normalStride);
                    vertexBufferViews[1] = GraphicsBuffer.New(GraphicsDevice, normalBuffer, normalStride, ResourceFlags.VertexBuffer).DisposeBy(GraphicsDevice);
                }

                if (hasTangent)
                {
                    Span <byte> tangentBuffer = GetVertexBuffer(tangentIndex, out int tangentStride);
                    vertexBufferViews[2] = GraphicsBuffer.New(GraphicsDevice, tangentBuffer, tangentStride, ResourceFlags.VertexBuffer).DisposeBy(GraphicsDevice);
                }

                if (hasTexCoord0)
                {
                    Span <byte> texCoord0Buffer = GetVertexBuffer(texCoord0Index, out int texCoord0Stride);
                    vertexBufferViews[3] = GraphicsBuffer.New(GraphicsDevice, texCoord0Buffer, texCoord0Stride, ResourceFlags.VertexBuffer).DisposeBy(GraphicsDevice);

                    if (!hasTangent)
                    {
                        Span <Vector4> tangentBuffer = VertexHelper.GenerateTangents(positionBuffer, texCoord0Buffer, indexBuffer, is32bitIndex);
                        vertexBufferViews[2] = GraphicsBuffer.New(GraphicsDevice, tangentBuffer, ResourceFlags.VertexBuffer).DisposeBy(GraphicsDevice);
                    }
                }
            }

            return(vertexBufferViews);
        }