Example #1
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public IOSkeleton ToIOSkeleton()
        {
            IOSkeleton ioskel = new IOSkeleton();

            Dictionary <SBBone, IOBone> sbtoio = new Dictionary <SBBone, IOBone>();

            foreach (var b in GetBones())
            {
                IOBone bone = new IOBone()
                {
                    Name          = b.Name,
                    Scale         = new System.Numerics.Vector3(b.SX, b.SY, b.SZ),
                    RotationEuler = new System.Numerics.Vector3(b.RX, b.RY, b.RZ),
                    Translation   = new System.Numerics.Vector3(b.X, b.Y, b.Z),
                };

                sbtoio.Add(b, bone);

                if (b.Parent == null)
                {
                    ioskel.RootBones.Add(bone);
                }
                else
                {
                    bone.Parent = sbtoio[b.Parent];
                }
            }

            return(ioskel);
        }
Example #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="model"></param>
        private List <Node> ProcessModel(IOModel model)
        {
            List <Node> nodes = new List <Node>();

            // bones
            foreach (var root in model.Skeleton.RootBones)
            {
                nodes.Add(ProcessSkeleton(root));
            }

            // get root bone
            IOBone rootBone = null;

            if (model.Skeleton != null && model.Skeleton.RootBones.Count > 0)
            {
                rootBone = model.Skeleton.RootBones[0];
            }

            // mesh
            foreach (var mesh in model.Meshes)
            {
                nodes.Add(ProcessMesh(mesh, model, rootBone));
            }

            return(nodes);
        }
Example #3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="bone"></param>
        /// <returns></returns>
        private HSD_JOBJ IOBoneToJOBJ(IOBone bone)
        {
            HSD_JOBJ jobj = new HSD_JOBJ()
            {
                TX = bone.TranslationX,
                TY = bone.TranslationY,
                TZ = bone.TranslationZ,
                RX = bone.RotationEuler.X,
                RY = bone.RotationEuler.Y,
                RZ = bone.RotationEuler.Z,
                SX = bone.ScaleX,
                SY = bone.ScaleY,
                SZ = bone.ScaleZ,
            };

            if (Settings.ImportBoneNames)
            {
                jobj.ClassName = bone.Name;
            }

            _cache.NameToJOBJ.Add(bone.Name, jobj);
            _cache.jobjToWorldTransform.Add(jobj, MatrixNumericsToTKMatrix(bone.WorldTransform));

            foreach (var child in bone.Children)
            {
                jobj.AddChild(IOBoneToJOBJ(child));
            }

            return(jobj);
        }
Example #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="bone"></param>
        /// <returns></returns>
        private HSD_JOBJ IOBoneToJOBJ(IOBone bone)
        {
#if DEBUG
            //
            if (Settings.CleanRoot)
            {
                if (bone.Parent == null)
                {
                    _cache.CleanRotMatrix = Matrix4.CreateFromQuaternion(new Quaternion(bone.Rotation.X, bone.Rotation.Y, bone.Rotation.Z, bone.Rotation.W));
                    bone.Rotation         = System.Numerics.Quaternion.Identity;
                }
                else
                {
                    // fix position
                    var pos = Vector3.TransformNormal(new Vector3(bone.TranslationX, bone.TranslationY, bone.TranslationZ), _cache.CleanRotMatrix);
                    bone.Translation = new System.Numerics.Vector3(pos.X, pos.Y, pos.Z);
                }

                // clean scale
                bone.Scale = new System.Numerics.Vector3(1, 1, 1);
            }

            //
            if (bone.Parent == null && Settings.Meleeify)
            {
                Meleeify(bone);
            }
#endif

            HSD_JOBJ jobj = new HSD_JOBJ()
            {
                TX = bone.TranslationX,
                TY = bone.TranslationY,
                TZ = bone.TranslationZ,
                RX = bone.RotationEuler.X,
                RY = bone.RotationEuler.Y,
                RZ = bone.RotationEuler.Z,
                SX = bone.ScaleX,
                SY = bone.ScaleY,
                SZ = bone.ScaleZ,
            };

            if (Settings.ImportBoneNames)
            {
                jobj.ClassName = bone.Name;
            }

            Console.WriteLine(bone.Name + " " + jobj.Children.Length);

            _cache.NameToJOBJ.Add(bone.Name, jobj);
            _cache.jobjToWorldTransform.Add(jobj, MatrixNumericsToTKMatrix(bone.WorldTransform));

            foreach (var child in bone.Children)
            {
                jobj.AddChild(IOBoneToJOBJ(child));
            }

            return(jobj);
        }
