Example #1
0
        public static SBSkeleton Open(string FileName, SBScene Scene)
        {
            SsbhFile File;

            if (Ssbh.TryParseSsbhFile(FileName, out File))
            {
                if (File is Skel skel)
                {
                    var Skeleton = new SBSkeleton();
                    Scene.Skeleton = Skeleton;

                    Dictionary <int, SBBone> idToBone   = new Dictionary <int, SBBone>();
                    Dictionary <SBBone, int> needParent = new Dictionary <SBBone, int>();
                    foreach (var b in skel.BoneEntries)
                    {
                        SBBone bone = new SBBone();
                        bone.Name      = b.Name;
                        bone.Type      = b.Type;
                        bone.Transform = Skel_to_TKMatrix(skel.Transform[b.Id]);
                        idToBone.Add(b.Id, bone);
                        if (b.ParentId == -1)
                        {
                            Skeleton.AddRoot(bone);
                        }
                        else
                        {
                            needParent.Add(bone, b.ParentId);
                        }
                    }
                    foreach (var v in needParent)
                    {
                        v.Key.Parent = idToBone[v.Value];
                    }

                    return(Skeleton);
                }
            }
            return(null);
        }
Example #2
0
        public static void Open(string FileName, SBScene Scene)
        {
            ISSBH_File File;

            if (SSBH.TryParseSSBHFile(FileName, out File))
            {
                if (File is SKEL skel)
                {
                    var Skeleton = new SBSkeleton();
                    Scene.Skeleton = Skeleton;

                    Dictionary <int, SBBone> idToBone   = new Dictionary <int, SBBone>();
                    Dictionary <SBBone, int> needParent = new Dictionary <SBBone, int>();
                    foreach (var b in skel.BoneEntries)
                    {
                        SBBone bone = new SBBone();
                        bone.Name      = b.Name;
                        bone.Type      = b.Type;
                        bone.Transform = Skel_to_TKMatrix(skel.Transform[b.ID]);
                        idToBone.Add(b.ID, bone);
                        if (b.ParentID == -1)
                        {
                            Skeleton.AddRoot(bone);
                        }
                        else
                        {
                            needParent.Add(bone, b.ParentID);
                        }
                    }
                    foreach (var v in needParent)
                    {
                        v.Key.Parent = idToBone[v.Value];
                    }
                }
            }
        }
