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]);
                }
            }
        }
Beispiel #2
0
        public Model Load(AssetManager assetManager, RenderContext renderContext, Stream stream, string sourcePath)
        {
            Scene scene = Importer.ImportFile(sourcePath, PostProcessSteps.Triangulate | PostProcessSteps.FlipUVs);

            if (scene == null || scene.SceneFlags.HasFlag(SceneFlags.Incomplete) || scene.RootNode == null)
            {
                throw new Exception("Assimp Error.");
            }

            var meshes = new List <Mesh>();

            string directory = Path.GetDirectoryName(sourcePath);

            Texture2D LoadFromTextureSlot(TextureSlot textureSlot, TextureType textureType)
            {
                var texture = assetManager.Load <Texture2D>(Path.Combine(directory, textureSlot.FilePath));

                texture.SetInfoFromTextureSlot(renderContext, ref textureSlot);

                texture.SetMinFilter(renderContext, TextureMinFilter.NearestMipmapLinear);
                return(texture);
            }

            List <Texture2D> LoadMaterialTextures(AssimpMaterial material, TextureType textureType)
            {
                List <Texture2D> textures = new List <Texture2D>();

                for (int i = 0; i < material.GetMaterialTextureCount(textureType); i++)
                {
                    material.GetMaterialTexture(textureType, i, out var textureSlot);

                    if (textureSlot.FilePath != null)
                    {
                        if (textureSlot.FilePath.Contains("*"))
                        {
                            throw new InvalidOperationException();
                        }

                        var texture = assetManager.Load <Texture2D>(Path.Combine(directory, textureSlot.FilePath));
                        texture.SetInfoFromTextureSlot(renderContext, ref textureSlot);
                        textures.Add(texture);
                    }
                }
                return(textures);
            }

            Mesh ProcessMesh(AssimpMesh mesh, System.Numerics.Matrix4x4 transformMatrix)
            {
                VertexPositionNormalTexture[] vertices = new VertexPositionNormalTexture[mesh.VertexCount];
                List <uint> indices = new List <uint>();

                // Process vertices
                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    Vector3D position = mesh.Vertices[i];
                    vertices[i].Position = Unsafe.As <Vector3D, Vector3>(ref position);
                    Vector3D normal = mesh.Normals[i];
                    vertices[i].Normal = Unsafe.As <Vector3D, Vector3>(ref normal);

                    if (mesh.HasTextureCoords(0))
                    {
                        Vector3D texCoord = mesh.TextureCoordinateChannels[0][i];
                        vertices[i].TexCoord = new Vector2(texCoord.X, 1 - texCoord.Y);
                    }
                }

                // Process indices
                for (int i = 0; i < mesh.FaceCount; i++)
                {
                    AssimpFace face = mesh.Faces[i];
                    for (int j = 0; j < face.IndexCount; j++)
                    {
                        indices.Add((uint)face.Indices[j]);
                    }
                }

                Mesh.MeshTextureInfo textures = new Mesh.MeshTextureInfo();

                // Process Material
                if (mesh.MaterialIndex >= 0)
                {
                    AssimpMaterial material = scene.Materials[mesh.MaterialIndex];

                    var texturezzz = material.GetAllMaterialTextures();

                    texturezzz = texturezzz.Where(x => x.FilePath != null).ToArray();

                    if (material.HasTextureDiffuse)
                    {
                        textures.Diffuse = LoadFromTextureSlot(material.TextureDiffuse, TextureType.Diffuse);
                    }

                    if (material.HasTextureSpecular)
                    {
                        textures.Specular = LoadFromTextureSlot(material.TextureSpecular, TextureType.Specular);
                    }

                    if (material.HasTextureLightMap)
                    {
                        textures.MetallicRoughness = LoadFromTextureSlot(material.TextureLightMap, TextureType.Lightmap);
                    }
                }

                return(new Mesh(renderContext, vertices, indices.ToArray(), textures, transformMatrix));
            }

            void ProcessNode(Node node, System.Numerics.Matrix4x4 transform)
            {
                var t             = node.Transform;
                var thisTransform = Unsafe.As <Matrix4x4, System.Numerics.Matrix4x4>(ref t);

                // Process all of the node's meshes
                for (int i = 0; i < node.MeshCount; i++)
                {
                    AssimpMesh mesh = scene.Meshes[node.MeshIndices[i]];
                    meshes.Add(ProcessMesh(mesh, transform * thisTransform));
                }

                // Recurse
                for (int i = 0; i < node.ChildCount; i++)
                {
                    ProcessNode(node.Children[i], transform * thisTransform);
                }
            }

            ProcessNode(scene.RootNode, System.Numerics.Matrix4x4.Identity);

            return(new Model(meshes.ToArray()));
        }
