Пример #1
0
        public static Onyx3D.Mesh ToOnyx3D(this Assimp.Mesh mesh)
        {
            Onyx3D.Mesh newMesh = new Onyx3D.Mesh();

            newMesh.Indices = mesh.GetIndices();
            for (int vi = 0; vi < mesh.VertexCount; ++vi)
            {
                Vertex newVertex = new Vertex();
                newVertex.Position = mesh.Vertices[vi].ToOnyx3D();

                if (mesh.HasTextureCoords(0))
                {
                    Assimp.Vector3D texCoord = mesh.TextureCoordinateChannels[0][vi];
                    newVertex.TexCoord = texCoord.ToOnyx3D().Xy;
                }
                if (mesh.HasNormals)
                {
                    newVertex.Normal = mesh.Normals[vi].ToOnyx3D().Normalized();
                    if (mesh.HasTangentBasis)
                    {
                        newVertex.Bitangent = mesh.BiTangents[vi].ToOnyx3D().Normalized();
                        newVertex.Tangent   = mesh.Tangents[vi].ToOnyx3D().Normalized();
                    }
                }


                newMesh.Vertices.Add(newVertex);
            }

            newMesh.GenerateVAO();
            return(newMesh);
        }
Пример #2
0
 private void SetAssimpNormalAttribute(Assimp.Mesh mesh)
 {
     if (!Attributes.CheckAttribute(GXVertexAttribute.Normal))
     {
         Attributes.SetAttributeData(GXVertexAttribute.Normal, new List <Vector3>());
     }
 }
        private static Assimp.Mesh ConvertMeshType8(MeshType8 mesh, Node node, int nodeIndex)
        {
            var aiMesh = new Assimp.Mesh {
                MaterialIndex = mesh.MaterialIndex
            };

            aiMesh.Faces.AddRange(mesh.Triangles.Select(x => new Assimp.Face(new int[] { x.A, x.B, x.C })));

            foreach (var batch in mesh.Batches)
            {
                (var positions, var normals) = batch.Transform(node.WorldTransform);

                aiMesh.Vertices.AddRange(positions.ToAssimp());

                if (normals != null)
                {
                    aiMesh.Normals.AddRange(normals.ToAssimp());
                }

                if (batch.TexCoords != null)
                {
                    aiMesh.TextureCoordinateChannels[0].AddRange(batch.TexCoords.ToAssimp());
                }
            }

            if (mesh.TexCoords2 != null)
            {
                aiMesh.TextureCoordinateChannels[1].AddRange(mesh.TexCoords2.ToAssimp());
            }

            AssignFauxWeights(aiMesh, node, nodeIndex);

            return(aiMesh);
        }
Пример #4
0
        private void InitSkinInfo(Assimp.Mesh mesh, AssimpSceneContainer container)
        {
            var          boneIDs     = new uvec4[mesh.VertexCount];
            var          boneWeights = new vec4[mesh.VertexCount];
            AllBoneInfos allBones    = container.GetAllBoneInfos();
            Dictionary <string, uint> nameIndexDict = allBones.nameIndexDict;

            for (int i = 0; i < mesh.BoneCount; i++)
            {
                Assimp.Bone bone      = mesh.Bones[i]; // bones that influence this mesh.
                uint        boneIndex = nameIndexDict[bone.Name];

                for (int j = 0; j < bone.VertexWeightCount; j++)
                {
                    Assimp.VertexWeight vertexWeight = bone.VertexWeights[j];
                    uint vertexID = vertexWeight.VertexID;
                    for (int t = 0; t < 4; t++)
                    {
                        if (boneWeights[vertexID][t] == 0.0f) // fill in x y z w.
                        {
                            boneIDs[vertexID][t]     = boneIndex;
                            boneWeights[vertexID][t] = vertexWeight.Weight;
                            break;
                        }
                    }
                }
            }
            this.boneIDs     = boneIDs;
            this.boneWeights = boneWeights;
        }
Пример #5
0
 private void SetAssimpPositionAttribute(Assimp.Mesh mesh)
 {
     if (!Attributes.CheckAttribute(GXVertexAttribute.Position))
     {
         Attributes.SetAttributeData(GXVertexAttribute.Position, new List <Vector3>());
     }
 }
Пример #6
0
        private void SetAssimpNormalAttribute(Assimp.Mesh mesh)
        {
            List <Vector3> tempList = new List <Vector3>();

            for (int vec = 0; vec < mesh.Normals.Count; vec++)
            {
                tempList.Add(mesh.Normals[vec].ToOpenTKVector3());
            }

            if (!Attributes.CheckAttribute(GXVertexAttribute.Normal))
            {
                Attributes.SetAttributeData(GXVertexAttribute.Normal, tempList);
            }
            else
            {
                List <Vector3> attribData = (List <Vector3>)Attributes.GetAttributeData(GXVertexAttribute.Normal);

                foreach (Vector3 vec in tempList)
                {
                    if (!attribData.Contains(vec))
                    {
                        attribData.Add(vec);
                    }
                }

                Attributes.SetAttributeData(GXVertexAttribute.Normal, attribData);
            }
        }
