private void FillBoneNodes(ref AMT_JOINT parentBone, XElement boneNode, ref AMT_MODEL amtModel)
        {
            //pego todos os nodes
            List<XElement> nodes = boneNode.Elements(XName.Get("node", Namespace)).ToList();
            foreach (var node in nodes)
            {
                //se é um bone
                if (node.Attribute("type") != null &&
                    node.Attribute("type").Value.Contains("JOINT"))
                {
                    Matrix matrix = Matrix.Identity;

                    //pega o nome e a matrix do bone
                    string boneName = node.Attribute("name").Value;
                    string boneId = node.Attribute("id").Value;
                    string sid = node.Attribute("sid").Value;
                    XElement matrixElement = node.Element(XName.Get("matrix", Namespace));
                    string matrixSID = null;
                    if (matrixElement.Attribute("sid") != null)
                        matrixSID = matrixElement.Attribute("sid").Value; //uso nas animacoes para achar o bone id/sid

                    matrix = Tools.ConvertStringToMatrix(matrixElement.Value, 0);

                    // Create this node, use the current number of bones as number.
                    AMT_JOINT newBone = new AMT_JOINT();
                    newBone.SID = sid;
                    newBone.TARGET = boneId + "/" + matrixSID;
                    newBone.ID = (uint)amtModel.Joints.Count();
                    newBone.ParentID = (int)parentBone.ID;
                    newBone.Name = boneName;

                    newBone.NumChildren = 0;
                    newBone.JointChildren = new List<uint>();

                    newBone.NumKF = 0;
                    newBone.KFData = new List<AMT_KF>();

                    newBone.IsAnimated = (uint)(string.IsNullOrEmpty(matrixSID) ? 0 : 1);
                    newBone.Flag = 0;

                    //atualiza o bone pai
                    parentBone.NumChildren++;
                    parentBone.JointChildren.Add(newBone.ID);

                    //matrix relativa
                    newBone.BindMatrix = matrix;
                    //absoluta = relativa do atual * absoluta do pai
                    newBone.MatrixAbsolute = matrix * parentBone.MatrixAbsolute;
                    //inversa da matriz relativa
                    newBone.InverseBindMatrix = Matrix.Invert(newBone.MatrixAbsolute);

                    amtModel.Joints.Add(newBone);

                    // vai para os filhos
                    FillBoneNodes(ref newBone, node, ref amtModel);
                }
            }
        }
        private void ConvertBones(XElement rootElement, ref AMT_MODEL amtModel)
        {
            //primeiro eu encontro o library_visual_scenes
            XElement libraryVisualScenes = rootElement.Element(XName.Get("library_visual_scenes", Namespace));
            XElement visualScene = libraryVisualScenes.Element(XName.Get("visual_scene", Namespace));

            //se tem o nodo skeleton
            XElement rootNode = FindRootSkeletonNodeId(visualScene);

            amtModel.Joints = new List<AMT_JOINT>();

            //Começo a percorrer os nodes procurando pela hierarquia de bones
            if (rootNode != null)
            {
                //adiciona o bone raiz
                Matrix matrix = Matrix.Identity;

                string sid = rootNode.Attribute("sid").Value;
                string boneId = rootNode.Attribute("id").Value;

                XElement matrixElement = rootNode.Element(XName.Get("matrix", Namespace));
                string matrixSID = null;
                if (matrixElement.Attribute("sid") != null)
                    matrixSID = matrixElement.Attribute("sid").Value; //uso nas animacoes para achar o bone id/sid

                matrix = Tools.ConvertStringToMatrix(matrixElement.Value, 0);

                AMT_JOINT newBone = new AMT_JOINT();
                newBone.SID = sid;
                newBone.TARGET = boneId + "/" + matrixSID;
                newBone.ID = 0;
                newBone.ParentID = -1; //nao tem pai
                newBone.Name = "Root";

                newBone.NumChildren = 0;
                newBone.JointChildren = new List<uint>();

                newBone.NumKF = 0;
                newBone.KFData = new List<AMT_KF>();

                //se nao tem sid entao ele nao é animado
                newBone.IsAnimated = (uint)(string.IsNullOrEmpty(matrixSID)? 0 : 1);
                newBone.Flag = 0;

                newBone.BindMatrix = matrix;
                newBone.MatrixAbsolute = matrix;
                newBone.InverseBindMatrix = Matrix.Invert(matrix);

                amtModel.Joints.Add(newBone);

                FillBoneNodes(ref newBone, rootNode, ref amtModel);
            }
        }