Beispiel #3
0
        private static Ai.Mesh CreateAiMeshFromSubMesh(SubMesh subMesh, Mesh mesh, Object obj, Ai.Scene aiScene, string name)
        {
            var aiMesh = new Ai.Mesh(name, Ai.PrimitiveType.Triangle);

            if (mesh.Positions != null)
            {
                aiMesh.Vertices.Capacity = mesh.Positions.Length;
                aiMesh.Vertices.AddRange(mesh.Positions.Select(x => x.ToAssimp()));
            }

            if (mesh.Normals != null)
            {
                aiMesh.Normals.Capacity = mesh.Normals.Length;
                aiMesh.Normals.AddRange(mesh.Normals.Select(x => x.ToAssimp()));
            }

            for (int i = 0; i < 4; i++)
            {
                var texCoords = mesh.GetTexCoordsChannel(i);

                if (texCoords == null)
                {
                    continue;
                }

                aiMesh.TextureCoordinateChannels[i].Capacity = texCoords.Length;
                aiMesh.TextureCoordinateChannels[i].AddRange(texCoords.Select(x => new Ai.Vector3D(x.ToAssimp(), 0)));
            }

            for (int i = 0; i < 2; i++)
            {
                var colors = mesh.GetColorsChannel(i);

                if (colors == null)
                {
                    continue;
                }

                aiMesh.VertexColorChannels[i].Capacity = colors.Length;
                aiMesh.VertexColorChannels[i].AddRange(colors.Select(x => x.ToAssimp()));
            }

            if (mesh.BoneWeights != null)
            {
                for (int i = 0; i < subMesh.BoneIndices.Length; i++)
                {
                    ushort boneIndex = subMesh.BoneIndices[i];
                    var    bone      = obj.Skin.Bones[boneIndex];

                    var aiBone = new Ai.Bone();

                    aiBone.Name         = bone.Name;
                    aiBone.OffsetMatrix = bone.InverseBindPoseMatrix.ToAssimpTransposed();

                    for (int j = 0; j < mesh.BoneWeights.Length; j++)
                    {
                        var boneWeight = mesh.BoneWeights[j];

                        if (boneWeight.Index1 == i)
                        {
                            aiBone.VertexWeights.Add(new Ai.VertexWeight(j, boneWeight.Weight1));
                        }

                        if (boneWeight.Index2 == i)
                        {
                            aiBone.VertexWeights.Add(new Ai.VertexWeight(j, boneWeight.Weight2));
                        }

                        if (boneWeight.Index3 == i)
                        {
                            aiBone.VertexWeights.Add(new Ai.VertexWeight(j, boneWeight.Weight3));
                        }

                        if (boneWeight.Index4 == i)
                        {
                            aiBone.VertexWeights.Add(new Ai.VertexWeight(j, boneWeight.Weight4));
                        }
                    }

                    aiMesh.Bones.Add(aiBone);
                }
            }

            var triangles = subMesh.GetTriangles();

            aiMesh.Faces.Capacity = triangles.Count;

            aiMesh.Faces.AddRange(triangles.Select(x =>
            {
                var aiFace = new Ai.Face();
                aiFace.Indices.Capacity = 3;
                aiFace.Indices.Add(( int )x.A);
                aiFace.Indices.Add(( int )x.B);
                aiFace.Indices.Add(( int )x.C);
                return(aiFace);
            }));

            var material = obj.Materials[( int )subMesh.MaterialIndex];

            int materialIndex = aiScene.Materials.FindIndex(x => x.Name == material.Name + "+" + obj.Name);

            if (materialIndex == -1)
            {
                materialIndex = aiScene.Materials.FindIndex(x => x.Name == material.Name);
            }

            aiMesh.MaterialIndex = materialIndex;

            return(aiMesh);
        }