Example #5
0
 public static void QueueBones(IOBone b, Queue <IOBone> q, IOSkeleton Skeleton)
 {
     q.Enqueue(b);
     foreach (IOBone c in b.Children)
     {
         QueueBones(c, q, Skeleton);
     }
 }
Example #6
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="bone"></param>
        /// <returns></returns>
        private Node ProcessSkeleton(IOBone bone)
        {
            Node n = new Node()
            {
                Name   = bone.Name,
                sID    = bone.Name,
                ID     = bone.Name,
                Matrix = new Matrix[] { new Matrix() },
                Type   = Node_Type.JOINT
            };

            n.Matrix[0].FromMatrix(bone.LocalTransform);

            n.node = new Node[bone.Children.Length];

            int childIndex = 0;

            foreach (var child in bone.Children)
            {
                n.node[childIndex++] = ProcessSkeleton(child);
            }

            return(n);
        }
Example #7
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="n"></param>
        /// <param name="bones"></param>
        private IOBone LoadNodes(Node n, IOBone parent, IOModel model, List <string> skeletonIds)
        {
            // create bone to represent node
            IOBone bone = new IOBone()
            {
                Name  = n.Name,
                AltID = n.sID
            };

            // load matrix
            if (n.Matrix != null && n.Matrix.Length >= 0)
            {
                bone.LocalTransform = n.Matrix[0].ToMatrix();
            }
            else
            {
                // or segmented transform
                Vector3 scale    = Vector3.One;
                Vector3 position = Vector3.Zero;
                Vector4 rx       = Vector4.UnitX;
                Vector4 ry       = Vector4.UnitY;
                Vector4 rz       = Vector4.UnitZ;

                if (n.Scale != null && n.Scale.Length > 0)
                {
                    var val = n.Scale[0].GetValues();
                    scale = new Vector3(val[0], val[1], val[2]);
                }

                if (n.Translate != null && n.Translate.Length > 0)
                {
                    var val = n.Translate[0].GetValues();
                    position = new Vector3(val[0], val[1], val[2]);
                }

                if (n.Rotate != null && n.Rotate.Length > 0)
                {
                    foreach (var r in n.Rotate)
                    {
                        var val = r.GetValues();
                        switch (r.sID)
                        {
                        case "rotationX":
                            rx = new Vector4(val[0], val[1], val[2], val[3]);
                            break;

                        case "rotationY":
                            ry = new Vector4(val[0], val[1], val[2], val[3]);
                            break;

                        case "rotationZ":
                            rz = new Vector4(val[0], val[1], val[2], val[3]);
                            break;
                        }
                    }
                }

                // create transform
                bone.LocalTransform = Matrix4x4.CreateTranslation(position) *
                                      Matrix4x4.CreateFromAxisAngle(new Vector3(rz.X, rz.Y, rz.Z), rz.W) *
                                      Matrix4x4.CreateFromAxisAngle(new Vector3(ry.X, ry.Y, ry.Z), ry.W) *
                                      Matrix4x4.CreateFromAxisAngle(new Vector3(rx.X, rx.Y, rx.Z), rx.W) *
                                      Matrix4x4.CreateScale(scale);
            }


            // add this node to parent
            if (parent != null)
            {
                parent.AddChild(bone);
            }

            // load children
            if (n.node != null)
            {
                foreach (var v in n.node)
                {
                    LoadNodes(v, bone, model, skeletonIds);
                }
            }


            // load instanced geometry
            if (n.Instance_Geometry != null)
            {
                foreach (var g in n.Instance_Geometry)
                {
                    var geom = LoadGeometryFromID(n, g.URL);
                    geom.TransformVertices(bone.WorldTransform);
                    geom.ParentBone = bone;
                    model.Meshes.Add(geom);
                }
            }

            // load instanced geometry controllers
            if (n.Instance_Controller != null)
            {
                foreach (var c in n.Instance_Controller)
                {
                    var geom = LoadGeometryControllerFromID(n, c.URL);
                    geom.TransformVertices(bone.WorldTransform);
                    geom.ParentBone = bone;
                    model.Meshes.Add(geom);
                }
            }

            // detect skeleton
            if ((!string.IsNullOrEmpty(bone.Name) && skeletonIds.Contains(bone.Name)) ||
                (n.Type == Node_Type.JOINT && parent == null) ||
                (n.Instance_Camera == null &&
                 n.Instance_Controller == null &&
                 n.Instance_Geometry == null &&
                 n.Instance_Light == null &&
                 n.Instance_Node == null &&
                 parent == null &&
                 n.node != null &&
                 n.node.Length > 0))
            {
                model.Skeleton.RootBones.Add(bone);
            }

            // complete
            return(bone);
        }