Example #3
0
        public IOModel ImportIOModel(string FileName)
        {
            IOModel    model    = new IOModel();
            SBSkeleton skeleton = new SBSkeleton();

            model.Skeleton = skeleton;

            var test = Fbx.FbxIO.ReadBinary(FileName);

            if (test.Version != Fbx.FbxVersion.v7_4)
            {
                throw new NotSupportedException($"Only FBX version 7.4 is currently supported: Imported version = {test.Version}");
            }

            // global settings
            float Scale = 1;

            // read global settings
            var settings = test.GetNodesByName("GlobalSettings");

            if (settings.Length != 0)
            {
                var prop70 = settings[0].GetNodesByName("Properties70");
                if (prop70.Length != 0)
                {
                    foreach (var property in prop70[0].Nodes)
                    {
                        if (property == null)
                        {
                            continue;
                        }
                        if (property.Properties.Count > 0 && property.Name == "P")
                        {
                            //TODO: this is inaccurate...
                            //if (property.Properties[0].Equals("UnitScaleFactor"))
                            //    Scale = (float)(double)property.Properties[4];
                        }
                    }
                }
            }

            FbxAccessor accessor = new FbxAccessor(FileName);

            //Bones
            var limbs = accessor.GetLimbNodes();

            SBConsole.WriteLine($"Limb Node Count: {limbs.Length}");

            foreach (var limb in limbs)
            {
                skeleton.AddRoot(ConvertLimbToSBBone(limb));
            }
            foreach (var root in skeleton.Roots)
            {
                root.Scale *= Scale;
            }

            // Fast access to bone indices
            Dictionary <string, int> BoneNameToIndex = new Dictionary <string, int>();

            foreach (var b in skeleton.Bones)
            {
                BoneNameToIndex.Add(b.Name, skeleton.IndexOfBone(b));
            }

            // Mesh

            var models = accessor.GetModels();

            SBConsole.WriteLine($"Model Node Count: {models.Count}");

            int YupAxis = accessor.GetOriginalXAxis();

            SBConsole.WriteLine("Yup: " + YupAxis);
            foreach (var mod in models)
            {
                // rotation 90
                Matrix4 transform = (ImportSettings.Rotate90 ? Matrix4.CreateRotationX(-90 * DegToRag) : Matrix4.Identity) * GetModelTransform(mod);

                foreach (var geom in mod.Geometries)
                {
                    IOMesh mesh = new IOMesh();
                    mesh.Name = mod.Name;
                    model.Meshes.Add(mesh);

                    // Create Rigging information
                    Vector4[] BoneIndices = new Vector4[geom.Vertices.Length];
                    Vector4[] BoneWeights = new Vector4[geom.Vertices.Length];
                    foreach (var deformer in geom.Deformers)
                    {
                        //TODO: this shouldn't happen...
                        if (!BoneNameToIndex.ContainsKey(deformer.Name))
                        {
                            continue;
                        }
                        int index = BoneNameToIndex[deformer.Name];

                        for (int i = 0; i < deformer.Indices.Length; i++)
                        {
                            int vertexIndex = deformer.Indices[i];
                            for (int j = 0; j < 4; j++)
                            {
                                if (BoneWeights[vertexIndex][j] == 0)
                                {
                                    BoneIndices[vertexIndex][j] = index;
                                    BoneWeights[vertexIndex][j] = (float)deformer.Weights[i];
                                    break;
                                }
                            }
                        }
                        //SBConsole.WriteLine(deformer.Name + " " + deformer.Weights.Length + " " + deformer.Indices.Length + " " + index);
                    }

                    // Explanation:
                    // negative values are used to indicate a stopping point for the face
                    // so every 3rd index needed to be adjusted
                    for (int i = 0; i < geom.Indices.Length; i += 3)
                    {
                        mesh.Indices.Add((uint)i);
                        mesh.Indices.Add((uint)i + 1);
                        mesh.Indices.Add((uint)i + 2);
                        mesh.Vertices.Add(CreateVertex(transform, geom, i, BoneIndices, BoneWeights, Scale));
                        mesh.Vertices.Add(CreateVertex(transform, geom, i + 1, BoneIndices, BoneWeights, Scale));
                        mesh.Vertices.Add(CreateVertex(transform, geom, i + 2, BoneIndices, BoneWeights, Scale));
                    }

                    mesh.HasPositions = true;

                    //SBConsole.WriteLine(geom.Vertices.Length);
                    foreach (var layer in geom.Layers)
                    {
                        switch (layer.Name)
                        {
                        case "LayerElementNormal":
                        case "LayerElementUV":
                        case "LayerElementColor":
                            break;

                        default:
                            SBConsole.WriteLine(layer.Name + " " + layer.ReferenceInformationType + " " + layer.Data.Length + " " + (layer.ReferenceInformationType.Equals("IndexToDirect") ? layer.Indices.Length.ToString() : ""));
                            break;
                        }
                    }
                    mesh.Optimize();
                }
            }

            return(model);
        }
