/// <summary> /// Gets vertex data from a given <see cref="AssimpMesh"/>. /// </summary> /// <param name="sceneMesh">The <see cref="AssimpMesh"/> to get vertex information from.</param> /// <param name="boneIndexByName">A lookup of bone index by name information.</param> /// <returns>An output list of vertices.</returns> private Vertex[] GetMeshVertices(AssimpMesh sceneMesh, Dictionary <string, uint> boneIndexByName) { var positions = sceneMesh.Vertices; var normals = sceneMesh.Normals; var tangents = sceneMesh.Tangents; var colors = sceneMesh.HasVertexColors(0) ? sceneMesh.VertexColorChannels[0] : null; var textureCoordinates = sceneMesh.HasTextureCoords(0) ? sceneMesh.TextureCoordinateChannels[0] : null; var boneWeightsByVertexIndex = GetBoneWeightsByVertexIndex(boneIndexByName, sceneMesh); var vertices = new List <Vertex>(); for (var i = 0; i < positions.Count; i++) { var position = positions[i]; var normal = normals[i]; var tangent = tangents[i]; var color = colors?[i]; var textureCoordinate = textureCoordinates?[i]; TryGetBoneIndicesAndWeights(boneWeightsByVertexIndex, i, out var boneIndices, out var boneWeights); vertices.Add(new Vertex(new Vector3(position.X, position.Y, position.Z), new Vector3(normal.X, normal.Y, normal.Z), new Vector3(tangent.X, tangent.Y, tangent.Z), color != null ? new Color(color.Value.R, color.Value.G, color.Value.B, color.Value.A) : new Color(1.0f, 1.0f, 1.0f, 1.0f), textureCoordinate != null ? new Vector2(textureCoordinate.Value.X, textureCoordinate.Value.Y) : Vector2.Zero, new ReadOnlyCollection <uint>(boneIndices), new ReadOnlyCollection <float>(boneWeights))); } return(vertices.ToArray()); }
private void _initMesh(Assimp.Mesh mesh) { Assimp.Vector3D Zero3D = new Assimp.Vector3D(0f); if (mesh.PrimitiveType == Assimp.PrimitiveType.Triangle) { // Populate the vertex attribute vectors for (int i = 0; i < mesh.VertexCount; i++) { Assimp.Vector3D pos = mesh.Vertices[i]; Assimp.Vector3D normal = mesh.Normals[i]; Assimp.Vector3D uv = mesh.HasTextureCoords(0) ? mesh.TextureCoordinateChannels[0][i] : Zero3D; positions.Add(new Vector3f(pos.X, pos.Y, pos.Z)); normals.Add(new Vector3f(normal.X, normal.Y, normal.Z)); uvs.Add(new Vector2f(uv.X, uv.Y)); } // Populate the index buffer for (int i = 0; i < mesh.FaceCount; i++) { Assimp.Face face = mesh.Faces[i]; // TODO: Find a suitable way to draw vertices... // Now only support triangulated faces indices.Add(face.Indices[0]); indices.Add(face.Indices[1]); indices.Add(face.Indices[2]); } } }
private Mesh ProcessMesh(Assimp.Mesh aMesh, Scene scene) { Mesh mesh = new Mesh(); for (int i = 0; i < aMesh.VertexCount; i++) { Vertex vertex = new Vertex { Position = new Vector3(aMesh.Vertices[i].X, aMesh.Vertices[i].Y, aMesh.Vertices[i].Z) }; if (aMesh.HasNormals) { vertex.Normals = new Vector3(aMesh.Normals[i].X, aMesh.Normals[i].Y, aMesh.Normals[i].Z); } if (aMesh.HasTextureCoords(0)) { vertex.TexCoords = new Vector2(aMesh.TextureCoordinateChannels[0][i].X, aMesh.TextureCoordinateChannels[0][i].Y); if (aMesh.HasTangentBasis) { vertex.Tangent = new Vector3(aMesh.Tangents[i].X, aMesh.Tangents[i].Y, aMesh.Tangents[i].Z); vertex.Bitangent = new Vector3(aMesh.BiTangents[i].X, aMesh.BiTangents[i].Y, aMesh.BiTangents[i].Z); } } else { vertex.TexCoords = Vector2.Zero; } mesh.Vertices = mesh.Vertices.Append(vertex).ToArray(); } for (int i = 0; i < aMesh.FaceCount; i++) { for (int j = 0; j < aMesh.Faces[i].IndexCount; j++) { mesh.Indices = mesh.Indices.Append(aMesh.Faces[i].Indices[j]).ToArray(); } } var material = scene.Materials[aMesh.MaterialIndex]; List <Texture> diffuseMaps = LoadMaterialTextures(material, TextureType.Diffuse, "texture_diffuse"); mesh.Textures.AddRange(diffuseMaps); List <Texture> specularMaps = LoadMaterialTextures(material, TextureType.Specular, "texture_specular"); mesh.Textures.AddRange(specularMaps); List <Texture> normalMaps = LoadMaterialTextures(material, TextureType.Normals, "texture_normal"); mesh.Textures.AddRange(normalMaps); List <Texture> heightMaps = LoadMaterialTextures(material, TextureType.Height, "texture_height"); mesh.Textures.AddRange(heightMaps); mesh.SetupMesh(); return(mesh); }
Mesh processMesh(Assimp.Mesh mesh, Assimp.Scene scene) { List <Vertex> vertices = null; List <int> indices = null; List <Texture> textures = null; for (int i = 0; i < mesh.VertexCount; i++) { Vertex vert = new Vertex(); Vector3 vec = new Vector3(); vec.X = mesh.Vertices[i].X; vec.Y = mesh.Vertices[i].Y; vec.Z = mesh.Vertices[i].Z; vert.position = vec; vec.X = mesh.Normals[i].X; vec.Y = mesh.Normals[i].Y; vec.Z = mesh.Normals[i].Z; vert.normal = vec; if (mesh.HasTextureCoords(0)) { Vector2 vec2 = new Vector2(); vec2.X = mesh.TextureCoordinateChannels[0][i].X; vec2.Y = mesh.TextureCoordinateChannels[0][i].Y; vert.texCoord = vec2; } else { vert.texCoord = new Vector2(0, 0); } vertices.Add(vert); } for (int i = 0; i < mesh.FaceCount; i++) { Assimp.Face face = new Face(); face = mesh.Faces[i]; for (int j = 0; j < face.IndexCount; j++) { indices.Add(face.Indices[j]); } } if (mesh.MaterialIndex >= 0) { Material material = scene.Materials[mesh.MaterialIndex]; List <Texture> diffuseMaps = new List <Texture>(); diffuseMaps.AddRange(loadMaterialTextures(material, TextureType.Diffuse, "texture_diffuse")); textures.InsertRange(textures.Count + 1, diffuseMaps); List <Texture> specularMaps = new List <Texture>(); specularMaps.AddRange(loadMaterialTextures(material, TextureType.Specular, "texture_specular")); textures.InsertRange(textures.Count + 1, specularMaps); } return(new Mesh(vertices, indices, textures)); }
/// <summary> /// Processes a Mesh in an Assimp Scene /// </summary> /// <param name="mesh">The Current mesh to process</param> /// <param name="s">The root scene</param> /// <param name="dir">The Relative directory of the Mesh File</param> /// <returns>The mesh loaded.</returns> private static Mesh processMesh(AssimpMesh mesh, Scene s, string dir, object handleIdentifier) { List <Vertex> vertices = new List <Vertex>(); List <uint> indices = new List <uint>(); List <Texture> textures = new List <Texture>(); Logger.Log(DebugChannel.Log | DebugChannel.EngineIO, "Converting Imported Mesh File Structure to GameEngine Engine Structure", 3); Logger.Log(DebugChannel.Log | DebugChannel.EngineIO, "Copying Vertex Data...", 2); for (int i = 0; i < mesh.VertexCount; i++) { Vector3D vert = mesh.Vertices[i]; Vector3D norm = mesh.Normals[i]; Vector3D tan = mesh.HasTangentBasis ? mesh.Tangents[i] : new Vector3D(0); Vector3D bit = mesh.HasTangentBasis ? mesh.BiTangents[i] : new Vector3D(0); Vector3D uv = mesh.HasTextureCoords(0) ? mesh.TextureCoordinateChannels[0][i] : new Vector3D(0); Vertex v = new Vertex { Position = new Vector3(vert.X, vert.Y, vert.Z), Normal = new Vector3(norm.X, norm.Y, norm.Z), UV = new Vector2(uv.X, uv.Y), Bittangent = new Vector3(bit.X, bit.Y, bit.Z), Tangent = new Vector3(tan.X, tan.Y, tan.Z) }; vertices.Add(v); } Logger.Log(DebugChannel.Log | DebugChannel.EngineIO, "Calculating Indices...", 2); for (int i = 0; i < mesh.FaceCount; i++) { Face f = mesh.Faces[i]; indices.AddRange(f.Indices.Select(x => (uint)x)); } Material m = s.Materials[mesh.MaterialIndex]; Logger.Log(DebugChannel.Log | DebugChannel.EngineIO, "Loading Baked Material: " + m.Name, 2); textures.AddRange(TextureLoader.LoadMaterialTextures(m, TextureType.Diffuse, dir)); textures.AddRange(TextureLoader.LoadMaterialTextures(m, TextureType.Specular, dir)); textures.AddRange(TextureLoader.LoadMaterialTextures(m, TextureType.Normals, dir)); textures.AddRange(TextureLoader.LoadMaterialTextures(m, TextureType.Height, dir)); setupMesh(indices.ToArray(), vertices.ToArray(), out int vao, out int vbo, out int ebo); long bytes = indices.Count * sizeof(uint) + vertices.Count * Vertex.VERTEX_BYTE_SIZE; return(new Mesh(ebo, vbo, vao, indices.Count, bytes, false, handleIdentifier)); }
private static void FbxIndexToFloatList(int faceIndex, Assimp.Mesh mesh, Face face, FbxMeshData fbxData) { int index = face.Indices[faceIndex]; Vector3D v = mesh.Vertices[index]; fbxData.vList.Add(v.X * fbxData.multiplier.X); fbxData.vList.Add(v.Y * fbxData.multiplier.Y); fbxData.vList.Add(v.Z * fbxData.multiplier.Z); if (mesh.HasTextureCoords(0)) { Vector3D uv = mesh.TextureCoordinateChannels[0][index]; fbxData.vtList.Add(uv.X); fbxData.vtList.Add(1 - uv.Y); } if (mesh.HasNormals) { Vector3D n = mesh.Normals[index]; fbxData.vnList.Add(n.X); fbxData.vnList.Add(n.Y); fbxData.vnList.Add(n.Z); } if (mesh.HasBones) { float[] bonesMapping = { -1, -1, -1, -1 }; float[] bonesWeight = { -1, -1, -1, -1 }; if (fbxData.bonesInfluences.ContainsKey(index)) { for (int i = 0; i < Math.Min(fbxData.bonesInfluences[index].Count, 4); i++) { int boneId = mesh.Bones.IndexOf(fbxData.bonesInfluences[index][i].bone); bonesMapping[i] = boneId; bonesWeight[i] = fbxData.bonesInfluences[index][i].weight; } } fbxData.bonesMappingList.Add(bonesMapping[0]); fbxData.bonesMappingList.Add(bonesMapping[1]); fbxData.bonesMappingList.Add(bonesMapping[2]); fbxData.bonesMappingList.Add(bonesMapping[3]); fbxData.bonesWeightList.Add(bonesWeight[0]); fbxData.bonesWeightList.Add(bonesWeight[1]); fbxData.bonesWeightList.Add(bonesWeight[2]); fbxData.bonesWeightList.Add(bonesWeight[3]); } }
private static List <float> ProcessTextCoord(Assimp.Mesh mesh) { List <float> textCoord = new List <float>(); if (mesh.HasTextureCoords(0)) { foreach (var tc in mesh.TextureCoordinateChannels[0]) { textCoord.Add(tc.X); textCoord.Add(1 - tc.Y); } } return(textCoord); }
private Mesh ProgressMesh(Assimp.Mesh mesh, Assimp.Scene scene) { List <Vertex> vertices = new List <Vertex>(); List <uint> indices = new List <uint>(); List <Texture> textures = new List <Texture>(); for (int i = 0; i < mesh.VertexCount; i++) { Vertex vertex = new Vertex(); vertex.Position = new OpenTK.Vector3(mesh.Vertices[i].X, mesh.Vertices[i].Y, mesh.Vertices[i].Z); vertex.Normal = new OpenTK.Vector3(mesh.Normals[i].X, mesh.Normals[i].Y, mesh.Normals[i].Z); if (mesh.HasTextureCoords(0)) { vertex.TexCoords = new OpenTK.Vector2(mesh.TextureCoordinateChannels[0][i].X, mesh.TextureCoordinateChannels[0][i].Y); } else { vertex.TexCoords = new OpenTK.Vector2(0, 0); } vertices.Add(vertex); } for (int i = 0; i < mesh.FaceCount; i++) { Face face = mesh.Faces[i]; for (int j = 0; j < face.IndexCount; j++) { indices.Add((uint)face.Indices[j]); } } if (mesh.MaterialIndex >= 0) { Material material = scene.Materials[mesh.MaterialIndex]; List <Texture> diffuseMap = LoadMaterialTextures(material, TextureType.Diffuse, "texture_diffuse"); textures.InsertRange(textures.Count, diffuseMap); List <Texture> specularMap = LoadMaterialTextures(material, TextureType.Specular, "texture_specular"); textures.InsertRange(textures.Count, specularMap); } return(new Mesh(vertices.ToArray(), indices.ToArray(), textures.ToArray())); }
IEnumerable <AssimpVertex> GetVertex(Assimp.Mesh m) { for (int i = 0; i < m.VertexCount; ++i) { Vector3 cc = m.Vertices[i].ToVector3(); var bw = GetWAndB(m, i); yield return(new AssimpVertex() { position = cc, uv = m.HasTextureCoords(0) ? m.TextureCoordinateChannels[0][i].ToVector3() : new Vector3(), tangent = m.HasTangentBasis ? m.Tangents[i].ToVector3() : new Vector3(), biTangent = m.HasTangentBasis ? m.BiTangents[i].ToVector3() : new Vector3(), normal = m.HasNormals ? m.Normals[i].ToVector3() : new Vector3(), BoneID = HasAnimation && m.HasBones ? GetBoneID(bw) : new Vector4(), BoneWheight = HasAnimation && m.HasBones ? GetWheight(bw) : new Vector4(), Color = m.HasVertexColors(0) ? m.VertexColorChannels[0][i].ToColor4() : new Color4(0.5f, 0.5f, 0.5f, 1) }); } yield break; }
Mesh processMesh(Assimp.Mesh mesh, Scene scene) { List <Vertex> vertices = new List <Vertex>(); List <uint> indices = new List <uint>(); List <MeshTexture> textures = new List <MeshTexture>(); for (int i = 0; i < mesh.VertexCount; i++) { Vertex vertex = new Vertex(); // 处理顶点位置、法线和纹理坐标 vertex.pos = mesh.Vertices[i].ToVector3(); vertex.normal = mesh.Normals[i].ToVector3(); if (mesh.HasTextureCoords(0)) { vertex.uv = mesh.TextureCoordinateChannels[0][i].XY().ToVector2(); } vertices.Add(vertex); } // 处理索引 foreach (var face in mesh.Faces) { foreach (uint indice in face.Indices) { indices.Add(indice); } } // 处理材质 if (mesh.MaterialIndex >= 0) { Material material = scene.Materials[mesh.MaterialIndex]; MeshTexture[] diffuseMaps = loadMaterialTextures(material, TextureType.Diffuse, "material.diffuse"); textures.AddRange(diffuseMaps); MeshTexture[] specularMaps = loadMaterialTextures(material, TextureType.Specular, "material.specular"); textures.AddRange(specularMaps); } return(new Mesh(vertices.ToArray(), indices.ToArray(), textures.ToArray())); }
//determine the number of elements in the vertex private int GetNoofInputElements(Assimp.Mesh mesh) { 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; int noofElements = 1; if (hasColors) { noofElements++; } if (hasNormals) { noofElements++; } if (hasTangents) { noofElements++; } if (hasBitangents) { noofElements++; } if (hasTexCoords) { noofElements++; } return(noofElements); }
void WriteVertices(Mesh assimpMesh, ModelData.MeshPart meshPart, ModelData.VertexBuffer vertexBuffer, int vertexBufferElementSize) { // Write all vertices meshPart.VertexBufferRange.Count = assimpMesh.VertexCount; vertexBuffer.Count = assimpMesh.VertexCount; vertexBuffer.Buffer = new byte[vertexBufferElementSize * assimpMesh.VertexCount]; // Update the MaximumBufferSizeInBytes needed to load this model if (vertexBuffer.Buffer.Length > model.MaximumBufferSizeInBytes) { model.MaximumBufferSizeInBytes = vertexBuffer.Buffer.Length; } var vertexStream = DataStream.Create(vertexBuffer.Buffer, true, true); for (int i = 0; i < assimpMesh.VertexCount; i++) { var position = assimpMesh.Vertices[i]; vertexStream.Write(position); // Store bounding points for BoundingSphere pre-calculation boundingPoints[currentBoundingPointIndex++] = new Vector3(position.X, position.Y, position.Z); // Add normals if (assimpMesh.HasNormals) { vertexStream.Write(assimpMesh.Normals[i]); } // Add colors if (assimpMesh.VertexColorChannelCount > 0) { for (int j = 0; j < assimpMesh.VertexColorChannelCount; j++) { if (assimpMesh.HasVertexColors(j)) { vertexStream.Write(assimpMesh.GetVertexColors(j)[i]); } } } // Add textures if (assimpMesh.TextureCoordsChannelCount > 0) { for (int j = 0; j < assimpMesh.TextureCoordsChannelCount; j++) { if (assimpMesh.HasTextureCoords(j)) { var uvCount = assimpMesh.GetUVComponentCount(j); var uv = assimpMesh.GetTextureCoords(j)[i]; if (uvCount == 2) { vertexStream.Write(new Vector2(uv.X, uv.Y)); } else { vertexStream.Write(uv); } } } } // Add tangent / bitangent if (assimpMesh.HasTangentBasis) { if (!options.ExcludeElements.Contains("Tangent")) { double w = Vector3D.Dot(assimpMesh.Normals[i], Vector3D.Cross(assimpMesh.Tangents[i], assimpMesh.Tangents[i])); Vector3D t = assimpMesh.Tangents[i]; Vector4 t4D = new Vector4(t.X, t.Y, t.Z, (float)w); vertexStream.Write(t4D); } if (!options.ExcludeElements.Contains("BiTangent")) { vertexStream.Write(assimpMesh.BiTangents[i]); } } } vertexStream.Dispose(); }
/// <summary> /// Draw a mesh using either its given material or a transparent "ghost" material. /// </summary> /// <param name="node">Current node</param> /// <param name="animated">Specifies whether animations should be played</param> /// <param name="showGhost">Indicates whether to substitute the mesh' material with a /// "ghost" surrogate material that allows looking through the geometry.</param> /// <param name="index">Mesh index in the scene</param> /// <param name="mesh">Mesh instance</param> /// <param name="flags"> </param> /// <returns></returns> protected override bool InternDrawMesh(Node node, bool animated, bool showGhost, int index, Mesh mesh, RenderFlags flags) { if (showGhost) { Owner.MaterialMapper.ApplyGhostMaterial(mesh, Owner.Raw.Materials[mesh.MaterialIndex], flags.HasFlag(RenderFlags.Shaded)); } else { Owner.MaterialMapper.ApplyMaterial(mesh, Owner.Raw.Materials[mesh.MaterialIndex], flags.HasFlag(RenderFlags.Textured), flags.HasFlag(RenderFlags.Shaded)); } if (GraphicsSettings.Default.BackFaceCulling) { GL.FrontFace(FrontFaceDirection.Ccw); GL.CullFace(CullFaceMode.Back); GL.Enable(EnableCap.CullFace); } else { GL.Disable(EnableCap.CullFace); } var hasColors = mesh.HasVertexColors(0); var hasTexCoords = mesh.HasTextureCoords(0); var skinning = mesh.HasBones && animated; foreach (var face in mesh.Faces) { BeginMode faceMode; switch (face.IndexCount) { case 1: faceMode = BeginMode.Points; break; case 2: faceMode = BeginMode.Lines; break; case 3: faceMode = BeginMode.Triangles; break; default: faceMode = BeginMode.Polygon; break; } GL.Begin(faceMode); for (var i = 0; i < face.IndexCount; i++) { var indice = face.Indices[i]; if (hasColors) { var vertColor = AssimpToOpenTk.FromColor(mesh.VertexColorChannels[0][indice]); GL.Color4(vertColor); } if (mesh.HasNormals) { Vector3 normal; if (skinning) { Skinner.GetTransformedVertexNormal(node, mesh, (uint)indice, out normal); } else { normal = AssimpToOpenTk.FromVector(mesh.Normals[indice]); } GL.Normal3(normal); } if (hasTexCoords) { var uvw = AssimpToOpenTk.FromVector(mesh.TextureCoordinateChannels[0][indice]); GL.TexCoord2(uvw.X, 1 - uvw.Y); } Vector3 pos; if (skinning) { Skinner.GetTransformedVertexPosition(node, mesh, (uint)indice, out pos); } else { pos = AssimpToOpenTk.FromVector(mesh.Vertices[indice]); } GL.Vertex3(pos); } GL.End(); } GL.Disable(EnableCap.CullFace); return skinning; }
private ModelData.MeshPart Process(ModelData.Mesh mesh, Assimp.Mesh assimpMesh) { var meshPart = new ModelData.MeshPart() { MaterialIndex = assimpMesh.MaterialIndex, VertexBufferRange = new ModelData.BufferRange() { Slot = mesh.VertexBuffers.Count }, IndexBufferRange = new ModelData.BufferRange() { Slot = mesh.IndexBuffers.Count } }; var vertexBuffer = new ModelData.VertexBuffer() { Layout = new List <VertexElement>() }; mesh.VertexBuffers.Add(vertexBuffer); var indexBuffer = new ModelData.IndexBuffer(); mesh.IndexBuffers.Add(indexBuffer); var layout = vertexBuffer.Layout; int vertexBufferElementSize = 0; // Add position layout.Add(VertexElement.PositionTransformed(Format.R32G32B32_Float, 0)); vertexBufferElementSize += Utilities.SizeOf <SharpDX.Vector3>(); // Add normals if (assimpMesh.HasNormals) { layout.Add(VertexElement.Normal(0, Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <SharpDX.Vector3>(); } // Add colors if (assimpMesh.VertexColorChannelCount > 0) { for (int localIndex = 0, i = 0; i < assimpMesh.VertexColorChannelCount; i++) { if (assimpMesh.HasVertexColors(i)) { layout.Add(VertexElement.Color(localIndex, Format.R32G32B32A32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <SharpDX.Color4>(); localIndex++; } } } // Add textures if (assimpMesh.TextureCoordsChannelCount > 0) { for (int localIndex = 0, i = 0; i < assimpMesh.TextureCoordsChannelCount; i++) { if (assimpMesh.HasTextureCoords(i)) { var uvCount = assimpMesh.GetUVComponentCount(i); if (uvCount == 2) { layout.Add(VertexElement.TextureCoordinate(localIndex, Format.R32G32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <SharpDX.Vector2>(); } else if (uvCount == 3) { layout.Add(VertexElement.TextureCoordinate(localIndex, Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <SharpDX.Vector3>(); } else { throw new InvalidOperationException("Unexpected uv count"); } localIndex++; } } } // Add tangent / bitangent if (assimpMesh.HasTangentBasis) { layout.Add(VertexElement.Tangent(Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <SharpDX.Vector3>(); layout.Add(VertexElement.BiTangent(Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <SharpDX.Vector3>(); } // Extract Skinning Indices / Weights bool hasWeights = false; var skinningCount = new int[assimpMesh.VertexCount]; var skinningIndices = new Int4[assimpMesh.VertexCount]; var skinningWeights = new Vector4[assimpMesh.VertexCount]; if (assimpMesh.HasBones) { meshPart.BoneOffsetMatrices = new Matrix[assimpMesh.BoneCount]; for (int i = 0; i < assimpMesh.Bones.Length; i++) { var bone = assimpMesh.Bones[i]; meshPart.BoneOffsetMatrices[i] = ConvertMatrix(bone.OffsetMatrix); if (bone.HasVertexWeights) { var boneNode = scene.RootNode.FindNode(bone.Name); var boneIndex = skinnedBones[boneNode]; for (int j = 0; j < bone.VertexWeightCount; j++) { var weights = bone.VertexWeights[j]; var vertexSkinningCount = skinningCount[weights.VertexID]; skinningIndices[weights.VertexID][vertexSkinningCount] = boneIndex; skinningWeights[weights.VertexID][vertexSkinningCount] = weights.Weight; skinningCount[weights.VertexID] = ++vertexSkinningCount; } hasWeights = true; } } if (hasWeights) { layout.Add(VertexElement.BlendIndices(Format.R16G16B16A16_SInt, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <SharpDX.Int4>(); layout.Add(VertexElement.BlendWeights(Format.R32G32B32A32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <SharpDX.Vector4>(); } } // Write all vertices meshPart.VertexBufferRange.Count = assimpMesh.VertexCount; vertexBuffer.Count = assimpMesh.VertexCount; vertexBuffer.Buffer = new byte[vertexBufferElementSize * assimpMesh.VertexCount]; // Update the MaximumBufferSizeInBytes needed to load this model if (vertexBuffer.Buffer.Length > model.MaximumBufferSizeInBytes) { model.MaximumBufferSizeInBytes = vertexBuffer.Buffer.Length; } var vertexStream = DataStream.Create(vertexBuffer.Buffer, true, true); for (int i = 0; i < assimpMesh.VertexCount; i++) { var position = assimpMesh.Vertices[i]; vertexStream.Write(position); // Store bounding points for BoundingSphere pre-calculation boundingPoints[currentBoundingPointIndex++] = new Vector3(position.X, position.Y, position.Z); // Add normals if (assimpMesh.HasNormals) { vertexStream.Write(assimpMesh.Normals[i]); } // Add colors if (assimpMesh.VertexColorChannelCount > 0) { for (int j = 0; j < assimpMesh.VertexColorChannelCount; j++) { if (assimpMesh.HasVertexColors(j)) { vertexStream.Write(assimpMesh.GetVertexColors(j)[i]); } } } // Add textures if (assimpMesh.TextureCoordsChannelCount > 0) { for (int j = 0; j < assimpMesh.TextureCoordsChannelCount; j++) { if (assimpMesh.HasTextureCoords(j)) { var uvCount = assimpMesh.GetUVComponentCount(j); var uv = assimpMesh.GetTextureCoords(j)[i]; if (uvCount == 2) { vertexStream.Write(new Vector2(uv.X, uv.Y)); } else { vertexStream.Write(uv); } } } } // Add tangent / bitangent if (assimpMesh.HasTangentBasis) { vertexStream.Write(assimpMesh.Tangents[i]); vertexStream.Write(assimpMesh.BiTangents[i]); } // Add Skinning Indices/Weights if (assimpMesh.HasBones && hasWeights) { vertexStream.Write(skinningIndices[i]); vertexStream.Write(skinningWeights[i]); } } vertexStream.Dispose(); // Write all indices var indices = assimpMesh.GetIntIndices(); indexBuffer.Count = indices.Length; meshPart.IndexBufferRange.Count = indices.Length; if (meshPart.VertexBufferRange.Count < 65536) { // Write only short indices if count is less than the size of a short indexBuffer.Buffer = new byte[indices.Length * 2]; using (var indexStream = DataStream.Create(indexBuffer.Buffer, true, true)) foreach (int index in indices) { indexStream.Write((ushort)index); } } else { // Otherwise, use full 32-bit precision to store indices indexBuffer.Buffer = new byte[indices.Length * 4]; using (var indexStream = DataStream.Create(indexBuffer.Buffer, true, true)) indexStream.WriteRange(indices); } // Update the MaximumBufferSizeInBytes needed to load this model if (indexBuffer.Buffer.Length > model.MaximumBufferSizeInBytes) { model.MaximumBufferSizeInBytes = indexBuffer.Buffer.Length; } return(meshPart); }
private void CreateBuffers(Node assimpnode, ModelNode parent_node, ref Matrix4x4 model_matrix) { // create new mesh ModelNode node = new ModelNode(_openGLFactory); if (parent_node != null) { parent_node.AddChild(node); } else { _model._root_node = node; } // set model matrix Matrix4x4 mm = assimpnode.Transform; node.ModelMatrix = new Matrix4( mm.A1, mm.A2, mm.A3, mm.A4, mm.B1, mm.B2, mm.B3, mm.B4, mm.C1, mm.C2, mm.C3, mm.C4, mm.D1, mm.D2, mm.D3, mm.D4); // combined model matrix Matrix4x4 prev_model = model_matrix; Matrix4x4 new_transform = assimpnode.Transform; model_matrix = new_transform * model_matrix; // ? has this to be reversed link in OpneTK? if (assimpnode.HasMeshes) { foreach (int index in assimpnode.MeshIndices) { Assimp.Mesh assimpmesh = _assimpmodel.Meshes[index]; AABB mesh_box = new AABB(); // extend bounding box by vertices for (int i = 0; i < assimpmesh.VertexCount; i++) { Vector3D tmp = assimpmesh.Vertices[i]; mesh_box = mesh_box | new Vector3(tmp.X, tmp.Y, tmp.Z); tmp = model_matrix * tmp; _model._scene_box = _model._scene_box | new Vector3(tmp.X, tmp.Y, tmp.Z); } // create Mesh uint tuple_index = 0; List <TVertexFormat> formalist = new List <TVertexFormat>(); OpenTK_library.Scene.Mesh mesh = new OpenTK_library.Scene.Mesh(); mesh.Box = mesh_box; node.Add(mesh); // specify vertices mesh.VertexAttribute = (tuple_index, 3); formalist.Add(new TVertexFormat(0, vertex_index, 3, (int)tuple_index, false)); tuple_index += 3; // specify normals if (assimpmesh.HasNormals) { mesh.NormalAttribute = (tuple_index, 3); formalist.Add(new TVertexFormat(0, normal_index, 3, (int)tuple_index, false)); tuple_index += 3; } // specify bi-normals and tangents if (assimpmesh.HasTangentBasis) { mesh.BinormalAttribute = (tuple_index, 3); formalist.Add(new TVertexFormat(0, binormal_index, 3, (int)tuple_index, false)); tuple_index += 3; mesh.TangentAttribute = (tuple_index, 3); formalist.Add(new TVertexFormat(0, tangent_index, 3, (int)tuple_index, false)); tuple_index += 3; } // specify texture channels for (int textur_channel = 0; assimpmesh.HasTextureCoords(textur_channel); ++textur_channel) { mesh.AddTextureAttrib((tuple_index, 3)); int attr_i = textur_channel == 0 ? texture0_index : (textureN_index + textur_channel - 1); formalist.Add(new TVertexFormat(0, attr_i, 3, (int)tuple_index, false)); tuple_index += 3; } // specify color channels for (int color_channel = 0; assimpmesh.HasVertexColors(color_channel); ++color_channel) { mesh.AddColorAttrib((tuple_index, 4)); int attr_i = color_channel == 0 ? color0_index : (colorN_index + color_channel - 1); formalist.Add(new TVertexFormat(0, attr_i, 4, (int)tuple_index, false)); tuple_index += 4; } // TODO $$$ bones if (assimpmesh.HasBones) { // [...] Console.WriteLine("bones not yet implemented"); } // set tuple size mesh.TupleSize = tuple_index; // setup index buffer List <float> attributes = new List <float>(); List <uint> indices = new List <uint>(); uint elem_index = 0; foreach (Face face in assimpmesh.Faces) { if (face.IndexCount < 3) { continue; // lines? } for (uint i = 2; i < (uint)face.IndexCount; i++) { indices.Add(elem_index); indices.Add(elem_index + 1); indices.Add(elem_index + i); } elem_index += (uint)face.IndexCount; for (int i = 0; i < face.IndexCount; i++) { int ei = face.Indices[i]; // add vertex attribute var vertex = assimpmesh.Vertices[ei]; attributes.Add(vertex.X); attributes.Add(vertex.Y); attributes.Add(vertex.Z); // add normals if (assimpmesh.HasNormals) { var normal = assimpmesh.Normals[ei]; attributes.Add(normal.X); attributes.Add(normal.Y); attributes.Add(normal.Z); } // add bi-normals and tangents if (assimpmesh.HasTangentBasis) { var binormal = assimpmesh.BiTangents[ei]; attributes.Add(binormal.X); attributes.Add(binormal.Y); attributes.Add(binormal.Z); var tangent = assimpmesh.Tangents[ei]; attributes.Add(tangent.X); attributes.Add(tangent.Y); attributes.Add(tangent.Z); } // add texture coordinates for (int textur_channel = 0; assimpmesh.HasTextureCoords(textur_channel); ++textur_channel) { var uvw = assimpmesh.TextureCoordinateChannels[textur_channel][ei]; attributes.Add(uvw.X); attributes.Add(uvw.Y); attributes.Add(uvw.Z); } // add color attributes for (int color_channel = 0; assimpmesh.HasVertexColors(color_channel); ++color_channel) { var vertColor = assimpmesh.VertexColorChannels[color_channel][ei]; attributes.Add(vertColor.R); attributes.Add(vertColor.G); attributes.Add(vertColor.B); attributes.Add(vertColor.A); } } } // setup vertex arrays and index array TVertexFormat[] format = formalist.ToArray(); var vao = _openGLFactory.NewVertexArrayObject(); vao.AppendVertexBuffer(0, (int)tuple_index, attributes.ToArray()); vao.Create(format, indices.ToArray()); mesh.FaceSize = 3; mesh.VertexArray = vao; } } for (int i = 0; i < assimpnode.ChildCount; i++) { CreateBuffers(assimpnode.Children[i], node, ref model_matrix); } model_matrix = prev_model; }
private Mesh ProcessMesh(Assimp.Mesh mesh, Scene scene) { List <Vertex> vertices = new List <Vertex>(); List <uint> indices = new List <uint>(); List <TextureInfo> textures = new List <TextureInfo>(); for (int i = 0; i < mesh.VertexCount; i++) { Vertex vertex = new Vertex(); Vector3 vector; vector.X = mesh.Vertices[i].X; vector.Y = mesh.Vertices[i].Y; vector.Z = mesh.Vertices[i].Z; vertex.Position = vector; vector.X = mesh.Normals[i].X; vector.Y = mesh.Normals[i].Y; vector.Z = mesh.Normals[i].Z; vertex.Normal = vector; if (mesh.HasTextureCoords(0)) { Vector2 vec; vec.X = mesh.TextureCoordinateChannels[0][i].X; vec.Y = mesh.TextureCoordinateChannels[0][i].Y; vertex.TexCoords = vec; } else { vertex.TexCoords = Vector2.Zero; } vector.X = mesh.Tangents[i].X; vector.Y = mesh.Tangents[i].Y; vector.Z = mesh.Tangents[i].Z; vertex.Tangent = vector; // bitangent vector.X = mesh.BiTangents[i].X; vector.Y = mesh.BiTangents[i].Y; vector.Z = mesh.Tangents[i].Z; vertex.Bitangent = vector; vertices.Add(vertex); } for (int i = 0; i < mesh.FaceCount; i++) { Face face = mesh.Faces[i]; // retrieve all indices of the face and store them in the indices vector for (int j = 0; j < face.IndexCount; j++) { indices.Add((uint)face.Indices[j]); //Console.WriteLine(face.Indices[j]); } } Material material = scene.Materials[mesh.MaterialIndex]; /*int test = 0; * foreach (TextureSlot slot in material.GetAllMaterialTextures()) * { * if (!paths.Contains(slot.FilePath)) * { * Console.WriteLine(slot.TextureType + " -- " + slot.FilePath); * paths.Add(slot.FilePath); * test++; * } * }*/ List <TextureInfo> diffuseMaps = LoadMaterialTextures(material, TextureType.Diffuse, "texture_diffuse"); textures.AddRange(diffuseMaps); // 2. specular maps List <TextureInfo> specularMaps = LoadMaterialTextures(material, TextureType.Specular, "texture_specular"); textures.AddRange(specularMaps); // 3. normal maps List <TextureInfo> normalMaps = LoadMaterialTextures(material, TextureType.Height, "texture_normal"); textures.AddRange(normalMaps); // 4. height maps List <TextureInfo> heightMaps = LoadMaterialTextures(material, TextureType.Ambient, "texture_height"); textures.AddRange(heightMaps); return(new Mesh(vertices.ToArray(), indices.ToArray(), textures.ToArray())); }
Mesh processMesh(Assimp.Mesh mesh, Scene scene) { List <VertexStruct> vertices = new List <VertexStruct>(); List <int> indices = new List <int>(); List <TextureStruct> textures = new List <TextureStruct>(); // process vertices for (int i = 0; i < mesh.VertexCount; i++) { VertexStruct vertex = new VertexStruct(); Vector3 vector3; vector3 = new Vector3(mesh.Vertices[i].X, mesh.Vertices[i].Y, mesh.Vertices[i].Z); vertex.Position = vector3; if (mesh.HasNormals) { vector3 = new Vector3(mesh.Normals[i].X, mesh.Normals[i].Y, mesh.Normals[i].Z); vertex.Normal = vector3; } if (mesh.HasTextureCoords(0)) { Vector2 vector2 = new Vector2(); vector2.X = mesh.TextureCoordinateChannels[0][i].X; vector2.Y = mesh.TextureCoordinateChannels[0][i].Y; vertex.TexCoords = vector2; } else { vertex.TexCoords = new Vector2(0.0f, 0.0f); } vertices.Add(vertex); } // process indices for (int i = 0; i < mesh.FaceCount; i++) { Face face = mesh.Faces[i]; for (int j = 0; j < face.IndexCount; j++) { indices.Add(face.Indices[j]); } } // process material if (mesh.MaterialIndex >= 0) { Material material = scene.Materials[mesh.MaterialIndex]; //System.Console.WriteLine(material.Name + " " + material.ShadingMode); TextureStruct[] diffuseMaps = loadMaterialTextures(material, TextureType.Diffuse, "texture_diffuse"); for (int i = 0; i < diffuseMaps.Length; i++) { textures.Add(diffuseMaps[i]); } TextureStruct[] specularMaps = loadMaterialTextures(material, TextureType.Specular, "texture_specular"); for (int i = 0; i < specularMaps.Length; i++) { textures.Add(specularMaps[i]); } } return(new Mesh(mesh.Name, vertices.ToArray(), indices.ToArray(), textures.ToArray())); }
void GetVertexFormat (Mesh mesh, int boneCount, out VertexFlags flags, out int stride) { stride = 3; flags = 0; if (mesh.HasNormals) { stride += 3; flags |= VertexFlags.Normal; } if (mesh.HasTextureCoords(0)) { stride += 2; flags |= VertexFlags.TexCoord0; } if (mesh.HasTextureCoords(1)) { stride += 2; flags |= VertexFlags.TexCoord0; } if (mesh.HasTextureCoords(2)) { stride += 2; flags |= VertexFlags.TexCoord0; } if (mesh.HasTextureCoords(3)) { stride += 2; flags |= VertexFlags.TexCoord0; } if (mesh.HasVertexColors(0)) { stride += 4; flags |= VertexFlags.Color0; } if (mesh.HasVertexColors(1)) { stride += 4; flags |= VertexFlags.Color1; } if (mesh.HasVertexColors(2)) { stride += 4; flags |= VertexFlags.Color2; } if (mesh.HasVertexColors(3)) { stride += 4; flags |= VertexFlags.Color3; } stride += boneCount * 2; }
public void Build( string filename, string intermediateDir, string outputDir, MyModelConfiguration configuration, byte[] havokCollisionShapes, bool checkOpenBoundaries, float[] lodDistances, bool overrideLods, Func <string, MyMaterialConfiguration> getMaterialByRef, IMyBuildLogger logger) { logger.LogMessage(MessageType.Info, "**FileName: " + filename); string withoutExtension = Path.GetFileNameWithoutExtension(filename); logger.LogMessage(MessageType.Info, "**Filename (without extension): " + withoutExtension); string directoryName = Path.GetDirectoryName(filename); logger.LogMessage(MessageType.Info, "**Directory Name: " + directoryName); //string contentDirectoryString = "content"; // int numberOfPathCharactersToCull = directoryName.ToLower().LastIndexOf(contentDirectoryString) + contentDirectoryString.Length + 1; var numberOfPathCharactersToCull = filename.LastIndexOf("models\\", StringComparison.OrdinalIgnoreCase); if (numberOfPathCharactersToCull == -1) { throw new Exception("Couldn't find 'models\\' in path provided: " + filename); } logger.LogMessage(MessageType.Info, "**Number of characters to cull: " + numberOfPathCharactersToCull); string culledPath = directoryName.Substring(numberOfPathCharactersToCull, directoryName.Length - numberOfPathCharactersToCull); // Used to cull 'content' from path name to create relative pathing. logger.LogMessage(MessageType.Info, "**Culled Path: " + culledPath); directoryName.Substring(0, numberOfPathCharactersToCull); Path.Combine(directoryName, withoutExtension + ".FBX"); AssimpContext assimpContext = new AssimpContext(); assimpContext.SetConfig((PropertyConfig) new NormalSmoothingAngleConfig(66f)); assimpContext.SetConfig((PropertyConfig) new FBXPreservePivotsConfig(false)); Scene scene = assimpContext.ImportFile(filename, PostProcessSteps.CalculateTangentSpace | PostProcessSteps.JoinIdenticalVertices | PostProcessSteps.Triangulate | PostProcessSteps.GenerateSmoothNormals | PostProcessSteps.SplitLargeMeshes | PostProcessSteps.LimitBoneWeights | PostProcessSteps.SortByPrimitiveType | PostProcessSteps.FindInvalidData | PostProcessSteps.GenerateUVCoords | PostProcessSteps.FlipWindingOrder); string outputDir1 = outputDir; if (scene.MeshCount == 0 && scene.AnimationCount == 0) { throw new Exception("Number of meshes is 0 and no animation present!"); } else { logger.LogMessage(MessageType.Info, "Found " + scene.MeshCount + " meshe(s).", "Meshes"); logger.LogMessage(MessageType.Info, "Found " + scene.AnimationCount + " animation(s).", "Animations"); } #region check UV for 0-sized faces if (scene.MeshCount > 0) { void LogUVError(Assimp.Mesh mesh, string message) { //logger.LogMessage(MessageType.Error, $"Mesh '{mesh.Name}' {message}"); throw new Exception($"Mesh '{mesh.Name}' {message}"); } for (int meshIdx = 0; meshIdx < scene.MeshCount; meshIdx++) { Assimp.Mesh mesh = scene.Meshes[meshIdx]; if (mesh.TextureCoordinateChannels == null || mesh.TextureCoordinateChannels.Length == 0) { LogUVError(mesh, "has no UV map/channel!"); continue; } int channels = 1; // don't care about other channels; if you want to, replace with: mesh.TextureCoordinateChannels.Length; for (int chIdx = 0; chIdx < channels; chIdx++) { if (!mesh.HasTextureCoords(0)) { LogUVError(mesh, "has no UV map/channel!"); continue; } List <Assimp.Vector3D> vectors = mesh.TextureCoordinateChannels[chIdx]; if (vectors == null || vectors.Count == 0) { LogUVError(mesh, "has no UV vectors in first map/channel!"); continue; } //Console.WriteLine($" channel={chIdx}"); //for (int v = 0; v < vectors.Count; v++) //{ // Console.WriteLine($" {v} == {vectors[v]}"); //} Assimp.Vector3D?lastVec = null; int sameVecInARow = 1; // these can be triangles, quads and prob more... so not safe to assume they're in pairs of 3. for (int v = 0; v < vectors.Count; v++) { Assimp.Vector3D vec = vectors[v]; if (!lastVec.HasValue) { lastVec = vec; } else { if (lastVec.Value == vec) { sameVecInARow++; if (sameVecInARow >= 3) { // Changed this to a warning instead of a LogUVError logger.LogMessage(MessageType.Warning, mesh.ToString() + "has UV with 3 identical vectors in a row, this likely means you have a face with an UV is 0-size which will cause SE to make the entire model shaderless."); break; } } else { lastVec = vec; sameVecInARow = 1; } } } } } } #endregion if (scene.MaterialCount > 0) { List <MyMaterialConfiguration> materialConfigurationList = new List <MyMaterialConfiguration>(); for (int index = 0; index < scene.MaterialCount; ++index) { MyMaterialConfiguration materialConfiguration = getMaterialByRef(scene.Materials[index].Name); if (materialConfiguration != null) { materialConfigurationList.Add(materialConfiguration); } } if (materialConfigurationList.Count > 0) { configuration.Materials = configuration.Materials != null ? ((IEnumerable <MyMaterialConfiguration>)configuration.Materials).Union <MyMaterialConfiguration>((IEnumerable <MyMaterialConfiguration>)materialConfigurationList.ToArray()).ToArray <MyMaterialConfiguration>() : materialConfigurationList.ToArray(); } } MyModelProcessor processor = this.CreateProcessor(configuration); if (configuration.Materials != null) { foreach (MyMaterialConfiguration material in configuration.Materials) { try { Dictionary <string, object> dictionary = new Dictionary <string, object>(); if (processor.MaterialProperties.Keys.Contains <string>(material.Name)) { logger.LogMessage(MessageType.Warning, "Material: " + material.Name + " is already defined in the processor. Not adding it again..", filename); } else { processor.MaterialProperties.Add(material.Name, dictionary); foreach (MyModelParameter parameter in material.Parameters) { dictionary.Add(parameter.Name, (object)parameter.Value); } } } catch (ArgumentException ex) { logger.LogMessage(MessageType.Warning, "Problem when processing materials: " + ex.Message, filename); } } } int num2 = 999; List <MyLODDescriptor> myLodDescriptorList = new List <MyLODDescriptor>(); for (int index = 0; index < num2; ++index) { string path = Path.Combine(directoryName, withoutExtension + "_LOD" + (object)(index + 1)) + ".fbx"; string str2 = Path.Combine(culledPath, withoutExtension + "_LOD" + (object)(index + 1)); if (File.Exists(path)) { if (overrideLods && lodDistances != null && (index < lodDistances.Length && (double)lodDistances[index] > 0.0)) { MyLODDescriptor myLodDescriptor = new MyLODDescriptor() { Distance = lodDistances[index], Model = str2 }; myLodDescriptorList.Add(myLodDescriptor); } else if (configuration.LODs != null && index < configuration.LODs.Length) { MyLODConfiguration loD = configuration.LODs[index]; MyLODDescriptor myLodDescriptor = new MyLODDescriptor() { Distance = loD.Distance, Model = str2, RenderQuality = loD.RenderQuality }; if (str2.ToLower() != loD.Model.ToLower()) { logger.LogMessage(MessageType.Warning, "LOD" + (object)(index + 1) + " name differs " + str2 + " and " + loD.Model, filename); } myLodDescriptorList.Add(myLodDescriptor); } else { logger.LogMessage(MessageType.Warning, "LOD" + (object)(index + 1) + " model exists but configuration is missing", filename); } } else if (configuration.LODs != null && index < configuration.LODs.Length) { logger.LogMessage(MessageType.Warning, "LOD model " + configuration.LODs[index].Model + " is missing", filename); } else { break; } } processor.LODs = myLodDescriptorList.ToArray(); processor.BoneGridMapping = configuration.BoneGridSize; processor.BoneMapping = configuration.BoneMapping != null ? ((IEnumerable <MyModelVector>)configuration.BoneMapping).Select <MyModelVector, Vector3>((Func <MyModelVector, Vector3>)(s => new Vector3((float)s.X, (float)s.Y, (float)s.Z))).ToArray <Vector3>() : (Vector3[])null; processor.HavokCollisionShapes = havokCollisionShapes; processor.Process(scene, filename, outputDir1, checkOpenBoundaries, logger); if (configuration.BoneGridSize.HasValue) { configuration.BoneMapping = ((IEnumerable <Vector3>)processor.BoneMapping).Select <Vector3, MyModelVector>((Func <Vector3, MyModelVector>)(s => (MyModelVector)s)).ToArray <MyModelVector>(); } List <MyMaterialConfiguration> materialConfigurationList1 = new List <MyMaterialConfiguration>(); foreach (KeyValuePair <string, Dictionary <string, object> > materialProperty in processor.MaterialProperties) { materialConfigurationList1.Add(new MyMaterialConfiguration() { Name = materialProperty.Key, Parameters = MyModelBuilder.GetParameters(materialProperty) }); } configuration.Materials = materialConfigurationList1.Count <= 0 ? (MyMaterialConfiguration[])null : materialConfigurationList1.ToArray(); if (processor.LODs == null) { return; } List <MyLODConfiguration> lodConfigurationList = new List <MyLODConfiguration>(); foreach (MyLODDescriptor loD in processor.LODs) { lodConfigurationList.Add(new MyLODConfiguration() { Distance = loD.Distance, Model = loD.Model, RenderQuality = loD.RenderQuality }); } configuration.LODs = lodConfigurationList.ToArray(); }
// Processa a malha lida pelo Assimp private Mesh ProcessMesh(Assimp.Mesh amesh, Assimp.Scene scene) { List <Vertex> vertices = new List <Vertex>(); List <uint> indices = new List <uint>(); List <Texture> textures = new List <Texture>(); Random r = new Random(); // Carrego pela malha do Assimp, a lista de vértice com a normal, UV (ST), tangente, bitangente for (int i = 0; i < amesh.VertexCount; i++) { Vertex vertex = new Vertex(); vertex.positionX = amesh.Vertices[i].X; vertex.positionY = amesh.Vertices[i].Y; vertex.positionZ = amesh.Vertices[i].Z; if (amesh.HasNormals) { vertex.normalX = amesh.Normals[i].X; vertex.normalY = amesh.Normals[i].Y; vertex.normalZ = amesh.Normals[i].Z; } if (amesh.HasTextureCoords(0)) { vertex.textureX = amesh.TextureCoordinateChannels[0][i].X; vertex.textureY = amesh.TextureCoordinateChannels[0][i].Y; vertex.bitangentX = amesh.BiTangents[i].X; vertex.bitangentY = amesh.BiTangents[i].Y; vertex.bitangentZ = amesh.BiTangents[i].Z; vertex.tangentX = amesh.Tangents[i].X; vertex.tangentY = amesh.Tangents[i].Y; vertex.tangentZ = amesh.Tangents[i].Z; } else { vertex.textureX = 0f; vertex.textureY = 0f; } vertex.colorA = (float)r.NextDouble(); vertex.colorR = (float)r.NextDouble(); vertex.colorB = (float)r.NextDouble(); vertex.colorG = 1f; vertices.Add(vertex); } // Carrega as informações das faces dos triâgulos, ou seja, informa quais vertices formam um triângulo da malha for (int i = 0; i < amesh.FaceCount; i++) { Assimp.Face face = amesh.Faces[i]; for (int j = 0; j < face.IndexCount; j++) { indices.Add((uint)face.Indices[j]); } } // Verifica se possui alguma textura ou arquivo mtl vinculado ao obj if (amesh.MaterialIndex >= 0) { Assimp.Material material = scene.Materials[amesh.MaterialIndex]; List <Texture> diffuseMaps = loadMaterialTextures(material, TextureType.Diffuse, "texture_diffuse"); textures.InsertRange(textures.Count, diffuseMaps); List <Texture> specularMaps = loadMaterialTextures(material, TextureType.Specular, "texture_specular"); textures.InsertRange(textures.Count, specularMaps); List <Texture> normalMaps = loadMaterialTextures(material, TextureType.Height, "texture_normal"); textures.InsertRange(textures.Count, normalMaps); } return(new Mesh(vertices, indices, textures)); }
private MonoKnight.Mesh ProcessMesh(Assimp.Mesh mesh, Assimp.Scene scene) { List <Vertex> vertices = new List <Vertex>(); List <int> indices = new List <int>(); List <Texture> textures = new List <Texture>(); // var boneDic = new Dictionary<string, Bone>(); //// //var invertGlobalTransform = AssimpMat4ToOpenTKMat4(scene.RootNode.Transform).Inverted(); // // // if(mesh.HasBones) // { // for (int i = 0; i < mesh.BoneCount; i++) // { // var assimpBone = mesh.Bones[i]; // if (!boneDic.ContainsKey(assimpBone.Name)) //{ // var bone = new Bone(); // bone.name = assimpBone.Name; // bone.offset = AssimpMat4ToOpenTKMat4(assimpBone.OffsetMatrix); // for (int j = 0; j < assimpBone.VertexWeightCount; j++) // { // VertexWeight vertexWeight; // vertexWeight.vertexId = assimpBone.VertexWeights[j].VertexID; // vertexWeight.weight = assimpBone.VertexWeights[j].Weight; // bone.weightList.Add(vertexWeight); // } // boneDic[assimpBone.Name] = bone; //} // } //} // for (int i = 0; i < mesh.VertexCount; i++) { Vertex vertex = new Vertex(); Vector3 vector = new Vector3(); vector.X = mesh.Vertices[i].X; vector.Y = mesh.Vertices[i].Y; vector.Z = mesh.Vertices[i].Z; vertex.position = vector; // if (mesh.HasNormals) { vector.X = mesh.Normals[i].X; vector.Y = mesh.Normals[i].Y; vector.Z = mesh.Normals[i].Z; vertex.normal = vector; } else { vertex.normal = Vector3.Zero; } // if (mesh.HasTextureCoords(0)) { Vector2 vec = new Vector2(); vec.X = mesh.TextureCoordinateChannels[0][i].X; vec.Y = mesh.TextureCoordinateChannels[0][i].Y; vertex.texCoord = vec; } else { vertex.texCoord = new Vector2(0.0f, 0.0f); } vertices.Add(vertex); } for (int i = 0; i < mesh.FaceCount; i++) { Face face = mesh.Faces[i]; for (int j = 0; j < face.IndexCount; j++) { indices.Add(face.Indices[j]); } } if (mesh.MaterialIndex >= 0) { Assimp.Material material = scene.Materials[mesh.MaterialIndex]; for (int i = 0; i < material.GetMaterialTextures(TextureType.Diffuse).Length; i++) { var texSlot = material.GetMaterialTextures(TextureType.Diffuse)[i]; Texture texture = new Texture(); texture.LoadFromPath(Path.Combine(modelDirPath, texSlot.FilePath)); textures.Add(texture); } //TODO other type texture } // return(new Mesh(ref vertices, ref indices, ref textures)); }
private void LoadFromNode(Assimp.Scene _scene, Assimp.Node _node, GraphicsDevice _device, SharpDX.Toolkit.Content.ContentManager _content, Matrix _transform) { // Sum up transformations recursively _transform = FromMatrix(_node.Transform) * _transform; Matrix transformInvTr = Helpers.CreateInverseTranspose(ref _transform); // Recursive load from scene if (_node.HasChildren) { foreach (Assimp.Node node in _node.Children) { LoadFromNode(_scene, node, _device, _content, _transform); } } if (_node.HasMeshes) { foreach (int meshIndex in _node.MeshIndices) { Assimp.Mesh mesh = _scene.Meshes[meshIndex]; ModelMesh modelMesh = new ModelMesh(); // if mesh has a diffuse texture extract it Assimp.Material material = _scene.Materials[mesh.MaterialIndex]; if (material != null && material.GetTextureCount(TextureType.Diffuse) > 0) { TextureSlot texture = material.GetTexture(TextureType.Diffuse, 0); // Create new texture for mesh var dxtexture = _content.Load <Texture2D>(texture.FilePath); modelMesh.DiffuseTexture = dxtexture; } // Position is mandarory if (!mesh.HasVertices) { throw new Exception("Model::Model(): Model has no vertices."); } // 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; int numElements = 1 + (hasTexCoords ? 1 : 0) + (hasColors ? 1 : 0) + (hasNormals ? 1 : 0) + (hasTangents ? 1 : 0) + (hasBitangents ? 1 : 0); // Create vertex element list: Here starts the section of creating SharpDX stuff VertexElement[] vertexElements = new VertexElement[numElements]; uint elementIndex = 0; vertexElements[elementIndex++] = new VertexElement("POSITION", 0, SharpDX.DXGI.Format.R32G32B32_Float, 0); int vertexSize = Utilities.SizeOf <Vector3>(); if (hasColors) { vertexElements[elementIndex++] = new VertexElement("COLOR", 0, SharpDX.DXGI.Format.R8G8B8A8_UInt, vertexSize); vertexSize += Utilities.SizeOf <Color>(); } if (hasNormals) { vertexElements[elementIndex++] = new VertexElement("NORMAL", 0, SharpDX.DXGI.Format.R32G32B32_Float, vertexSize); vertexSize += Utilities.SizeOf <Vector3>(); } if (hasTangents) { vertexElements[elementIndex++] = new VertexElement("TANGENT", 0, SharpDX.DXGI.Format.R32G32B32_Float, vertexSize); vertexSize += Utilities.SizeOf <Vector3>(); } if (hasBitangents) { vertexElements[elementIndex++] = new VertexElement("BITANGENT", 0, SharpDX.DXGI.Format.R32G32B32_Float, vertexSize); vertexSize += Utilities.SizeOf <Vector3>(); } if (hasTexCoords) { vertexElements[elementIndex++] = new VertexElement("TEXCOORD", 0, SharpDX.DXGI.Format.R32G32_Float, vertexSize); vertexSize += Utilities.SizeOf <Vector2>(); } // Set the vertex elements and size modelMesh.InputLayout = VertexInputLayout.New(VertexBufferLayout.New(0, vertexElements)); modelMesh.VertexSize = vertexSize; // Determine primitive type switch (mesh.PrimitiveType) { case Assimp.PrimitiveType.Point: modelMesh.PrimitiveTopology = SharpDX.Toolkit.Graphics.PrimitiveType.PointList; break; case Assimp.PrimitiveType.Line: modelMesh.PrimitiveTopology = SharpDX.Toolkit.Graphics.PrimitiveType.LineList; break; case Assimp.PrimitiveType.Triangle: modelMesh.PrimitiveTopology = SharpDX.Toolkit.Graphics.PrimitiveType.TriangleList; break; default: throw new Exception("Model::Model(): Unknown primitive type"); } // Create data stream for vertices //System.IO.MemoryStream vertexStream = new System.IO.MemoryStream(mesh.VertexCount * vertexSize); DataStream vertexStream = new DataStream(mesh.VertexCount * vertexSize, true, true); for (int i = 0; i < mesh.VertexCount; i++) { vertexStream.Write <Vector3>(Helpers.Transform(FromVector(mesh.Vertices[i]), ref _transform)); if (hasColors) { vertexStream.Write <Color>(FromColor(mesh.GetVertexColors(0)[i])); } if (hasNormals) { vertexStream.Write <Vector3>(Helpers.Transform(FromVector(mesh.Normals[i]), ref transformInvTr)); } if (hasTangents) { vertexStream.Write <Vector3>(Helpers.Transform(FromVector(mesh.Tangents[i]), ref transformInvTr)); } if (hasBitangents) { vertexStream.Write <Vector3>(Helpers.Transform(FromVector(mesh.BiTangents[i]), ref transformInvTr)); } if (hasTexCoords) { vertexStream.Write <Vector2>(new Vector2(mesh.GetTextureCoords(0)[i].X, mesh.GetTextureCoords(0)[i].Y)); } } vertexStream.Position = 0; // Create new vertex buffer var vertexBuffer = SharpDX.Toolkit.Graphics.Buffer.Vertex.New(_device, vertexStream); // Add it to the mesh modelMesh.VertexBuffer = vertexBuffer; modelMesh.VertexCount = mesh.VertexCount; modelMesh.PrimitiveCount = mesh.FaceCount; // Create new index buffer var indexBuffer = SharpDX.Toolkit.Graphics.Buffer.Index.New(_device, mesh.GetIndices()); // Add it to the mesh modelMesh.IndexBuffer = indexBuffer; modelMesh.IndexCount = mesh.GetIndices().GetLength(0); m_meshes.Add(modelMesh); } } }
private IEnumerable<PosNormalTexTanSkinned> ExtractVertices(Mesh mesh, IReadOnlyDictionary<uint, List<VertexWeight>> vertToBoneWeights, bool flipTexY) { var verts = new List<PosNormalTexTanSkinned>(); for (var i = 0; i < mesh.VertexCount; i++) { var pos = mesh.HasVertices ? mesh.Vertices[i].ToVector3() : new Vector3(); _min = Vector3.Minimize(_min, pos); _max = Vector3.Maximize(_max, pos); var norm = mesh.HasNormals ? mesh.Normals[i] : new Vector3D(); var tan = mesh.HasTangentBasis ? mesh.Tangents[i] : new Vector3D(); var texC = new Vector3D(); if (mesh.HasTextureCoords(0)) { var coord = mesh.GetTextureCoords(0)[i]; if (flipTexY) { coord.Y = -coord.Y; } texC = coord; } var weights = vertToBoneWeights[(uint) i].Select(w => w.Weight).ToArray(); var boneIndices = vertToBoneWeights[(uint) i].Select(w => (byte) w.VertexID).ToArray(); var v = new PosNormalTexTanSkinned(pos, norm.ToVector3(), texC.ToVector2(), tan.ToVector3(), weights.First(), boneIndices); verts.Add(v); } return verts; }
void ProcessMesh(Assimp.Mesh mesh, Assimp.Scene scene, VertexMode mode) { Mesh m = new Mesh(); for (int i = 0; i < mesh.VertexCount; i++) { if (mesh.HasVertices) { Vec3 vec3 = new Vec3(mesh.Vertices[i]); m.positions.Add(vec3); } else { Console.WriteLine("[" + i + "]: " + "No Vertices"); } if (mesh.HasNormals) { Vec3 normal = new Vec3(mesh.Normals[i]); m.normals.Add(normal); } else { Console.WriteLine("[" + i + "]: " + "No Normals"); } if (mode == VertexMode.TextureAndNormal) { if (mesh.HasTangentBasis) { Vec3 tangent = new Vec3(mesh.Tangents[i]); m.tangents.Add(tangent); } else { Console.WriteLine("[" + i + "]: " + "No Tangents"); } } if (mode == VertexMode.TextureAndNormal || mode == VertexMode.TextureOnly) { if (mesh.HasTextureCoords(0)) { Vec2 uv = new Vec2(mesh.TextureCoordinateChannels[0][i]); m.uvs.Add(uv); } else { Console.WriteLine("[" + i + "]: " + "No TextureCoordinate"); } } } foreach (Face f in mesh.Faces) { for (int j = 0; j < f.IndexCount; j++) { m.indices.Add(f.Indices[j]); } } m.materialIndex = mesh.MaterialIndex; this._meshes.Add(m); }
//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; }
private Mesh processMesh(Assimp.Mesh mesh, Assimp.Scene scene) { // Data to fill List <Vertex> vertices = new List <Vertex>(); List <uint> indices = new List <uint>(); List <Texture> textures = new List <Texture>(); // Walk through each of the mesh's vertices for (int i = 0; i < mesh.VertexCount; i++) { Vertex vertex = new Vertex(); //Vertex3 vector = new Vertex3(); // We declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to glm's vec3 class so we transfer the data to this placeholder glm::vec3 first. // Positions vertex.Position.X = mesh.Vertices[i].X; vertex.Position.Y = mesh.Vertices[i].Y; vertex.Position.Z = mesh.Vertices[i].Z; //vertex.Position = vector; // Normals vertex.Normal.X = mesh.Normals[i].X; vertex.Normal.Y = mesh.Normals[i].Y; vertex.Normal.Z = mesh.Normals[i].Z; //vertex.Normal = vector; // Texture Coordinates if (mesh.HasTextureCoords(0)) // Does the mesh contain texture coordinates? { Vertex2f vec; // A vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't // use models where a vertex can have multiple texture coordinates so we always take the first set (0). vec.x = mesh.TextureCoordinateChannels[0][i].X; vec.y = mesh.TextureCoordinateChannels[0][i].Y; vertex.TexCoords.X = vec.X; vertex.TexCoords.Y = vec.Y; } else { vertex.TexCoords.X = vertex.TexCoords.Y = 0; } vertices.Add(vertex); } // Now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices. for (int i = 0; i < mesh.FaceCount; i++) { Assimp.Face face = mesh.Faces[i]; // Retrieve all indices of the face and store them in the indices vector for (int j = 0; j < face.IndexCount; j++) { indices.Add((uint)face.Indices[j]); } } // Process materials if (mesh.MaterialIndex >= 0) { Assimp.Material material = scene.Materials[mesh.MaterialIndex]; // We assume a convention for sampler names in the shaders. Each diffuse texture should be named // as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER. // Same applies to other texture as the following list summarizes: // Diffuse: texture_diffuseN // Specular: texture_specularN // Normal: texture_normalN // 1. Diffuse maps List <Texture> diffuseMaps = this.loadMaterialTextures(material, TextureType.Diffuse, "texture_diffuse"); textures.InsertRange(textures.Count, diffuseMaps); // 2. Specular maps List <Texture> specularMaps = this.loadMaterialTextures(material, TextureType.Specular, "texture_specular"); textures.InsertRange(textures.Count, specularMaps); } // Return a mesh object created from the extracted mesh data return(new Mesh(vertices, indices, textures)); }
public void SetMesh(MainWindow host, Mesh mesh, string meshName) { Debug.Assert(mesh != null); Debug.Assert(host != null); Debug.Assert(meshName != null); _mesh = mesh; _host = host; labelVertexCount.Text = mesh.VertexCount + " Vertices"; labelFaceCount.Text = mesh.FaceCount + " Faces"; Text = meshName + " - Details"; checkedListBoxPerFace.CheckOnClick = false; checkedListBoxPerFace.SetItemCheckState(0, mesh.PrimitiveType.HasFlag(PrimitiveType.Triangle) ? CheckState.Checked : CheckState.Unchecked); checkedListBoxPerFace.SetItemCheckState(1, mesh.PrimitiveType.HasFlag(PrimitiveType.Line) ? CheckState.Checked : CheckState.Unchecked); checkedListBoxPerFace.SetItemCheckState(2, mesh.PrimitiveType.HasFlag(PrimitiveType.Point) ? CheckState.Checked : CheckState.Unchecked); checkedListBoxPerVertex.CheckOnClick = false; checkedListBoxPerVertex.SetItemCheckState(0, CheckState.Checked); checkedListBoxPerVertex.SetItemCheckState(1, mesh.HasNormals ? CheckState.Checked : CheckState.Unchecked); checkedListBoxPerVertex.SetItemCheckState(2, mesh.HasTangentBasis ? CheckState.Checked : CheckState.Unchecked); Debug.Assert(mesh.TextureCoordinateChannels.Length >= 4); for (var i = 0; i < 4; ++i) { checkedListBoxPerVertex.SetItemCheckState(3 + i, mesh.HasTextureCoords(i) ? CheckState.Checked : CheckState.Unchecked); } Debug.Assert(mesh.VertexColorChannels.Length >= 4); for (var i = 0; i < 4; ++i) { checkedListBoxPerVertex.SetItemCheckState(7 + i, mesh.HasVertexColors(i) ? CheckState.Checked : CheckState.Unchecked); } checkedListBoxPerVertex.SetItemCheckState(11, mesh.HasBones ? CheckState.Checked : CheckState.Unchecked); }
private Mesh ProcessMesh(Assimp.Mesh mesh, Scene scene) { var vertices = new List <MeshVertex>(); var indices = new List <int>(); var textures = new List <MeshTexture>(); var color = new MeshColor(); for (int i = 0; i < mesh.VertexCount; i++) { var vertex = new MeshVertex(); // process vertex positions, normals and texture coordinates var pos = mesh.Vertices[i]; vertex.Position = new Vector3(pos.X, pos.Y, pos.Z); var norm = mesh.Normals[i]; vertex.Normal = new Vector3(norm.X, norm.Y, norm.Z); if (mesh.HasTextureCoords(0)) // does the mesh contain texture coordinates? { var tex = mesh.TextureCoordinateChannels[0][i]; vertex.TexCoords = new Vector2(tex.X, tex.Y); } else { vertex.TexCoords = Vector2.Zero; } vertices.Add(vertex); } // process indices for (int i = 0; i < mesh.FaceCount; i++) { Face face = mesh.Faces[i]; for (int j = 0; j < face.IndexCount; j++) { indices.Add(face.Indices[j]); } } // process material if (mesh.MaterialIndex >= 0) { Material material = scene.Materials[mesh.MaterialIndex]; // get all the needed material textures if (material.HasTextureDiffuse) { List <MeshTexture> diffuseMaps = LoadMaterialTextures(material, TextureType.Diffuse, "texture_diffuse"); textures.AddRange(diffuseMaps); } if (material.HasTextureSpecular) { List <MeshTexture> specularMaps = LoadMaterialTextures(material, TextureType.Specular, "texture_specular"); textures.AddRange(specularMaps); } // get all the needed material colors (default values if they're not presented) color.Ambient = material.ColorAmbient; color.Diffuse = material.ColorDiffuse; color.Specular = material.ColorSpecular; color.Shininess = material.Shininess; } return(new Mesh(mesh.Name, vertices.ToArray(), indices.ToArray(), textures.ToArray(), color)); }
private static Mesh ConvertAssimpMeshToGeometry(Ai.Mesh aiMesh, Ai.Material material, Dictionary <string, NodeInfo> nodeLookup, ref int nextBoneIndex, Dictionary <int, List <int> > nodeToBoneIndices, List <Matrix4x4> boneInverseBindMatrices, ref Matrix4x4 nodeWorldTransform, ref Matrix4x4 nodeInverseWorldTransform, List <Vector3> transformedVertices, ModelConverterOptions options) { if (!aiMesh.HasVertices) { throw new Exception("Assimp mesh has no vertices"); } var geometry = new Mesh(); var geometryTransformedVertices = new Vector3[aiMesh.VertexCount]; geometry.Vertices = aiMesh.Vertices .Select(x => new Vector3(x.X, x.Y, x.Z)) .ToArray(); for (int i = 0; i < geometry.Vertices.Length; i++) { geometryTransformedVertices[i] = Vector3.Transform(geometry.Vertices[i], nodeWorldTransform); } transformedVertices.AddRange(geometryTransformedVertices); if (aiMesh.HasNormals) { geometry.Normals = aiMesh.Normals .Select(x => new Vector3(x.X, x.Y, x.Z)) .ToArray(); } if (aiMesh.HasTextureCoords(0)) { geometry.TexCoordsChannel0 = aiMesh.TextureCoordinateChannels[0] .Select(x => new Vector2(x.X, x.Y)) .ToArray(); } if (aiMesh.HasTextureCoords(1)) { geometry.TexCoordsChannel1 = aiMesh.TextureCoordinateChannels[1] .Select(x => new Vector2(x.X, x.Y)) .ToArray(); } if (aiMesh.HasTextureCoords(2)) { geometry.TexCoordsChannel2 = aiMesh.TextureCoordinateChannels[2] .Select(x => new Vector2(x.X, x.Y)) .ToArray(); } if (aiMesh.HasVertexColors(0)) { geometry.ColorChannel0 = aiMesh.VertexColorChannels[0] .Select(x => ( uint )(( byte )(x.B * 255f) | ( byte )(x.G * 255f) << 8 | ( byte )(x.R * 255f) << 16 | ( byte )(x.A * 255f) << 24)) .ToArray(); } else if (options.GenerateVertexColors) { geometry.ColorChannel0 = new uint[geometry.VertexCount]; for (int i = 0; i < geometry.ColorChannel0.Length; i++) { geometry.ColorChannel0[i] = 0xFFFFFFFF; } } if (aiMesh.HasVertexColors(1)) { geometry.ColorChannel1 = aiMesh.VertexColorChannels[1] .Select(x => ( uint )(( byte )(x.B * 255f) | ( byte )(x.G * 255f) << 8 | ( byte )(x.R * 255f) << 16 | ( byte )(x.A * 255f) << 24)) .ToArray(); } if (aiMesh.HasFaces) { geometry.TriangleIndexFormat = aiMesh.VertexCount <= ushort.MaxValue ? TriangleIndexFormat.UInt16 : TriangleIndexFormat.UInt32; geometry.Triangles = aiMesh.Faces .Select(x => new Triangle(( uint )x.Indices[0], ( uint )x.Indices[1], ( uint )x.Indices[2])) .ToArray(); } if (aiMesh.HasBones) { geometry.VertexWeights = new VertexWeight[geometry.VertexCount]; for (int i = 0; i < geometry.VertexWeights.Length; i++) { geometry.VertexWeights[i].Indices = new byte[4]; geometry.VertexWeights[i].Weights = new float[4]; } var vertexWeightCounts = new int[geometry.VertexCount]; for (var i = 0; i < aiMesh.Bones.Count; i++) { var aiMeshBone = aiMesh.Bones[i]; // Find node index for the bone var boneLookupData = nodeLookup[AssimpConverterCommon.UnescapeName(aiMeshBone.Name)]; int nodeIndex = boneLookupData.Index; // Calculate inverse bind matrix var boneNode = boneLookupData.Node; var bindMatrix = boneNode.WorldTransform * nodeInverseWorldTransform; if (options.ConvertSkinToZUp) { bindMatrix *= YToZUpMatrix; } Matrix4x4.Invert(bindMatrix, out var inverseBindMatrix); // Get bone index int boneIndex; if (!nodeToBoneIndices.TryGetValue(nodeIndex, out var boneIndices)) { // No entry for the node was found, so we add a new one boneIndex = nextBoneIndex++; nodeToBoneIndices.Add(nodeIndex, new List <int>() { boneIndex }); boneInverseBindMatrices.Add(inverseBindMatrix); } else { // Entry for the node was found // Try to find the bone index based on whether the inverse bind matrix matches boneIndex = -1; foreach (int index in boneIndices) { if (boneInverseBindMatrices[index].Equals(inverseBindMatrix)) { boneIndex = index; } } if (boneIndex == -1) { // None matching inverse bind matrix was found, so we add a new entry boneIndex = nextBoneIndex++; nodeToBoneIndices[nodeIndex].Add(boneIndex); boneInverseBindMatrices.Add(inverseBindMatrix); } } foreach (var aiVertexWeight in aiMeshBone.VertexWeights) { int vertexWeightCount = vertexWeightCounts[aiVertexWeight.VertexID]++; geometry.VertexWeights[aiVertexWeight.VertexID].Indices[vertexWeightCount] = ( byte )boneIndex; geometry.VertexWeights[aiVertexWeight.VertexID].Weights[vertexWeightCount] = aiVertexWeight.Weight; } } } geometry.MaterialName = AssimpConverterCommon.UnescapeName(material.Name); geometry.BoundingBox = BoundingBox.Calculate(geometry.Vertices); geometry.BoundingSphere = BoundingSphere.Calculate(geometry.BoundingBox.Value, geometry.Vertices); geometry.Flags |= GeometryFlags.Flag80000000; return(geometry); }
unsafe void WriteMesh (Mesh mesh, BinaryWriter writer) { var boneSlotCount = this.GetBoneSlotCount(mesh); VertexFlags flags; int stride; this.GetVertexFormat(mesh, boneSlotCount, out flags, out stride); var count = mesh.VertexCount; writer.Write(mesh.Name); writer.Write((uint)flags); writer.Write(boneSlotCount); writer.Write(mesh.MaterialIndex); var vertices = new float[stride * count]; int idx = 0, offset = 0; foreach (var pos in mesh.Vertices) { vertices[idx] = pos.X; vertices[idx + 1] = pos.Y; vertices[idx + 2] = pos.Z; idx += stride; } offset = idx = 3; if (mesh.HasNormals) { foreach (var norm in mesh.Normals) { vertices[idx] = norm.X; vertices[idx + 1] = norm.Y; vertices[idx + 2] = norm.Z; idx += stride; } offset += 3; idx = offset; } for (var i = 0; i < 4; i++) { if (mesh.HasTextureCoords(i)) { if (mesh.UVComponentCount[i] != 2) Console.WriteLine("WARNING: texture coordinates should have 2 components, but this channel has " + mesh.UVComponentCount[i]); foreach (var uv in mesh.TextureCoordinateChannels[i]) { vertices[idx] = uv.X; vertices[idx + 1] = uv.Y; idx += stride; } offset += 2; idx = offset; } } for (var i = 0; i < 4; i++) { if (mesh.HasVertexColors(i)) { foreach (var c in mesh.VertexColorChannels[i]) { vertices[idx] = c.R; vertices[idx + 1] = c.G; vertices[idx + 2] = c.B; vertices[idx + 3] = c.A; idx += stride; } offset += 4; idx = offset; } } // add bone information to every vertex for(var i = 0; i < mesh.BoneCount; i++) { foreach (var weight in mesh.Bones[i].VertexWeights) { if (weight.Weight > 0f) { idx = (stride * weight.VertexID) + offset; while (vertices[idx] != 0f) idx++; vertices[idx] = weight.Weight; vertices[idx + boneSlotCount] = i; } } } writer.Write(vertices.Length); writer.Flush(); fixed(float *fp = &vertices[0]) { byte* bp = (byte*)fp; using (var ms = new UnmanagedMemoryStream(bp, vertices.Length * sizeof(float))) { ms.CopyTo(writer.BaseStream); } } count = mesh.FaceCount; var indices = new int[count * 3]; idx = 0; for (var i = 0; i < count; i++) { var face = mesh.Faces[i]; var faceIndices = face.Indices; if (face.IndexCount != 3) throw new InvalidOperationException("Polygonal faces are not supported, faces must be triangles."); indices[idx++] = faceIndices[0]; indices[idx++] = faceIndices[1]; indices[idx++] = faceIndices[2]; } writer.Write(indices.Length); writer.Flush(); fixed(int *ip = &indices[0]) { byte* bp = (byte*)ip; using (var ms = new UnmanagedMemoryStream(bp, indices.Length * sizeof(float))) { ms.CopyTo(writer.BaseStream); } } count = mesh.BoneCount; writer.Write(count); for (var i = 0; i < count; i++) { var bone = mesh.Bones[i]; writer.Write(bone.Name); writer.Write(bone.OffsetMatrix); var weightCount = bone.VertexWeightCount; writer.Write(weightCount); for (var j = 0; j < weightCount; j++) { var weight = bone.VertexWeights[i]; writer.Write(weight.VertexID); writer.Write(weight.Weight); } } }
//private const PostProcessSteps DefaultPostProcessSteps // = PostProcessSteps.None; //TODO: add support for VertexPosition Type public static byte[] GenerateVertexBytesArrayFromAssimp(VertexRuntimeTypes henzaiVertexType, Assimp.Mesh aiMesh, int index) { Vector3D pPos = aiMesh.Vertices[index]; Vector3D pNormal = aiMesh.Normals[index]; Vector3D pTexCoord = aiMesh.HasTextureCoords(0) ? aiMesh.TextureCoordinateChannels[0][index] : Zero3D; Color4D pColor = aiMesh.HasVertexColors(0) ? aiMesh.VertexColorChannels[0][index] : Nocolor; Vector3D pTangent = aiMesh.HasTangentBasis ? aiMesh.Tangents[index] : Zero3D; Vector3D pBiTangent = aiMesh.HasTangentBasis ? aiMesh.BiTangents[index] : Zero3D; byte[] bytes; byte[] posAsBytes = ByteMarshal.StructToBytes(pPos); byte[] colorAsBytes = ByteMarshal.StructToBytes(pColor); byte[] normalAsBytes = ByteMarshal.StructToBytes(pNormal); byte[] texCoordAsBytes = ByteMarshal.StructToBytes(pTexCoord.ToVector2()); byte[] tangentAsBytes = ByteMarshal.StructToBytes(pTangent); byte[] bitangentAsBytes = ByteMarshal.StructToBytes(pBiTangent); switch (henzaiVertexType) { case VertexRuntimeTypes.VertexPosition: bytes = new byte[VertexPosition.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPosition.PositionOffset, posAsBytes.Length); break; case VertexRuntimeTypes.VertexPositionColor: bytes = new byte[VertexPositionColor.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPositionColor.PositionOffset, posAsBytes.Length); Array.Copy(colorAsBytes, 0, bytes, VertexPositionColor.ColorOffset, colorAsBytes.Length); break; case VertexRuntimeTypes.VertexPositionTexture: bytes = new byte[VertexPositionTexture.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPositionTexture.PositionOffset, posAsBytes.Length); Array.Copy(texCoordAsBytes, 0, bytes, VertexPositionTexture.TextureCoordinatesOffset, texCoordAsBytes.Length); break; case VertexRuntimeTypes.VertexPositionNormalTexture: bytes = new byte[VertexPositionNormalTexture.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPositionNormalTexture.PositionOffset, posAsBytes.Length); Array.Copy(normalAsBytes, 0, bytes, VertexPositionNormalTexture.NormalOffset, normalAsBytes.Length); Array.Copy(texCoordAsBytes, 0, bytes, VertexPositionNormalTexture.TextureCoordinatesOffset, texCoordAsBytes.Length); break; case VertexRuntimeTypes.VertexPositionNormal: bytes = new byte[VertexPositionNormal.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPositionNormal.PositionOffset, posAsBytes.Length); Array.Copy(normalAsBytes, 0, bytes, VertexPositionNormal.NormalOffset, normalAsBytes.Length); break; case VertexRuntimeTypes.VertexPositionNormalTextureTangent: bytes = new byte[VertexPositionNormalTextureTangent.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPositionNormalTextureTangent.PositionOffset, posAsBytes.Length); Array.Copy(normalAsBytes, 0, bytes, VertexPositionNormalTextureTangent.NormalOffset, normalAsBytes.Length); Array.Copy(texCoordAsBytes, 0, bytes, VertexPositionNormalTextureTangent.TextureCoordinatesOffset, texCoordAsBytes.Length); Array.Copy(tangentAsBytes, 0, bytes, VertexPositionNormalTextureTangent.TangentOffset, tangentAsBytes.Length); break; case VertexRuntimeTypes.VertexPositionNormalTextureTangentBitangent: bytes = new byte[VertexPositionNormalTextureTangentBitangent.SizeInBytes]; Array.Copy(posAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.PositionOffset, posAsBytes.Length); Array.Copy(normalAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.NormalOffset, normalAsBytes.Length); Array.Copy(texCoordAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.TextureCoordinatesOffset, texCoordAsBytes.Length); Array.Copy(tangentAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.TangentOffset, tangentAsBytes.Length); Array.Copy(bitangentAsBytes, 0, bytes, VertexPositionNormalTextureTangentBitangent.BitangentOffset, bitangentAsBytes.Length); break; default: throw new NotImplementedException($"{henzaiVertexType.ToString("g")} not implemented"); } return(bytes); }
private Mesh ProcessMesh(Assimp.Mesh mesh, Assimp.Scene scene, Assimp.Matrix4x4 transform) { List <Vertex> vertices = new List <Vertex>(); List <uint> indices = new List <uint>(); List <Texture> textures = new List <Texture>(); for (int i = 0; i < mesh.VertexCount; ++i) { var vertex = new Vertex() { Position = new Vector3(mesh.Vertices[i].X, mesh.Vertices[i].Y, mesh.Vertices[i].Z), Normal = new Vector3(mesh.Normals[i].X, mesh.Normals[i].Y, mesh.Normals[i].Z) }; if (mesh.HasTextureCoords(0)) { var texCoords = new Vector2(mesh.TextureCoordinateChannels[0][i].X, mesh.TextureCoordinateChannels[0][i].Y); vertex.TexCoords = texCoords; } else { vertex.TexCoords = new Vector2(0, 0); } if (mesh.HasTangentBasis) { vertex.Tangent = new Vector3(mesh.Tangents[i].X, mesh.Tangents[i].Y, mesh.Tangents[i].Z); vertex.BiTangent = new Vector3(mesh.BiTangents[i].X, mesh.BiTangents[i].Y, mesh.BiTangents[i].Z); } vertices.Add(vertex); } for (int i = 0; i < mesh.FaceCount; ++i) { var face = mesh.Faces[i]; for (int f = 0; f < face.IndexCount; ++f) { indices.Add((uint)face.Indices[f]); } } if (mesh.MaterialIndex >= 0) { var material = scene.Materials[mesh.MaterialIndex]; var diffuseMaps = LoadMaterialTextures(material, TextureType.Diffuse, "texture_diffuse"); textures.AddRange(diffuseMaps); if (diffuseMaps.Count == 0) { textures.Add(Texture.LoadFromData(new[] { (byte)(material.ColorDiffuse.R * 255), (byte)(material.ColorDiffuse.G * 255), (byte)(material.ColorDiffuse.B * 255), (byte)(material.ColorDiffuse.A * 255) }, 1, 1, 4, "texture_diffuse")); } var specularMaps = LoadMaterialTextures(material, TextureType.Specular, "texture_specular"); textures.AddRange(specularMaps); if (specularMaps.Count == 0) { textures.Add(Texture.LoadFromData(new[] { (byte)(material.ColorSpecular.R * 255), (byte)(material.ColorSpecular.G * 255), (byte)(material.ColorSpecular.B * 255), (byte)(material.ColorSpecular.A * 255) }, 1, 1, 4, "texture_specular")); } var normalMaps = LoadMaterialTextures(material, TextureType.Normals, "texture_normal"); textures.AddRange(normalMaps); var emissiveMaps = LoadMaterialTextures(material, TextureType.Emissive, "texture_emissive"); textures.AddRange(emissiveMaps); if (specularMaps.Count == 0) { textures.Add(Texture.LoadFromData(new[] { (byte)(material.ColorEmissive.R * 255), (byte)(material.ColorEmissive.G * 255), (byte)(material.ColorEmissive.B * 255), (byte)(material.ColorEmissive.A * 255) }, 1, 1, 4, "texture_emissive")); } var unknownMaps = LoadMaterialTextures(material, TextureType.Unknown, "texture_unknown"); // includes roughness textures.AddRange(unknownMaps); } var oglTransform = new System.Numerics.Matrix4x4( transform.A1, transform.A2, transform.A3, transform.A4, transform.B1, transform.B2, transform.B3, transform.B4, transform.C1, transform.C2, transform.C3, transform.C4, transform.D1, transform.D2, transform.D3, transform.D4 ); return(new Mesh(vertices, indices, textures, oglTransform)); }
/// <summary> /// Determine the number of elements in the vertex. /// </summary> private static int GetNumberOfInputElements(Mesh mesh) { bool hasTexCoords = mesh.HasTextureCoords(0); bool hasColors = mesh.HasVertexColors(0); bool hasNormals = mesh.HasNormals; bool hasTangents = mesh.Tangents != null; bool hasBitangents = mesh.BiTangents != null; int noofElements = 1; if (hasColors) noofElements++; if (hasNormals) noofElements++; if (hasTangents) noofElements++; if (hasBitangents) noofElements++; if (hasTexCoords) noofElements++; return noofElements; }
void createMeshes(Node node) { if (node.HasMeshes) { foreach (int meshIndex in node.MeshIndices) { Assimp.Mesh amesh = myScene.Meshes[meshIndex]; //create the material Graphics.Material mat = createMaterial(myScene.Materials[amesh.MaterialIndex]); //create the geometry Graphics.Mesh mesh = new Graphics.Mesh(); mesh.primativeType = OpenTK.Graphics.OpenGL.PrimitiveType.Triangles; mesh.indexBase = currIndexOffset; mesh.indexCount = amesh.FaceCount * 3; mesh.material = mat; //get the indices foreach (Face face in amesh.Faces) { for (int i = 0; i < 3; i++) { index.Add((UInt16)(face.Indices[i] + currVertOffset)); currIndexOffset++; } } //get the verts for (int i = 0; i < amesh.VertexCount; i++) { V3N3T2 v = new V3N3T2(); v.Position = toVector(amesh.Vertices[i]); if (amesh.HasNormals == true) { v.Normal = toVector(amesh.Normals[i]); } if (amesh.HasTextureCoords(0) == true) { v.TexCoord = toVector2D(amesh.TextureCoordinateChannels[0][i]); } myVerts.Add(v); } currVertOffset += amesh.VertexCount; myModel.myMeshes.Add(mesh); } } if (node.HasChildren) { foreach (Node child in node.Children) { createMeshes(child); } } }
private void AddVertexData(CModel model, Assimp.Scene scene, Node node, Device device, ref Matrix transform, string modelPath, CShaderResource shaderResource) { // TODO henning With this we don't preserve hiearchy in the models meshes, for now this is the wanted behavior but maybe we want to think about this in the future Matrix previousTransform = transform; transform = Matrix.Multiply(previousTransform, FromAssimpMatrix(node.Transform)); if (node.HasMeshes) { foreach (int index in node.MeshIndices) { // Get the mesh from the scene Assimp.Mesh assimpMesh = scene.Meshes[index]; // Create a mesh in our engine format CMesh mesh = new CMesh(); mesh.Transform.SetFromMatrix(in transform); model.AddMesh(ref mesh); //Extract diffuse texture from Assimp Material // TODO henning extract other textures if we want Material material = scene.Materials[assimpMesh.MaterialIndex]; if (material != null && material.GetMaterialTextureCount(TextureType.Diffuse) > 0) { TextureSlot texture; if (material.GetMaterialTexture(TextureType.Diffuse, 0, out texture)) { // Create texture asset mesh.Material = CMaterial.CreateDefaultMaterial(); CTextureSampler textureSampler = new CTextureSampler(device, device.ImmediateContext, modelPath + "\\" + texture.FilePath); mesh.Material.SetTextureParameter(new SHashedName("DiffuseTexture"), textureSampler); mesh.Material.FinishLoading(); } else { mesh.Material = CRenderer.Instance.ResourceManager.DefaultTextureMaterial; } } else { mesh.Material = CRenderer.Instance.ResourceManager.DefaultTextureMaterial; } mesh.Material.SetColorParameter(new SHashedName("tintColor"), new Vector4(1, 1, 1, 1)); int numInputElements = 6; // We always provide all data to the vertex buffer so shaders can rely on them being available if it is not in the asset we will add a default value bool hasTexCoords = assimpMesh.HasTextureCoords(0); bool hasColors = assimpMesh.HasVertexColors(0); bool hasNormals = assimpMesh.HasNormals; bool hasTangents = assimpMesh.Tangents != null && assimpMesh.Tangents.Count > 0; bool hasBiTangents = assimpMesh.BiTangents != null && assimpMesh.BiTangents.Count > 0; // Create InputElement list InputElement[] vertexElements = new InputElement[numInputElements]; uint elementIndex = 0; vertexElements[elementIndex] = new InputElement("POSITION", 0, SharpDX.DXGI.Format.R32G32B32_Float, 0); elementIndex++; int vertexSize = Utilities.SizeOf <Vector3>(); // TODO henning evaluate if we need 32bit vertex color range vertexElements[elementIndex] = new InputElement("COLOR", 0, SharpDX.DXGI.Format.R32G32B32A32_Float, 0); elementIndex++; vertexSize += Utilities.SizeOf <Vector4>(); vertexElements[elementIndex] = new InputElement("NORMAL", 0, SharpDX.DXGI.Format.R32G32B32_Float, 0); elementIndex++; vertexSize += Utilities.SizeOf <Vector3>(); vertexElements[elementIndex] = new InputElement("TANGENT", 0, SharpDX.DXGI.Format.R32G32B32_Float, 0); elementIndex++; vertexSize += Utilities.SizeOf <Vector3>(); vertexElements[elementIndex] = new InputElement("BITANGENT", 0, SharpDX.DXGI.Format.R32G32B32_Float, 0); elementIndex++; vertexSize += Utilities.SizeOf <Vector3>(); vertexElements[elementIndex] = new InputElement("TEXCOORD", 0, SharpDX.DXGI.Format.R32G32_Float, 0); elementIndex++; vertexSize += Utilities.SizeOf <Vector2>(); // Set InputElements and Vertex Size on mesh mesh.m_sizePerVertex = vertexSize; List <Vector3D> positions = assimpMesh.Vertices; List <Vector3D> texCoords = assimpMesh.TextureCoordinateChannels[0]; // TODO henning support multiple UV channels if wanted List <Vector3D> normals = assimpMesh.Normals; List <Vector3D> tangents = assimpMesh.Tangents; List <Vector3D> biTangents = assimpMesh.BiTangents; List <Color4D> colors = assimpMesh.VertexColorChannels[0]; switch (assimpMesh.PrimitiveType) { case PrimitiveType.Point: mesh.m_primitiveTopology = SharpDX.Direct3D.PrimitiveTopology.PointList; break; case PrimitiveType.Line: mesh.m_primitiveTopology = SharpDX.Direct3D.PrimitiveTopology.LineList; break; case PrimitiveType.Triangle: mesh.m_primitiveTopology = SharpDX.Direct3D.PrimitiveTopology.TriangleList; break; default: throw new NotImplementedException("Primitive Type not supported: " + assimpMesh.PrimitiveType.ToString()); } DataStream vertexStream = new DataStream(assimpMesh.VertexCount * vertexSize, true, true); for (int i = 0; i < assimpMesh.VertexCount; i++) { //add position, after transforming it with accumulated node transform { Vector3 pos = FromAssimpVector(positions[i]); vertexStream.Write(pos); } if (hasColors) { Vector4 vertColor = FromAssimpColor(colors[i]); vertexStream.Write(vertColor); } else { vertexStream.Write(new Vector4(1, 1, 1, 1)); } if (hasNormals) { Vector3 normal = FromAssimpVector(normals[i]); vertexStream.Write(normal); } else { vertexStream.Write(new Vector3(0, 0, 0)); } if (hasTangents) { Vector3 tangent = FromAssimpVector(tangents[i]); vertexStream.Write(tangent); } else { vertexStream.Write(new Vector3(0, 0, 0)); } if (hasBiTangents) { Vector3 biTangent = FromAssimpVector(biTangents[i]); vertexStream.Write(biTangent); } else { vertexStream.Write(new Vector3(0, 0, 0)); } if (hasTexCoords) { vertexStream.Write(new Vector2(texCoords[i].X, texCoords[i].Y)); } else { vertexStream.Write(new Vector2(0, 0)); } } vertexStream.Position = 0; BufferDescription vertexDescription = new BufferDescription { BindFlags = BindFlags.VertexBuffer, Usage = ResourceUsage.Default, CpuAccessFlags = CpuAccessFlags.None, SizeInBytes = assimpMesh.VertexCount * vertexSize, OptionFlags = ResourceOptionFlags.None }; mesh.m_vertexBuffer = new Buffer(device, vertexStream, vertexDescription); vertexStream.Dispose(); mesh.m_vertexCount = assimpMesh.VertexCount; mesh.m_primitiveCount = assimpMesh.FaceCount; int[] indices = assimpMesh.GetIndices(); mesh.m_indexBuffer = Buffer.Create(device, BindFlags.IndexBuffer, indices); mesh.m_indexCount = indices.Length; } } for (int i = 0; i < node.ChildCount; i++) { AddVertexData(model, scene, node.Children[i], device, ref transform, modelPath, shaderResource); } transform = previousTransform; }
private ModelData.MeshPart Process(ModelData.Mesh mesh, Mesh assimpMesh) { var meshPart = new ModelData.MeshPart { PrimitiveTopology = PrimitiveTopology.TriangleList, VertexBufferRange = new ModelData.BufferRange { Slot = mesh.VertexBuffers.Count }, IndexBufferRange = new ModelData.BufferRange { Slot = mesh.IndexBuffers.Count } }; var vertexBuffer = new ModelData.VertexBuffer { Layout = new List <VertexElement>() }; mesh.VertexBuffers.Add(vertexBuffer); var indexBuffer = new ModelData.IndexBuffer(); mesh.IndexBuffers.Add(indexBuffer); var layout = vertexBuffer.Layout; int vertexBufferElementSize = 0; // Add position layout.Add(VertexElement.PositionTransformed(Format.R32G32B32_Float, 0)); vertexBufferElementSize += SharpDX.Utilities.SizeOf <Vector3>(); // Add normals if (assimpMesh.HasNormals) { layout.Add(VertexElement.Normal(0, Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += SharpDX.Utilities.SizeOf <Vector3>(); } // Add colors if (assimpMesh.VertexColorChannelCount > 0) { for (int localIndex = 0, i = 0; i < assimpMesh.VertexColorChannelCount; i++) { if (assimpMesh.HasVertexColors(i)) { layout.Add(VertexElement.Normal(localIndex, Format.R32G32B32A32_Float, vertexBufferElementSize)); vertexBufferElementSize += SharpDX.Utilities.SizeOf <Color4>(); localIndex++; } } } // Add textures if (assimpMesh.TextureCoordsChannelCount > 0) { for (int localIndex = 0, i = 0; i < assimpMesh.TextureCoordsChannelCount; i++) { if (assimpMesh.HasTextureCoords(i)) { var uvCount = assimpMesh.GetUVComponentCount(i); if (uvCount == 2) { layout.Add(VertexElement.TextureCoordinate(localIndex, Format.R32G32_Float, vertexBufferElementSize)); vertexBufferElementSize += SharpDX.Utilities.SizeOf <Vector2>(); } else if (uvCount == 3) { layout.Add(VertexElement.TextureCoordinate(localIndex, Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += SharpDX.Utilities.SizeOf <Vector3>(); } else { throw new InvalidOperationException("Unexpected uv count"); } localIndex++; } } } if (options.ModelOperations.HasFlag(ModelOperation.CalculateBarycentricCoordinates)) { layout.Add(new VertexElement("BARYCENTRIC", 0, Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += SharpDX.Utilities.SizeOf <Vector3>(); } else // Add tangent / bitangent if (assimpMesh.HasTangentBasis) { if (!options.ExcludeElements.Contains("Tangent")) { layout.Add(VertexElement.Tangent(Format.R32G32B32A32_Float, vertexBufferElementSize)); vertexBufferElementSize += SharpDX.Utilities.SizeOf <Vector4>(); } if (!options.ExcludeElements.Contains("BiTangent")) { layout.Add(VertexElement.BiTangent(Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += SharpDX.Utilities.SizeOf <Vector3>(); } } if (options.ModelOperations.HasFlag(ModelOperation.CalculateBarycentricCoordinates)) { WriteBarycentricVertices(assimpMesh, meshPart, vertexBuffer, vertexBufferElementSize); } else { WriteVertices(assimpMesh, meshPart, vertexBuffer, vertexBufferElementSize); } WriteIndices(assimpMesh, meshPart, indexBuffer); return(meshPart); }