Example #8
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="l"></param>
        /// <returns></returns>
        private IOBone CreateBoneFromNode(FbxNode l)
        {
            IOBone bone = new IOBone()
            {
                Name = GetNameWithoutNamespace(l.Properties[NodeDescSize - 2].ToString())
            };

            // scan and extract info from properties
            var properties = l.GetNodesByName("P");

            if (properties.Length == 0)
            {
                properties = l.GetNodesByName("Property");
            }

            Quaternion preRot  = new Quaternion(0, 0, 0, 1);
            Quaternion postRot = new Quaternion(0, 0, 0, 1);

            foreach (var prop in properties)
            {
                if (prop.Properties.Count < PropertyDescSize)
                {
                    continue;
                }

                if (prop.Properties[0].ToString() == "PreRotation")
                {
                    preRot = MathExt.FromEulerAngles(
                        MathExt.DegToRad((float)(double)prop.Properties[PropertyDescSize]),
                        MathExt.DegToRad((float)(double)prop.Properties[PropertyDescSize + 1]),
                        MathExt.DegToRad((float)(double)prop.Properties[PropertyDescSize + 2]));
                }

                if (prop.Properties[0].ToString() == "PostRotation")
                {
                    postRot = MathExt.FromEulerAngles(
                        MathExt.DegToRad((float)(double)prop.Properties[PropertyDescSize]),
                        MathExt.DegToRad((float)(double)prop.Properties[PropertyDescSize + 1]),
                        MathExt.DegToRad((float)(double)prop.Properties[PropertyDescSize + 2]));
                }

                if (prop.Properties[0].ToString() == "Lcl Translation")
                {
                    bone.Translation = new Vector3((float)(double)prop.Properties[PropertyDescSize], (float)(double)prop.Properties[PropertyDescSize + 1], (float)(double)prop.Properties[PropertyDescSize + 2]);
                }

                if (prop.Properties[0].ToString() == "Lcl Rotation")
                {
                    bone.RotationEuler = new Vector3(
                        MathExt.DegToRad((float)(double)prop.Properties[PropertyDescSize]),
                        MathExt.DegToRad((float)(double)prop.Properties[PropertyDescSize + 1]),
                        MathExt.DegToRad((float)(double)prop.Properties[PropertyDescSize + 2]));
                }

                if (prop.Properties[0].ToString() == "Lcl Scaling")
                {
                    bone.Scale = new Vector3((float)(double)prop.Properties[PropertyDescSize], (float)(double)prop.Properties[PropertyDescSize + 1], (float)(double)prop.Properties[PropertyDescSize + 2]);
                }
            }

            bone.Rotation = preRot * bone.Rotation * postRot;

            return(bone);
        }