Пример #7
0
        private static PartialModel AppendPartialMesh(Assimp.Mesh mesh)
        {
            var primitiveType = OpenTK.Graphics.OpenGL.PrimitiveType.Triangles;

            if (mesh.Faces[0].IndexCount == 4)
            {
                primitiveType = OpenTK.Graphics.OpenGL.PrimitiveType.Quads;
            }

            int curIdx  = GeneralMeshBuffer.IndexCount;
            int curVert = GeneralMeshBuffer.VertexCount;

            GeneralMeshBuffer.LoadModelVertices(mesh, true);
            int idxCount        = GeneralMeshBuffer.IndexCount - curIdx;
            var vertices        = GeneralMeshBuffer.GetVertices().Skip(curVert);
            var vertexPositions = vertices.Select(x => x.Position).ToList();

            var bounding = BBox.FromVertices(vertexPositions);

            var model = new PartialModel(GeneralMeshBuffer, curIdx, curVert, idxCount, primitiveType);

            model.BoundingBox = bounding;
            model.Vertices    = vertexPositions;
            LoadedModels.Add(model);
            //model.LoadVertices();
            //model.CalculateBoundingBox();
            return(model);
        }
Пример #8
0
        public _MeshPrimitiveDecoder(Assimp.Mesh mesh, TMaterial material)
        {
            _Source   = mesh;
            _Material = material;

            _ColorCount = 0;
            if (mesh.HasVertexColors(0))
            {
                _ColorCount = 1;
            }
            if (mesh.HasVertexColors(1))
            {
                _ColorCount = 2;
            }

            _TexCoordCount = 0;
            if (mesh.HasTextureCoords(0))
            {
                _TexCoordCount = 1;
            }
            if (mesh.HasTextureCoords(1))
            {
                _TexCoordCount = 2;
            }

            if (mesh.HasBones)
            {
                var influences = new List <(int bone, float weight)> [_Source.VertexCount];
Пример #9
0
        public void InitAssImp(Assimp.Scene aiRoot, Scene.Entity3D root)
        {
            if (aiRoot.HasAnimations == false)
            {
                return;
            }

            _skeleton = CreateBoneTree(aiRoot.RootNode, null);
            Console.WriteLine("Proc bones:" + _skeleton.Name + " C:" + _skeleton.Children.Count);
            foreach (Assimp.Mesh mesh in aiRoot.Meshes)
            {
                foreach (Assimp.Bone bone in mesh.Bones)
                {
                    if (!_bonesByName.TryGetValue(bone.Name, out Bone found))
                    {
                        continue;
                    }

                    bool skip = (from t in _bones let bname = bone.Name where t.Name == bname select t).Any();
                    if (skip)
                    {
                        continue;
                    }

                    found.Offset = ToTK(bone.OffsetMatrix);
                    _bones.Add(found);
                    _bonesToIndex[found.Name] = _bones.IndexOf(found);
                }
                Assimp.Mesh mesh1 = mesh;
                foreach (string bone in _bonesByName.Keys.Where(b => mesh1.Bones.All(b1 => b1.Name != b) && b.StartsWith("Bone")))
                {
                    _bonesByName[bone].Offset = _bonesByName[bone].Parent.Offset;
                    _bones.Add(_bonesByName[bone]);
                    _bonesToIndex[bone] = _bones.IndexOf(_bonesByName[bone]);
                }
            }
            ExtractAnimations(aiRoot);

            const float timestep = 1.0f / 30.0f;

            for (int i = 0; i < Animations.Count; i++)
            {
                SetAnimationIndex(i);
                float dt = 0.0f;
                for (float ticks = 0.0f; ticks < Animations[i].Duration; ticks += Animations[i].TicksPerSecond / 30.0f)
                {
                    dt += timestep;
                    Calculate(dt);
                    List <OpenTK.Matrix4> trans = new List <OpenTK.Matrix4>();
                    for (int a = 0; a < _bones.Count; a++)
                    {
                        OpenTK.Matrix4 rotMat = _bones[a].Offset * _bones[a].GlobalTransform;
                        trans.Add(rotMat);
                    }
                    Animations[i].Transforms.Add(trans);
                }
            }
            Console.WriteLine("Finished loading animations with " + _bones.Count + " bones");
        }
Пример #10
0
        public Drawable(Vector3 position, Assimp.Mesh assMesh) : base(position)
        {
            Position = position;
            Mesh     = new Mesh(position, Vector3.Zero, assMesh);

            Drawables.Add(this);
            Renderer.InvalidateAll();
        }
Пример #11
0
        public Gizmo(Vector3 position, Assimp.Mesh assMesh) : base(position, assMesh)
        {
            Mesh = new Mesh(position, Vector3.Zero, assMesh)
            {
                DrawInFront = true
            };

            AllowRotation = true;
        }
Пример #12
0
        private bool addToVBO(Assimp.Mesh mesh, ref List <float> vboData)
        {
            if (getFlags(mesh) != m_currentFlags)
            {
                textBoxInfo.Text += Environment.NewLine + "Skipping mesh with invalid vertex data...";
                return(false);
            }
            for (var i = 0; i < mesh.VertexCount; ++i)
            {
                var pos = mesh.Vertices[i];
                vboData.Add(pos.X);
                vboData.Add(pos.Y);
                vboData.Add(pos.Z);

                if (mesh.HasVertexColors(0))
                {
                    var colour = mesh.VertexColorChannels[0][i];
                    vboData.Add(colour.R);
                    vboData.Add(colour.G);
                    vboData.Add(colour.B);
                }

                var normal = mesh.Normals[i];
                vboData.Add(normal.X);
                vboData.Add(normal.Y);
                vboData.Add(normal.Z);

                if (mesh.HasTangentBasis)
                {
                    var tan   = mesh.Tangents[i];
                    var bitan = mesh.BiTangents[i];
                    vboData.Add(tan.X);
                    vboData.Add(tan.Y);
                    vboData.Add(tan.Z);

                    vboData.Add(bitan.X);
                    vboData.Add(bitan.Y);
                    vboData.Add(bitan.Z);
                }

                if (mesh.HasTextureCoords(0))
                {
                    var uv = mesh.TextureCoordinateChannels[0][i];
                    vboData.Add(uv.X);
                    vboData.Add(uv.Y);
                }

                if (mesh.HasTextureCoords(1))
                {
                    var uv = mesh.TextureCoordinateChannels[1][i];
                    vboData.Add(uv.X);
                    vboData.Add(uv.Y);
                }
            }
            return(true);
        }
Пример #13
0
        private static Geometry ConvertGeometry(Assimp.Mesh mesh, float scale, VertexLayout vertexLayout, VertexComponent[] vertexComponents, bool combineVB, bool combineIB, out BoundingBox meshBoundingBox)
        {
            VkPrimitiveTopology[] primitiveTopology =
            {
                VkPrimitiveTopology.PointList,
                VkPrimitiveTopology.PointList,
                VkPrimitiveTopology.LineList,
                VkPrimitiveTopology.LineList,
                VkPrimitiveTopology.TriangleList,
            };

            if (!combineVB)
            {
                vertexBuffer.Clear();
            }

            if (!combineIB)
            {
                indexBuffer.Clear();
            }

            ConvertGeom(scale, (uint)vertexOffset, mesh, out meshBoundingBox, vertexComponents);

            var geometry = new Geometry
            {
                Name         = mesh.Name,
                VertexLayout = vertexLayout
            };

            if (!combineVB)
            {
                geometry.VertexBuffer = Buffer.Create(VkBufferUsageFlags.VertexBuffer, false, sizeof(float), vertexBuffer.Count, vertexBuffer.Data);
            }

            if (!combineIB)
            {
                geometry.IndexBuffer = Buffer.Create(VkBufferUsageFlags.IndexBuffer, false, sizeof(uint), indexBuffer.Count, indexBuffer.Data);
            }

            geometry.SetDrawRange(primitiveTopology[(int)mesh.PrimitiveType], indexOffset, (uint)mesh.FaceCount * 3, 0 /*vertexOffset*/);

            if (combineVB)
            {
                vertexOffset += mesh.VertexCount;
            }

            if (combineIB)
            {
                indexOffset += (uint)mesh.FaceCount * 3;
            }

            return(geometry);
        }
        private static void AssignFauxWeights(Assimp.Mesh aiMesh, Node node, int nodeIndex)
        {
            var aiBone = new Assimp.Bone {
                Name = FormatNodeName(node, nodeIndex), OffsetMatrix = node.WorldTransform.Inverted().ToAssimp()
            };

            for (int i = 0; i < aiMesh.VertexCount; i++)
            {
                aiBone.VertexWeights.Add(new Assimp.VertexWeight(i, 1f));
            }

            aiMesh.Bones.Add(aiBone);
        }
Пример #15
0
        public Mesh(Assimp.Mesh mesh)
        {
            Assign();

            bbox = new BoundingBox(Vector3.PositiveInfinity, Vector3.NegativeInfinity);

            GL.BindVertexArray(Vao);
            GL.EnableVertexAttribArray(0);
            GL.EnableVertexAttribArray(1);

            int[] indices = mesh.GetIndices();
            GL.BindBuffer(BufferTarget.ElementArrayBuffer, Ebo);
            GL.BufferData(BufferTarget.ElementArrayBuffer, sizeof(int) * indices.Length, indices, BufferUsageHint.StaticDraw);
            iCount = indices.Length;

            // positions + normals
            float[] vertexData = new float[mesh.VertexCount * 6];
            for (int i = 0; i < mesh.VertexCount; ++i)
            {
                vertexData[i * 6 + 0] = mesh.Vertices[i].X;
                vertexData[i * 6 + 1] = mesh.Vertices[i].Y;
                vertexData[i * 6 + 2] = mesh.Vertices[i].Z;

                bbox.MinPoint.X = Math.Min(bbox.MinPoint.X, mesh.Vertices[i].X);
                bbox.MinPoint.Y = Math.Min(bbox.MinPoint.Y, mesh.Vertices[i].Y);
                bbox.MinPoint.Z = Math.Min(bbox.MinPoint.Z, mesh.Vertices[i].Z);
                bbox.MaxPoint.X = Math.Max(bbox.MaxPoint.X, mesh.Vertices[i].X);
                bbox.MaxPoint.Y = Math.Max(bbox.MaxPoint.Y, mesh.Vertices[i].Y);
                bbox.MaxPoint.Z = Math.Max(bbox.MaxPoint.Z, mesh.Vertices[i].Z);

                try
                {
                    vertexData[i * 6 + 3] = mesh.Normals[i].X;
                    vertexData[i * 6 + 4] = mesh.Normals[i].Y;
                    vertexData[i * 6 + 5] = mesh.Normals[i].Z;
                }
                catch (System.ArgumentOutOfRangeException)
                {
                    System.Console.Error.WriteLine("Failed indexing mesh normals");
                    throw;
                }
            }

            GL.BindBuffer(BufferTarget.ArrayBuffer, Vbo);
            GL.BufferData(BufferTarget.ArrayBuffer, sizeof(float) * vertexData.Length, vertexData, BufferUsageHint.StaticDraw);

            GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 24, new IntPtr(0));
            GL.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 24, new IntPtr(12));

            vCount = mesh.VertexCount;
        }
