Ejemplo n.º 1
0
        /// <summary>
        /// Reads the data from a compressed track
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        private object[] ReadCompressed(SSBHParser reader, uint flags)
        {
            List <object> output = new List <object>();

            uint dataOffset = (uint)reader.BaseStream.Position;
            SSBHAnimCompressedHeader header = reader.ByteToType <SSBHAnimCompressedHeader>();

            if (CheckFlag(flags, 0x00FF, ANIM_TRACKFLAGS.Boolean))
            {
                ReadBooleans(reader, output, dataOffset, header);
            }
            if (CheckFlag(flags, 0x00FF, ANIM_TRACKFLAGS.Texture))
            {
                // TODO: What type is this
            }
            if (CheckFlag(flags, 0x00FF, ANIM_TRACKFLAGS.Float))
            {
                //TODO: What type is this
            }
            if (CheckFlag(flags, 0x00FF, ANIM_TRACKFLAGS.PatternIndex))
            {
                //TODO: What type is this
            }
            if (CheckFlag(flags, 0x00FF, ANIM_TRACKFLAGS.Vector4))
            {
                ReadVector4(reader, output, dataOffset, header);
            }
            if (CheckFlag(flags, 0x00FF, ANIM_TRACKFLAGS.Transform))
            {
                ReadTransform(reader, output, dataOffset, header);
            }

            return(output.ToArray());
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Reads the data out of the given track.
        /// </summary>
        /// <param name="track"></param>
        /// <returns></returns>
        public object[] ReadTrack(AnimTrack track)
        {
            //Console.WriteLine(Track.Name + " " + Track.Flags.ToString("X") + " " + Track.FrameCount + " " + Track.DataOffset.ToString("X"));
            List <object> output = new List <object>();

            using (SSBHParser parser = new SSBHParser(new MemoryStream(animFile.Buffer)))
            {
                parser.Seek(track.DataOffset);

                if (CheckFlag(track.Flags, 0xFF00, ANIM_TRACKFLAGS.Constant))
                {
                    output.Add(ReadDirect(parser, track.Flags));
                }
                if (CheckFlag(track.Flags, 0xFF00, ANIM_TRACKFLAGS.ConstTransform))
                {
                    // TODO: investigate more
                    output.Add(ReadDirect(parser, track.Flags));
                }
                if (CheckFlag(track.Flags, 0xFF00, ANIM_TRACKFLAGS.Direct))
                {
                    for (int i = 0; i < track.FrameCount; i++)
                    {
                        output.Add(ReadDirect(parser, track.Flags));
                    }
                }
                if (CheckFlag(track.Flags, 0xFF00, ANIM_TRACKFLAGS.Compressed))
                {
                    output.AddRange(ReadCompressed(parser, track.Flags));
                }
            }

            return(output.ToArray());
        }
Ejemplo n.º 3
0
 public static bool TryParseSSBHFile(byte[] FileData, out ISSBH_File HBSSFile)
 {
     HBSSFile = null;
     using (SSBHParser R = new SSBHParser(new MemoryStream(FileData)))
     {
         return(R.TryParse(out HBSSFile));
     }
 }
Ejemplo n.º 4
0
 /// <summary>
 /// Trys to parse an SSBH file from a byte array
 /// </summary>
 /// <param name="fileData"></param>
 /// <param name="hbssFile"></param>
 /// <returns>true if parsing was successful</returns>
 public static bool TryParseSSBHFile(byte[] fileData, out ISSBH_File hbssFile)
 {
     hbssFile = null;
     using (var parser = new SSBHParser(new MemoryStream(fileData)))
     {
         return(parser.TryParse(out hbssFile));
     }
 }
Ejemplo n.º 5
0
        private void ReadVector4(SSBHParser reader, List <object> output, uint dataOffset, SSBHAnimCompressedHeader header)
        {
            var decompressed = DecompressValues(reader, dataOffset, header, 4);

            foreach (var decom in decompressed)
            {
                output.Add(new AnimTrackCustomVector4(decom[0], decom[1], decom[2], decom[3]));
            }
        }
Ejemplo n.º 6
0
        private void ReadTransform(SSBHParser reader, List <object> output, uint dataOffset, SSBHAnimCompressedHeader header)
        {
            var decompressed = DecompressTransform(reader, dataOffset, header);

            foreach (var v in decompressed)
            {
                output.Add(v);
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Reads direct information from track
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="flags"></param>
        /// <returns></returns>
        private object ReadDirect(SSBHParser reader, uint flags)
        {
            if (CheckFlag(flags, 0x00FF, ANIM_TRACKFLAGS.Transform))
            {
                var Transform = new AnimTrackTransform()
                {
                    SX = reader.ReadSingle(),
                    SY = reader.ReadSingle(),
                    SZ = reader.ReadSingle(),
                    RX = reader.ReadSingle(),
                    RY = reader.ReadSingle(),
                    RZ = reader.ReadSingle(),
                    RW = reader.ReadSingle(),
                    X  = reader.ReadSingle(),
                    Y  = reader.ReadSingle(),
                    Z  = reader.ReadSingle(),
                    CompensateScale = reader.ReadInt32()
                };

                return(Transform);
            }

            if (CheckFlag(flags, 0x00FF, ANIM_TRACKFLAGS.Texture))
            {
                return(new AnimTrackTexture()
                {
                    UnkFloat1 = reader.ReadSingle(),
                    UnkFloat2 = reader.ReadSingle(),
                    UnkFloat3 = reader.ReadSingle(),
                    UnkFloat4 = reader.ReadSingle(),
                    Unknown = reader.ReadInt32()
                });
            }

            if (CheckFlag(flags, 0x00FF, ANIM_TRACKFLAGS.Float))
            {
                return(reader.ReadSingle());
            }

            if (CheckFlag(flags, 0x00FF, ANIM_TRACKFLAGS.PatternIndex))
            {
                return(reader.ReadInt32());
            }

            if (CheckFlag(flags, 0x00FF, ANIM_TRACKFLAGS.Boolean))
            {
                return(reader.ReadByte() == 1);
            }

            if (CheckFlag(flags, 0x00FF, ANIM_TRACKFLAGS.Vector4))
            {
                return(new AnimTrackCustomVector4(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()));
            }

            return(null);
        }
Ejemplo n.º 8
0
        private static float[] GetDefaultValues(SSBHParser parser, int valueCount)
        {
            float[] defaultValues = new float[valueCount];
            for (int i = 0; i < valueCount; i++)
            {
                defaultValues[i] = parser.ReadSingle();
            }

            return(defaultValues);
        }
Ejemplo n.º 9
0
        private static void ReadBooleans(SSBHParser reader, List <object> output, uint dataOffset, SSBHAnimCompressedHeader header)
        {
            reader.Seek((int)dataOffset + header.CompressedDataOffset);
            // note: there is a section for "default" and "compressed items" but they seem to always be 0-ed out

            for (int i = 0; i < header.FrameCount; i++)
            {
                output.Add(reader.ReadBits(header.BitsPerEntry) == 1);
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Decompresses values in a track
        /// </summary>
        /// <param name="parser"></param>
        /// <param name="dataOffset"></param>
        /// <param name="header"></param>
        /// <param name="valueCount"></param>
        /// <returns></returns>
        private List <float[]> DecompressValues(SSBHParser parser, uint dataOffset, SSBHAnimCompressedHeader header, int valueCount)
        {
            List <float[]> transforms = new List <float[]>(header.FrameCount);

            // PreProcess
            SSBHAnimCompressedItem[] items = parser.ByteToType <SSBHAnimCompressedItem>(valueCount);

            parser.Seek(dataOffset + header.DefaultDataOffset);

            float[] defaultValues = GetDefaultValues(parser, valueCount);

            parser.Seek(dataOffset + header.CompressedDataOffset);
            for (int frameIndex = 0; frameIndex < header.FrameCount; frameIndex++)
            {
                // Copy default values.
                float[] values = new float[valueCount];
                for (int i = 0; i < valueCount; i++)
                {
                    values[i] = defaultValues[i];
                }

                for (int itemIndex = 0; itemIndex < items.Length; itemIndex++)
                {
                    var item = items[itemIndex];

                    // Decompress
                    int valueBitCount = (int)item.Count;
                    if (valueBitCount == 0)
                    {
                        continue;
                    }

                    int value = parser.ReadBits(valueBitCount);
                    int scale = 0;
                    for (int k = 0; k < valueBitCount; k++)
                    {
                        scale |= 0x1 << k;
                    }

                    float frameValue = Lerp(item.Start, item.End, 0, 1, value / (float)scale);
                    if (float.IsNaN(frameValue))
                    {
                        frameValue = 0;
                    }

                    values[itemIndex] = frameValue;
                }

                transforms.Add(values);
            }

            return(transforms);
        }
Ejemplo n.º 11
0
        public override void PostProcess(SSBHParser R)
        {
            R.Seek(OffsetToData);

            if (DataType == MatlEnums.ParamDataType.Float)
            {
                DataObject = R.ReadSingle();
            }
            else if (DataType == MatlEnums.ParamDataType.Boolean)
            {
                DataObject = R.ReadUInt32() == 1;
            }
            else if (DataType == MatlEnums.ParamDataType.Vector4)
            {
                DataObject = R.Parse <MatlVector4>();
            }
            else if (DataType == MatlEnums.ParamDataType.String)
            {
                DataObject = R.Parse <MtalString>();
            }
            else if (DataType == MatlEnums.ParamDataType.Sampler)
            {
                DataObject = R.Parse <MtalSampler>();
            }
            else if (DataType == MatlEnums.ParamDataType.UvTransform)
            {
                DataObject = R.Parse <MTAL_UVTransform>();
            }
            else if (DataType == MatlEnums.ParamDataType.BlendState)
            {
                DataObject = R.Parse <MatlBlendState>();
            }
            else if (DataType == MatlEnums.ParamDataType.RasterizerState)
            {
                DataObject = R.Parse <MatlRasterizerState>();
            }
        }
Ejemplo n.º 12
0
 public virtual void PostProcess(SSBHParser Parser)
 {
 }
Ejemplo n.º 13
0
        /// <summary>
        /// decompresses transform values from a track
        /// </summary>
        /// <param name="parser"></param>
        /// <param name="dataOffset"></param>
        /// <param name="header"></param>
        /// <returns></returns>
        private AnimTrackTransform[] DecompressTransform(SSBHParser parser, uint dataOffset, SSBHAnimCompressedHeader header)
        {
            AnimTrackTransform[] transforms = new AnimTrackTransform[header.FrameCount];

            // PreProcess
            SSBHAnimCompressedItem[] items = parser.ByteToType <SSBHAnimCompressedItem>(9);

            parser.Seek(dataOffset + header.DefaultDataOffset);

            float XSCA = parser.ReadSingle();
            float YSCA = parser.ReadSingle();
            float ZSCA = parser.ReadSingle();
            float XROT = parser.ReadSingle();
            float YROT = parser.ReadSingle();
            float ZROT = parser.ReadSingle();
            float WROT = parser.ReadSingle();
            float XPOS = parser.ReadSingle();
            float YPOS = parser.ReadSingle();
            float ZPOS = parser.ReadSingle();
            float CSCA = parser.ReadSingle();

            parser.Seek(dataOffset + header.CompressedDataOffset);
            for (int frame = 0; frame < header.FrameCount; frame++)
            {
                AnimTrackTransform transform = new AnimTrackTransform()
                {
                    X  = XPOS,
                    Y  = YPOS,
                    Z  = ZPOS,
                    RX = XROT,
                    RY = YROT,
                    RZ = ZROT,
                    RW = WROT,
                    SX = XSCA,
                    SY = YSCA,
                    SZ = ZSCA,
                    CompensateScale = CSCA
                };
                for (int itemIndex = 0; itemIndex < items.Length; itemIndex++)
                {
                    // First check if this track should be parsed
                    // TODO: Don't hard code these flags.
                    if (!((itemIndex == 0 && (header.Flags & 0x3) == 0x3) || //isotropic scale
                          (itemIndex >= 0 && itemIndex <= 2 && (header.Flags & 0x3) == 0x1) ||       //normal scale
                          (itemIndex > 2 && itemIndex <= 5 && (header.Flags & 0x4) > 0) ||
                          (itemIndex > 5 && itemIndex <= 8 && (header.Flags & 0x8) > 0)))
                    {
                        continue;
                    }

                    var item = items[itemIndex];

                    // Decompress
                    int valueBitCount = (int)item.Count;
                    if (valueBitCount == 0)
                    {
                        continue;
                    }

                    int value = parser.ReadBits(valueBitCount);
                    int scale = 0;
                    for (int k = 0; k < valueBitCount; k++)
                    {
                        scale |= 0x1 << k;
                    }

                    float frameValue = Lerp(item.Start, item.End, 0, 1, value / (float)scale);
                    if (float.IsNaN(frameValue))
                    {
                        frameValue = 0;
                    }

                    // the Transform type relies a lot on flags

                    if ((header.Flags & 0x3) == 0x3)
                    {
                        //Scale Compensate
                        if (itemIndex == 0)
                        {
                            transform.CompensateScale = frameValue;
                        }
                    }
                    if ((header.Flags & 0x3) == 0x1)
                    {
                        //Scale normal
                        switch (itemIndex)
                        {
                        case 0:
                            transform.SX = frameValue;
                            break;

                        case 1:
                            transform.SY = frameValue;
                            break;

                        case 2:
                            transform.SZ = frameValue;
                            break;
                        }
                    }
                    //Rotation and Position
                    switch (itemIndex)
                    {
                    case 3:
                        transform.RX = frameValue;
                        break;

                    case 4:
                        transform.RY = frameValue;
                        break;

                    case 5:
                        transform.RZ = frameValue;
                        break;

                    case 6:
                        transform.X = frameValue;
                        break;

                    case 7:
                        transform.Y = frameValue;
                        break;

                    case 8:
                        transform.Z = frameValue;
                        break;
                    }
                }

                // Rotations have an extra bit at the end
                if ((header.Flags & 0x4) > 0)
                {
                    bool wFlip = parser.ReadBits(1) == 1;

                    // W is calculated
                    transform.RW = (float)Math.Sqrt(Math.Abs(1 - (transform.RX * transform.RX + transform.RY * transform.RY + transform.RZ * transform.RZ)));

                    if (wFlip)
                    {
                        transform.RW = -transform.RW;
                    }
                }

                transforms[frame] = transform;
            }

            return(transforms);
        }
Ejemplo n.º 14
0
        public object[] ReadTrack(AnimTrack Track)
        {
            Console.WriteLine(Track.Name + " " + Track.Flags.ToString() + " " + Track.FrameCount + " " + Track.DataOffset.ToString("X"));
            List <object> output = new List <object>();

            using (SSBHParser parser = new SSBHParser(new MemoryStream(AnimFile.Buffer)))
            {
                parser.Seek(Track.DataOffset);

                if (CheckFlag(Track.Flags, 0x00FF, ANIM_TRACKFLAGS.Boolean))
                {
                    if (CheckFlag(Track.Flags, 0xFF00, ANIM_TRACKFLAGS.Animated))
                    {
                        int Unk_4      = parser.ReadInt16();
                        int TrackFlag  = parser.ReadInt16();
                        int Unk1       = parser.ReadInt16();
                        int Unk2       = parser.ReadInt16();
                        int DataStart  = parser.ReadInt32();
                        int FrameCount = parser.ReadInt32();

                        parser.Seek((int)Track.DataOffset + DataStart);
                        for (int i = 0; i < FrameCount; i++)
                        {
                            output.Add(new AnimTrackBool(parser.ReadBits(1) == 1));
                        }
                    }
                    else
                    if (CheckFlag(Track.Flags, 0xFF00, ANIM_TRACKFLAGS.Constant))
                    {
                        output.Add(new AnimTrackBool(parser.ReadBits(1) == 1));
                    }
                }
                if (CheckFlag(Track.Flags, 0x00FF, ANIM_TRACKFLAGS.Vector4))
                {
                    if (CheckFlag(Track.Flags, 0xFF00, ANIM_TRACKFLAGS.Animated))
                    {
                        int Unk_4      = parser.ReadInt16();
                        int TrackFlag  = parser.ReadInt16();
                        int Unk1       = parser.ReadInt16();
                        int Unk2       = parser.ReadInt16();
                        int DataStart  = parser.ReadInt32();
                        int FrameCount = parser.ReadInt32();

                        int[]   ByteCounts = new int[9];
                        int[]   BitCounts  = new int[9];
                        float[] Start      = new float[9];
                        float[] End        = new float[9];
                        for (int i = 0; i < 4; i++)
                        {
                            Start[i] = parser.ReadSingle();
                            End[i]   = parser.ReadSingle();
                            long Count = parser.ReadInt64();
                            long bytes = (Count >> 3);
                            int  bits  = ((int)Count & 0x7);

                            if ((i >= 0 && i <= 0 && (TrackFlag & 0x3) == 0x3) || //isotrophic scale
                                (i >= 0 && i <= 2 && (TrackFlag & 0x3) == 0x1) || //normal scale
                                (i > 2 && i <= 5 && (TrackFlag & 0x4) > 0) ||
                                (i > 5 && i <= 8 && (TrackFlag & 0x8) > 0))
                            {
                                //reads
                                {
                                    BitCounts[i]  = bits;
                                    ByteCounts[i] = (int)bytes;
                                }
                            }
                        }

                        float X = parser.ReadSingle();
                        float Y = parser.ReadSingle();
                        float Z = parser.ReadSingle();
                        float W = parser.ReadSingle();

                        parser.Seek((int)Track.DataOffset + DataStart);
                        for (int i = 0; i < FrameCount; i++)
                        {
                            AnimTrackCustomVector4 Vector = new AnimTrackCustomVector4();
                            for (int j = 0; j < 4; j++)
                            {
                                int ValueBitCount = ByteCounts[j] * 8 + BitCounts[j];
                                int Value         = parser.ReadBits(ValueBitCount);
                                int scale         = 0;
                                for (int k = 0; k < ValueBitCount; k++)
                                {
                                    scale |= 0x1 << k;
                                }

                                float FrameValue = Lerp(Start[j], End[j], 0, 1, Value / (float)scale);
                                if (float.IsNaN(FrameValue))
                                {
                                    FrameValue = 0;
                                }

                                switch (j)
                                {
                                case 0: if (ValueBitCount > 0)
                                    {
                                        Vector.X = FrameValue;
                                    }
                                    else
                                    {
                                        Vector.X = X;
                                    } break;

                                case 1: if (ValueBitCount > 0)
                                    {
                                        Vector.Y = FrameValue;
                                    }
                                    else
                                    {
                                        Vector.Y = Y;
                                    } break;

                                case 2: if (ValueBitCount > 0)
                                    {
                                        Vector.Z = FrameValue;
                                    }
                                    else
                                    {
                                        Vector.Z = Z;
                                    } break;

                                case 3: if (ValueBitCount > 0)
                                    {
                                        Vector.W = FrameValue;
                                    }
                                    else
                                    {
                                        Vector.W = W;
                                    } break;
                                }
                            }

                            output.Add(Vector);
                        }
                    }
                    else
                    if (CheckFlag(Track.Flags, 0xFF00, ANIM_TRACKFLAGS.Constant))
                    {
                        output.Add(new AnimTrackCustomVector4()
                        {
                            X = parser.ReadSingle(),
                            Y = parser.ReadSingle(),
                            Z = parser.ReadSingle(),
                            W = parser.ReadSingle()
                        });
                    }
                }
                if (CheckFlag(Track.Flags, 0x00FF, ANIM_TRACKFLAGS.Transform))
                {
                    if (CheckFlag(Track.Flags, 0xFF00, ANIM_TRACKFLAGS.Animated))
                    {
                        int Unk_4      = parser.ReadInt16();
                        int TrackFlag  = parser.ReadInt16();
                        int Unk1       = parser.ReadInt16();
                        int Unk2       = parser.ReadInt16();
                        int DataStart  = parser.ReadInt32();
                        int FrameCount = parser.ReadInt32();

                        int[]   ByteCounts = new int[9];
                        int[]   BitCounts  = new int[9];
                        float[] Start      = new float[9];
                        float[] End        = new float[9];
                        for (int i = 0; i < 9; i++)
                        {
                            Start[i] = parser.ReadSingle();
                            End[i]   = parser.ReadSingle();
                            long Count = parser.ReadInt64();
                            long bytes = (Count >> 3);
                            int  bits  = ((int)Count & 0x7);

                            if ((i >= 0 && i <= 0 && (TrackFlag & 0x3) == 0x3) || //isotrophic scale
                                (i >= 0 && i <= 2 && (TrackFlag & 0x3) == 0x1) || //normal scale
                                (i > 2 && i <= 5 && (TrackFlag & 0x4) > 0) ||
                                (i > 5 && i <= 8 && (TrackFlag & 0x8) > 0))
                            {
                                //reads
                                {
                                    BitCounts[i]  = bits;
                                    ByteCounts[i] = (int)bytes;
                                }
                            }
                        }

                        float XSCA = parser.ReadSingle();
                        float YSCA = parser.ReadSingle();
                        float ZSCA = parser.ReadSingle();
                        float XROT = parser.ReadSingle();
                        float YROT = parser.ReadSingle();
                        float ZROT = parser.ReadSingle();
                        float WROT = parser.ReadSingle();
                        float XPOS = parser.ReadSingle();
                        float YPOS = parser.ReadSingle();
                        float ZPOS = parser.ReadSingle();

                        parser.ReadInt32(); // ????

                        parser.Seek((int)Track.DataOffset + DataStart);
                        for (int i = 0; i < FrameCount; i++)
                        {
                            AnimTrackTransform Transform = new AnimTrackTransform();
                            for (int j = 0; j < 9; j++)
                            {
                                int ValueBitCount = ByteCounts[j] * 8 + BitCounts[j];
                                int Value         = parser.ReadBits(ValueBitCount);
                                int scale         = 0;
                                for (int k = 0; k < ValueBitCount; k++)
                                {
                                    scale |= 0x1 << k;
                                }

                                float FrameValue = Lerp(Start[j], End[j], 0, 1, Value / (float)scale);
                                if (float.IsNaN(FrameValue))
                                {
                                    FrameValue = 0;
                                }

                                if ((TrackFlag & 0x3) == 0x3)
                                {
                                    //Scale Isotropic
                                    if (j == 0)
                                    {
                                        Transform.SX = FrameValue;
                                        Transform.SY = FrameValue;
                                        Transform.SZ = FrameValue;
                                    }
                                }
                                else if ((TrackFlag & 0x3) == 0x1)
                                {
                                    //Scale normal
                                    switch (j)
                                    {
                                    case 0:
                                        if (ValueBitCount > 0)
                                        {
                                            Transform.SX = FrameValue;
                                        }
                                        else
                                        {
                                            Transform.SX = XSCA;
                                        }
                                        break;

                                    case 1:
                                        if (ValueBitCount > 0)
                                        {
                                            Transform.SY = FrameValue;
                                        }
                                        else
                                        {
                                            Transform.SY = YSCA;
                                        }
                                        break;

                                    case 2:
                                        if (ValueBitCount > 0)
                                        {
                                            Transform.SZ = FrameValue;
                                        }
                                        else
                                        {
                                            Transform.SZ = ZSCA;
                                        }
                                        break;
                                    }
                                }
                                else
                                {
                                    Transform.SX = XSCA;
                                    Transform.SY = YSCA;
                                    Transform.SZ = ZSCA;
                                }

                                //Rotation
                                if ((TrackFlag & 0x4) > 0)
                                {
                                    switch (j)
                                    {
                                    case 3:
                                        if (ValueBitCount > 0)
                                        {
                                            Transform.RX = FrameValue;
                                        }
                                        else
                                        {
                                            Transform.RX = XROT;
                                        }
                                        break;

                                    case 4:
                                        if (ValueBitCount > 0)
                                        {
                                            Transform.RY = FrameValue;
                                        }
                                        else
                                        {
                                            Transform.RY = YROT;
                                        }
                                        break;

                                    case 5:
                                        if (ValueBitCount > 0)
                                        {
                                            Transform.RZ = FrameValue;
                                        }
                                        else
                                        {
                                            Transform.RZ = ZROT;
                                        }
                                        break;
                                    }
                                }
                                else
                                {
                                    Transform.RX = XROT;
                                    Transform.RY = YROT;
                                    Transform.RZ = ZROT;
                                    Transform.RW = WROT;
                                }

                                // Position
                                if ((TrackFlag & 0x8) > 0)
                                {
                                    switch (j)
                                    {
                                    case 6:
                                        if (ValueBitCount > 0)
                                        {
                                            Transform.X = FrameValue;
                                        }
                                        else
                                        {
                                            Transform.X = XPOS;
                                        }
                                        break;

                                    case 7:
                                        if (ValueBitCount > 0)
                                        {
                                            Transform.Y = FrameValue;
                                        }
                                        else
                                        {
                                            Transform.Y = YPOS;
                                        }
                                        break;

                                    case 8:
                                        if (ValueBitCount > 0)
                                        {
                                            Transform.Z = FrameValue;
                                        }
                                        else
                                        {
                                            Transform.Z = ZPOS;
                                        }
                                        break;
                                    }
                                }
                                else
                                {
                                    Transform.X = XPOS;
                                    Transform.Y = YPOS;
                                    Transform.Z = ZPOS;
                                }
                            }
                            if ((TrackFlag & 0x4) > 0)
                            {
                                // Rotation w
                                bool Wflip = parser.ReadBits(1) == 1;// (TrackFlag & 0x1) == 0 ? parser.ReadBits(1) == 1 : true;

                                Transform.RW = (float)Math.Sqrt(Math.Abs(1 - (Transform.RX * Transform.RX + Transform.RY * Transform.RY + Transform.RZ * Transform.RZ)));

                                if (Wflip)
                                {
                                    Transform.RW = -Transform.RW;
                                }
                            }

                            output.Add(Transform);
                        }
                    }
                    else if (CheckFlag(Track.Flags, 0xFF00, ANIM_TRACKFLAGS.ConstTransform))
                    {
                        output.Add(new AnimTrackTransform()
                        {
                            SX = parser.ReadSingle(),
                            SY = parser.ReadSingle(),
                            SZ = parser.ReadSingle(),
                            RX = parser.ReadSingle(),
                            RY = parser.ReadSingle(),
                            RZ = parser.ReadSingle(),
                            RW = parser.ReadSingle(),
                            X  = parser.ReadSingle(),
                            Y  = parser.ReadSingle(),
                            Z  = parser.ReadSingle(),
                        });

                        parser.ReadInt32(); // ????
                    }
                }
            }

            return(output.ToArray());
        }