//Create meshes and add vertex and index buffers private void AddVertexData(Model model, Scene scene, Node node, Device device, ref Matrix transform) { Matrix previousTransform = transform; transform = Matrix.Multiply(previousTransform, FromMatrix(node.Transform)); //also calculate inverse transpose matrix for normal/tangent/bitagent transformation Matrix invTranspose = transform; invTranspose.Invert(); invTranspose.Transpose(); if (node.HasMeshes) { foreach (int index in node.MeshIndices) { //get a mesh from the scene Assimp.Mesh mesh = scene.Meshes[index]; //create new mesh to add to model ModelMesh modelMesh = new ModelMesh(); model.AddMesh(ref modelMesh); //if mesh has a material extract the diffuse texture, if present Material material = scene.Materials[mesh.MaterialIndex]; if (material != null && material.GetMaterialTextureCount(TextureType.Diffuse) > 0) { material.GetMaterialTexture(TextureType.Diffuse, 0, out TextureSlot texture); //create new texture for mesh modelMesh.AddTextureDiffuse(device, m_modelPath + "\\" + texture.FilePath); } //determine the elements in the vertex bool hasTexCoords = mesh.HasTextureCoords(0); bool hasColors = mesh.HasVertexColors(0); bool hasNormals = mesh.HasNormals; bool hasTangents = mesh.Tangents != null && mesh.Tangents.Count > 0; bool hasBitangents = mesh.BiTangents != null && mesh.BiTangents.Count > 0; //create vertex element list InputElement[] vertexElements = new InputElement[GetNoofInputElements(mesh)]; uint elementIndex = 0; vertexElements[elementIndex++] = new InputElement("POSITION", 0, Format.R32G32B32_Float, 0, 0); short vertexSize = (short)Utilities.SizeOf <Vector3>(); if (hasColors) { vertexElements[elementIndex++] = new InputElement("COLOR", 0, Format.R8G8B8A8_UInt, vertexSize, 0); vertexSize += (short)Utilities.SizeOf <Color>(); } if (hasNormals) { vertexElements[elementIndex++] = new InputElement("NORMAL", 0, Format.R32G32B32_Float, vertexSize, 0); vertexSize += (short)Utilities.SizeOf <Vector3>(); } if (hasTangents) { vertexElements[elementIndex++] = new InputElement("TANGENT", 0, Format.R32G32B32_Float, vertexSize, 0); vertexSize += (short)Utilities.SizeOf <Vector3>(); } if (hasBitangents) { vertexElements[elementIndex++] = new InputElement("BITANGENT", 0, Format.R32G32B32_Float, vertexSize, 0); vertexSize += (short)Utilities.SizeOf <Vector3>(); } if (hasTexCoords) { vertexElements[elementIndex++] = new InputElement("TEXCOORD", 0, Format.R32G32_Float, vertexSize, 0); vertexSize += (short)Utilities.SizeOf <Vector2>(); } //set the vertex elements and size modelMesh.InputElements = vertexElements; modelMesh.VertexSize = vertexSize; //get pointers to vertex data var positions = mesh.Vertices; var texCoords = mesh.TextureCoordinateChannels[0]; var normals = mesh.Normals; var tangents = mesh.Tangents; var biTangents = mesh.BiTangents; var colours = mesh.VertexColorChannels[0]; //also determine primitive type switch (mesh.PrimitiveType) { case PrimitiveType.Point: modelMesh.PrimitiveTopology = PrimitiveTopology.PointList; break; case PrimitiveType.Line: modelMesh.PrimitiveTopology = PrimitiveTopology.LineList; break; case PrimitiveType.Triangle: modelMesh.PrimitiveTopology = PrimitiveTopology.TriangleList; break; default: throw new Exception("ModelLoader::AddVertexData(): Unknown primitive type"); } //create data stream for vertices DataStream vertexStream = new DataStream(mesh.VertexCount * vertexSize, true, true); for (int i = 0; i < mesh.VertexCount; i++) { //add position, after transforming it with accumulated node transform { Vector4 result; Vector3 pos = FromVector(positions[i]); Vector3.Transform(ref pos, ref transform, out result); vertexStream.Write <Vector3>(new Vector3(result.X, result.Y, result.Z)); } if (hasColors) { Color vertColor = FromColor(mesh.VertexColorChannels[0][i]); vertexStream.Write <Color>(vertColor); } if (hasNormals) { Vector4 result; Vector3 normal = FromVector(normals[i]); Vector3.Transform(ref normal, ref invTranspose, out result); vertexStream.Write <Vector3>(new Vector3(result.X, result.Y, result.Z)); } if (hasTangents) { Vector4 result; Vector3 tangent = FromVector(tangents[i]); Vector3.Transform(ref tangent, ref invTranspose, out result); vertexStream.Write <Vector3>(new Vector3(result.X, result.Y, result.Z)); } if (hasBitangents) { Vector4 result; Vector3 biTangent = FromVector(biTangents[i]); Vector3.Transform(ref biTangent, ref invTranspose, out result); vertexStream.Write <Vector3>(new Vector3(result.X, result.Y, result.Z)); } if (hasTexCoords) { vertexStream.Write <Vector2>(new Vector2(texCoords[i].X, 1 - texCoords[i].Y)); } } vertexStream.Position = 0; //create new vertex buffer var vertexBuffer = new Buffer(device, vertexStream, new BufferDescription() { BindFlags = BindFlags.VertexBuffer, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None, SizeInBytes = mesh.VertexCount * vertexSize, Usage = ResourceUsage.Default } ); //add it to the mesh modelMesh.VertexBuffer = vertexBuffer; modelMesh.VertexCount = mesh.VertexCount; modelMesh.PrimitiveCount = mesh.FaceCount; //get pointer to indices data uint[] indices = mesh.GetIndices().Select(i => (uint)i).ToArray(); //create data stream for indices DataStream indexStream = new DataStream(indices.GetLength(0) * sizeof(uint), true, true); for (int i = 0; i < indices.GetLength(0); i++) { indexStream.Write <uint>(indices[i]); } indexStream.Position = 0; //create new index buffer var indexBuffer = new Buffer(device, indexStream, new BufferDescription() { BindFlags = BindFlags.IndexBuffer, CpuAccessFlags = CpuAccessFlags.None, OptionFlags = ResourceOptionFlags.None, SizeInBytes = indices.GetLength(0) * sizeof(uint), Usage = ResourceUsage.Default } ); //add it to the mesh modelMesh.IndexBuffer = indexBuffer; modelMesh.IndexCount = indices.GetLength(0); } } //if node has more children process them as well for (int i = 0; i < node.ChildCount; i++) { AddVertexData(model, scene, node.Children[i], device, ref transform); } transform = previousTransform; }
public void AddMesh(ref ModelMesh mesh) { m_meshes.Add(mesh); }