Пример #16
0
        private void addToIndexArray(Assimp.Mesh mesh, ref List <int>[] idxArray, int offset)
        {
            int idx = mesh.MaterialIndex;

            if (idxArray[idx] == null)
            {
                idxArray[idx] = new List <int>();
            }

            for (var i = 0; i < mesh.FaceCount; ++i)
            {
                idxArray[idx].Add(mesh.Faces[i].Indices[0] + offset);
                idxArray[idx].Add(mesh.Faces[i].Indices[1] + offset);
                idxArray[idx].Add(mesh.Faces[i].Indices[2] + offset);
            }
        }
Пример #17
0
        public static Vector2[] GetTexCoords(this Assimp.Mesh mesh)
        {
            var uvs = new Vector2[mesh.VertexCount];

            for (int i = 0; i < mesh.VertexCount; i++)
            {
                if (i >= mesh.TextureCoordinateChannels[0].Count)
                {
                    uvs[i] = Vector2.Zero;
                }
                else
                {
                    uvs[i] = new Vector2(mesh.TextureCoordinateChannels[0][i].X, mesh.TextureCoordinateChannels[0][i].Y);
                }
            }

            return(uvs);
        }
Пример #18
0
        public void LoadModelVertices(Assimp.Mesh mesh, bool append = false)
        {
            var  verts      = new List <VertVNT>();
            bool isTextured = mesh.HasTextureCoords(0);

            for (int i = 0; i < mesh.VertexCount; i++)
            {
                verts.Add(new VertVNT()
                {
                    Position = mesh.Vertices[i].ToGL(),
                    Normal   = mesh.Normals[i].ToGL(),
                    TexCoord = isTextured ? mesh.TextureCoordinateChannels[0][i].ToGL().Xy : Vector2.Zero
                });
            }

            if (append)
            {
                AppendVertices(verts.Select(x => x.Cast <T>()));
            }
            else
            {
                SetVertices(verts.Select(x => x.Cast <T>()));
            }

            var indices      = new List <int>();
            int indexPerFace = mesh.Faces[0].IndexCount;

            foreach (var face in mesh.Faces)
            {
                if (face.IndexCount == indexPerFace)
                {
                    indices.AddRange(face.Indices);
                }
            }

            if (append)
            {
                AppendIndices(indices);
            }
            else
            {
                SetIndices(indices);
            }
        }
