Пример #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="FileName"></param>
        /// <param name="animation"></param>
        /// <param name="skeleton"></param>
        private void ExportFigaTree(string FileName, SBAnimation animation, SBSkeleton skeleton)
        {
            HSDRawFile  file = new HSDRawFile();
            HSDRootNode root = new HSDRootNode();

            if (HSDSettings.RootName == "" || HSDSettings.RootName == null)
            {
                HSDSettings.RootName = System.IO.Path.GetFileNameWithoutExtension(FileName);
            }

            if (HSDSettings.RootName == "" || HSDSettings.RootName == null)
            {
                HSDSettings.RootName = animation.Name;
            }

            root.Name = HSDSettings.RootName;

            if (root.Name == null || !root.Name.EndsWith("_figatree"))
            {
                System.Windows.Forms.MessageBox.Show($"Warning, the root name does not end with \"_figatree\"\n{root.Name}");
            }

            file.Roots.Add(root);

            var nodes = new List <FigaTreeNode>();

            int boneIndex = -1;

            foreach (var skelnode in skeleton.Bones)
            {
                FigaTreeNode animNode = new FigaTreeNode();
                nodes.Add(animNode);

                boneIndex++;
                // skip trans n and rotn tracks
                if (boneIndex == 0)
                {
                    continue;
                }

                var node = animation.TransformNodes.Find(e => e.Name == skelnode.Name);
                if (node == null)
                {
                    continue;
                }

                foreach (var track in node.Tracks)
                {
                    HSD_Track animTrack = new HSD_Track();
                    animTrack.FOBJ       = EncodeFOBJ(track);
                    animTrack.DataLength = (short)animTrack.FOBJ.Buffer.Length;
                    animNode.Tracks.Add(animTrack);
                }
            }

            HSD_FigaTree tree = new HSD_FigaTree();

            tree.FrameCount = animation.FrameCount;
            tree.Type       = 1;
            tree.Nodes      = nodes;

            root.Data = tree;
            file.Save(FileName);
        }
Пример #2
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);
        }