Beispiel #4
0
        private static Ai.Node ConvertAiNodeFromMesh(Mesh mesh, Ai.Scene aiScene, bool appendTags = false)
        {
            var aiNode = new Ai.Node(mesh.Name);

            foreach (var subMesh in mesh.SubMeshes)
            {
                foreach (var indexTable in subMesh.IndexTables)
                {
                    var aiSubMeshNode = new Ai.Node(subMesh.Name);
                    var aiMesh        = new Ai.Mesh(subMesh.Name, Ai.PrimitiveType.Triangle);

                    var material = mesh.Materials[indexTable.MaterialIndex];
                    aiMesh.MaterialIndex = aiScene.Materials.FindIndex(x => x.Name.Equals(material.Name));

                    if (subMesh.Vertices != null)
                    {
                        aiMesh.Vertices.AddRange(subMesh.Vertices.Select(
                                                     x => new Ai.Vector3D(x.X, x.Y, x.Z)));
                    }

                    if (subMesh.Normals != null)
                    {
                        aiMesh.Normals.AddRange(subMesh.Normals.Select(
                                                    x => new Ai.Vector3D(x.X, x.Y, x.Z)));
                    }

                    if (subMesh.UVChannel1 != null)
                    {
                        aiMesh.TextureCoordinateChannels[0].AddRange(subMesh.UVChannel1.Select(
                                                                         x => new Ai.Vector3D(x.X, 1.0f - x.Y, 0.0f)));
                    }

                    if (subMesh.UVChannel2 != null)
                    {
                        aiMesh.TextureCoordinateChannels[1].AddRange(subMesh.UVChannel2.Select(
                                                                         x => new Ai.Vector3D(x.X, 1.0f - x.Y, 0.0f)));
                    }

                    // Why does 3DS Max go retarded when colors are exported?
                    if (subMesh.Colors != null)
                    {
                        aiMesh.VertexColorChannels[0].AddRange(subMesh.Colors.Select(
                                                                   x => new Ai.Color4D(x.R, x.G, x.B, x.A)));
                    }

                    foreach (var triangle in indexTable.GetTriangles())
                    {
                        var aiFace = new Ai.Face();
                        aiFace.Indices.Add(triangle.A);
                        aiFace.Indices.Add(triangle.B);
                        aiFace.Indices.Add(triangle.C);
                        aiMesh.Faces.Add(aiFace);
                    }

                    if (indexTable.BoneIndices != null)
                    {
                        for (int i = 0; i < indexTable.BoneIndices.Length; i++)
                        {
                            int boneIndex = indexTable.BoneIndices[i];
                            var bone      = mesh.Skin.Bones[boneIndex];
                            var aiBone    = new Ai.Bone();
                            aiBone.Name         = bone.Name;
                            aiBone.OffsetMatrix = bone.Matrix.ToAssimp();

                            if (appendTags)
                            {
                                aiBone.Name = $"{aiBone.Name}{Tag.Create( "ID", bone.Id )}";
                            }

                            for (int j = 0; j < subMesh.BoneWeights.Length; j++)
                            {
                                var weight = subMesh.BoneWeights[j];
                                if (weight.Index1 == i)
                                {
                                    aiBone.VertexWeights.Add(new Ai.VertexWeight
                                    {
                                        VertexID = j,
                                        Weight   = weight.Weight1
                                    });
                                }

                                if (weight.Index2 == i)
                                {
                                    aiBone.VertexWeights.Add(new Ai.VertexWeight
                                    {
                                        VertexID = j,
                                        Weight   = weight.Weight2
                                    });
                                }

                                if (weight.Index3 == i)
                                {
                                    aiBone.VertexWeights.Add(new Ai.VertexWeight
                                    {
                                        VertexID = j,
                                        Weight   = weight.Weight3
                                    });
                                }

                                if (weight.Index4 == i)
                                {
                                    aiBone.VertexWeights.Add(new Ai.VertexWeight
                                    {
                                        VertexID = j,
                                        Weight   = weight.Weight4
                                    });
                                }
                            }

                            aiMesh.Bones.Add(aiBone);
                        }
                    }

                    aiNode.Children.Add(aiSubMeshNode);
                    aiSubMeshNode.MeshIndices.Add(aiScene.MeshCount);
                    aiScene.Meshes.Add(aiMesh);
                }
            }

            if (appendTags)
            {
                aiNode.Name = $"{aiNode.Name}{Tag.Create( "ID", mesh.Id )}";
            }

            return(aiNode);
        }
Beispiel #5
0
        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));
        }