Example #9
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="root"></param>
        private static void Meleeify(IOBone root)
        {
            Dictionary <IOBone, System.Numerics.Matrix4x4> worldTransform = new Dictionary <IOBone, System.Numerics.Matrix4x4>();
            Queue <IOBone> queue = new Queue <IOBone>();

            // gather final positions
            queue.Enqueue(root);
            while (queue.Count > 0)
            {
                var bone = queue.Dequeue();

                worldTransform.Add(bone, bone.WorldTransform);

                foreach (var child in bone.Children)
                {
                    queue.Enqueue(child);
                }
            }

            // reset skeleton
            queue.Enqueue(root);
            while (queue.Count > 0)
            {
                var bone = queue.Dequeue();

                // reset rotation and scale
                List <string> specialBones = new List <string>()
                {
                    "LShoulderJA", "RShoulderJA",
                    "RHaveN", "LHaveN",
                    "LLegJA", "LFootJA",
                    "RLegJA", "RFootJA"
                };

                List <string> commonBones = new List <string>()
                {
                    "TopN", "TransN", "XRotN", "YRotN", "HipN", "WaistN", "LLegJA", "LLegJ", "LKneeJ", "LFootJA", "LFootJ", "RLegJA", "RLegJ", "RKneeJ", "RFootJA", "RFootJ", "BustN", "LShoulderN", "LShoulderJA", "LShoulderJ", "LArmJ", "LHandN", "L1stNa", "L1stNb", "L2ndNa", "L2ndNb", "L3rdNa", "L3rdNb", "L4thNa", "L4thNb", "LThumbNa", "LThumbNb", "LHandNb", "NeckN", "HeadN", "RShoulderN", "RShoulderJA", "RShoulderJ", "RArmJ", "RHandN", "R1stNa", "R1stNb", "R2ndNa", "R2ndNb", "R3rdNa", "R3rdNb", "R4thNa", "R4thNb", "RThumbNa", "RThumbNb", "RHandNb", "ThrowN", "TransN2"
                };

                Vector3[] specialBoneRotations = new Vector3[]
                {
                    new Vector3(-90, 0, 0), new Vector3(-90, 0, -180),
                    new Vector3(0, -90, -180), new Vector3(-90, -90, 270),
                    new Vector3(-90, 0, -90), new Vector3(0, 0, -90),
                    new Vector3(-90, 0, -90), new Vector3(0, 0, -90)
                };

                var boneIndex = specialBones.IndexOf(bone.Name);

                if (boneIndex != -1)
                {
                    var r = specialBoneRotations[boneIndex];
                    bone.RotationEuler = new System.Numerics.Vector3((float)(r.X * Math.PI / 180), (float)(r.Y * Math.PI / 180), (float)(r.Z * Math.PI / 180));
                }
                else
                if (commonBones.Contains(bone.Name))
                {
                    bone.Rotation = new System.Numerics.Quaternion(0, 0, 0, 1);
                }
                bone.Scale = new System.Numerics.Vector3(1, 1, 1);

                bone.Translation = new System.Numerics.Vector3(0, 0, 0);

                // calcuate new translation
                if (bone.Parent != null)
                {
                    var currentPoint = System.Numerics.Vector3.Transform(System.Numerics.Vector3.Zero, bone.WorldTransform);
                    var targetPoint  = System.Numerics.Vector3.Transform(System.Numerics.Vector3.Zero, worldTransform[bone]);
                    var dis          = System.Numerics.Vector3.Subtract(targetPoint, currentPoint);

                    if (System.Numerics.Matrix4x4.Invert(bone.Parent.WorldTransform, out System.Numerics.Matrix4x4 inverse))
                    {
                        bone.Translation = System.Numerics.Matrix4x4.Multiply(worldTransform[bone], inverse).Translation;

                        Console.WriteLine(bone.Name + " " + bone.Translation.ToString());
                    }
                }

                foreach (var child in bone.Children)
                {
                    queue.Enqueue(child);
                }
            }
        }
