public static Assimp.Matrix4x4 AssimpCalculateInverseMatrix(STBone bone)
        {
            Assimp.Matrix4x4 transf;

            //Get parent transform for a smooth matrix
            if (bone.Parent != null && bone.Parent is STBone)
            {
                transf = AssimpCalculateInverseMatrix((STBone)bone.Parent);
            }
            else
            {
                transf = Assimp.Matrix4x4.Identity;
            }

            //Now calculate the matrix with TK matrices
            var trans = Assimp.Matrix4x4.FromTranslation(new Vector3D(bone.position[0], bone.position[1], bone.position[2]));
            var scale = Assimp.Matrix4x4.FromScaling(new Vector3D(bone.scale[0], bone.scale[1], bone.scale[2]));
            var rotX  = Assimp.Matrix4x4.FromRotationX(bone.rotation[0]);
            var rotY  = Assimp.Matrix4x4.FromRotationY(bone.rotation[1]);
            var rotZ  = Assimp.Matrix4x4.FromRotationZ(bone.rotation[2]);

            var result = scale * (rotX * rotY * rotZ) * trans;

            result.Inverse();

            return(transf);
        }
        public static Matrix4x4 GetBoneMatrix(STBone bone)
        {
            var pos  = Matrix4x4.FromTranslation(new Vector3D(bone.position[0], bone.position[1], bone.position[2]));
            var rotx = Matrix4x4.FromRotationX(bone.rotation[0]);
            var roty = Matrix4x4.FromRotationY(bone.rotation[1]);
            var rotz = Matrix4x4.FromRotationZ(bone.rotation[2]);
            var sca  = Matrix4x4.FromScaling(new Vector3D(bone.scale[0], bone.scale[1], bone.scale[2]));

            return(sca * (rotx * roty * rotz) * pos);
        }
示例#3
0
        private void SaveBones(Node parentBone, STBone bone, STSkeleton skeleton)
        {
            Node boneNode = new Node(bone.Text);

            parentBone.Children.Add(boneNode);

            boneNode.Transform = AssimpHelper.GetBoneMatrix(bone);

            foreach (STBone child in bone.GetChildren())
            {
                SaveBones(boneNode, child, skeleton);
            }
        }
示例#4
0
        public void update(bool reset = false)
        {
            Updated = true;
            List <STBone> nodesToProcess = new List <STBone>();

            // Add all root nodes from the VBN
            foreach (STBone b in bones)
            {
                if (b.Parent == null)
                {
                    nodesToProcess.Add(b);
                }
            }

            // some special processing for the root bones before we start
            foreach (STBone b in nodesToProcess)
            {
                b.transform = Matrix4.CreateScale(b.sca) * Matrix4.CreateFromQuaternion(b.rot) * Matrix4.CreateTranslation(b.pos);
                // scale down the model in its entirety only when mid-animation (i.e. reset == false)
                if (!reset)
                {
                    b.transform *= Matrix4.CreateScale(1);
                }
            }

            // Process as a tree from the root node's children and beyond. These
            // all use the same processing, unlike the root nodes.
            int numRootNodes = nodesToProcess.Count;

            for (int i = 0; i < numRootNodes; i++)
            {
                nodesToProcess.AddRange(nodesToProcess[0].GetChildren());
                nodesToProcess.RemoveAt(0);
            }
            while (nodesToProcess.Count > 0)
            {
                // DFS
                STBone currentBone = nodesToProcess[0];
                nodesToProcess.RemoveAt(0);
                nodesToProcess.AddRange(currentBone.GetChildren());

                // Process this node
                currentBone.transform = Matrix4.CreateScale(currentBone.sca) * Matrix4.CreateFromQuaternion(currentBone.rot) * Matrix4.CreateTranslation(currentBone.pos);
                if (currentBone.Parent != null)
                {
                    currentBone.transform = currentBone.transform * ((STBone)currentBone.Parent).transform;
                }
            }
        }
