Ejemplo n.º 1
0
        public static MeshBuffers CreateMeshBuffers(Mesh mesh, ShaderVertexAttributeCollection shaderAttributes, BufferHint usageHint)
        {
            if (mesh == null)
            {
                throw new ArgumentNullException("mesh");
            }

            if (shaderAttributes == null)
            {
                throw new ArgumentNullException("shaderAttributes");
            }

            MeshBuffers meshBuffers = new MeshBuffers();

            if (mesh.Indices != null)
            {
                if (mesh.Indices.Datatype == IndicesType.UnsignedShort)
                {
                    IList <ushort> meshIndices = ((IndicesUnsignedShort)mesh.Indices).Values;

                    ushort[] indices = new ushort[meshIndices.Count];
                    for (int j = 0; j < meshIndices.Count; ++j)
                    {
                        indices[j] = meshIndices[j];
                    }

                    IndexBuffer indexBuffer = Device.CreateIndexBuffer(usageHint, indices.Length * sizeof(ushort));
                    indexBuffer.CopyFromSystemMemory(indices);
                    meshBuffers.IndexBuffer = indexBuffer;
                }
                else if (mesh.Indices.Datatype == IndicesType.UnsignedInt)
                {
                    IList <uint> meshIndices = ((IndicesUnsignedInt)mesh.Indices).Values;

                    uint[] indices = new uint[meshIndices.Count];
                    for (int j = 0; j < meshIndices.Count; ++j)
                    {
                        indices[j] = meshIndices[j];
                    }

                    IndexBuffer indexBuffer = Device.CreateIndexBuffer(usageHint, indices.Length * sizeof(uint));
                    indexBuffer.CopyFromSystemMemory(indices);
                    meshBuffers.IndexBuffer = indexBuffer;
                }
                else
                {
                    throw new NotSupportedException("mesh.Indices.Datatype " +
                                                    mesh.Indices.Datatype.ToString() + " is not supported.");
                }
            }

            //
            // Emulated double precision vectors are a special case:  one mesh vertex attribute
            // yields two shader vertex attributes.  As such, these are handled separately before
            // normal attributes.
            //
            HashSet <string> ignoreAttributes = new HashSet <string>();

            foreach (VertexAttribute attribute in mesh.Attributes)
            {
                if (attribute is VertexAttributeDoubleVector3)
                {
                    VertexAttributeDoubleVector3 emulated = (VertexAttributeDoubleVector3)attribute;

                    int highLocation = -1;
                    int lowLocation  = -1;

                    foreach (ShaderVertexAttribute shaderAttribute in shaderAttributes)
                    {
                        if (shaderAttribute.Name == emulated.Name + "High")
                        {
                            highLocation = shaderAttribute.Location;
                        }
                        else if (shaderAttribute.Name == emulated.Name + "Low")
                        {
                            lowLocation = shaderAttribute.Location;
                        }

                        if ((highLocation != -1) && (lowLocation != -1))
                        {
                            break;
                        }
                    }

                    if ((highLocation == -1) && (lowLocation == -1))
                    {
                        //
                        // The shader did not have either attribute.  No problem.
                        //
                        continue;
                    }
                    else if ((highLocation == -1) || (lowLocation == -1))
                    {
                        throw new ArgumentException("An emulated double vec3 mesh attribute requires both " + emulated.Name + "High and " + emulated.Name + "Low vertex attributes, but the shader only contains one matching attribute.");
                    }

                    //
                    // Copy both high and low parts into a single vertex buffer.
                    //
                    IList <Vector3D> values = ((VertexAttribute <Vector3D>)attribute).Values;

                    Vector3F[] vertices = new Vector3F[2 * values.Count];

                    int j = 0;
                    for (int i = 0; i < values.Count; ++i)
                    {
                        EmulatedVector3D v = new EmulatedVector3D(values[i]);
                        vertices[j++] = v.High;
                        vertices[j++] = v.Low;
                    }

                    VertexBuffer vertexBuffer = Device.CreateVertexBuffer(usageHint, ArraySizeInBytes.Size(vertices));
                    vertexBuffer.CopyFromSystemMemory(vertices);

                    int stride = 2 * SizeInBytes <Vector3F> .Value;
                    meshBuffers.Attributes[highLocation] =
                        new VertexBufferAttribute(vertexBuffer, ComponentDatatype.Float, 3, false, 0, stride);
                    meshBuffers.Attributes[lowLocation] =
                        new VertexBufferAttribute(vertexBuffer, ComponentDatatype.Float, 3, false, SizeInBytes <Vector3F> .Value, stride);

                    ignoreAttributes.Add(emulated.Name + "High");
                    ignoreAttributes.Add(emulated.Name + "Low");
                }
            }

            // TODO:  Not tested exhaustively
            foreach (ShaderVertexAttribute shaderAttribute in shaderAttributes)
            {
                if (ignoreAttributes.Contains(shaderAttribute.Name))
                {
                    continue;
                }

                if (!mesh.Attributes.Contains(shaderAttribute.Name))
                {
                    throw new ArgumentException("Shader requires vertex attribute \"" + shaderAttribute.Name + "\", which is not present in mesh.");
                }

                VertexAttribute attribute = mesh.Attributes[shaderAttribute.Name];


                if (attribute.Datatype == VertexAttributeType.EmulatedDoubleVector3)
                {
                    IList <Vector3D> values = ((VertexAttribute <Vector3D>)attribute).Values;

                    Vector3F[] valuesArray = new Vector3F[values.Count];
                    for (int i = 0; i < values.Count; ++i)
                    {
                        valuesArray[i] = values[i].ToVector3F();
                    }

                    VertexBuffer vertexBuffer = Device.CreateVertexBuffer(usageHint, ArraySizeInBytes.Size(valuesArray));
                    vertexBuffer.CopyFromSystemMemory(valuesArray);
                    meshBuffers.Attributes[shaderAttribute.Location] =
                        new VertexBufferAttribute(vertexBuffer, ComponentDatatype.Float, 3);
                }
                else if (attribute.Datatype == VertexAttributeType.HalfFloat)
                {
                    VertexBuffer vertexBuffer = CreateVertexBuffer(((VertexAttribute <Half>)attribute).Values, usageHint);

                    meshBuffers.Attributes[shaderAttribute.Location] =
                        new VertexBufferAttribute(vertexBuffer, ComponentDatatype.HalfFloat, 1);
                }
                else if (attribute.Datatype == VertexAttributeType.HalfFloatVector2)
                {
                    VertexBuffer vertexBuffer = CreateVertexBuffer(((VertexAttribute <Vector2H>)attribute).Values, usageHint);

                    meshBuffers.Attributes[shaderAttribute.Location] =
                        new VertexBufferAttribute(vertexBuffer, ComponentDatatype.HalfFloat, 2);
                }
                else if (attribute.Datatype == VertexAttributeType.HalfFloatVector3)
                {
                    VertexBuffer vertexBuffer = CreateVertexBuffer(((VertexAttribute <Vector3H>)attribute).Values, usageHint);

                    meshBuffers.Attributes[shaderAttribute.Location] =
                        new VertexBufferAttribute(vertexBuffer, ComponentDatatype.HalfFloat, 3);
                }
                else if (attribute.Datatype == VertexAttributeType.HalfFloatVector4)
                {
                    VertexBuffer vertexBuffer = CreateVertexBuffer(((VertexAttribute <Vector4H>)attribute).Values, usageHint);

                    meshBuffers.Attributes[shaderAttribute.Location] =
                        new VertexBufferAttribute(vertexBuffer, ComponentDatatype.HalfFloat, 4);
                }
                else if (attribute.Datatype == VertexAttributeType.Float)
                {
                    VertexBuffer vertexBuffer = CreateVertexBuffer(((VertexAttribute <float>)attribute).Values, usageHint);

                    meshBuffers.Attributes[shaderAttribute.Location] =
                        new VertexBufferAttribute(vertexBuffer, ComponentDatatype.Float, 1);
                }
                else if (attribute.Datatype == VertexAttributeType.FloatVector2)
                {
                    VertexBuffer vertexBuffer = CreateVertexBuffer(((VertexAttribute <Vector2F>)attribute).Values, usageHint);

                    meshBuffers.Attributes[shaderAttribute.Location] =
                        new VertexBufferAttribute(vertexBuffer, ComponentDatatype.Float, 2);
                }
                else if (attribute.Datatype == VertexAttributeType.FloatVector3)
                {
                    VertexBuffer vertexBuffer = CreateVertexBuffer(((VertexAttribute <Vector3F>)attribute).Values, usageHint);

                    meshBuffers.Attributes[shaderAttribute.Location] =
                        new VertexBufferAttribute(vertexBuffer, ComponentDatatype.Float, 3);
                }
                else if (attribute.Datatype == VertexAttributeType.FloatVector4)
                {
                    VertexBuffer vertexBuffer = CreateVertexBuffer(((VertexAttribute <Vector4F>)attribute).Values, usageHint);

                    meshBuffers.Attributes[shaderAttribute.Location] =
                        new VertexBufferAttribute(vertexBuffer, ComponentDatatype.Float, 4);
                }
                else if (attribute.Datatype == VertexAttributeType.UnsignedByte)
                {
                    if (attribute is VertexAttributeRGBA)
                    {
                        VertexBuffer vertexBuffer = CreateVertexBuffer(((VertexAttribute <byte>)attribute).Values, usageHint);

                        meshBuffers.Attributes[shaderAttribute.Location] =
                            new VertexBufferAttribute(vertexBuffer, ComponentDatatype.UnsignedByte, 4, true, 0, 0);
                    }

                    else if (attribute is VertexAttributeRGB)
                    {
                        VertexBuffer vertexBuffer = CreateVertexBuffer(((VertexAttribute <byte>)attribute).Values, usageHint);

                        meshBuffers.Attributes[shaderAttribute.Location] =
                            new VertexBufferAttribute(vertexBuffer, ComponentDatatype.UnsignedByte, 3, true, 0, 0);
                    }
                    else
                    {
                        VertexBuffer vertexBuffer = CreateVertexBuffer(((VertexAttribute <byte>)attribute).Values, usageHint);

                        meshBuffers.Attributes[shaderAttribute.Location] =
                            new VertexBufferAttribute(vertexBuffer, ComponentDatatype.UnsignedByte, 1);
                    }
                }
                else
                {
                    Debug.Fail("attribute.Datatype");
                }
            }

            return(meshBuffers);
        }
Ejemplo n.º 2
0
 public virtual VertexArray CreateVertexArray(Mesh mesh, ShaderVertexAttributeCollection shaderAttributes, BufferHint usageHint)
 {
     return(CreateVertexArray(Device.CreateMeshBuffers(mesh, shaderAttributes, usageHint)));
 }