Example #10
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public IOScene GetScene(string filePath)
        {
            IOScene scene = new IOScene();

            IOModel model = new IOModel();

            scene.Models.Add(model);

            using (FileStream stream = new FileStream(filePath, FileMode.Open))
                using (StreamReader r = new StreamReader(stream))
                {
                    Dictionary <string, IOMesh> nameToMesh  = new Dictionary <string, IOMesh>();
                    HashSet <IOBone>            meshBones   = new HashSet <IOBone>();
                    Dictionary <int, IOBone>    idxToBone   = new Dictionary <int, IOBone>();
                    Dictionary <int, int>       idxToParent = new Dictionary <int, int>();

                    string mode = "";
                    int    time = 0;

                    while (!r.EndOfStream)
                    {
                        // read and clean line args
                        var line = r.ReadLine().Trim();
                        var args = Regex.Replace(line, @"\s+", " ").Split(' ');

                        // check for grouping
                        switch (args[0])
                        {
                        case "nodes":
                        case "skeleton":
                        case "triangles":
                        case "end":
                            mode = args[0];
                            break;
                        }

                        switch (mode)
                        {
                        case "nodes":
                            if (args.Length >= 3)
                            {
                                args = line.Split('"');

                                var index       = int.Parse(args[0].Trim());
                                var name        = args[1];
                                var parentIndex = int.Parse(args[2].Trim());

                                IOBone bone = new IOBone()
                                {
                                    Name = name
                                };

                                idxToBone.Add(index, bone);
                                idxToParent.Add(index, parentIndex);
                            }
                            break;

                        case "skeleton":
                            if (args.Length == 2 && args[0] == "time")
                            {
                                int.TryParse(args[1], out time);
                            }
                            if (args.Length == 7)
                            {
                                var index = int.Parse(args[0]);

                                if (time == 0)
                                {
                                    idxToBone[index].Translation   = new System.Numerics.Vector3(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3]));
                                    idxToBone[index].RotationEuler = new System.Numerics.Vector3(float.Parse(args[4]), float.Parse(args[5]), float.Parse(args[6]));
                                }
                            }
                            break;

                        case "triangles":
                        {
                            if (args.Length > 0 && args.Length < 9 && args[0] != "triangles")
                            {
                                var material = string.Join(" ", args);

                                var v1 = ParseVertex(r.ReadLine(), idxToBone, out IOBone parent);
                                var v2 = ParseVertex(r.ReadLine(), idxToBone, out parent);
                                var v3 = ParseVertex(r.ReadLine(), idxToBone, out parent);

                                var meshName = parent.Name + material;

                                if (!meshBones.Contains(parent))
                                {
                                    meshBones.Add(parent);
                                }

                                meshName = Regex.Replace(meshName.Trim(), @"\s+", "_").Replace("#", "");

                                if (!nameToMesh.ContainsKey(meshName))
                                {
                                    // create and load material
                                    IOMaterial mat = new IOMaterial()
                                    {
                                        Name = material
                                    };
                                    scene.Materials.Add(mat);

                                    // create io mesh
                                    var iomesh = new IOMesh()
                                    {
                                        Name = meshName
                                    };

                                    // create triangle polygon
                                    iomesh.Polygons.Add(new IOPolygon()
                                        {
                                            MaterialName  = material,
                                            PrimitiveType = IOPrimitive.TRIANGLE
                                        });

                                    nameToMesh.Add(meshName, iomesh);
                                }

                                var mesh = nameToMesh[meshName];
                                mesh.Polygons[0].Indicies.Add(mesh.Vertices.Count);
                                mesh.Polygons[0].Indicies.Add(mesh.Vertices.Count + 1);
                                mesh.Polygons[0].Indicies.Add(mesh.Vertices.Count + 2);
                                mesh.Vertices.Add(v1);
                                mesh.Vertices.Add(v2);
                                mesh.Vertices.Add(v3);
                            }
                        }
                        break;
                        }
                    }

                    // create skeleton hierarchy
                    foreach (var bone in idxToBone)
                    {
                        var parent = idxToParent[bone.Key];

                        if (parent == -1)
                        {
                            if (meshBones.Count > 1 && meshBones.Contains(bone.Value))
                            {
                                continue;
                            }
                            else
                            {
                                model.Skeleton.RootBones.Add(bone.Value);
                            }
                        }
                        else
                        {
                            idxToBone[parent].AddChild(bone.Value);
                        }
                    }

                    // dump mesh
                    model.Meshes.AddRange(nameToMesh.Values);
                }

            return(scene);
        }