示例#5
0
        public List <STBone> getBoneTreeOrder()
        {
            List <STBone>  bone = new List <STBone>();
            Queue <STBone> q    = new Queue <STBone>();

            q.Enqueue(bones[0]);

            while (q.Count > 0)
            {
                STBone b = q.Dequeue();
                foreach (STBone bo in b.GetChildren())
                {
                    q.Enqueue(bo);
                }
                bone.Add(b);
            }
            return(bone);
        }
示例#6
0
            public void SetKeyFromBone(float frame, STBone bone)
            {
                Vector3 rot = ANIM.quattoeul(bone.rot);

                if (rot.X != bone.rotation[0] || rot.Y != bone.rotation[1] || rot.Z != bone.rotation[2])
                {
                    XROT.GetKeyFrame(frame).Value = bone.rot.X;
                    YROT.GetKeyFrame(frame).Value = bone.rot.Y;
                    ZROT.GetKeyFrame(frame).Value = bone.rot.Z;
                    WROT.GetKeyFrame(frame).Value = bone.rot.W;
                }
                if (bone.pos.X != bone.position[0] || bone.pos.Y != bone.position[1] || bone.pos.Z != bone.position[2])
                {
                    XPOS.GetKeyFrame(frame).Value = bone.pos.X;
                    YPOS.GetKeyFrame(frame).Value = bone.pos.Y;
                    ZPOS.GetKeyFrame(frame).Value = bone.pos.Z;
                }
                if (bone.sca.X != bone.scale[0] || bone.sca.Y != bone.scale[1] || bone.sca.Z != bone.scale[2])
                {
                    XSCA.GetKeyFrame(frame).Value = bone.sca.X;
                    YSCA.GetKeyFrame(frame).Value = bone.sca.Y;
                    ZSCA.GetKeyFrame(frame).Value = bone.sca.Z;
                }
            }
示例#7
0
        private void CreateByNode(Node node, STSkeleton skeleton, short SmoothIndex, short RigidIndex, bool IsRoot, ref Assimp.Matrix4x4 rootTransform)
        {
            Matrix4x4 trafo        = node.Transform;
            Matrix4x4 world        = trafo * rootTransform;
            var       transformMat = AssimpHelper.TKMatrix(world);

            int matchedBoneIndex = skeleton.bones.FindIndex(item => item.Name == node.Name);

            if (matchedBoneIndex < 0)
            {
                tempBoneNodes.Add(node);

                STBone bone = new STBone();
                bone.skeletonParent = skeleton;
                skeleton.bones.Add(bone);

                bone.Text = node.Name;
                bone.SmoothMatrixIndex = (short)skeleton.bones.IndexOf(bone);
                bone.RigidMatrixIndex  = -1; //Todo calculate these

                STConsole.WriteLine($"-".Repeat(30));
                STConsole.WriteLine($"Processing Bone {bone.Text}");
                STConsole.WriteLine($"SmoothMatrixIndex {bone.SmoothMatrixIndex}");
                STConsole.WriteLine($"RigidMatrixIndex {bone.RigidMatrixIndex}");
                STConsole.WriteLine($"Transform Matrix {transformMat}");
                STConsole.WriteLine($"-".Repeat(30));

                if (IsRoot)
                {
                    bone.parentIndex = -1;
                    transformMat     = AssimpHelper.TKMatrix(world * Matrix4x4.FromRotationX(MathHelper.DegreesToRadians(BoneRotation)));
                }
                else
                {
                    if (tempBoneNodes.Contains(node.Parent))
                    {
                        bone.parentIndex = tempBoneNodes.IndexOf(node.Parent);
                    }
                }


                var scale    = transformMat.ExtractScale();
                var rotation = transformMat.ExtractRotation();
                var position = transformMat.ExtractTranslation();

                var rotEular = AssimpHelper.ToEular(rotation);

                bone.position = new float[] { position.X, position.Y, position.Z };
                bone.scale    = new float[] { scale.X, scale.Y, scale.Z };
                bone.rotation = new float[] { rotEular.X, rotEular.Y, rotEular.Z, 0 };
            }
            else
            {
                STConsole.WriteLine($"Duplicate node name found for bone {node.Name}!", Color.Red);
            }

            foreach (Node child in node.Children)
            {
                CreateByNode(child, skeleton, SmoothIndex, RigidIndex, false, ref rootTransform);
            }
        }