Пример #19
0
        bool use_float_for_texcoords(Assimp.Mesh mesh, int texchannel)
        {
            // SuperBMD normally converts UV coords into signed 16 bit integers
            // with a fractional part of 8 bits so these are the minimum and maximum values that can be represented.
            float min = -(float)(1 << 15) / (float)(1 << 8);
            float max = (float)((1 << 15) - 1) / (float)(1 << 8);

            foreach (Assimp.Vector3D texcoord in mesh.TextureCoordinateChannels[texchannel])
            {
                if (texcoord.X < min || texcoord.X > max || texcoord.Y < min || texcoord.Y > max)
                {
                    // Texture coordinates exceed the maximum limit so we need
                    // to use floats
                    return(true);
                }
            }

            return(false);
        }
        private static Assimp.Mesh ConvertMeshType4(MeshType4 mesh, Node node, int nodeIndex)
        {
            var aiMesh = new Assimp.Mesh {
                MaterialIndex = mesh.MaterialIndex
            };

            aiMesh.Faces.AddRange(mesh.Triangles.Select(x => new Assimp.Face(new int[] { x.A, x.B, x.C })));

            (var positions, var normals) = mesh.Transform(node.WorldTransform);

            aiMesh.Vertices.AddRange(positions.ToAssimp());

            if (normals != null)
            {
                aiMesh.Normals.AddRange(normals.ToAssimp());
            }

            AssignFauxWeights(aiMesh, node, nodeIndex);

            return(aiMesh);
        }
Пример #21
0
        private void GetBound(Assimp.Mesh mesh, ref vec3 max, ref vec3 min, ref bool first)
        {
            foreach (var item in mesh.Vertices)
            {
                if (first)
                {
                    max   = new vec3(item.X, item.Y, item.Z);
                    min   = max;
                    first = false;
                }
                else
                {
                    if (max.x < item.X)
                    {
                        max.x = item.X;
                    }
                    if (max.y < item.Y)
                    {
                        max.y = item.Y;
                    }
                    if (max.z < item.Z)
                    {
                        max.z = item.Z;
                    }

                    if (item.X < min.x)
                    {
                        min.x = item.X;
                    }
                    if (item.Y < min.y)
                    {
                        min.y = item.Y;
                    }
                    if (item.Z < min.z)
                    {
                        min.z = item.Z;
                    }
                }
            }
        }
        private static IEnumerable <Assimp.Mesh> ConvertMeshType2(MeshType2 mesh, List <Node> nodes)
        {
            foreach (var batch in mesh.Batches)
            {
                var aiMesh = new Assimp.Mesh {
                    MaterialIndex = mesh.MaterialIndex
                };

                aiMesh.Faces.AddRange(batch.Triangles.Select(x => new Assimp.Face(new int[] { x.A, x.B, x.C })));

                (var positions, var normals, var weights) = batch.Transform(nodes);

                aiMesh.Vertices.AddRange(positions.ToAssimp());

                if (normals != null)
                {
                    aiMesh.Normals.AddRange(normals.ToAssimp());
                }

                ConvertWeights(nodes, new Dictionary <int, Assimp.Bone>(), weights, aiMesh, 0);

                if (batch.Colors != null)
                {
                    aiMesh.VertexColorChannels[0].AddRange(batch.Colors.ToAssimp());
                }

                if (batch.TexCoords != null)
                {
                    aiMesh.TextureCoordinateChannels[0].AddRange(batch.TexCoords.ToAssimp());
                }

                if (batch.TexCoords2 != null)
                {
                    aiMesh.TextureCoordinateChannels[1].AddRange(batch.TexCoords2.ToAssimp());
                }

                yield return(aiMesh);
            }
        }
        private AllBoneInfos InitBonesInfo(Assimp.Scene aiScene)
        {
            List <BoneInfo> boneInfos     = new List <BoneInfo>();
            var             nameIndexDict = new Dictionary <string, uint>();

            for (int i = 0; i < aiScene.MeshCount; i++)
            {
                Assimp.Mesh mesh = aiScene.Meshes[i];
                for (int j = 0; j < mesh.BoneCount; j++)
                {
                    Assimp.Bone bone     = mesh.Bones[j];
                    string      boneName = bone.Name;
                    if (!nameIndexDict.ContainsKey(boneName))
                    {
                        var boneInfo = new BoneInfo(bone);
                        boneInfos.Add(boneInfo);
                        nameIndexDict.Add(boneName, (uint)(boneInfos.Count - 1));
                    }
                }
            }

            return(new AllBoneInfos(boneInfos.ToArray(), nameIndexDict));
        }