Example #11
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        private static IOVertex ParseVertex(string line, Dictionary <int, IOBone> idxToBones, out IOBone parentBone)
        {
            var args = Regex.Replace(line.Trim(), @"\s+", " ").Split(' ');

            IOVertex vertex = new IOVertex();

            // parse parent index
            int parent = int.Parse(args[0]);

            // parse attributes
            vertex.Position = new System.Numerics.Vector3(float.Parse(args[1]), float.Parse(args[2]), float.Parse(args[3]));
            vertex.Normal   = new System.Numerics.Vector3(float.Parse(args[4]), float.Parse(args[5]), float.Parse(args[6]));
            vertex.UVs.Add(new System.Numerics.Vector2(float.Parse(args[7]), float.Parse(args[8])));

            // transform by parent so we can ignore it
            if (parent != -1)
            {
                vertex.Transform(idxToBones[parent].WorldTransform);
                parentBone = idxToBones[parent];
            }
            else
            {
                parentBone = null;
            }

            // parse weights
            if (args.Length >= 10)
            {
                int links = int.Parse(args[9]);

                for (int i = 0; i < links; i++)
                {
                    vertex.Envelope.Weights.Add(new IOBoneWeight()
                    {
                        BoneName = idxToBones[int.Parse(args[10 + i * 2])].Name,
                        Weight   = float.Parse(args[11 + i * 2])
                    });
                }
            }

            return(vertex);
        }
Example #12
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="mesh"></param>
        /// <returns></returns>
        private Node ProcessMesh(IOMesh mesh, IOModel model, IOBone rootBone)
        {
            Node n = new Node()
            {
                Name = mesh.Name,
                sID  = mesh.Name,
                ID   = mesh.Name,
                Type = Node_Type.NODE
            };

            var materials = mesh.Polygons.Select(e => e.MaterialName).Distinct();

            if (mesh.HasEnvelopes())
            {
                var geom = new Instance_Controller();

                geom.URL = "#" + GenerateGeometryController(mesh, model.Skeleton);

                if (rootBone != null)
                {
                    geom.Skeleton = new Skeleton[] { new Skeleton()
                                                     {
                                                         Value = "#" + rootBone.Name
                                                     } }
                }
                ;

                n.Instance_Controller = new Instance_Controller[] { geom };

                n.Instance_Controller[0].Bind_Material = new IONET.Collada.FX.Materials.Bind_Material[]
                {
                    new Bind_Material()
                    {
                        Technique_Common = new FX.Technique_Common.Technique_Common_Bind_Material()
                        {
                            Instance_Material = materials.Select(e => new Instance_Material_Geometry()
                            {
                                Symbol = e, Target = "#" + e
                            }).ToArray()
                        }
                    }
                };
            }
            else
            {
                var geom = new Instance_Geometry();

                geom.URL = "#" + GenerateGeometry(mesh);

                n.Instance_Geometry = new Instance_Geometry[] { geom };

                n.Instance_Geometry[0].Bind_Material = new IONET.Collada.FX.Materials.Bind_Material[]
                {
                    new Bind_Material()
                    {
                        Technique_Common = new FX.Technique_Common.Technique_Common_Bind_Material()
                        {
                            Instance_Material = materials.Select(e => new Instance_Material_Geometry()
                            {
                                Symbol = e, Target = "#" + e
                            }).ToArray()
                        }
                    }
                };
            }

            return(n);
        }