Beispiel #6
0
        /// <summary>
        /// Constructs a new Mesh.
        /// </summary>
        /// <param name="mesh">Unmanaged AiMesh struct.</param>
        internal Mesh(AiMesh mesh)
        {
            _name = mesh.Name.GetString();
            _primitiveType = mesh.PrimitiveTypes;
            _vertexCount = (int) mesh.NumVertices;
            _materialIndex = (int) mesh.MaterialIndex;

            //Load per-vertex arrays
            if(mesh.NumVertices > 0) {
                if(mesh.Vertices != IntPtr.Zero) {
                    _vertices = MemoryHelper.MarshalArray<Vector3D>(mesh.Vertices, _vertexCount);
                }
                if(mesh.Normals != IntPtr.Zero) {
                    _normals = MemoryHelper.MarshalArray<Vector3D>(mesh.Normals, _vertexCount);
                }
                if(mesh.Tangents != IntPtr.Zero) {
                    _tangents = MemoryHelper.MarshalArray<Vector3D>(mesh.Tangents, _vertexCount);
                }
                if(mesh.BiTangents != IntPtr.Zero) {
                    _bitangents = MemoryHelper.MarshalArray<Vector3D>(mesh.BiTangents, _vertexCount);
                }
            }

            //Load faces
            if(mesh.NumFaces > 0 && mesh.Faces != IntPtr.Zero) {
                AiFace[] faces = MemoryHelper.MarshalArray<AiFace>(mesh.Faces, (int) mesh.NumFaces);
                _faces = new Face[faces.Length];
                for(int i = 0; i < _faces.Length; i++) {
                    _faces[i] = new Face(faces[i]);
                }
            }

            //Load UVW components - this should match the texture coordinate channels
            uint[] components = mesh.NumUVComponents;
            if(components != null) {
                _texComponentNumber = new List<uint>();
                foreach(uint num in components) {
                    if(num > 0) {
                        _texComponentNumber.Add(num);
                    }
                }
            }

            //Load texture coordinate channels
            IntPtr[] texCoords = mesh.TextureCoords;
            if(texCoords != null) {
                _texCoords = new List<Vector3D[]>();
                foreach(IntPtr texPtr in texCoords) {
                    if(texPtr != IntPtr.Zero) {
                        _texCoords.Add(MemoryHelper.MarshalArray<Vector3D>(texPtr, _vertexCount));
                    }
                }
            }

            //Load vertex color channels
            IntPtr[] vertexColors = mesh.Colors;
            if(vertexColors != null) {
                _colors = new List<Color4D[]>();
                foreach(IntPtr colorPtr in vertexColors) {
                    if(colorPtr != IntPtr.Zero) {
                        _colors.Add(MemoryHelper.MarshalArray<Color4D>(colorPtr, _vertexCount));
                    }
                }
            }

            //Load bones
            if(mesh.NumBones > 0 && mesh.Bones != IntPtr.Zero) {
                AiBone[] bones = MemoryHelper.MarshalArray<AiBone>(mesh.Bones, (int) mesh.NumBones, true);
                _bones = new Bone[bones.Length];
                for(int i = 0; i < _bones.Length; i++) {
                    _bones[i] = new Bone(bones[i]);
                }
            }

            //Load anim meshes (attachment meshes)
            if(mesh.NumAnimMeshes > 0 && mesh.AnimMeshes != IntPtr.Zero) {
                AiAnimMesh[] animMeshes = MemoryHelper.MarshalArray<AiAnimMesh>(mesh.AnimMeshes, (int) mesh.NumAnimMeshes, true);
                _meshAttachments = new MeshAnimationAttachment[animMeshes.Length];
                for(int i = 0; i < _meshAttachments.Length; i++) {
                    _meshAttachments[i] = new MeshAnimationAttachment(animMeshes[i]);
                }
            }
        }