示例#8
0
        private Mesh SaveMesh(STGenericObject genericObj, int index, STSkeleton skeleton, List <int> NodeArray)
        {
            //Assimp is weird so use mesh_# for the name. We'll change it back after save
            Mesh mesh = new Mesh($"mesh_{ index }", PrimitiveType.Triangle);

            mesh.MaterialIndex = genericObj.MaterialIndex;

            List <Vector3D> textureCoords0 = new List <Vector3D>();
            List <Vector3D> textureCoords1 = new List <Vector3D>();
            List <Vector3D> textureCoords2 = new List <Vector3D>();
            List <Color4D>  vertexColors   = new List <Color4D>();

            int vertexID = 0;

            foreach (Vertex v in genericObj.vertices)
            {
                mesh.Vertices.Add(new Vector3D(v.pos.X, v.pos.Y, v.pos.Z));
                mesh.Normals.Add(new Vector3D(v.nrm.X, v.nrm.Y, v.nrm.Z));
                textureCoords0.Add(new Vector3D(v.uv0.X, v.uv0.Y, 0));
                textureCoords1.Add(new Vector3D(v.uv1.X, v.uv1.Y, 0));
                textureCoords2.Add(new Vector3D(v.uv2.X, v.uv2.Y, 0));
                vertexColors.Add(new Color4D(v.col.X, v.col.Y, v.col.Z, v.col.W));
                mesh.TextureCoordinateChannels[0] = textureCoords0;
                mesh.TextureCoordinateChannels[1] = textureCoords1;
                mesh.TextureCoordinateChannels[2] = textureCoords2;
                mesh.VertexColorChannels[0]       = vertexColors;

                if (skeleton != null)
                {
                    for (int j = 0; j < v.boneIds.Count; j++)
                    {
                        if (j < genericObj.VertexSkinCount)
                        {
                            //Get the bone via the node array and bone index from the vertex
                            STBone STbone = skeleton.bones[NodeArray[v.boneIds[j]]];

                            //Find the index of a bone. If it doesn't exist then we add it
                            int boneInd = mesh.Bones.FindIndex(x => x.Name == STbone.Text);

                            if (boneInd == -1)
                            {
                                var matrices = Switch_Toolbox.Library.IO.MatrixExenstion.CalculateInverseMatrix(STbone);

                                //Set the inverse matrix
                                Matrix4x4 transform = matrices.inverse.FromNumerics();

                                //Create a new assimp bone
                                Bone bone = new Bone();
                                bone.Name         = STbone.Text;
                                bone.OffsetMatrix = STbone.invert.ToMatrix4x4();
                                mesh.Bones.Add(bone);
                                BoneNames.Add(bone.Name);

                                boneInd = mesh.Bones.IndexOf(bone); //Set the index of the bone for the vertex weight
                            }

                            int MinWeightAmount = 0;

                            //Check if the max amount of weights is higher than the current bone id
                            if (v.boneWeights.Count > j && v.boneWeights[j] > MinWeightAmount)
                            {
                                if (v.boneWeights[j] <= 1)
                                {
                                    mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, v.boneWeights[j]));
                                }
                                else
                                {
                                    mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, 1));
                                }
                            }
                            else if (v.boneWeights.Count == 0 || v.boneWeights[j] > MinWeightAmount)
                            {
                                mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, 1));
                            }
                        }
                    }
                }


                vertexID++;
            }
            List <int> faces = genericObj.lodMeshes[genericObj.DisplayLODIndex].faces;

            for (int f = 0; f < faces.Count; f++)
            {
                mesh.Faces.Add(new Face(new int[] { faces[f++], faces[f++], faces[f] }));
            }

            mesh.TextureCoordinateChannels.SetValue(textureCoords0, 0);

            return(mesh);
        }