Пример #24
0
        /// <summary>
        /// Transform the vertex positions and normals in the mesh by the transform of the root node.
        /// </summary>
        /// <param name="assimpMesh"></param>
        /// <param name="rootNode"></param>
        private static void TransformMeshVertices(Assimp.Mesh assimpMesh, Assimp.Node rootNode)
        {
            var worldTransform    = ComputeWorldTransform(rootNode);
            var worldTransformInv = worldTransform;

            worldTransformInv.Transpose();
            worldTransformInv.Inverse();

            for (int j = 0; j < assimpMesh.Vertices.Count; j++)
            {
                var vector = assimpMesh.Vertices[j];
                Assimp.Unmanaged.AssimpLibrary.Instance.TransformVecByMatrix4(ref vector, ref worldTransform);
                assimpMesh.Vertices[j] = vector;
            }

            for (int j = 0; j < assimpMesh.Normals.Count; j++)
            {
                var vector = assimpMesh.Normals[j];
                Assimp.Unmanaged.AssimpLibrary.Instance
                .TransformVecByMatrix4(ref vector, ref worldTransformInv);
                assimpMesh.Normals[j] = vector;
            }
        }
        private static Assimp.Mesh ConvertMeshType7(MeshType7 mesh, List <Node> nodes)
        {
            var aiBoneLookup = new Dictionary <int, Assimp.Bone>();

            var aiMesh = new Assimp.Mesh {
                MaterialIndex = mesh.MaterialIndex
            };

            aiMesh.Faces.AddRange(mesh.Triangles.Select(x => new Assimp.Face(new int[] { x.A, x.B, x.C })));

            foreach (var batch in mesh.Batches)
            {
                (var positions, var normals, var weights) = batch.Transform(nodes);

                ConvertWeights(nodes, aiBoneLookup, weights, aiMesh, aiMesh.VertexCount);

                aiMesh.Vertices.AddRange(positions.ToAssimp());

                if (normals != null)
                {
                    aiMesh.Normals.AddRange(normals.ToAssimp());
                }

                if (batch.TexCoords != null)
                {
                    aiMesh.TextureCoordinateChannels[0].AddRange(batch.TexCoords.ToAssimp());
                }
            }

            if (mesh.TexCoords2 != null)
            {
                aiMesh.TextureCoordinateChannels[1].AddRange(mesh.TexCoords2.ToAssimp());
            }

            return(aiMesh);
        }