Beispiel #7
0
        private Ai.Mesh ConvertGeometry(Scene scene, Node geometryNode, Geometry geometry)
        {
            var aiMesh = new Ai.Mesh(Ai.PrimitiveType.Triangle);

            if (geometry.Flags.HasFlag(GeometryFlags.HasMaterial))
            {
                aiMesh.MaterialIndex = mAiScene.Materials.FindIndex(x => x.Name == AssimpConverterCommon.EscapeName(geometry.MaterialName));
            }

            if (geometry.Flags.HasFlag(GeometryFlags.HasTriangles))
            {
                foreach (var triangle in geometry.Triangles)
                {
                    var aiFace = new Ai.Face();
                    aiFace.Indices.Add(( int )triangle.A);
                    aiFace.Indices.Add(( int )triangle.B);
                    aiFace.Indices.Add(( int )triangle.C);
                    aiMesh.Faces.Add(aiFace);
                }
            }

            if (geometry.VertexAttributeFlags.HasFlag(VertexAttributeFlags.Position))
            {
                foreach (var vertex in geometry.Vertices)
                {
                    aiMesh.Vertices.Add(new Ai.Vector3D(vertex.X, vertex.Y, vertex.Z));
                }
            }

            if (geometry.VertexAttributeFlags.HasFlag(VertexAttributeFlags.Normal))
            {
                foreach (var normal in geometry.Normals)
                {
                    aiMesh.Normals.Add(new Ai.Vector3D(normal.X, normal.Y, normal.Z));
                }
            }

            if (geometry.VertexAttributeFlags.HasFlag(VertexAttributeFlags.Tangent))
            {
                foreach (var tangent in geometry.Tangents)
                {
                    aiMesh.Tangents.Add(new Ai.Vector3D(tangent.X, tangent.Y, tangent.Z));
                }
            }

            if (geometry.VertexAttributeFlags.HasFlag(VertexAttributeFlags.Binormal))
            {
                foreach (var binormal in geometry.Binormals)
                {
                    aiMesh.BiTangents.Add(new Ai.Vector3D(binormal.X, binormal.Y, binormal.Z));
                }
            }

            if (geometry.VertexAttributeFlags.HasFlag(VertexAttributeFlags.TexCoord0))
            {
                foreach (var vertex in geometry.TexCoordsChannel0)
                {
                    aiMesh.TextureCoordinateChannels[0].Add(new Ai.Vector3D(vertex.X, vertex.Y, 0));
                }
            }

            if (geometry.VertexAttributeFlags.HasFlag(VertexAttributeFlags.TexCoord1))
            {
                foreach (var vertex in geometry.TexCoordsChannel1)
                {
                    aiMesh.TextureCoordinateChannels[1].Add(new Ai.Vector3D(vertex.X, vertex.Y, 0));
                }
            }

            if (geometry.VertexAttributeFlags.HasFlag(VertexAttributeFlags.TexCoord2))
            {
                foreach (var vertex in geometry.TexCoordsChannel2)
                {
                    aiMesh.TextureCoordinateChannels[2].Add(new Ai.Vector3D(vertex.X, vertex.Y, 0));
                }
            }

            /* todo: colors
             * if ( geometry.VertexAttributeFlags.HasFlag( VertexAttributeFlags.Color0 ) )
             * {
             *  foreach ( var color in geometry.ColorChannel0 )
             *  {
             *      aiMesh.VertexColorChannels[0].Add( new Ai.Color4D( color. ))
             *  }
             * }
             */

            if (geometry.Flags.HasFlag(GeometryFlags.HasVertexWeights))
            {
                var boneMap = new Dictionary <int, Ai.Bone>();

                for (int i = 0; i < geometry.VertexWeights.Length; i++)
                {
                    var vertexWeight = geometry.VertexWeights[i];

                    for (int j = 0; j < 4; j++)
                    {
                        var boneWeight = vertexWeight.Weights[j];
                        if (boneWeight == 0f)
                        {
                            continue;
                        }

                        var boneIndex = vertexWeight.Indices[j];
                        var nodeIndex = scene.BonePalette.BoneToNodeIndices[boneIndex];

                        if (!boneMap.ContainsKey(nodeIndex))
                        {
                            var aiBone   = new Ai.Bone();
                            var boneNode = scene.GetNode(nodeIndex);

                            aiBone.Name = AssimpConverterCommon.EscapeName(boneNode.Name);
                            aiBone.VertexWeights.Add(new Ai.VertexWeight(i, boneWeight));

                            Matrix4x4.Invert(geometryNode.WorldTransform, out Matrix4x4 invGeometryNodeWorldTransform);
                            Matrix4x4.Invert(boneNode.WorldTransform * invGeometryNodeWorldTransform, out Matrix4x4 offsetMatrix);
                            aiBone.OffsetMatrix = new Ai.Matrix4x4(offsetMatrix.M11, offsetMatrix.M21, offsetMatrix.M31, offsetMatrix.M41,
                                                                   offsetMatrix.M12, offsetMatrix.M22, offsetMatrix.M32, offsetMatrix.M42,
                                                                   offsetMatrix.M13, offsetMatrix.M23, offsetMatrix.M33, offsetMatrix.M43,
                                                                   offsetMatrix.M14, offsetMatrix.M24, offsetMatrix.M34, offsetMatrix.M44);
                            boneMap[nodeIndex] = aiBone;
                        }
                        else
                        {
                            boneMap[nodeIndex].VertexWeights.Add(new Ai.VertexWeight(i, boneWeight));
                        }
                    }
                }

                aiMesh.Bones.AddRange(boneMap.Values);
            }

            return(aiMesh);
        }