Пример #3
0
        public SBAnimation ImportSBAnimation(string FileName, SBSkeleton skeleton)
        {
            SBAnimation anim = new SBAnimation();

            HSDRawFile f = new HSDRawFile(FileName);

            foreach (var root in f.Roots)
            {
                if (root == null || root.Data == null)
                {
                    continue;
                }
                anim.Name = root.Name;
                if (root.Data is HSD_AnimJoint joint)
                {
                    var joints = joint.BreathFirstList;

                    int nodeIndex = -1;
                    foreach (var j in joints)
                    {
                        nodeIndex++;
                        if (j.AOBJ == null || j.AOBJ.FObjDesc == null)
                        {
                            continue;
                        }

                        SBConsole.WriteLine(nodeIndex + " " + j.Flags.ToString("X8") + " " + j.AOBJ.Flags.ToString());

                        SBTransformAnimation a = new SBTransformAnimation();
                        if (nodeIndex < skeleton.Bones.Length)
                        {
                            a.Name = skeleton.Bones[nodeIndex].Name;
                        }
                        else
                        {
                            a.Name = "JOBJ_" + nodeIndex;
                        }
                        anim.TransformNodes.Add(a);

                        anim.FrameCount = Math.Max(anim.FrameCount, j.AOBJ.EndFrame);

                        foreach (var fobj in j.AOBJ.FObjDesc.List)
                        {
                            a.Tracks.Add(DecodeFOBJ(fobj.ToFOBJ()));
                        }
                    }
                }
                if (root.Data is HSD_FigaTree tree)
                {
                    anim.FrameCount = tree.FrameCount;
                    int nodeIndex = 0;
                    foreach (var node in tree.Nodes)
                    {
                        SBTransformAnimation a = new SBTransformAnimation();
                        a.Name = skeleton.Bones[nodeIndex++].Name;
                        anim.TransformNodes.Add(a);

                        foreach (var att in node.Tracks)
                        {
                            if (att.FOBJ == null)
                            {
                                continue;
                            }

                            a.Tracks.Add(DecodeFOBJ(att.FOBJ));
                        }
                    }
                }
                if (root.Data is HSD_MatAnimJoint matjoint)
                {
                    var joints = matjoint.BreathFirstList;

                    anim.FrameCount = 0;

                    int nodeIndex = -1;
                    foreach (var j in joints)
                    {
                        if (j.MaterialAnimation == null)
                        {
                            continue;
                        }

                        var matAnims = j.MaterialAnimation.List;

                        foreach (var manim in matAnims)
                        {
                            nodeIndex++;
                            var aobj = manim.AnimationObject;
                            if (aobj != null)
                            {
                                anim.FrameCount = Math.Max(anim.FrameCount, aobj.EndFrame);
                            }

                            var texanim = manim.TextureAnimation;

                            if (texanim == null)
                            {
                                continue;
                            }
                            var texAOBJ = texanim.AnimationObject;

                            if (texAOBJ == null || texAOBJ.FObjDesc == null)
                            {
                                continue;
                            }

                            anim.FrameCount = Math.Max(anim.FrameCount, texAOBJ.EndFrame);

                            //TODO: tex anim is a list
                            if (texanim != null)
                            {
                                SBTextureAnimation textureAnim = new SBTextureAnimation();
                                anim.TextureNodes.Add(textureAnim);
                                textureAnim.MeshName        = "DOBJ_" + nodeIndex;
                                textureAnim.TextureAttibute = texanim.GXTexMapID.ToString();

                                textureAnim.Keys = DecodeFOBJ(texAOBJ.FObjDesc.ToFOBJ()).Keys;

                                for (int i = 0; i < texanim.ImageCount; i++)
                                {
                                    HSD_TOBJ tobj = new HSD_TOBJ();
                                    tobj.ImageData = texanim.ImageBuffers.Array[i].Data;
                                    if (texanim.TlutCount > i)
                                    {
                                        tobj.TlutData = texanim.TlutBuffers.Array[i].Data;
                                    }
                                    var surface = new SBSurface();
                                    surface.Arrays.Add(new MipArray()
                                    {
                                        Mipmaps = new List <byte[]>()
                                        {
                                            tobj.GetDecodedImageData()
                                        }
                                    });
                                    surface.Width          = tobj.ImageData.Width;
                                    surface.Height         = tobj.ImageData.Height;
                                    surface.PixelFormat    = PixelFormat.Bgra;
                                    surface.PixelType      = PixelType.UnsignedByte;
                                    surface.InternalFormat = InternalFormat.Rgba;
                                    textureAnim.Surfaces.Add(surface);
                                }
                            }
                        }
                    }

                    SBConsole.WriteLine(nodeIndex);
                }
            }

            return(anim);
        }
Пример #4
0
 public void ExportSBAnimation(string FileName, SBAnimation animation, SBSkeleton skeleton)
 {
     ExportIOAnimationAsANIM(FileName, animation, skeleton);
 }
Пример #5
0
        public static void ExportIOAnimationAsANIM(string fname, SBAnimation animation, SBSkeleton Skeleton)
        {
            IO_MayaANIM anim = new IO_MayaANIM();

            anim.header.endTime = animation.FrameCount + 1;
            if (!MayaSettings.UseRadians)
            {
                anim.header.angularUnit = "deg";
            }

            // get bone order
            List <SBBone> BonesInOrder = getBoneTreeOrder(Skeleton);

            if (MayaSettings.Maya2015)
            {
                BonesInOrder = BonesInOrder.OrderBy(f => f.Name, StringComparer.Ordinal).ToList();
            }

            if (MayaSettings.RemoveRedundantFrames)
            {
                animation.Optimize();
            }

            foreach (SBBone b in BonesInOrder)
            {
                AnimBone animBone = new AnimBone()
                {
                    name = b.Name
                };
                anim.Bones.Add(animBone);
                // Add Tracks
                SBTransformAnimation node = null;
                foreach (var animNode in animation.TransformNodes)
                {
                    if (animNode.Name.Equals(b.Name))
                    {
                        node = animNode;
                        break;
                    }
                }
                if (node == null)
                {
                    continue;
                }

                //TODO: bake scale for compensate scale...

                foreach (var track in node.Tracks)
                {
                    switch (track.Type)
                    {
                    case SBTrackType.TranslateX:
                        AddAnimData(animBone, track.Keys, ControlType.translate, TrackType.translateX);
                        break;

                    case SBTrackType.TranslateY:
                        AddAnimData(animBone, track.Keys, ControlType.translate, TrackType.translateY);
                        break;

                    case SBTrackType.TranslateZ:
                        AddAnimData(animBone, track.Keys, ControlType.translate, TrackType.translateZ);
                        break;

                    case SBTrackType.RotateX:
                        AddAnimData(animBone, track.Keys, ControlType.rotate, TrackType.rotateX);
                        break;

                    case SBTrackType.RotateY:
                        AddAnimData(animBone, track.Keys, ControlType.rotate, TrackType.rotateY);
                        break;

                    case SBTrackType.RotateZ:
                        AddAnimData(animBone, track.Keys, ControlType.rotate, TrackType.rotateZ);
                        break;

                    case SBTrackType.ScaleX:
                        AddAnimData(animBone, track.Keys, ControlType.scale, TrackType.scaleX);
                        break;

                    case SBTrackType.ScaleY:
                        AddAnimData(animBone, track.Keys, ControlType.scale, TrackType.scaleY);
                        break;

                    case SBTrackType.ScaleZ:
                        AddAnimData(animBone, track.Keys, ControlType.scale, TrackType.scaleZ);
                        break;
                    }
                }
            }


            anim.Save(fname);
        }