Пример #26
0
        public bool ExportToFile(String fileName)
        {
            string name = Utility.CleanName(Name).TrimEnd(new char[] { '_' });

            Assimp.Node            rootNode  = new Assimp.Node(name);
            List <Assimp.Material> materials = new List <Assimp.Material>();
            List <Assimp.Mesh>     meshes    = new List <Assimp.Mesh>();

            for (int modelIndex = 0; modelIndex < ModelCount; modelIndex++)
            {
                SRModel model     = Models[modelIndex];
                string  modelName = name + "-" + modelIndex;

                Assimp.Node modelNode = new Assimp.Node(modelName);

                for (int groupIndex = 0; groupIndex < model.GroupCount; groupIndex++)
                {
                    Tree group = model.Groups[groupIndex];
                    if (group == null)
                    {
                        continue;
                    }

                    string groupName = name + "-" + modelIndex + "-" + groupIndex;

                    Assimp.Node groupNode = new Assimp.Node(groupName);

                    for (int materialIndex = 0; materialIndex < model.MaterialCount; materialIndex++)
                    {
                        int        totalPolygonCount = (int)group.mesh.polygonCount;
                        List <int> polygonList       = new List <int>();

                        for (int p = 0; p < totalPolygonCount; p++)
                        {
                            if (group.mesh.polygons[p].material.ID == materialIndex)
                            {
                                polygonList.Add(p);
                            }
                        }

                        int polygonCount = polygonList.Count;
                        if (polygonCount > 0)
                        {
                            #region Mesh
                            string      meshName = name + "-" + modelIndex + "-" + groupIndex + "-" + materialIndex;
                            Assimp.Mesh mesh     = new Assimp.Mesh(meshName);
                            mesh.PrimitiveType = Assimp.PrimitiveType.Triangle;

                            ref      Polygon[] polygons = ref group.mesh.polygons;
                            Vector[] positions = model.Positions;
                            Vector[] normals   = model.Normals;
                            UInt32[] colors    = model.Colours;
                            UV[]     uvs       = model.UVs;
                            int      i         = 0;
                            for (int p = 0; p < polygonCount; p++)
                            {
                                ref Polygon polygon = ref polygons[polygonList[p]];

                                ref Vertex vert1 = ref polygon.v1;
                                ref Vertex vert2 = ref polygon.v2;
                                ref Vertex vert3 = ref polygon.v3;

                                ref Vector pos1 = ref positions[vert1.positionID];
Пример #27
0
 public AnimationModel(Assimp.Mesh mesh, AssimpSceneContainer container)
 {
     this.mesh      = mesh;
     this.container = container;
     InitSkinInfo(mesh, container);
 }
        private static void ConvertWeights(List <Node> nodes, Dictionary <int, Assimp.Bone> aiBoneLookup, NodeWeight[][] weights, Assimp.Mesh aiMesh, int vertexBaseIndex)
        {
            for (int i = 0; i < weights.Length; i++)
            {
                foreach (var nodeWeight in weights[i])
                {
                    if (nodeWeight.Weight == 0f)
                    {
                        continue;
                    }

                    if (!aiBoneLookup.TryGetValue(nodeWeight.NodeIndex, out var aiBone))
                    {
                        var node = nodes[nodeWeight.NodeIndex];
                        aiMesh.Bones.Add(aiBoneLookup[nodeWeight.NodeIndex] = aiBone = new Assimp.Bone
                        {
                            Name         = FormatNodeName(node, nodeWeight.NodeIndex),
                            OffsetMatrix = node.WorldTransform.Inverted().ToAssimp()
                        });
                    }

                    aiBone.VertexWeights.Add(new Assimp.VertexWeight(vertexBaseIndex + i, nodeWeight.Weight));
                }
            }
        }
Пример #29
0
        public static Assimp.Scene CreateAssimpScene(this IGeometryModel model, Assimp.AssimpContext context, string formatId)
        {
            var scale = ModelViewerPlugin.Settings.GeometryScale;

            //either Assimp or collada has issues when there is a name conflict
            const string bonePrefix = "~";
            const string geomPrefix = "-";
            const string scenPrefix = "$";

            var scene = new Assimp.Scene();

            scene.RootNode = new Assimp.Node($"{scenPrefix}{model.Name}");

            //Assimp is Y-up in inches by default - this forces it to export as Z-up in meters
            scene.RootNode.Transform = (CoordinateSystem.HaloCEX * ModelViewerPlugin.Settings.AssimpScale).ToAssimp4x4();

            #region Nodes
            var allNodes = new List <Assimp.Node>();
            foreach (var node in model.Nodes)
            {
                var result = new Assimp.Node($"{bonePrefix}{node.Name}");

                var q   = new System.Numerics.Quaternion(node.Rotation.X, node.Rotation.Y, node.Rotation.Z, node.Rotation.W);
                var mat = System.Numerics.Matrix4x4.CreateFromQuaternion(q);
                mat.Translation  = new System.Numerics.Vector3(node.Position.X * scale, node.Position.Y * scale, node.Position.Z * scale);
                result.Transform = mat.ToAssimp4x4();

                allNodes.Add(result);
            }

            for (int i = 0; i < model.Nodes.Count; i++)
            {
                var node = model.Nodes[i];
                if (node.ParentIndex >= 0)
                {
                    allNodes[node.ParentIndex].Children.Add(allNodes[i]);
                }
                else
                {
                    scene.RootNode.Children.Add(allNodes[i]);
                }
            }
            #endregion

            var meshLookup = new List <int>();

            #region Meshes
            for (int i = 0; i < model.Meshes.Count; i++)
            {
                var geom = model.Meshes[i];
                if (geom.Submeshes.Count == 0)
                {
                    meshLookup.Add(-1);
                    continue;
                }

                meshLookup.Add(scene.MeshCount);

                foreach (var sub in geom.Submeshes)
                {
                    var m = new Assimp.Mesh($"mesh{i:D3}");

                    var indices = geom.Indicies.Skip(sub.IndexStart).Take(sub.IndexLength);

                    var minIndex  = indices.Min();
                    var maxIndex  = indices.Max();
                    var vertCount = maxIndex - minIndex + 1;

                    if (geom.IndexFormat == IndexFormat.TriangleStrip)
                    {
                        indices = indices.Unstrip();
                    }

                    indices = indices.Select(x => x - minIndex);
                    var vertices = geom.Vertices.Skip(minIndex).Take(vertCount);

                    if (geom.BoundsIndex >= 0)
                    {
                        vertices = vertices.Select(v => (IVertex) new CompressedVertex(v, model.Bounds[geom.BoundsIndex.Value]));
                    }

                    int vIndex     = -1;
                    var boneLookup = new Dictionary <int, Assimp.Bone>();
                    foreach (var v in vertices)
                    {
                        vIndex++;

                        if (v.Position.Count > 0)
                        {
                            m.Vertices.Add(v.Position[0].ToAssimp3D(scale));

                            //some Halo shaders use position W as the colour alpha - add it to a colour channel to preserve it
                            //also assimp appears to have issues exporting obj when a colour channel exists so only do this for collada
                            if (formatId == "collada" && v.Color.Count == 0 && !float.IsNaN(v.Position[0].W))
                            {
                                m.VertexColorChannels[0].Add(new Assimp.Color4D {
                                    R = v.Position[0].W
                                });
                            }
                        }

                        if (v.Normal.Count > 0)
                        {
                            m.Normals.Add(v.Normal[0].ToAssimp3D());
                        }

                        if (v.TexCoords.Count > 0)
                        {
                            m.TextureCoordinateChannels[0].Add(v.TexCoords[0].ToAssimpUV());
                        }

                        if (geom.VertexWeights == VertexWeights.None && !geom.NodeIndex.HasValue)
                        {
                            continue;
                        }

                        #region Vertex Weights
                        var weights = new List <Tuple <int, float> >(4);

                        if (geom.NodeIndex.HasValue)
                        {
                            weights.Add(Tuple.Create <int, float>(geom.NodeIndex.Value, 1));
                        }
                        else if (geom.VertexWeights == VertexWeights.Skinned)
                        {
                            var ind = v.BlendIndices[0];
                            var wt  = v.BlendWeight[0];

                            if (wt.X > 0)
                            {
                                weights.Add(Tuple.Create((int)ind.X, wt.X));
                            }
                            if (wt.Y > 0)
                            {
                                weights.Add(Tuple.Create((int)ind.Y, wt.Y));
                            }
                            if (wt.Z > 0)
                            {
                                weights.Add(Tuple.Create((int)ind.Z, wt.Z));
                            }
                            if (wt.W > 0)
                            {
                                weights.Add(Tuple.Create((int)ind.W, wt.W));
                            }
                        }

                        foreach (var val in weights)
                        {
                            Assimp.Bone b;
                            if (boneLookup.ContainsKey(val.Item1))
                            {
                                b = boneLookup[val.Item1];
                            }
                            else
                            {
                                var t = model.Nodes[val.Item1].OffsetTransform;
                                t.M41 *= scale;
                                t.M42 *= scale;
                                t.M43 *= scale;

                                b = new Assimp.Bone
                                {
                                    Name         = bonePrefix + model.Nodes[val.Item1].Name,
                                    OffsetMatrix = t.ToAssimp4x4()
                                };

                                m.Bones.Add(b);
                                boneLookup.Add(val.Item1, b);
                            }

                            b.VertexWeights.Add(new Assimp.VertexWeight(vIndex, val.Item2));
                        }
                        #endregion
                    }

                    m.SetIndices(indices.ToArray(), 3);
                    m.MaterialIndex = sub.MaterialIndex;

                    scene.Meshes.Add(m);
                }
            }
            #endregion

            #region Regions
            foreach (var reg in model.Regions)
            {
                var regNode = new Assimp.Node($"{geomPrefix}{reg.Name}");
                foreach (var perm in reg.Permutations)
                {
                    var meshStart = meshLookup[perm.MeshIndex];
                    if (meshStart < 0)
                    {
                        continue;
                    }

                    var permNode = new Assimp.Node($"{geomPrefix}{perm.Name}");
                    if (perm.TransformScale != 1 || !perm.Transform.IsIdentity)
                    {
                        permNode.Transform = Assimp.Matrix4x4.FromScaling(new Assimp.Vector3D(perm.TransformScale)) * perm.Transform.ToAssimp4x4(scale);
                    }

                    var meshCount = Enumerable.Range(perm.MeshIndex, perm.MeshCount).Sum(i => model.Meshes[i].Submeshes.Count);
                    permNode.MeshIndices.AddRange(Enumerable.Range(meshStart, meshCount));

                    regNode.Children.Add(permNode);
                }

                if (regNode.ChildCount > 0)
                {
                    scene.RootNode.Children.Add(regNode);
                }
            }
            #endregion

            #region Materials
            foreach (var mat in model.Materials)
            {
                var m = new Assimp.Material {
                    Name = mat?.Name ?? "unused"
                };

                //prevent max from making every material super shiny
                m.ColorEmissive = m.ColorReflective = m.ColorSpecular = new Assimp.Color4D(0, 0, 0, 1);
                m.ColorDiffuse  = m.ColorTransparent = new Assimp.Color4D(1);

                //max only seems to care about diffuse
                var dif = mat?.Submaterials.FirstOrDefault(s => s.Usage == MaterialUsage.Diffuse);
                if (dif != null)
                {
                    var suffix   = dif.Bitmap.SubmapCount > 1 ? "[0]" : string.Empty;
                    var filePath = $"{dif.Bitmap.Name}{suffix}.{ModelViewerPlugin.Settings.MaterialExtension}";

                    //collada spec says it requires URI formatting, and Assimp doesn't do it for us
                    //for some reason "new Uri(filePath, UriKind.Relative)" doesnt change the slashes, have to use absolute uri
                    if (formatId == FormatId.Collada)
                    {
                        filePath = new Uri("X:\\", UriKind.Absolute).MakeRelativeUri(new Uri(System.IO.Path.Combine("X:\\", filePath))).ToString();
                    }

                    m.TextureDiffuse = new Assimp.TextureSlot
                    {
                        BlendFactor = 1,
                        FilePath    = filePath,
                        TextureType = Assimp.TextureType.Diffuse
                    };
                }

                scene.Materials.Add(m);
            }
            #endregion

            return(scene);
        }
Пример #30
0
        public Assimp.Mesh ToAssimp(Hatzap.Models.Mesh mesh)
        {
            var verts = mesh.Vertices;
            var norms = mesh.Normals;
            var tangents = mesh.Tangents;
            var binormals = mesh.Binormals;
            var uv = mesh.UV;
            var colors = mesh.Colors;

            var amesh = new Assimp.Mesh(Assimp.PrimitiveType.Triangle);

            for (int i = 0; i < verts.Length; i++)
            {
                if (verts != null) amesh.Vertices.Add(new Assimp.Vector3D(verts[i].X, verts[i].Y, verts[i].Z));
                if (norms != null) amesh.Normals.Add(new Assimp.Vector3D(norms[i].X, norms[i].Y, norms[i].Z));
                if (tangents != null) amesh.Tangents.Add(new Assimp.Vector3D(tangents[i].X, tangents[i].Y, tangents[i].Z));
                if (binormals != null) amesh.BiTangents.Add(new Assimp.Vector3D(binormals[i].X, binormals[i].Y, binormals[i].Z));
                if (uv != null)
                {
                    for (int j = 0; j < uv.Length; j++)
                    {
                        amesh.TextureCoordinateChannels[j].Add(new Assimp.Vector3D(uv[j][i].X, uv[j][i].Y, uv[j][i].Z));
                    }

                }
                if (colors != null)
                {
                    for (int j = 0; j < uv.Length; j++)
                    {
                        amesh.VertexColorChannels[j].Add(new Assimp.Color4D(colors[j][i].X, colors[j][i].Y, colors[j][i].Z, colors[j][i].W));
                    }
                }
            }

            return amesh;
        }
Пример #31
0
 public DrawableRotated(Vector3 position, Vector3 rotation, Assimp.Mesh assMesh) : base(position, rotation)
 {
 }
Пример #32
0
        public static Assimp.Scene ToAssimpScene(RWScene scene)
        {
            Assimp.Scene aiScene = new Assimp.Scene();

            int drawCallIdx = 0;
            int materialIdx = 0;
            int totalSplitIdx = 0;
            List<int> meshStartIndices = new List<int>();
            foreach (RWDrawCall drawCall in scene.DrawCalls)
            {
                meshStartIndices.Add(totalSplitIdx);
                var mesh = scene.Meshes[drawCall.MeshIndex];
                var node = scene.Nodes[drawCall.NodeIndex];

                int splitIdx = 0;
                foreach (RWMeshMaterialSplit split in mesh.MaterialSplitData.MaterialSplits)
                {
                    Assimp.Mesh aiMesh = new Assimp.Mesh(Assimp.PrimitiveType.Triangle);
                    aiMesh.Name = string.Format("DrawCall{0}_Split{1}", drawCallIdx.ToString("00"), splitIdx.ToString("00"));
                    aiMesh.MaterialIndex = split.MaterialIndex + materialIdx;

                    // get split indices
                    int[] indices = split.Indices;
                    if (mesh.MaterialSplitData.PrimitiveType == RWPrimitiveType.TriangleStrip)
                        indices = MeshUtilities.ToTriangleList(indices, true);

                    // pos & nrm
                    for (int i = 0; i < indices.Length; i++)
                    {
                        if (mesh.HasVertices)
                        {
                            var vert = Vector3.Transform(mesh.Vertices[indices[i]], node.WorldTransform);
                            aiMesh.Vertices.Add(vert.ToAssimpVector3D());
                        }
                        if (mesh.HasNormals)
                        {
                            var nrm = Vector3.TransformNormal(mesh.Normals[indices[i]], node.WorldTransform);
                            aiMesh.Normals.Add(nrm.ToAssimpVector3D());
                        }
                    }

                    // tex coords
                    if (mesh.HasTexCoords)
                    {
                        for (int i = 0; i < mesh.TextureCoordinateChannelCount; i++)
                        {
                            List<Assimp.Vector3D> texCoordChannel = new List<Assimp.Vector3D>();

                            for (int j = 0; j < indices.Length; j++)
                            {
                                texCoordChannel.Add(mesh.TextureCoordinateChannels[i][indices[j]].ToAssimpVector3D(0));
                            }

                            aiMesh.TextureCoordinateChannels[i] = texCoordChannel;
                        }
                    }

                    // colors
                    if (mesh.HasColors)
                    {
                        List<Assimp.Color4D> vertColorChannel = new List<Assimp.Color4D>();

                        for (int i = 0; i < indices.Length; i++)
                        {
                            var color = mesh.Colors[indices[i]];
                            vertColorChannel.Add(new Assimp.Color4D(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f));
                        }

                        aiMesh.VertexColorChannels[0] = vertColorChannel;
                    }

                    // generate temporary face indices
                    int[] tempIndices = new int[aiMesh.VertexCount];
                    for (int i = 0; i < aiMesh.VertexCount; i++)
                        tempIndices[i] = i;

                    aiMesh.SetIndices(tempIndices, 3);

                    // add the mesh to the list
                    aiScene.Meshes.Add(aiMesh);

                    splitIdx++;
                }

                totalSplitIdx += splitIdx;

                foreach (RWMaterial mat in mesh.Materials)
                {
                    Assimp.Material aiMaterial = new Assimp.Material();
                    aiMaterial.AddProperty(new Assimp.MaterialProperty(Assimp.Unmanaged.AiMatKeys.NAME, "Material" + (materialIdx++).ToString("00")));

                    if (mat.IsTextured)
                    {
                        aiMaterial.AddProperty(new Assimp.MaterialProperty(Assimp.Unmanaged.AiMatKeys.TEXTURE_BASE, mat.TextureReference.ReferencedTextureName + ".png", Assimp.TextureType.Diffuse, 0));
                    }

                    aiScene.Materials.Add(aiMaterial);
                }

                drawCallIdx++;
            }

            // store node lookup
            Dictionary<RWSceneNode, Assimp.Node> nodeLookup = new Dictionary<RWSceneNode, Assimp.Node>();

            // first create the root node
            var rootNode = new Assimp.Node("SceneRoot");
            rootNode.Transform = scene.Nodes[0].Transform.ToAssimpMatrix4x4();
            nodeLookup.Add(scene.Nodes[0], rootNode);

            for (int i = 1; i < scene.Nodes.Count - 1; i++)
            {
                var node = scene.Nodes[i];
                string name = node.BoneMetadata.BoneNameID.ToString();

                var aiNode = new Assimp.Node(name);
                aiNode.Transform = node.Transform.ToAssimpMatrix4x4();

                // get the associated meshes for this node
                var drawCalls = scene.DrawCalls.FindAll(dc => dc.NodeIndex == i);
                foreach (var drawCall in drawCalls)
                {
                    for (int j = 0; j < scene.Meshes[drawCall.MeshIndex].MaterialCount; j++)
                    {
                        aiNode.MeshIndices.Add(meshStartIndices[scene.DrawCalls.IndexOf(drawCall)] + j);
                    }
                }

                nodeLookup[node.Parent].Children.Add(aiNode);
                nodeLookup.Add(node, aiNode);
            }

            aiScene.RootNode = rootNode;

            return aiScene;
        }