internal void LoadPrimitveFromFile(string fileName, out DebugVertexType[] vertices, out UInt16[] indices) { Assimp.Scene scene = m_importer.ImportFile(fileName, PostProcessPreset.TargetRealTimeMaximumQuality | PostProcessPreset.ConvertToLeftHanded); // Loaded primitive files should always only contain a single mesh so we load only the first mesh if (scene.HasMeshes) { Assimp.Mesh assimpMesh = scene.Meshes[0]; vertices = new DebugVertexType[assimpMesh.Vertices.Count]; indices = new UInt16[assimpMesh.GetIndices().Length]; for (int i = 0; i < assimpMesh.Vertices.Count; ++i) { Vector3 position = FromAssimpVector(assimpMesh.Vertices[i]); vertices[i].position = position; } for (int i = 0; i < assimpMesh.GetIndices().Length; i++) { int index = assimpMesh.GetIndices()[i]; indices[i] = (UInt16)index; } } else { vertices = new DebugVertexType[0]; indices = new UInt16[0]; } }
/// <summary> /// Import a mesh from a model file. /// </summary> /// <param name="path"></param> /// <returns></returns> public static Mesh Load(string path) { Mesh mesh = new Mesh() { Path = path }; a.AssimpContext context = new a.AssimpContext(); a.Scene scene = context.ImportFile(path, a.PostProcessSteps.Triangulate); a.Mesh aMesh = scene.Meshes[0]; mesh.vertices = new Vector4[aMesh.VertexCount]; mesh.normals = new Vector4[aMesh.VertexCount]; mesh.uvs = new Vector4[aMesh.VertexCount]; for (int i = 0; i < aMesh.VertexCount; i++) { a.Vector3D aVertex = aMesh.Vertices[i]; a.Vector3D aNormal = aMesh.Normals[i]; a.Vector3D aUv = aMesh.TextureCoordinateChannels[0][i]; mesh.vertices[i] = new Vector4(aVertex.X, aVertex.Y, aVertex.Z, 1f); mesh.normals[i] = new Vector4(aNormal.X, aNormal.Y, aNormal.Z, 0f); mesh.uvs[i] = new Vector4(aUv.X, aUv.Y, 0f, 0f); } mesh.indices = aMesh.GetIndices(); return(mesh); }
private static void ProcessMesh(ref Assimp.Mesh mesh, ref Mesh result) { if (mesh != null) { if (!string.IsNullOrWhiteSpace(mesh.Name)) { result.Name = mesh.Name; } List <float> vertices = new List <float>(); foreach (Vector3D pos in mesh.Vertices) { vertices.Add(pos.X); vertices.Add(pos.Y); vertices.Add(pos.Z); } result.Vertices = vertices.ToArray(); List <float> uvs = new List <float>(); foreach (Vector3D uv in mesh.TextureCoordinateChannels[0]) { uvs.Add(uv.X); uvs.Add(1.0f - uv.Y); } result.UVs = uvs.ToArray(); List <float> normals = new List <float>(); foreach (Vector3D normal in mesh.Normals) { normals.Add(normal.X); normals.Add(normal.Y); normals.Add(normal.Z); } result.Normals = normals.ToArray(); result.Indices = mesh.GetIndices().Select(i => (uint)i).ToArray(); } }
public DX11IndexedGeometry LoadFromMesh(Assimp.Mesh mesh, AssimpLoadInformation loadInfo, bool allowRawView = false) { uint[] inds = mesh.GetIndices(); if (inds.Length > 0 && mesh.VertexCount > 0) { int vertexsize; var layout = mesh.InputLayout(loadInfo, out vertexsize); BoundingBox bb; DataStream ds = mesh.LoadVertices(loadInfo, vertexsize, out bb); DX11IndexedGeometry geom = new DX11IndexedGeometry(device) { HasBoundingBox = true, BoundingBox = bb, IndexBuffer = DX11IndexBuffer.CreateImmutable(device, inds, allowRawView), InputLayout = layout, PrimitiveType = "AssimpModel", Tag = null, Topology = SharpDX.Direct3D.PrimitiveTopology.TriangleList, VertexBuffer = DX11VertexBuffer.CreateImmutable(device, mesh.VertexCount, vertexsize, ds, allowRawView) }; ds.Dispose(); return(geom); } return(null); }
private Core.Entities.Mesh convertAssimpToEngineFormat(Mesh assimpMesh) { Core.Entities.Mesh mesh = new Core.Entities.Mesh(); mesh.Vertices = assimpMesh.Vertices.AssimpListToOpentkVector().ToArray(); mesh.Normals = assimpMesh.Normals.AssimpListToOpentkVector().ToArray(); mesh.UvCoords = assimpMesh.TextureCoordinateChannels[0].GetUVCoordChanel().ToArray(); mesh.Indeces = assimpMesh.GetIndices(); return(mesh); }
static meshData ProcessMesh(Assimp.Mesh mesh, Assimp.Scene scene) { Vector3[] post = mesh.Vertices.Select(x => x.V()).ToArray(); Vector3[] norm = mesh.Normals.Select(x => x.V()).ToArray(); Vector3[] tang = mesh.Tangents.Select(x => x.V()).ToArray(); Vector2[] uves = mesh.TextureCoordinateChannels[0].Select(x => x.VX()).ToArray(); int[] inde = mesh.GetIndices(); var materialIndex = mesh.MaterialIndex; return(new meshData(post, inde, norm, tang, uves)); }
public virtual int[] GetIndices(int offset = 0) { int[] indices = AssMesh.GetIndices(); if (offset != 0) { for (int i = 0; i < indices.Length; i++) { indices[i] += offset; } } return(indices); }
public static Mesh Clone(this Mesh mesh) { var newMesh = new Mesh(mesh.PrimitiveType); newMesh.Vertices.AddRange(mesh.Vertices); newMesh.SetIndices(mesh.GetIndices(), mesh.Faces[0].IndexCount); if (newMesh.HasNormals) { newMesh.Normals.AddRange(mesh.Normals); } for (int i = 0; i < mesh.TextureCoordinateChannelCount; i++) { newMesh.TextureCoordinateChannels[i].AddRange(mesh.TextureCoordinateChannels[i]); } foreach (var bone in mesh.Bones) { newMesh.Bones.Add(new Bone(bone.Name, bone.OffsetMatrix, bone.VertexWeights.ToArray())); } return(newMesh); }
//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 ModelData.MeshPart Process(ModelData.Mesh mesh, Assimp.Mesh assimpMesh, Node parentNode) { 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 <Vector3>(); // Add normals if (assimpMesh.HasNormals) { layout.Add(VertexElement.Normal(0, Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += 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.Color(localIndex, Format.R32G32B32A32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <Color4>(); localIndex++; } } } // Add textures if (assimpMesh.TextureCoordinateChannelCount > 0) { for (int localIndex = 0, i = 0; i < assimpMesh.TextureCoordinateChannelCount; i++) { if (assimpMesh.HasTextureCoords(i)) { var uvCount = assimpMesh.UVComponentCount[i]; if (uvCount == 2) { layout.Add(VertexElement.TextureCoordinate(localIndex, Format.R32G32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <Vector2>(); } else if (uvCount == 3) { layout.Add(VertexElement.TextureCoordinate(localIndex, Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <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 <Vector3>(); layout.Add(VertexElement.BiTangent(Format.R32G32B32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <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) { for (int i = 0; i < assimpMesh.Bones.Count; i++) { var bone = assimpMesh.Bones[i]; var boneNode = scene.RootNode.FindNode(bone.Name); if (bone.HasVertexWeights) { var skinnedBoneIndex = meshPart.SkinnedBones.Count; meshPart.SkinnedBones.Add(new ModelData.SkinnedBone { BoneIndex = skeletonNodes[boneNode], InverseBindTransform = ConvertMatrix(bone.OffsetMatrix) }); for (int j = 0; j < bone.VertexWeightCount; j++) { var weights = bone.VertexWeights[j]; var vertexSkinningCount = skinningCount[weights.VertexID]; skinningIndices[weights.VertexID][vertexSkinningCount] = skinnedBoneIndex; skinningWeights[weights.VertexID][vertexSkinningCount] = weights.Weight; skinningCount[weights.VertexID] = ++vertexSkinningCount; } hasWeights = true; } } if (hasWeights) { layout.Add(VertexElement.BlendIndices(Format.R16G16B16A16_SInt, vertexBufferElementSize)); vertexBufferElementSize += 8; layout.Add(VertexElement.BlendWeights(Format.R32G32B32A32_Float, vertexBufferElementSize)); vertexBufferElementSize += Utilities.SizeOf <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++) { Vector3 position = ConvertVector(assimpMesh.Vertices[i]); vertexStream.Write(position); // Store bounding points for BoundingSphere pre-calculation boundingPoints[currentBoundingPointIndex++] = position; // Add normals if (assimpMesh.HasNormals) { var normal = ConvertVector(assimpMesh.Normals[i]); vertexStream.Write(normal); } // Add colors if (assimpMesh.VertexColorChannelCount > 0) { for (int j = 0; j < assimpMesh.VertexColorChannelCount; j++) { if (assimpMesh.HasVertexColors(j)) { vertexStream.Write(assimpMesh.VertexColorChannels[j][i]); } } } // Add textures if (assimpMesh.TextureCoordinateChannelCount > 0) { for (int j = 0; j < assimpMesh.TextureCoordinateChannelCount; j++) { if (assimpMesh.HasTextureCoords(j)) { var uvCount = assimpMesh.UVComponentCount[j]; var uv = assimpMesh.TextureCoordinateChannels[j][i]; if (uvCount == 2) { vertexStream.Write(new Vector2(uv.X, uv.Y)); } else { vertexStream.Write(uv); } } } } // Add tangent / bitangent if (assimpMesh.HasTangentBasis) { var tangent = ConvertVector(assimpMesh.Normals[i]); var bitangent = ConvertVector(assimpMesh.Normals[i]); vertexStream.Write(tangent); vertexStream.Write(bitangent); } // Add Skinning Indices/Weights if (assimpMesh.HasBones && hasWeights) { var vertexSkinndingIndices = skinningIndices[i]; vertexStream.Write((short)vertexSkinndingIndices.X); vertexStream.Write((short)vertexSkinndingIndices.Y); vertexStream.Write((short)vertexSkinndingIndices.Z); vertexStream.Write((short)vertexSkinndingIndices.W); vertexStream.Write(skinningWeights[i]); } } vertexStream.Dispose(); // Write all indices var indices = assimpMesh.GetIndices(); 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 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 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 void LoadMeshInternal(int meshIndex, CMeshAsset asset, CMeshLoadingJob loadingJob, string assetPath, string nameOverride = null, bool bAlwaysImport = false) { Assimp.Mesh assimpMesh = loadingJob.Scene.Meshes[meshIndex]; // Load texture and material from the file if present //todo henning extract more textures Material material = loadingJob.Scene.Materials[assimpMesh.MaterialIndex]; if (material != null && material.GetMaterialTextureCount(TextureType.Diffuse) > 0) { if (material.GetMaterialTexture(TextureType.Diffuse, 0, out TextureSlot texture)) { if (loadingJob.LoadedMaterials == null || !loadingJob.LoadedMaterials.TryGetValue(material.Name, out CMaterialAsset materialAsset)) { materialAsset = new CMaterialAsset(); loadingJob.LoadedMaterials?.Add(material.Name, materialAsset); // Make sure we only load each referenced texture once if (loadingJob.LoadedTextures == null || !loadingJob.LoadedTextures.TryGetValue(texture.FilePath, out CTextureAsset textureAsset)) { textureAsset = CImportManager.Instance.TextureImporter.ImportTextureAsync(loadingJob.BasePath + "\\" + texture.FilePath, assetPath + "Textures/"); loadingJob.LoadedTextures?.Add(texture.FilePath, textureAsset); } SShaderParameter textureParameter = new SShaderParameter() { parameterData = new CAssetReference <CTextureAsset>(textureAsset), parameterType = EShaderParameterType.Texture }; materialAsset.MaterialParameters.Add(new SMaterialParameterEntry(new SHashedName("DiffuseTexture"), textureParameter)); materialAsset.Name = material.Name; if (CAssetRegistry.Instance.RequestRegisterAsset(materialAsset, assetPath + "Materials/", out CMaterialAsset existingMaterial)) { existingMaterial.WaitUntilLoaded(); existingMaterial.CopyFrom(existingMaterial); } materialAsset.LoadFinished(); } asset.MaterialAsset = materialAsset; } } 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; switch (assimpMesh.PrimitiveType) { case PrimitiveType.Point: asset.PrimitiveTopology = PrimitiveTopology.PointList; break; case PrimitiveType.Line: asset.PrimitiveTopology = PrimitiveTopology.LineList; break; case PrimitiveType.Triangle: asset.PrimitiveTopology = PrimitiveTopology.TriangleList; break; default: throw new ArgumentOutOfRangeException("Primtive Type not supported: " + assimpMesh.PrimitiveType.ToString()); } asset.FaceCount = assimpMesh.FaceCount; asset.VertexData = new SVertexInfo[assimpMesh.VertexCount]; Vector3 boundingBoxMin = new Vector3(1e10f, 1e10f, 1e10f); Vector3 boundingBoxMax = new Vector3(-1e10f, -1e10f, -1e10f); for (int i = 0; i < assimpMesh.VertexCount; i++) { SVertexInfo vertexInfo = new SVertexInfo(); vertexInfo.position = FromAssimpVector(assimpMesh.Vertices[i]); boundingBoxMin.X = Math.Min(vertexInfo.position.X, boundingBoxMin.X); boundingBoxMin.Y = Math.Min(vertexInfo.position.Y, boundingBoxMin.Y); boundingBoxMin.Z = Math.Min(vertexInfo.position.Z, boundingBoxMin.Z); boundingBoxMax.X = Math.Max(vertexInfo.position.X, boundingBoxMax.X); boundingBoxMax.Y = Math.Max(vertexInfo.position.Y, boundingBoxMax.Y); boundingBoxMax.Z = Math.Max(vertexInfo.position.Z, boundingBoxMax.Z); if (hasColors) { vertexInfo.color = FromAssimpColor(assimpMesh.VertexColorChannels[0][i]); } else { vertexInfo.color = Vector4.One; } if (hasNormals) { vertexInfo.normal = FromAssimpVector(assimpMesh.Normals[i]); } if (hasBiTangents) { vertexInfo.biTangent = FromAssimpVector(assimpMesh.BiTangents[i]); } if (hasTangents) { vertexInfo.tangent = FromAssimpVector(assimpMesh.Tangents[i]); } if (hasTexCoords) { Vector3D assimpTexCoord = assimpMesh.TextureCoordinateChannels[0][i]; vertexInfo.texCoord = new Vector2(assimpTexCoord.X, assimpTexCoord.Y); } asset.VertexData[i] = vertexInfo; } asset.AABBMin = boundingBoxMin; asset.AABBMax = boundingBoxMax; asset.IndexData = assimpMesh.GetIndices(); asset.Name = nameOverride ?? assimpMesh.Name; if (CAssetRegistry.Instance.RequestRegisterAsset(asset, assetPath, out CMeshAsset existingAsset, true)) { existingAsset.WaitUntilLoaded(); asset.CopyFrom(existingAsset); } }
/// <summary> /// internal. /// </summary> internal static Scene ConvertFromAssimp(Assimp.Scene _Scene) { Scene Result = new Scene(); LoadTextures(_Scene); Result.CompileEnable = false; for (int i = 0; i < _Scene.Meshes.Count; i++) { D3DMesh _M = new D3DMesh(); _M.CompileEnable = false; Assimp.Mesh M = _Scene.Meshes[i]; List <int> _Indices = new List <int>(M.Faces.Count * 4); if (M.Faces.Count > 0) { for (int j = 0; j < M.Faces.Count; j++) { if (M.Faces[j].Indices.Count > 4) { _Indices.Add(M.Faces[j].Indices[0]); _Indices.Add(M.Faces[j].Indices[1]); _Indices.Add(M.Faces[j].Indices[4]); _Indices.Add(M.Faces[j].Indices[4]); _Indices.Add(M.Faces[j].Indices[1]); _Indices.Add(M.Faces[j].Indices[2]); _Indices.Add(M.Faces[j].Indices[4]); _Indices.Add(M.Faces[j].Indices[2]); _Indices.Add(M.Faces[j].Indices[3]); } else if (M.Faces[j].Indices.Count > 3) { _Indices.Add(M.Faces[j].Indices[0]); _Indices.Add(M.Faces[j].Indices[1]); _Indices.Add(M.Faces[j].Indices[3]); _Indices.Add(M.Faces[j].Indices[3]); _Indices.Add(M.Faces[j].Indices[1]); _Indices.Add(M.Faces[j].Indices[2]); } else { _Indices.Add(M.Faces[j].Indices[0]); _Indices.Add(M.Faces[j].Indices[1]); _Indices.Add(M.Faces[j].Indices[2]); } } _M.Indices = _Indices.ToArray(); } Result.Meshes.Add(_M); //----------------Indices-------------------- int[] Indices = M.GetIndices(); _M.Material = AssimpConv.ConvertMaterial(_Scene.Materials[M.MaterialIndex]); _M.Texture = LoadTexture(_Scene.Materials[M.MaterialIndex]); List <Vector3D> Vertices = M.Vertices; _M.Position = new xyzf[Vertices.Count]; for (int j = 0; j < Vertices.Count; j++) { Vector3D V = Vertices[j]; _M.Position[j] = new xyzf(V.X, V.Y, V.Z); } List <Vector3D> Normals = M.Normals; _M.Normals = new xyzf[Normals.Count]; for (int j = 0; j < Normals.Count; j++) { Vector3D V = Normals[j]; _M.Normals[j] = new xyzf(V.X, V.Y, V.Z).normalized(); } if (M.TextureCoordinateChannelCount > 0) { _M.TextureCoords = new xyf[M.TextureCoordinateChannels[0].Count]; for (int j = 0; j < M.TextureCoordinateChannels[0].Count; j++) { Vector3D V = M.TextureCoordinateChannels[0][j]; _M.TextureCoords[j] = new xyf(V.X, V.Y); } } _M.Bones = new List <Bone>(); for (int k = 0; k < M.BoneCount; k++) { Assimp.Bone B = M.Bones[k]; VertexWeight[] VW = new VertexWeight[B.VertexWeights.Count]; for (int g = 0; g < VW.Length; g++) { VW[g] = new VertexWeight(B.VertexWeights[g].VertexID, B.VertexWeights[g].Weight); } Bone _B = new Bone(B.Name, AssimpConv.ConvertTransform(B.OffsetMatrix), VW); _M.Bones.Add(_B); } } LoadNode(_Scene, Result); MoveTranslucentAtEnd(Result); Result._Scene = _Scene; Result.SceneAnimator = new SceneAnimator(Result); return(Result); }