private static void ReadTrack(BinaryReaderExt r, int frameCount, int type, FOBJ_Player track, uint dataOffset, AnimNode node)
        {
            var offset = r.ReadUInt32() + dataOffset;
            var temp   = r.Position;

            r.Seek(offset);

            int   fCount = -1;
            float scale  = 0;

            float[] frame = null, step = null, tan = null;

            if (type == 0x1)
            {
                fCount = r.ReadUInt16();
                r.Skip(2);
                scale = r.ReadSingle();
                float stepb = r.ReadSingle();
                float base2 = r.ReadSingle();

                frame = new float[fCount];
                step  = new float[fCount];
                tan   = new float[fCount];

                for (int i = 0; i < fCount; i++)
                {
                    var v = r.ReadInt32();
                    frame[i] = (v >> 24) & 0xFF;
                    int th = v & 0xFFFFFF;
                    step[i] = base2 + ((th >> 12) & 0xfff) * stepb;
                    tan[i]  = (Sign12Bit(th & 0xfff) / 32f);

                    track.Keys.Add(new FOBJKey()
                    {
                        Frame = frame[i], Value = step[i], Tan = tan[i], InterpolationType = GXInterpolationType.HSD_A_OP_SPL
                    });
                }
            }

            if (type == 0x2)
            {
                fCount = r.ReadUInt16();
                r.Skip(2);
                scale = r.ReadSingle();
                float stepb = r.ReadSingle();
                float base2 = r.ReadSingle();

                frame = new float[fCount];
                step  = new float[fCount];
                tan   = new float[fCount];

                for (int i = 0; i < fCount; i++)
                {
                    frame[i] = r.ReadUInt16() / 32f;
                    step[i]  = base2 + r.ReadUInt16() * stepb;
                    tan[i]   = (r.ReadInt16() / 256f);

                    track.Keys.Add(new FOBJKey()
                    {
                        Frame = frame[i], Value = step[i], Tan = tan[i], InterpolationType = GXInterpolationType.HSD_A_OP_SPL
                    });
                }
            }

            if (type == 0x3)
            {
                fCount = r.ReadUInt16();
                r.Skip(2);
                scale = r.ReadSingle();

                frame = new float[fCount];
                step  = new float[fCount];
                tan   = new float[fCount];

                for (int i = 0; i < fCount; i++)
                {
                    frame[i] = r.ReadSingle();
                    step[i]  = r.ReadSingle();
                    tan[i]   = r.ReadSingle();

                    track.Keys.Add(new FOBJKey()
                    {
                        Frame = frame[i], Value = step[i], Tan = tan[i], InterpolationType = GXInterpolationType.HSD_A_OP_SPL
                    });
                }
            }

            if (type == 0x4)
            {
                float stepb = r.ReadSingle();
                float base2 = r.ReadSingle();
                for (int i = 0; i < frameCount; i++)
                {
                    float v = base2 + stepb * (r.ReadByte());

                    track.Keys.Add(new FOBJKey()
                    {
                        Frame = i, Value = v, InterpolationType = GXInterpolationType.HSD_A_OP_LIN
                    });
                }
            }

            if (type == 0x6)
            {
                for (int i = 0; i < frameCount; i++)
                {
                    float v = r.ReadSingle();

                    track.Keys.Add(new FOBJKey()
                    {
                        Frame = i, Value = v, InterpolationType = GXInterpolationType.HSD_A_OP_LIN
                    });
                }
            }

            r.Seek(temp);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static JointAnimManager LoadCHR0(string filePath, JointMap jointMap)
        {
            JointAnimManager anim = new JointAnimManager();

            for (int i = 0; i < jointMap.Count; i++)
            {
                anim.Nodes.Add(new AnimNode());
            }

            using (BinaryReaderExt r = new BinaryReaderExt(new FileStream(filePath, FileMode.Open)))
            {
                r.BigEndian = true;
                if (r.BaseStream.Length < 4 || new string(r.ReadChars(4)) != "CHR0")
                {
                    throw new InvalidDataException("CHR0 file is not valid");
                }

                r.Skip(4);

                int versionNum = r.ReadInt32();

                if (versionNum != 4)
                {
                    throw new InvalidDataException($"CHR0 version {versionNum} not supported");
                }

                r.Seek(0x10);

                var indexGroupOffset = r.ReadUInt32();
                var animName         = r.ReadString(r.ReadInt32(), -1);

                r.Skip(4);
                anim.FrameCount = r.ReadUInt16() - 1;
                int animDataCount = r.ReadUInt16();
                r.Skip(8);

                r.Seek(indexGroupOffset);
                var sectionOffset = r.ReadUInt32() + indexGroupOffset;
                int sectionCount  = r.ReadInt32();

                for (uint i = 0; i < sectionCount; i++)
                {
                    r.Seek(indexGroupOffset + 8 + 16 * i);
                    r.Skip(4); // id and unknown
                    r.Skip(2); // let
                    r.Skip(2); // right
                    var boneName   = r.ReadString(r.ReadInt32() + (int)indexGroupOffset, -1);
                    var dataOffset = r.ReadUInt32() + indexGroupOffset;
                    if (dataOffset == indexGroupOffset)
                    {
                        sectionCount += 1;
                        continue;
                    }

                    if (jointMap.IndexOf(boneName) == -1)
                    {
                        continue;
                    }

                    r.Seek(dataOffset);

                    var nameOff = r.Position + r.ReadUInt32();
                    var flags   = r.ReadInt32();
                    //Console.WriteLine(boneName + " " + flags.ToString("X"));
                    //r.PrintPosition();
                    //01BFE019
                    int t_type = (flags >> 0x1e) & 0x3;
                    int r_type = (flags >> 0x1b) & 0x7;
                    int s_type = (flags >> 0x19) & 0x3;

                    int hasT = (flags >> 0x18) & 0x1;
                    int hasR = (flags >> 0x17) & 0x1;
                    int hasS = (flags >> 0x16) & 0x1;

                    int Zfixed = (flags >> 0x15) & 0x1;
                    int Yfixed = (flags >> 0x14) & 0x1;
                    int Xfixed = (flags >> 0x13) & 0x1;

                    int RZfixed = (flags >> 0x12) & 0x1;
                    int RYfixed = (flags >> 0x11) & 0x1;
                    int RXfixed = (flags >> 0x10) & 0x1;

                    int SZfixed = (flags >> 0xf) & 0x1;
                    int SYfixed = (flags >> 0xe) & 0x1;
                    int SXfixed = (flags >> 0xd) & 0x1;

                    int Tiso = (flags >> 0x6) & 0x1;
                    int Riso = (flags >> 0x5) & 0x1;
                    int Siso = (flags >> 0x4) & 0x1;

                    AnimNode    node   = new AnimNode();
                    FOBJ_Player trackX = new FOBJ_Player()
                    {
                        JointTrackType = JointTrackType.HSD_A_J_TRAX
                    };
                    FOBJ_Player trackY = new FOBJ_Player()
                    {
                        JointTrackType = JointTrackType.HSD_A_J_TRAY
                    };
                    FOBJ_Player trackZ = new FOBJ_Player()
                    {
                        JointTrackType = JointTrackType.HSD_A_J_TRAZ
                    };
                    FOBJ_Player trackRX = new FOBJ_Player()
                    {
                        JointTrackType = JointTrackType.HSD_A_J_ROTX
                    };
                    FOBJ_Player trackRY = new FOBJ_Player()
                    {
                        JointTrackType = JointTrackType.HSD_A_J_ROTY
                    };
                    FOBJ_Player trackRZ = new FOBJ_Player()
                    {
                        JointTrackType = JointTrackType.HSD_A_J_ROTZ
                    };
                    FOBJ_Player trackSX = new FOBJ_Player()
                    {
                        JointTrackType = JointTrackType.HSD_A_J_SCAX
                    };
                    FOBJ_Player trackSY = new FOBJ_Player()
                    {
                        JointTrackType = JointTrackType.HSD_A_J_SCAY
                    };
                    FOBJ_Player trackSZ = new FOBJ_Player()
                    {
                        JointTrackType = JointTrackType.HSD_A_J_SCAZ
                    };

                    if (hasS == 1)
                    {
                        ReadKeys(r, node, (int)anim.FrameCount, trackSX, trackSY, trackSZ, Siso == 1, SXfixed == 1, SYfixed == 1, SZfixed == 1, s_type, dataOffset);
                    }

                    if (hasR == 1)
                    {
                        ReadKeys(r, node, (int)anim.FrameCount, trackRX, trackRY, trackRZ, Riso == 1, RXfixed == 1, RYfixed == 1, RZfixed == 1, r_type, dataOffset);
                    }

                    if (hasT == 1)
                    {
                        ReadKeys(r, node, (int)anim.FrameCount, trackX, trackY, trackZ, Tiso == 1, Xfixed == 1, Yfixed == 1, Zfixed == 1, t_type, dataOffset);
                    }

                    if (trackX.Keys.Count > 0)
                    {
                        node.Tracks.Add(trackX);
                    }
                    if (trackY.Keys.Count > 0)
                    {
                        node.Tracks.Add(trackY);
                    }
                    if (trackZ.Keys.Count > 0)
                    {
                        node.Tracks.Add(trackZ);
                    }
                    if (trackRX.Keys.Count > 0)
                    {
                        node.Tracks.Add(trackRX);
                    }
                    if (trackRY.Keys.Count > 0)
                    {
                        node.Tracks.Add(trackRY);
                    }
                    if (trackRZ.Keys.Count > 0)
                    {
                        node.Tracks.Add(trackRZ);
                    }
                    if (trackSX.Keys.Count > 0)
                    {
                        node.Tracks.Add(trackSX);
                    }
                    if (trackSY.Keys.Count > 0)
                    {
                        node.Tracks.Add(trackSY);
                    }
                    if (trackSZ.Keys.Count > 0)
                    {
                        node.Tracks.Add(trackSZ);
                    }

                    foreach (var k in trackRX.Keys)
                    {
                        k.Value = MathHelper.DegreesToRadians(k.Value);
                        k.Tan   = MathHelper.DegreesToRadians(k.Tan);
                    }
                    foreach (var k in trackRY.Keys)
                    {
                        k.Value = MathHelper.DegreesToRadians(k.Value);
                        k.Tan   = MathHelper.DegreesToRadians(k.Tan);
                    }
                    foreach (var k in trackRZ.Keys)
                    {
                        k.Value = MathHelper.DegreesToRadians(k.Value);
                        k.Tan   = MathHelper.DegreesToRadians(k.Tan);
                    }

                    //Console.WriteLine(boneName + " Tracks:" + node.Tracks.Count + " " + flags.ToString("X"));
                    //Console.WriteLine($"{trackX.Keys.Count} {trackY.Keys.Count} {trackZ.Keys.Count}");
                    //Console.WriteLine($"{trackRX.Keys.Count} {trackRY.Keys.Count} {trackRZ.Keys.Count}");
                    //Console.WriteLine($"{trackSX.Keys.Count} {trackSY.Keys.Count} {trackSZ.Keys.Count}");
                    anim.Nodes[jointMap.IndexOf(boneName)] = node;
                }
            }

            return(anim);
        }
        private static void ReadKeys(BinaryReaderExt r, AnimNode node, int frameCount, FOBJ_Player xtrack, FOBJ_Player ytrack, FOBJ_Player ztrack, bool isIsotrophic, bool isXFixed, bool isYFixed, bool isZFixed, int type, uint dataOffset)
        {
            if (isIsotrophic)
            {
                var temp = r.Position + 4;
                if (!isXFixed && !isYFixed && !isZFixed)
                {
                    var offset = r.ReadUInt32() + r.Position;
                    r.Seek(offset);
                }
                float iss = r.ReadSingle();
                xtrack.Keys.Add(new FOBJKey()
                {
                    Frame = 0, Value = iss, InterpolationType = GXInterpolationType.HSD_A_OP_KEY
                });
                ytrack.Keys.Add(new FOBJKey()
                {
                    Frame = 0, Value = iss, InterpolationType = GXInterpolationType.HSD_A_OP_KEY
                });
                ztrack.Keys.Add(new FOBJKey()
                {
                    Frame = 0, Value = iss, InterpolationType = GXInterpolationType.HSD_A_OP_KEY
                });
                r.Seek(temp);
            }
            else
            {
                if (isXFixed)
                {
                    xtrack.Keys.Add(new FOBJKey()
                    {
                        Frame = 0, Value = r.ReadSingle(), InterpolationType = GXInterpolationType.HSD_A_OP_KEY
                    });
                }
                else
                {
                    ReadTrack(r, frameCount, type, xtrack, dataOffset, node);
                }

                if (isYFixed)
                {
                    ytrack.Keys.Add(new FOBJKey()
                    {
                        Frame = 0, Value = r.ReadSingle(), InterpolationType = GXInterpolationType.HSD_A_OP_KEY
                    });
                }
                else
                {
                    ReadTrack(r, frameCount, type, ytrack, dataOffset, node);
                }

                if (isZFixed)
                {
                    ztrack.Keys.Add(new FOBJKey()
                    {
                        Frame = 0, Value = r.ReadSingle(), InterpolationType = GXInterpolationType.HSD_A_OP_KEY
                    });
                }
                else
                {
                    ReadTrack(r, frameCount, type, ztrack, dataOffset, node);
                }
            }
        }
Exemple #4
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public bool DoIt(string[] args)
        {
            if (args.Length >= 6)
            {
                // parse args
                var targetAnimFile = Path.GetFullPath(args[1]);
                var destAnimFile   = Path.GetFullPath(args[2]);
                var newSymbol      = args[3];
                var boneIniTarget  = Path.GetFullPath(args[4]);
                var boneInitDest   = Path.GetFullPath(args[5]);

                // load bone inis
                var target = new BoneMap(boneIniTarget);
                var dest   = new BoneMap(boneInitDest);

                SkeletonPorter  port      = null;
                List <HSD_JOBJ> jobjsFrom = null;
                List <HSD_JOBJ> jobjsTo   = null;

                if (args.Length >= 8)
                {
                    jobjsFrom = (new HSDRawFile(args[6]).Roots[0].Data as HSD_JOBJ).BreathFirstList;
                    jobjsTo   = (new HSDRawFile(args[7]).Roots[0].Data as HSD_JOBJ).BreathFirstList;
                    port      = new SkeletonPorter(
                        new HSDRawFile(args[6]).Roots[0].Data as HSD_JOBJ,
                        new HSDRawFile(args[7]).Roots[0].Data as HSD_JOBJ,
                        target,
                        dest);
                }

                // retarget animation
                HSDRawFile inputAnim  = new HSDRawFile(targetAnimFile);
                var        targetTree = inputAnim.Roots[0].Data as HSD_FigaTree;

                List <FigaTreeNode> newNodes = new List <FigaTreeNode>();
                for (int i = 0; i < dest.Count; i++)
                {
                    newNodes.Add(new FigaTreeNode());
                }

                int nodeIndex = 0;
                foreach (var n in targetTree.Nodes)
                {
                    string boneName = "";

                    boneName = target.GetName(nodeIndex);
                    var ind = dest.GetIndex(boneName);

                    if (ind != -1)
                    {
                        //System.Diagnostics.Debug.WriteLine($"{boneName} {nodeIndex} {ind}");

                        if (port != null && port.HasBone(boneName))
                        {
                            var jobj = jobjsFrom[nodeIndex];

                            FOBJ_Player rx = new FOBJ_Player(); rx.Keys.Add(new FOBJKey()
                            {
                                Value = jobj.RX, InterpolationType = GXInterpolationType.HSD_A_OP_CON
                            });
                            FOBJ_Player ry = new FOBJ_Player(); ry.Keys.Add(new FOBJKey()
                            {
                                Value = jobj.RY, InterpolationType = GXInterpolationType.HSD_A_OP_CON
                            });
                            FOBJ_Player rz = new FOBJ_Player(); rz.Keys.Add(new FOBJKey()
                            {
                                Value = jobj.RZ, InterpolationType = GXInterpolationType.HSD_A_OP_CON
                            });

                            HSD_Track rotXTrack = new HSD_Track();
                            HSD_Track rotYTrack = new HSD_Track();
                            HSD_Track rotZTrack = new HSD_Track();

                            foreach (var track in n.Tracks)
                            {
                                var fobj = track.ToFOBJ();
                                var keys = fobj.GetDecodedKeys();
                                switch (fobj.JointTrackType)
                                {
                                case JointTrackType.HSD_A_J_ROTX:
                                    rx.Keys = keys;
                                    break;

                                case JointTrackType.HSD_A_J_ROTY:
                                    ry.Keys = keys;
                                    break;

                                case JointTrackType.HSD_A_J_ROTZ:
                                    rz.Keys = keys;
                                    break;

                                default:
                                    //newNodes[ind].Tracks.Add(track);
                                    break;
                                }
                            }

                            rotXTrack.FromFOBJ(OrientTrack(boneName, port, rx.Keys, JointTrackType.HSD_A_J_ROTX, jobj, jobjsTo[nodeIndex]));
                            rotYTrack.FromFOBJ(OrientTrack(boneName, port, ry.Keys, JointTrackType.HSD_A_J_ROTY, jobj, jobjsTo[nodeIndex]));
                            rotZTrack.FromFOBJ(OrientTrack(boneName, port, rz.Keys, JointTrackType.HSD_A_J_ROTZ, jobj, jobjsTo[nodeIndex]));

                            newNodes[ind].Tracks.Add(rotXTrack);
                            newNodes[ind].Tracks.Add(rotYTrack);
                            newNodes[ind].Tracks.Add(rotZTrack);

                            foreach (var track in newNodes[ind].Tracks)
                            {
                                //System.Diagnostics.Debug.WriteLine(track.FOBJ.JointTrackType + " " + track.FOBJ.GetDecodedKeys().Count);
                            }
                        }
                        else
                        if (ind < newNodes.Count && ind >= 0)
                        {
                            newNodes[ind] = n;
                        }
                    }

                    nodeIndex++;
                }

                // save new file
                HSD_FigaTree figatree = new HSD_FigaTree();
                figatree.FrameCount = targetTree.FrameCount;
                figatree.Type       = targetTree.Type;
                figatree.Nodes      = newNodes;
                System.Console.WriteLine(destAnimFile);
                HSDRawFile file = new HSDRawFile();
                file.Roots.Add(new HSDRootNode()
                {
                    Name = newSymbol, Data = figatree
                });
                file.Save(destAnimFile);

                return(true);
            }

            return(false);
        }