Пример #6
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);
        }
Пример #7
0
        public SBAnimation ImportSBAnimation(string FileName, SBSkeleton skeleton)
        {
            SBAnimation anim = new SBAnimation();

            using (StreamReader r = new StreamReader(new FileStream(FileName, FileMode.Open)))
            {
                if (r.ReadLine() != "#SBAnimation Version 1")
                {
                    return(anim);
                }

                while (!r.EndOfStream)
                {
                    var line = r.ReadLine();
                    var args = line.Trim().Split(' ');

                    switch (args[0])
                    {
                    case "comment":
                        break;

                    case "FrameCount":
                        anim.FrameCount = int.Parse(args[1]);
                        break;

                    case "visibility":
                        SBVisibilityAnimation visAnim = new SBVisibilityAnimation();
                        visAnim.MeshName = args[1];
                        var visLien = r.ReadLine();
                        if (visLien == "{")
                        {
                            visLien = r.ReadLine();
                            while (!r.EndOfStream && visLien != "}")
                            {
                                visLien = visLien.Replace(" ", "");
                                var frame = visLien.Substring(0, visLien.IndexOf(":")).Trim();
                                var value = visLien.Substring(visLien.IndexOf(":") + 1, visLien.Length - (visLien.IndexOf(":") + 1)).Trim();
                                visAnim.Visibility.AddKey(float.Parse(frame), bool.Parse(value));
                                visLien = r.ReadLine();
                            }
                        }
                        anim.VisibilityNodes.Add(visAnim);
                        break;

                    case "bone":
                        if (args[1].Contains(".anim"))
                        {
                            IO_MayaANIM manim = new IO_MayaANIM();
                            var         bones = manim.ImportSBAnimation(Path.GetDirectoryName(FileName) + "/" + args[1], skeleton);
                            anim.TransformNodes.AddRange(bones.TransformNodes);
                        }
                        break;

                    case "material":
                        SBMaterialAnimation matAnim = new SBMaterialAnimation();
                        matAnim.MaterialName  = args[1];
                        matAnim.AttributeName = args[2];
                        var matLien = r.ReadLine();
                        if (matLien == "{")
                        {
                            matLien = r.ReadLine();
                            while (!r.EndOfStream && matLien != "}")
                            {
                                matLien = matLien.Replace(" ", "");
                                var frame = matLien.Substring(0, matLien.IndexOf(":")).Trim();
                                var value = matLien.Substring(matLien.IndexOf(":") + 1, matLien.Length - (matLien.IndexOf(":") + 1)).Trim();

                                var vector = value.Replace(")", "").Replace("(", "").Split(',');
                                if (vector.Length != 4)
                                {
                                    continue;
                                }

                                matAnim.Keys.AddKey(float.Parse(frame), new Vector4(float.Parse(vector[0]), float.Parse(vector[1]), float.Parse(vector[2]), float.Parse(vector[3])));
                                matLien = r.ReadLine();
                            }
                        }
                        anim.MaterialNodes.Add(matAnim);
                        break;
                    }
                }
            }

            return(anim);
        }