示例#9
0
        public void NextFrame(STSkeleton skeleton, bool isChild = false)
        {
            if (Frame >= FrameCount)
            {
                return;
            }

            if (Frame == 0 && !isChild)
            {
                skeleton.reset();
            }


            foreach (object child in Children)
            {
                if (child is Animation)
                {
                    ((Animation)child).SetFrame(Frame);
                    ((Animation)child).NextFrame(skeleton, isChild: true);
                }
            }

            bool Updated = false; // no need to update skeleton of animations that didn't change

            foreach (KeyNode node in Bones)
            {
                // Get Skeleton Node
                STBone b = null;
                b = skeleton.getBone(node.Text);
                if (b == null)
                {
                    continue;
                }
                Updated = true;

                b.pos.X = node.XPOS.GetValue(Frame);
                b.pos.Y = node.YPOS.GetValue(Frame);
                b.pos.Z = node.ZPOS.GetValue(Frame);

                if (node.XSCA.HasAnimation())
                {
                    b.sca.X = node.XSCA.GetValue(Frame);
                }
                else
                {
                    b.sca.X = 1;
                }
                if (node.YSCA.HasAnimation())
                {
                    b.sca.Y = node.YSCA.GetValue(Frame);
                }
                else
                {
                    b.sca.Y = 1;
                }
                if (node.ZSCA.HasAnimation())
                {
                    b.sca.Z = node.ZSCA.GetValue(Frame);
                }
                else
                {
                    b.sca.Z = 1;
                }


                if (node.XROT.HasAnimation() || node.YROT.HasAnimation() || node.ZROT.HasAnimation())
                {
                    if (node.RotType == RotationType.QUATERNION)
                    {
                        KeyFrame[] x  = node.XROT.GetFrame(Frame);
                        KeyFrame[] y  = node.YROT.GetFrame(Frame);
                        KeyFrame[] z  = node.ZROT.GetFrame(Frame);
                        KeyFrame[] w  = node.WROT.GetFrame(Frame);
                        Quaternion q1 = new Quaternion(x[0].Value, y[0].Value, z[0].Value, w[0].Value);
                        Quaternion q2 = new Quaternion(x[1].Value, y[1].Value, z[1].Value, w[1].Value);
                        if (x[0].Frame == Frame)
                        {
                            b.rot = q1;
                        }
                        else
                        if (x[1].Frame == Frame)
                        {
                            b.rot = q2;
                        }
                        else
                        {
                            b.rot = Quaternion.Slerp(q1, q2, (Frame - x[0].Frame) / (x[1].Frame - x[0].Frame));
                        }
                    }
                    else
                    if (node.RotType == RotationType.EULER)
                    {
                        float x = node.XROT.HasAnimation() ? node.XROT.GetValue(Frame) : b.rotation[0];
                        float y = node.YROT.HasAnimation() ? node.YROT.GetValue(Frame) : b.rotation[1];
                        float z = node.ZROT.HasAnimation() ? node.ZROT.GetValue(Frame) : b.rotation[2];
                        b.rot = EulerToQuat(z, y, x);
                    }
                }
            }
            Frame += 1f;
            if (Frame >= FrameCount)
            {
                Frame = 0;
            }

            if (!isChild && Updated)
            {
                skeleton.update();
            }
        }
 public static Syroot.Maths.Matrix3x4 CalculateInverseMatrix(STBone bone)
 {
     return(FromAssimpMatrix(AssimpCalculateInverseMatrix(bone)));
 }