Beispiel #8
0
        // 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));
        }
Beispiel #9
0
        /// <summary>
        /// Apply the EditMesh to a given Mesh. Call this only if you hold the monitor on
        /// the mesh or can otherwise ensure mutual exclusion.
        /// 
        /// This can be called multiple times. The EditMesh can be re-used afterwards.
        /// 
        /// Mesh name and material index are unchanged.
        /// </summary>
        /// <param name="mesh"></param>
        public void ApplyToMesh(Mesh mesh)
        {
            // Find subsets of vertices that are identical in all vertex components
            // and can be merged. To do this fast, we exploit the adjacency list in
            // the vertices. Each merge-able set must be a subset of already adjacent
            // vertices.
            Dictionary<EditVertex, int> indices = new Dictionary<EditVertex, int>();
            Dictionary<int, EditVertex> reverseIndices = new Dictionary<int, EditVertex>();
            int cursor = 0;
            foreach (EditVertex vert in Vertices)
            {
                if (indices.ContainsKey(vert))
                {
                    continue;
                }
                foreach (EditVertex adjacentVert in vert.AdjacentVertices)
                {
                    if (adjacentVert == vert || vert.CanBeMergedWith(adjacentVert))
                    {
                        indices[adjacentVert] = cursor;
                    }
                }
                reverseIndices[cursor] = vert;
                ++cursor;
            }

            // Allocate output channels only if all input vertices set a component.
            bool hasNormals = Vertices.All(vert => vert.Normal.HasValue);
            bool hasTangentSpace = Vertices.All(vert => vert.Tangent.HasValue && vert.Bitangent.HasValue);
            bool[] hasTexCoords = Enumerable.Range(0, EditVertex.MaxTexcoordChannels).
                Select(i => Vertices.All(vert => vert.TexCoord[i].HasValue)).ToArray();
            bool[] hasColors = Enumerable.Range(0, EditVertex.MaxColorChannels).
                Select(i => Vertices.All(vert => vert.Color[i].HasValue)).ToArray();

            mesh.Vertices.Clear();
            mesh.Normals.Clear();
            mesh.Tangents.Clear();
            mesh.BiTangents.Clear();

            mesh.Vertices.Capacity = indices.Count;         
            if (hasNormals)
            {
                mesh.Normals.Capacity = indices.Count;
            }
            if (hasTangentSpace)
            {
                mesh.Tangents.Capacity = indices.Count;
                mesh.BiTangents.Capacity = indices.Count;
            }
            for (var i = 0; i < EditVertex.MaxTexcoordChannels; ++i)
            {
                mesh.TextureCoordinateChannels[i].Clear();
                mesh.TextureCoordinateChannels[i].Capacity = indices.Count;
            }
            for (var i = 0; i < EditVertex.MaxColorChannels; ++i)
            {
                mesh.VertexColorChannels[i].Clear();
                mesh.VertexColorChannels[i].Capacity = indices.Count;
            }
           
            // Store unique indices.
            for (var i = 0; i < reverseIndices.Count; ++i)
            {
                var srcVert = reverseIndices[i];
                mesh.Vertices.Add(srcVert.Position);
                if (hasNormals)
                {

                    mesh.Normals.Add(srcVert.Normal.Value);
                }
                if (hasTangentSpace)
                {
                    mesh.Tangents.Add(srcVert.Tangent.Value);
                    mesh.BiTangents.Add(srcVert.Bitangent.Value);
                }
                for (var c = 0; c < EditVertex.MaxTexcoordChannels; ++c)
                {
                    if (hasTexCoords[c])
                    {
                        mesh.TextureCoordinateChannels[c].Add(srcVert.TexCoord[c].Value);
                    }
                }
                for (var c = 0; c < EditVertex.MaxColorChannels; ++c)
                {
                    if (hasColors[c])
                    {
                        mesh.VertexColorChannels[c].Add(srcVert.Color[c].Value);
                    }
                }              
            }

            mesh.Faces.Clear();
            mesh.Faces.Capacity = Faces.Count;
            foreach (var srcFace in Faces)
            {
                var face = new Face();
                foreach (var srcVert in srcFace.Vertices)
                {
                    face.Indices.Add(indices[srcVert]);
                }
                mesh.Faces.Add(face);
            }
            UpdateMeshPrimitiveTypeFlags(mesh);
        }