Example #4
0
        public IOModel ImportIOModel(string FileName)
        {
            IOModel    model    = new IOModel();
            SBSkeleton skeleton = new SBSkeleton();

            Dictionary <int, SBBone>    indexToBone    = new Dictionary <int, SBBone>();
            Dictionary <string, IOMesh> materialToMesh = new Dictionary <string, IOMesh>();
            List <SBBone> PostProcessBones             = new List <SBBone>();
            List <int>    boneParents = new List <int>();

            string[] lines          = File.ReadAllLines(FileName);
            string   CurrentSection = "";

            for (int i = 0; i < lines.Length; i++)
            {
                string[] args = Regex.Replace(lines[i].Trim(), @"\s+", " ").Split(' ');

                if (args[0].Equals("end"))
                {
                    CurrentSection = "";
                }
                else
                if (args[0].Equals("time"))
                {
                }
                else
                if (args[0].Equals("nodes"))
                {
                    CurrentSection = args[0];
                }
                else
                if (args[0].Equals("skeleton"))
                {
                    CurrentSection = args[0];
                }
                else
                if (args[0].Equals("triangles"))
                {
                    CurrentSection = args[0];
                }
                else
                {
                    switch (CurrentSection)
                    {
                    case "nodes":
                        var bone = new SBBone();
                        bone.Name = args[1].Replace("\"", "");
                        Console.WriteLine(bone.Name + " " + args[2]);
                        boneParents.Add(int.Parse(args[2]));
                        PostProcessBones.Add(bone);
                        indexToBone.Add(int.Parse(args[0]), bone);
                        break;

                    case "skeleton":
                        var skel = PostProcessBones[int.Parse(args[0])];
                        skel.Transform = Matrix4.Identity;
                        skel.X         = float.Parse(args[1]);
                        skel.Y         = float.Parse(args[2]);
                        skel.Z         = float.Parse(args[3]);
                        skel.RX        = float.Parse(args[4]);
                        skel.RY        = float.Parse(args[5]);
                        skel.RZ        = float.Parse(args[6]);
                        break;

                    case "triangles":
                        string material = args[0];
                        if (!materialToMesh.ContainsKey(material))
                        {
                            var iomesh = new IOMesh();
                            iomesh.HasPositions   = true;
                            iomesh.HasNormals     = true;
                            iomesh.HasUV0         = true;
                            iomesh.HasBoneWeights = true;
                            iomesh.Name           = material;
                            materialToMesh.Add(material, iomesh);
                        }
                        var mesh = materialToMesh[material];
                        mesh.Vertices.Add(ReadVertex(Regex.Replace(lines[i + 1].Trim(), @"\s+", " ").Split(' ')));
                        mesh.Vertices.Add(ReadVertex(Regex.Replace(lines[i + 2].Trim(), @"\s+", " ").Split(' ')));
                        mesh.Vertices.Add(ReadVertex(Regex.Replace(lines[i + 3].Trim(), @"\s+", " ").Split(' ')));
                        i += 3;
                        break;
                    }
                }
            }

            //PostProcessBones
            int boneIndex = 0;

            foreach (var bone in PostProcessBones)
            {
                if (boneParents[boneIndex] == -1)
                {
                    skeleton.AddRoot(bone);
                }
                else
                {
                    bone.Parent = indexToBone[boneParents[boneIndex]];
                }
                boneIndex++;
            }

            model.Skeleton = skeleton;
            // finalize meshes
            foreach (var pair in materialToMesh)
            {
                model.Meshes.Add(pair.Value);
                pair.Value.Optimize();
                SBConsole.WriteLine($"Imported {pair.Key} from SMD");

                //finalize rigging
                for (int i = 0; i < pair.Value.Vertices.Count; i++)
                {
                    var vertex = pair.Value.Vertices[i];
                    vertex.BoneIndices.X   = model.Skeleton.IndexOfBone(indexToBone[(int)vertex.BoneIndices.X]);
                    vertex.BoneIndices.Y   = model.Skeleton.IndexOfBone(indexToBone[(int)vertex.BoneIndices.Y]);
                    vertex.BoneIndices.Z   = model.Skeleton.IndexOfBone(indexToBone[(int)vertex.BoneIndices.Z]);
                    vertex.BoneIndices.W   = model.Skeleton.IndexOfBone(indexToBone[(int)vertex.BoneIndices.W]);
                    pair.Value.Vertices[i] = vertex;
                }
            }

            return(model);
        }