示例#11
0
        private void SaveMeshes(Scene scene, STGenericModel model, STSkeleton skeleton, string FileName, List <int> NodeArray)
        {
            int MeshIndex = 0;

            foreach (var obj in model.Nodes[0].Nodes)
            {
                var genericObj = (STGenericObject)obj;

                Mesh mesh = new Mesh(genericObj.Text, PrimitiveType.Triangle);
                mesh.MaterialIndex = genericObj.MaterialIndex;

                List <Vector3D> textureCoords0 = new List <Vector3D>();
                List <Vector3D> textureCoords1 = new List <Vector3D>();
                List <Vector3D> textureCoords2 = new List <Vector3D>();
                List <Color4D>  vertexColors   = new List <Color4D>();

                int vertexID = 0;
                foreach (Vertex v in genericObj.vertices)
                {
                    mesh.Vertices.Add(new Vector3D(v.pos.X, v.pos.Y, v.pos.Z));
                    mesh.Normals.Add(new Vector3D(v.nrm.X, v.nrm.Y, v.nrm.Z));
                    textureCoords0.Add(new Vector3D(v.uv0.X, v.uv0.Y, 0));
                    textureCoords1.Add(new Vector3D(v.uv1.X, v.uv1.Y, 0));
                    textureCoords2.Add(new Vector3D(v.uv2.X, v.uv2.Y, 0));
                    vertexColors.Add(new Color4D(v.col.X, v.col.Y, v.col.Z, v.col.W));
                    mesh.TextureCoordinateChannels[0] = textureCoords0;
                    mesh.TextureCoordinateChannels[1] = textureCoords1;
                    mesh.TextureCoordinateChannels[2] = textureCoords2;
                    mesh.VertexColorChannels[0]       = vertexColors;

                    for (int j = 0; j < v.boneIds.Count; j++)
                    {
                        if (j < genericObj.VertexSkinCount)
                        {
                            //Get the bone via the node array and bone index from the vertex
                            STBone STbone = skeleton.bones[NodeArray[v.boneIds[j]]];

                            //Find the index of a bone. If it doesn't exist then we add it
                            int boneInd = mesh.Bones.FindIndex(x => x.Name == STbone.Text);

                            if (boneInd == -1)
                            {
                                var matrices = Switch_Toolbox.Library.IO.MatrixExenstion.CalculateInverseMatrix(STbone);

                                //Set the inverse matrix
                                Matrix4x4 transform = matrices.inverse.FromNumerics();

                                //Create a new assimp bone
                                Bone bone = new Bone();
                                bone.Name         = STbone.Text;
                                bone.OffsetMatrix = transform;

                                mesh.Bones.Add(bone);
                                BoneNames.Add(bone.Name);

                                boneInd = mesh.Bones.IndexOf(bone); //Set the index of the bone for the vertex weight
                            }

                            //Check if the max amount of weights is higher than the current bone id
                            if (v.boneWeights.Count > j)
                            {
                                if (v.boneWeights[j] <= 1)
                                {
                                    mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, v.boneWeights[j]));
                                }
                                else
                                {
                                    mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, 1));
                                }
                            }
                            else
                            {
                                mesh.Bones[boneInd].VertexWeights.Add(new VertexWeight(vertexID, 1));
                            }
                        }
                    }
                    vertexID++;
                }
                List <int> faces = genericObj.lodMeshes[genericObj.DisplayLODIndex].faces;
                for (int f = 0; f < faces.Count; f++)
                {
                    mesh.Faces.Add(new Face(new int[] { faces[f++], faces[f++], faces[f] }));
                }

                mesh.TextureCoordinateChannels.SetValue(textureCoords0, 0);

                scene.Meshes.Add(mesh);

                MeshIndex++;
            }
            Node geomNode = new Node(Path.GetFileNameWithoutExtension(FileName), scene.RootNode);

            for (int ob = 0; ob < scene.MeshCount; ob++)
            {
                geomNode.MeshIndices.Add(ob);
            }
            scene.RootNode.Children.Add(geomNode);
        }