//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) { TextureSlot texture; material.GetMaterialTexture(TextureType.Diffuse, 0, out 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; bool hasBitangents = mesh.BiTangents != null; //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 Vector3D[] positions = mesh.Vertices.ToArray(); Vector3D[] texCoords = mesh.TextureCoordinateChannels[0].ToArray(); Vector3D[] normals = mesh.Normals.ToArray(); Vector3D[] tangents = mesh.Tangents.ToArray(); Vector3D[] biTangents = mesh.BiTangents.ToArray(); Color4D[] colours = mesh.VertexColorChannels[0].ToArray(); //also determine primitive type switch (mesh.PrimitiveType) { case Assimp.PrimitiveType.Point: modelMesh.PrimitiveTopology = PrimitiveTopology.PointList; break; case Assimp.PrimitiveType.Line: modelMesh.PrimitiveTopology = PrimitiveTopology.LineList; break; case Assimp.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].ToArray()[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.GetUnsignedIndices(); //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; }