Example #1
0
        /*type 1  - collisions
         * type 2  - spawns
         * type 3  - respawns
         * type 4  - camera bounds
         * type 5  - death boundaries
         * type 6  - ???
         * type 7  - ITEMPT_transform
         * type 8  - enemyGenerator
         * type 9  - ITEMPT
         * type 10 - fsAreaCam (and other fsArea's ? )
         * type 11 - fsCamLimit
         * type 12 - damageShapes (damage sphere and damage capsule are the only ones I've seen, type 2 and 3 respectively)
         * type 13 - item spawners
         * type 14 - general shapes (general rect, general path, etc.)
         * type 15 - general points
         * type 16 - ???
         * type 17 - FsStartPoint
         * type 18 - ???
         * type 19 - ???*/

        public override void Read(string filename)
        {
            FileData f = new FileData(filename);

            f.seek(0xB);//It's magic
            int collisionCount = f.readInt();

            for (int i = 0; i < collisionCount; i++)
            {
                Collision temp = new Collision();
                temp.read(f);
                collisions.Add(temp);
            }
            f.skip(1); //Seperation char

            int spawnCount = f.readInt();

            for (int i = 0; i < spawnCount; i++)
            {
                Point temp = new Point();
                f.skip(0xD);
                temp.name = f.readString(f.pos(), 0x38);
                f.skip(0x38);
                f.skip(1);//Seperation char
                temp.subname = f.readString(f.pos(), 0x40);
                f.skip(0xA6);
                temp.x = f.readFloat();
                temp.y = f.readFloat();
                spawns.Add(temp);
            }
            f.skip(1);//Seperation char

            int respawnCount = f.readInt();

            for (int i = 0; i < respawnCount; i++)
            {
                Point temp = new Point();
                f.skip(0xD);
                temp.name = f.readString(f.pos(), 0x38);
                f.skip(0x38);
                f.skip(1);//Seperation char
                temp.subname = f.readString(f.pos(), 0x40);
                f.skip(0xA6);
                temp.x = f.readFloat();
                temp.y = f.readFloat();
                respawns.Add(temp);
            }
            f.skip(1);//Seperation char

            int cameraCount = f.readInt();

            for (int i = 0; i < cameraCount; i++)
            {
                Bounds temp = new Bounds();
                f.skip(0xD);
                temp.name = f.readString(f.pos(), 0x38);
                f.skip(0x38);
                f.skip(1);//Seperation char
                temp.subname = f.readString(f.pos(), 0x40);
                f.skip(0xA6);
                temp.left   = f.readFloat();
                temp.right  = f.readFloat();
                temp.top    = f.readFloat();
                temp.bottom = f.readFloat();
                cameraBounds.Add(temp);
            }
            f.skip(1);//Seperation char

            int blastzoneCount = f.readInt();

            for (int i = 0; i < blastzoneCount; i++)
            {
                Bounds temp = new Bounds();
                f.skip(0xD);
                temp.name = f.readString(f.pos(), 0x38);
                f.skip(0x38);
                f.skip(1);//Seperation char
                temp.subname = f.readString(f.pos(), 0x40);
                f.skip(0xA6);
                temp.left   = f.readFloat();
                temp.right  = f.readFloat();
                temp.top    = f.readFloat();
                temp.bottom = f.readFloat();
                blastzones.Add(temp);
            }
            f.skip(1);            //Seperation char

            if (f.readInt() != 0) //1
            {
                return;
            }
            f.skip(1);            //Seperation char

            if (f.readInt() != 0) //2
            {
                return;
            }
            f.skip(1);//Seperation char

            int enemyGeneratorCount = f.readInt();

            if (enemyGeneratorCount != 0)
            {
                return;
            }
            f.skip(1);            //Seperation char

            if (f.readInt() != 0) //4
            {
                return;
            }
            f.skip(1);//Seperation char

            int fsAreaCamCount = f.readInt();

            if (fsAreaCamCount != 0)
            {
                return;
            }
            f.skip(1);//Seperation char

            int fsCamLimitCount = f.readInt();

            if (fsCamLimitCount != 0)
            {
                return;
            }
            f.skip(1);//Seperation char

            int damageShapeCount = f.readInt();

            for (int i = 0; i < damageShapeCount; i++)
            {
                f.skip(0xD);

                string tempName = f.readString(f.pos(), 0x38);
                f.skip(0x38);
                f.skip(1);//Seperation char
                string tempSubname = f.readString(f.pos(), 0x40);
                f.skip(0xA6);
                int shapeType = f.readInt();
                if (shapeType == 2)
                {
                    Sphere temp = new Sphere();
                    temp.name    = tempName;
                    temp.subname = tempSubname;
                    temp.x       = f.readFloat();
                    temp.y       = f.readFloat();
                    temp.z       = f.readFloat();
                    temp.radius  = f.readFloat();
                    f.skip(0x11);
                    damageSpheres.Add(temp);
                }
                else if (shapeType == 3)
                {
                    Capsule temp = new Capsule();
                    temp.name    = tempName;
                    temp.subname = tempSubname;
                    temp.x       = f.readFloat();
                    temp.y       = f.readFloat();
                    temp.z       = f.readFloat();
                    temp.dx      = f.readFloat();
                    temp.dy      = f.readFloat();
                    temp.dz      = f.readFloat();
                    temp.r       = f.readFloat();
                    temp.unk     = f.readFloat();
                    f.skip(1);
                    damageCapsules.Add(temp);
                }
                else
                {
                    throw new NotImplementedException();
                }
            }
            f.skip(1);//Seperation char

            int itemCount = f.readInt();

            for (int i = 0; i < itemCount; i++)
            {
                ItemSpawner temp = new ItemSpawner();
                temp.read(f);
                items.Add(temp);
            }
            f.skip(1);//Seperation char

            int generalShapeCount = f.readInt();

            for (int i = 0; i < generalShapeCount; i++)
            {
                f.skip(0xD);

                string tempName = f.readString(f.pos(), 0x38);
                f.skip(0x38);
                f.skip(1);//Seperation char
                string tempSubname = f.readString(f.pos(), 0x40);
                f.skip(0xAB);
                int             shapeType = f.readInt();
                LVDGeneralShape p;
                if (shapeType == 1)
                {
                    p = new GeneralPoint();
                }
                else if (shapeType == 3)
                {
                    p = new GeneralRect();
                }
                else if (shapeType == 4)
                {
                    p = new GeneralPath();
                }
                else
                {
                    throw new Exception($"Unknown shape type {shapeType} at offset {f.pos() - 4}");
                }
                p.name    = tempName;
                p.subname = tempSubname;
                p.Read(f);
                generalShapes.Add(p);
            }
            f.skip(1);

            int generalPointCount = f.readInt();

            for (int i = 0; i < generalPointCount; i++)
            {
                Point temp = new Point();
                f.skip(0xD);
                temp.name = f.readString(f.pos(), 0x38);
                f.skip(0x38);
                f.skip(1);//Seperation char
                temp.subname = f.readString(f.pos(), 0x40);
                f.skip(0xAF);
                temp.x = f.readFloat();
                temp.y = f.readFloat();
                f.skip(0x14);
                generalPoints.Add(temp);
            }

            if (f.readInt() != 0) //8
            {
                return;           //no clue how to be consistent in reading these so...
            }
            f.skip(1);

            if (f.readInt() != 0) //8
            {
                return;           //no clue how to be consistent in reading these so...
            }
            f.skip(1);

            if (f.readInt() != 0) //8
            {
                return;           //no clue how to be consistent in reading these so...
            }
            f.skip(1);

            if (f.readInt() != 0) //8
            {
                return;           //no clue how to be consistent in reading these so...
            }
            f.skip(1);

            if (f.readInt() != 0) //8
            {
                return;           //no clue how to be consistent in reading these so...
            }
            f.skip(1);

            if (f.readInt() != 0) //8
            {
                return;           //no clue how to be consistent in reading these so...
            }
            f.skip(1);

            //LVD doesn't end here and neither does my confusion, will update this part later
        }
Example #2
0
        public override void Read(string filename)
        {
            bchHeader header = new bchHeader();
            FileData  f      = new FileData(filename);

            f.Endian = System.IO.Endianness.Little;

            f.skip(4);
            header.backwardCompatibility = f.readByte();
            header.forwardCompatibility  = f.readByte();
            header.version = f.readUShort();

            header.mainHeaderOffset  = f.readInt();
            header.stringTableOffset = f.readInt();
            header.gpuCommandsOffset = f.readInt();
            header.dataOffset        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedOffset = f.readInt();
            }
            header.relocationTableOffset = f.readInt();

            header.mainHeaderLength  = f.readInt();
            header.stringTableLength = f.readInt();
            header.gpuCommandsLength = f.readInt();
            header.dataLength        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedLength = f.readInt();
            }
            header.relocationTableLength = f.readInt();

            header.uninitializedDataSectionLength        = f.readInt();
            header.uninitializedDescriptionSectionLength = f.readInt();

            if (header.backwardCompatibility > 7)
            {
                header.flags        = f.readUShort();
                header.addressCount = f.readUShort();
            }

            // Relocation table
            for (int i = 0; i < header.relocationTableLength; i += 4)
            {
                f.seek(header.relocationTableOffset + i);
                int  val  = f.readInt();
                int  off  = val & 0x1FFFFFF;
                byte flag = (byte)(val >> 25);

                switch (flag)
                {
                case 0:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset);
                    break;

                case 1:
                    f.seek(off + header.mainHeaderOffset);
                    f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset);
                    break;

                case 2:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset);
                    break;

                case 0xc:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset);
                    break;
                }

                f.seek((off * 4) + header.gpuCommandsOffset);
                if (header.backwardCompatibility < 6)
                {
                    switch (flag)
                    {
                    case 0x23: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex

                    //case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, ((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (header.backwardCompatibility < 8)
                {
                    switch (flag)
                    {
                    case 0x24: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex

                    //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (header.backwardCompatibility < 0x21)
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex

                    //case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x29: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex relative to Data Offset

                    //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset
                    case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset

                    case 0x2b: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataExtendedOffset); break;        //Vertex relative to Data Extended Offset

                    //case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset
                    case 0x2d: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataExtendedOffset) & 0x7fffffff); break;     //Index 8 bits mode relative to Data Extended Offset
                    }
                }
            }


            // Content Header
            f.seek(header.mainHeaderOffset);
            bchContentHeader content = new bchContentHeader();

            {
                content.modelsPointerTableOffset        = f.readInt();
                content.modelsPointerTableEntries       = f.readInt();
                content.modelsNameOffset                = f.readInt();
                content.materialsPointerTableOffset     = f.readInt();
                content.materialsPointerTableEntries    = f.readInt();
                content.materialsNameOffset             = f.readInt();
                content.shadersPointerTableOffset       = f.readInt();
                content.shadersPointerTableEntries      = f.readInt();
                content.shadersNameOffset               = f.readInt();
                content.texturesPointerTableOffset      = f.readInt();
                content.texturesPointerTableEntries     = f.readInt();
                content.texturesNameOffset              = f.readInt();
                content.materialsLUTPointerTableOffset  = f.readInt();
                content.materialsLUTPointerTableEntries = f.readInt();
                content.materialsLUTNameOffset          = f.readInt();
                content.lightsPointerTableOffset        = f.readInt();
                content.lightsPointerTableEntries       = f.readInt();
                content.lightsNameOffset                = f.readInt();
                content.camerasPointerTableOffset       = f.readInt();
                content.camerasPointerTableEntries      = f.readInt();
                content.camerasNameOffset               = f.readInt();
                content.fogsPointerTableOffset          = f.readInt();
                content.fogsPointerTableEntries         = f.readInt();
                content.fogsNameOffset = f.readInt();
                content.skeletalAnimationsPointerTableOffset    = f.readInt();
                content.skeletalAnimationsPointerTableEntries   = f.readInt();
                content.skeletalAnimationsNameOffset            = f.readInt();
                content.materialAnimationsPointerTableOffset    = f.readInt();
                content.materialAnimationsPointerTableEntries   = f.readInt();
                content.materialAnimationsNameOffset            = f.readInt();
                content.visibilityAnimationsPointerTableOffset  = f.readInt();
                content.visibilityAnimationsPointerTableEntries = f.readInt();
                content.visibilityAnimationsNameOffset          = f.readInt();
                content.lightAnimationsPointerTableOffset       = f.readInt();
                content.lightAnimationsPointerTableEntries      = f.readInt();
                content.lightAnimationsNameOffset           = f.readInt();
                content.cameraAnimationsPointerTableOffset  = f.readInt();
                content.cameraAnimationsPointerTableEntries = f.readInt();
                content.cameraAnimationsNameOffset          = f.readInt();
                content.fogAnimationsPointerTableOffset     = f.readInt();
                content.fogAnimationsPointerTableEntries    = f.readInt();
                content.fogAnimationsNameOffset             = f.readInt();
                content.scenePointerTableOffset             = f.readInt();
                content.scenePointerTableEntries            = f.readInt();
                content.sceneNameOffset = f.readInt();
            }


            //Skeletal animation
            for (int index1 = 0; index1 < content.skeletalAnimationsPointerTableEntries; index1++)
            {
                f.seek(content.skeletalAnimationsPointerTableOffset + (index1 * 4));
                int dataOffset = f.readInt();
                f.seek(dataOffset);


                string skeletalAnimationName = f.readString(f.readInt(), -1);
                int    animationFlags        = f.readInt();
                //int skeletalAnimationloopMode = f.readByte();  //pas ça du tout
                float skeletalAnimationframeSize = f.readFloat();
                int   boneTableOffset            = f.readInt();
                int   boneTableEntries           = f.readInt();
                int   metaDataPointerOffset      = f.readInt();

                //Debug.WriteLine("Animation Name: " + skeletalAnimationName);
                //Debug.WriteLine("BonetableOffset: " + boneTableOffset.ToString("X"));
                //Debug.WriteLine("BonetableEntry: " + boneTableEntries.ToString("X"));

                for (int i = 0; i < boneTableEntries; i++)
                {
                    f.seek(boneTableOffset + (i * 4));
                    int offset = f.readInt();

                    OSkeletalAnimationBone bone = new OSkeletalAnimationBone();

                    f.seek(offset);
                    bone.name = f.readString(f.readInt(), -1);
                    Console.WriteLine("Bone Name: " + bone.name);
                    int animationTypeFlags = f.readInt();
                    int flags = f.readInt();

                    OSegmentType segmentType = (OSegmentType)((animationTypeFlags >> 16) & 0xf);
                    switch (segmentType)
                    {
                    case OSegmentType.transform:
                        f.seek(offset + 0x18);

                        int notExistMask = 0x80000;
                        int constantMask = 0x200;

                        for (int j = 0; j < 2; j++)
                        {
                            for (int axis = 0; axis < 3; axis++)
                            {
                                bool notExist = (flags & notExistMask) > 0;
                                bool constant = (flags & constantMask) > 0;

                                OAnimationKeyFrameGroup frame = new OAnimationKeyFrameGroup();
                                frame.exists = !notExist;
                                if (frame.exists)
                                {
                                    if (constant)
                                    {
                                        frame.interpolation = OInterpolationMode.linear;
                                        frame.keyFrames.Add(new OAnimationKeyFrame(f.readFloat(), 0));
                                    }
                                    else
                                    {
                                        int frameOffset = f.readInt();
                                        int position    = f.pos();
                                        f.seek(frameOffset);
                                        //getAnimationKeyFrame(input, frame);
                                        f.seek(position);
                                    }
                                }
                                else
                                {
                                    f.seek(f.pos() + 0x04);
                                }

                                if (j == 0)
                                {
                                    switch (axis)
                                    {
                                    case 0: bone.rotationX = frame; break;

                                    case 1: bone.rotationY = frame; break;

                                    case 2: bone.rotationZ = frame; break;
                                    }
                                }
                                else
                                {
                                    switch (axis)
                                    {
                                    case 0: bone.translationX = frame; break;

                                    case 1: bone.translationY = frame; break;

                                    case 2: bone.translationZ = frame; break;
                                    }
                                }

                                notExistMask <<= 1;
                                constantMask <<= 1;
                            }

                            constantMask <<= 1;
                        }

                        break;

                    case OSegmentType.transformQuaternion:
                        bone.isFrameFormat = true;

                        int scaleOffset       = f.readInt();
                        int rotationOffset    = f.readInt();
                        int translationOffset = f.readInt();

                        if ((flags & 0x20) == 0)
                        {
                            bone.scale.exists = true;
                            f.seek(scaleOffset);

                            if ((flags & 4) > 0)
                            {
                                bone.scale.vector.Add(new Vector4(
                                                          f.readFloat(),
                                                          f.readFloat(),
                                                          f.readFloat(),
                                                          0));
                            }
                            else
                            {
                                bone.scale.startFrame = f.readFloat();
                                bone.scale.endFrame   = f.readFloat();

                                int scaleFlags      = f.readInt();
                                int scaleDataOffset = f.readInt();
                                int scaleEntries    = f.readInt();

                                f.seek(scaleDataOffset);
                                for (int j = 0; j < scaleEntries; j++)
                                {
                                    bone.scale.vector.Add(new Vector4(
                                                              f.readFloat(),
                                                              f.readFloat(),
                                                              f.readFloat(),
                                                              0));
                                }
                            }
                        }

                        if ((flags & 0x10) == 0)
                        {
                            bone.rotationQuaternion.exists = true;
                            f.seek(rotationOffset);

                            if ((flags & 2) > 0)
                            {
                                bone.rotationQuaternion.vector.Add(new Vector4(
                                                                       f.readFloat(),
                                                                       f.readFloat(),
                                                                       f.readFloat(),
                                                                       f.readFloat()));
                            }
                            else
                            {
                                bone.rotationQuaternion.startFrame = f.readFloat();
                                bone.rotationQuaternion.endFrame   = f.readFloat();

                                int rotationFlags      = f.readInt();
                                int rotationDataOffset = f.readInt();
                                int rotationEntries    = f.readInt();

                                f.seek(rotationDataOffset);
                                for (int j = 0; j < rotationEntries; j++)
                                {
                                    bone.rotationQuaternion.vector.Add(new Vector4(
                                                                           f.readFloat(),
                                                                           f.readFloat(),
                                                                           f.readFloat(),
                                                                           f.readFloat()));
                                }
                            }
                        }

                        if ((flags & 8) == 0)
                        {
                            bone.translation.exists = true;
                            f.seek(translationOffset);

                            if ((flags & 1) > 0)
                            {
                                bone.translation.vector.Add(new Vector4(
                                                                f.readFloat(),
                                                                f.readFloat(),
                                                                f.readFloat(),
                                                                0));
                            }
                            else
                            {
                                bone.translation.startFrame = f.readFloat();
                                bone.translation.endFrame   = f.readFloat();

                                int translationFlags      = f.readInt();
                                int translationDataOffset = f.readInt();
                                int translationEntries    = f.readInt();

                                f.seek(translationDataOffset);
                                for (int j = 0; j < translationEntries; j++)
                                {
                                    bone.translation.vector.Add(new Vector4(
                                                                    f.readFloat(),
                                                                    f.readFloat(),
                                                                    f.readFloat(),
                                                                    0));
                                }
                            }
                        }

                        break;

                    case OSegmentType.transformMatrix:
                        bone.isFullBakedFormat = true;

                        f.readInt();
                        f.readInt();
                        int matrixOffset = f.readInt();
                        int entries      = f.readInt();

                        f.seek(matrixOffset);
                        for (int j = 0; j < entries; j++)
                        {
                            /*OMatrix transform = new OMatrix();
                             * transform.M11 = f.readFloat();
                             * transform.M21 = f.readFloat();
                             * transform.M31 = f.readFloat();
                             * transform.M41 = f.readFloat();
                             *
                             * transform.M12 = f.readFloat();
                             * transform.M22 = f.readFloat();
                             * transform.M32 = f.readFloat();
                             * transform.M42 = f.readFloat();
                             *
                             * transform.M13 = f.readFloat();
                             * transform.M23 = f.readFloat();
                             * transform.M33 = f.readFloat();
                             * transform.M43 = f.readFloat();
                             *
                             * bone.transform.Add(transform);*/
                        }

                        break;

                    default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.name));
                    }

                    //skeletalAnimation.bone.Add(bone);
                }
            }

            //Shaders (unused for now, until someone wants to add them)
            for (int index = 0; index < content.shadersPointerTableEntries; index++)
            {
                f.seek(content.shadersPointerTableOffset + (index * 4));
                int dataOffset = f.readInt();
                f.seek(dataOffset);

                int shaderDataOffset = f.readInt();
                int shaderDataLength = f.readInt();
            }

            // Textures
            // WIP Section
            for (int index = 0; index < content.texturesPointerTableEntries; index++)
            {
                f.seek(content.texturesPointerTableOffset + (index * 4));
                int dOffset = f.readInt();
                f.seek(dOffset);

                int textureCommandsOffset    = f.readInt();
                int textureCommandsWordCount = f.readInt();

                f.seek(f.pos() + 0x14);
                String textureName = f.readString(f.readInt(), -1);
                //Debug.WriteLine("gpuCommandOffset: " + header.gpuCommandsOffset.ToString("X"));
                f.seek(textureCommandsOffset);
                //Debug.WriteLine("textureCommandOffset: " + textureCommandsOffset.ToString("X"));
                BCH_Texture tex = new BCH_Texture();
                textures.Add(textureName, tex);

                tex.Height = f.readUShort();
                tex.Width  = f.readUShort();
                f.skip(12);
                int doffset = f.readInt();
                //Debug.WriteLine("doffset: " + doffset.ToString("X"));
                f.skip(4);
                tex.type = f.readInt();
                tex.data = f.getSection(doffset, f.size() - doffset);

                tex.texture = _3DS.DecodeImage(tex.data, tex.Width, tex.Height, (_3DS.Tex_Formats)tex.type);
                tex.display = Rendering.Texture.CreateGlTextureFromBitmap(tex.texture);
            }

            // Model data

            for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++)
            {
                f.seek(content.modelsPointerTableOffset + (modelIndex * 4));
                int objectsHeaderOffset = f.readInt();

                // Objects
                f.seek(objectsHeaderOffset);
                BCH_Model model = new BCH_Model();
                models.Add(model);

                model.flags                     = f.readByte();
                model.skeletonScaleType         = f.readByte();
                model.silhouetteMaterialEntries = f.readUShort();

                model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , 0, 0, 0, 1);

                int materialsTableOffset  = f.readInt();
                int materialsTableEntries = f.readInt();
                int materialsNameOffset   = f.readInt();
                int verticesTableOffset   = f.readInt();
                //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X"));
                int verticesTableEntries = f.readInt();
                f.skip(0x28);
                int    skeletonOffset              = f.readInt();
                int    skeletonEntries             = f.readInt();
                int    skeletonNameOffset          = f.readInt();
                int    objectsNodeVisibilityOffset = f.readInt();
                int    objectsNodeCount            = f.readInt();
                String name = f.readString(f.readInt(), -1);
                int    objectsNodeNameEntries = f.readInt();
                int    objectsNodeNameOffset  = f.readInt();
                f.readInt(); //0x0
                int metaDataPointerOffset = f.readInt();

                f.seek(objectsNodeVisibilityOffset);
                int nodeVisibility = f.readInt();

                string[] objectName = new string[objectsNodeNameEntries];
                f.seek(objectsNodeNameOffset);
                int rootReferenceBit = f.readInt(); //Radix tree
                int rootLeftNode     = f.readUShort();
                int rootRightNode    = f.readUShort();
                int rootNameOffset   = f.readInt();

                for (int i = 0; i < objectsNodeNameEntries; i++)
                {
                    int   referenceBit = f.readInt();
                    short leftNode     = f.readShort();
                    short rightNode    = f.readShort();
                    objectName[i] = f.readString(f.readInt(), -1);
                    //Debug.WriteLine(objectName[i]);
                }

                // Materials
                // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM

                String[] materialNames = new String[materialsTableEntries];
                for (int index = 0; index < materialsTableEntries; index++)
                {
                    f.seek(materialsTableOffset + (index * 0x2c));

                    int materialParametersOffset = f.readInt();
                    f.readInt();
                    f.readInt();
                    f.readInt();
                    int textureCommandsOffset    = f.readInt();
                    int textureCommandsWordCount = f.readInt();

                    int materialMapperOffset = f.readInt();
                    materialNames[index] = f.readString(f.readInt(), -1);
                }

                // Object Descriptions...
                // Assumes MBN is already loaded for now
                f.seek(verticesTableOffset);
                List <objDes> objDescriptors = new List <objDes>();
                if (mbn == null)
                {
                    mbn = new Smash_Forge.MBN();
                    for (int index = 0; index < verticesTableEntries; index++)
                    {
                        mbn.mesh.Add(new MBN.Mesh());
                    }
                    mbn.PreRender();
                }
                for (int index = 0; index < mbn.mesh.Count; index++)
                {
                    int i = f.readUShort();
                    if (index > mbn.mesh.Count)
                    {
                        break;
                    }
                    if (i > materialNames.Length)
                    {
                        break;
                    }
                    mbn.mesh[index].texId = textures[materialNames[i]].display;
                    Console.WriteLine("Tex index" + mbn.mesh[index].texId);
                    f.skip(2); // flags
                    int nameId = f.readUShort();
                    mbn.mesh[index].Text = objectName[nameId];

                    // node visibility TODO: finish...
                    mbn.mesh[index].Checked = ((nodeVisibility & (1 << nameId)) > 0);

                    mbn.mesh[index].renderPriority = f.readUShort();

                    objDes des = new objDes();
                    objDescriptors.Add(des);
                    des.vshAttBufferCommandOffset = f.readInt();
                    des.vshAttBufferCommandCount  = f.readInt();
                    des.faceOffset = f.readInt();
                    des.faceCount  = f.readInt();
                    des.vshAttBufferCommandOffsetEx = f.readInt();
                    des.vshAttBufferCommandCountEx  = f.readInt();

                    f.skip(12);  // center vector
                    f.skip(4);   // flagsOffset
                    f.skip(4);   // 0?
                    f.readInt(); //bbOffsets[i]

                    //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X"));
                }

                //Skeleton
                f.seek(skeletonOffset);
                for (int index = 0; index < skeletonEntries; index++)
                {
                    Bone bone = new Smash_Forge.Bone(model.skeleton);
                    //Bone bone = new Bone(bones);
                    int boneFlags = f.readInt();
                    bone.parentIndex = f.readShort();
                    short boneSpace = f.readShort();
                    bone.scale       = new float[3];
                    bone.rotation    = new float[3];
                    bone.position    = new float[3];
                    bone.scale[0]    = f.readFloat();
                    bone.scale[1]    = f.readFloat();
                    bone.scale[2]    = f.readFloat();
                    bone.rotation[0] = f.readFloat();
                    bone.rotation[1] = f.readFloat();
                    bone.rotation[2] = f.readFloat();
                    bone.position[0] = f.readFloat();
                    bone.position[1] = f.readFloat();
                    bone.position[2] = f.readFloat();

                    // bone matrix... not really needed to be stored per say
                    f.skip(4 * 4 * 3);

                    bone.Text = f.readString(f.readInt(), -1);

                    f.skip(4); // Meta data
                    bones.bones.Add(bone);


                    model.skeleton.bones.Add(bone);
                }
                model.skeleton.reset();
                model.skeleton.update();
            }
        }
Example #3
0
        public void Read(byte[] file)
        {
            FileData f = new FileData(file);

            f.Endian = Endianness.Big;
            f.seek(0);

            f.seek(4);                 // magic check
            SwitchCheck = f.readInt(); //Switch version only has padded magic
            verNumD     = f.readByte();
            verNumC     = f.readByte();
            verNumB     = f.readByte();
            verNumA     = f.readByte();
            if (SwitchCheck == 0x20202020)
            {
                //Console.WriteLine("Version = " + verNumA + "." + verNumB + "." + verNumC + "." + verNumD);
                if (f.readShort() == 0xFEFF)
                {
                    f.Endian = Endianness.Big;
                }
                else
                {
                    f.Endian = Endianness.Little;
                }
                f.skip(2); //Size Headeer
                f.skip(4); //File Name Direct
                int fileAlignment         = f.readInt();
                int RelocationTableOffset = f.readInt();
                int BfresSize             = f.readInt();

                string name = f.readString(readOffset(f) + 2, -1);

                f.skip(4); // Padding
                long FMDLOffset      = f.readInt64();
                long FMDLDict        = f.readInt64();
                long FSKAOffset      = f.readInt64();
                long FSKADict        = f.readInt64();
                long FMAAOffset      = f.readInt64();
                long FMAADict        = f.readInt64();
                long FVISOffset      = f.readInt64();
                long FVISDict        = f.readInt64();
                long FSHUOffset      = f.readInt64();
                long FSHUDict        = f.readInt64();
                long FSCNOffset      = f.readInt64();
                long FSCNDict        = f.readInt64();
                long BuffMemPool     = f.readInt64();
                long BuffMemPoolInfo = f.readInt64();
                long EMBOffset       = f.readInt64();
                long EMBDict         = f.readInt64();
                f.skip(8); // Padding
                long StringTableOffset = f.readInt64();
                int  unk11             = f.readInt();
                int  FMDLCount         = f.readShort();
                /*FSKACount =*/ f.readShort();
                int FMAACount = f.readShort();
                int FVISCount = f.readShort();
                int FSHUCount = f.readShort();
                int FSCNCount = f.readShort();
                int EMBCount  = f.readShort();
                f.skip(12); // Padding
                            // //Console.WriteLine($"FMDLOffset {FMDLOffset} FMDLCount {FMDLCount} FMDLDict {FMDLDict} FSKAOffset {FSKAOffset} FSKADict {FSKADict}");
                            //  //Console.WriteLine($"FMAAOffset {FMAAOffset} FMAADict {FMAADict} FVISOffset {FVISOffset} FSHUOffset {FSKAOffset} FSKADict {FSHUDict}");

                //FMDLs -Models-
                for (int i = 0; i < EMBCount; i++)
                {
                    f.seek((int)EMBOffset + (i * 16));
                    int DataOffset = f.readInt();
                    f.seek(DataOffset);
                    string EmMagic = f.readString(f.pos(), 4);

                    if (EmMagic.Equals("BNTX")) //Textures
                    {
                        f.skip(24);
                        int size = f.readInt();
                        f.seek(DataOffset);
                        BinaryTexture t = new BinaryTexture(f.GetStream(size));
                        textures.Add(t.Name, t);
                    }
                }
                f.seek((int)FMDLOffset);
                for (int i = 0; i < FMDLCount; i++)
                {
                    //   //Console.WriteLine("Reading FMDL....");

                    FMDL_Model model = new FMDL_Model();



                    //FMDL modelTest = new FMDL();
                    //modelTest.Read(f);
                    f.skip(16);

                    FMDLheader fmdl_info = new FMDLheader
                    {
                        name           = f.readString(f.readInt() + 2, -1),
                        padding        = f.readInt(),
                        eofString      = f.readInt64(),
                        fsklOff        = f.readInt64(),
                        fvtxArrOff     = f.readInt64(),
                        fshpOffset     = f.readInt64(),
                        fshpIndx       = f.readInt64(),
                        fmatOffset     = f.readInt64(),
                        fmatIndx       = f.readInt64(),
                        UserDataOffset = f.readInt64(),
                        padding1       = f.readInt64(),
                        padding2       = f.readInt64(),
                        fvtxCount      = f.readShort(),
                        fshpCount      = f.readShort(),
                        fmatCount      = f.readShort(),
                        paramCount     = f.readShort(),
                        VertCount      = f.readInt(),
                        unk2           = f.readInt(),
                    };
                    int NextFMDL = f.pos();

                    //Models.Nodes.Add(fmdl_info.name);
                    //   //Console.WriteLine($" Name {fmdl_info.name} eofString {fmdl_info.eofString} fsklOff {fmdl_info.fsklOff}");
                    //  //Console.WriteLine(fmdl_info.fvtxCount);

                    List <FVTXH> FVTXArr = new List <FVTXH>();
                    f.seek((int)fmdl_info.fvtxArrOff);
                    for (int vtx = 0; vtx < fmdl_info.fvtxCount; vtx++)
                    {
                        //   //Console.WriteLine("Reading FVTX....");
                        f.skip(16);
                        FVTXArr.Add(new FVTXH
                        {
                            attArrOff           = f.readInt64(),
                            attIndxOff          = f.readInt64(),
                            unk1                = f.readInt64(),
                            unk2                = f.readInt64(),
                            unk3                = f.readInt64(),
                            buffSizeOff         = f.readInt64(),
                            buffStrideSizeOff   = f.readInt64(),
                            buffArrOff          = f.readInt64(),
                            buffOff             = f.readInt(),
                            attCount            = f.readByte(),
                            buffCount           = f.readByte(),
                            sectIndx            = f.readShort(),
                            vertCount           = f.readInt(),
                            SkinWeightInfluence = f.readInt()
                        });
                        //  //Console.WriteLine($"attCount {FVTXArr[vtx].attCount}");
                    }


                    f.seek((int)fmdl_info.fmatOffset);
                    List <FMATH> FMATheaders = new List <FMATH>();
                    for (int mat = 0; mat < fmdl_info.fmatCount; mat++)
                    {
                        //    //Console.WriteLine("Reading FMAT....");
                        f.skip(16);


                        FMATH fmat_info = new FMATH
                        {
                            name            = f.readString((int)f.readInt64() + 2, -1),
                            renderInfoOff   = f.readInt64(),
                            renderInfoIndx  = f.readInt64(),
                            shaderAssignOff = f.readInt64(),
                            u1                 = f.readInt64(),
                            texSelOff          = f.readInt64(),
                            u2                 = f.readInt64(),
                            texAttSelOff       = f.readInt64(),
                            texAttIndxOff      = f.readInt64(),
                            matParamArrOff     = f.readInt64(),
                            matParamIndxOff    = f.readInt64(),
                            matParamOff        = f.readInt64(),
                            userDataOff        = f.readInt64(),
                            userDataIndxOff    = f.readInt64(),
                            volatileFlagOffset = f.readInt64(),
                            u3                 = f.readInt64(),
                            samplerSlotOff     = f.readInt64(),
                            textureSlotOff     = f.readInt64(),
                            flags              = f.readInt(), //This toggles material visabilty
                            sectIndx           = f.readShort(),
                            rendParamCount     = f.readShort(),
                            texSelCount        = f.readByte(),
                            texAttSelCount     = f.readByte(),
                            matParamCount      = f.readShort(),
                            u4                 = f.readShort(),
                            matParamSize       = f.readShort(),
                            rawParamDataSize   = f.readShort(),
                            userDataCount      = f.readShort(),
                            padding            = f.readInt(),
                        };
                        string FMATNameOffset = fmat_info.name;
                        // //Console.WriteLine($"{FMATNameOffset} {fmat_info.texSelCount} ");
                        FMATheaders.Add(fmat_info);
                    }

                    f.seek((int)fmdl_info.fsklOff + 16);
                    // //Console.WriteLine("Reading FSKL....");
                    FSKLH fskl_info = new FSKLH
                    {
                        boneIndxOff     = f.readInt64(),
                        boneArrOff      = f.readInt64(),
                        invIndxArrOff   = f.readInt64(),
                        invMatrArrOff   = f.readInt64(),
                        padding1        = f.readInt64(),
                        fsklType        = f.readInt(), //flags
                        boneArrCount    = f.readShort(),
                        invIndxArrCount = f.readShort(),
                        exIndxCount     = f.readShort(),
                        u1 = f.readInt(),
                    };

                    f.seek((int)fmdl_info.fsklOff + 16);
                    FSKLH fskl_infov8 = new FSKLH
                    {
                        boneIndxOff     = f.readInt64(),
                        boneArrOff      = f.readInt64(),
                        invIndxArrOff   = f.readInt64(),
                        invMatrArrOff   = f.readInt64(),
                        padding1        = f.readInt64(),
                        padding2        = f.readInt64(),
                        padding3        = f.readInt64(),
                        fsklType        = f.readInt(), //flags
                        boneArrCount    = f.readShort(),
                        invIndxArrCount = f.readShort(),
                        exIndxCount     = f.readShort(),
                        u1 = f.readInt(),
                    };
                    //  //Console.WriteLine($"Bone Count {fskl_info.boneArrCount}");

                    //FSKL and many other sections will be revised and cleaner later

                    if (verNumB == 8)
                    {
                        model.Node_Array = new int[fskl_infov8.invIndxArrCount + fskl_infov8.exIndxCount];
                        f.seek((int)fskl_infov8.invIndxArrOff);
                        for (int nodes = 0; nodes < fskl_infov8.invIndxArrCount + fskl_infov8.exIndxCount; nodes++)
                        {
                            model.Node_Array[nodes] = (f.readShort());
                        }
                    }
                    else
                    {
                        model.Node_Array = new int[fskl_info.invIndxArrCount + fskl_info.exIndxCount];
                        f.seek((int)fskl_info.invIndxArrOff);
                        for (int nodes = 0; nodes < fskl_info.invIndxArrCount + fskl_info.exIndxCount; nodes++)
                        {
                            model.Node_Array[nodes] = (f.readShort());
                        }
                    }



                    List <FSHPH> FSHPArr = new List <FSHPH>();
                    // //Console.WriteLine("Reading FSHP....");
                    f.seek((int)fmdl_info.fshpOffset);
                    for (int shp = 0; shp < fmdl_info.fshpCount; shp++)
                    {
                        f.skip(16);
                        FSHPArr.Add(new FSHPH
                        {
                            polyNameOff      = f.readInt(),
                            u1               = f.readInt(),
                            fvtxOff          = f.readInt64(),
                            lodMdlOff        = f.readInt64(),
                            fsklIndxArrOff   = f.readInt64(),
                            u3               = f.readInt64(),
                            u4               = f.readInt64(),
                            boundingBoxOff   = f.readInt64(),
                            radiusOff        = f.readInt64(),
                            padding          = f.readInt64(),
                            flags            = f.readInt(),
                            sectIndx         = f.readShort(),
                            fmatIndx         = f.readShort(),
                            fsklIndx         = f.readShort(),
                            fvtxIndx         = f.readShort(),
                            fsklIndxArrCount = f.readShort(),
                            matrFlag         = f.readByte(),
                            lodMdlCount      = f.readByte(),
                            visGrpCount      = f.readInt(),
                            visGrpIndxOff    = f.readShort(),
                            visGrpNodeOff    = f.readShort(),
                        });
                    }

                    // //Console.WriteLine("Reading Bones....");

                    // //Console.WriteLine("Reading FSHP Array....");

                    //MeshTime!!

                    for (int m = 0; m < FSHPArr.Count; m++)
                    {
                        Mesh poly = new Mesh();


                        poly.name = f.readString(FSHPArr[m].polyNameOff + 2, -1);


                        //    //Console.WriteLine("Polygon = " + poly.name);

                        List <attdata> AttrArr = new List <attdata>();
                        f.seek((int)FVTXArr[FSHPArr[m].fvtxIndx].attArrOff);
                        for (int att = 0; att < FVTXArr[FSHPArr[m].fvtxIndx].attCount; att++)
                        {
                            string AttType = f.readString(f.readInt() + 2, -1);

                            f.skip(4); //padding
                            f.Endian = Endianness.Big;
                            int vertType = f.readShort();
                            f.skip(2);
                            f.Endian = Endianness.Little;
                            int buffOff  = f.readShort();
                            int buffIndx = f.readShort();
                            //   //Console.WriteLine($"{AttType} Type = {vertType} Offset = {buffOff} Index = {buffIndx} ");
                            AttrArr.Add(new attdata {
                                attName = AttType, buffIndx = buffIndx, buffOff = buffOff, vertType = vertType
                            });
                        }


                        //Get RLT real quick for buffer offset
                        f.seek(0x18);
                        int RTLOffset = f.readInt();

                        f.seek(RTLOffset);
                        f.skip(0x030);
                        int DataStart = f.readInt();

                        // //Console.WriteLine($"RLT {DataStart}");


                        List <buffData> BuffArr = new List <buffData>();
                        f.seek((int)FVTXArr[FSHPArr[m].fvtxIndx].buffArrOff);
                        for (int buff = 0; buff < FVTXArr[FSHPArr[m].fvtxIndx].buffCount; buff++)
                        {
                            buffData data = new buffData();
                            f.seek((int)FVTXArr[FSHPArr[m].fvtxIndx].buffSizeOff + ((buff) * 0x10));
                            data.buffSize = f.readInt();
                            f.seek((int)FVTXArr[FSHPArr[m].fvtxIndx].buffStrideSizeOff + ((buff) * 0x10));
                            data.strideSize = f.readInt();

                            //So these work by grabbing the RLT offset first and then adding the buffer offset. Then they keep adding each other by their buffer sizes
                            if (buff == 0)
                            {
                                data.DataOffset = (DataStart + FVTXArr[FSHPArr[m].fvtxIndx].buffOff);
                            }
                            if (buff > 0)
                            {
                                data.DataOffset = BuffArr[buff - 1].DataOffset + BuffArr[buff - 1].buffSize;
                            }
                            if (data.DataOffset % 8 != 0)
                            {
                                data.DataOffset = data.DataOffset + (8 - (data.DataOffset % 8));
                            }

                            BuffArr.Add(data);
                            //   //Console.WriteLine("Data Offset = " + data.DataOffset + " Vertex Buffer Size =" + data.buffSize + " Index = " + buff + " vertexStrideSize size =" + data.strideSize);
                        }

                        for (int v = 0; v < FVTXArr[FSHPArr[m].fvtxIndx].vertCount; v++)
                        {
                            Vertex vert = new Vertex();
                            for (int attr = 0; attr < AttrArr.Count; attr++)
                            {
                                f.seek(((BuffArr[AttrArr[attr].buffIndx].DataOffset) + (AttrArr[attr].buffOff) + (BuffArr[AttrArr[attr].buffIndx].strideSize * v)));
                                switch (AttrArr[attr].attName)
                                {
                                case "_p0":
                                    if (AttrArr[attr].vertType == 1301)
                                    {
                                        vert.pos = new Vector3 {
                                            X = f.readHalfFloat(), Y = f.readHalfFloat(), Z = f.readHalfFloat()
                                        }
                                    }
                                    ;
                                    if (AttrArr[attr].vertType == 1304)
                                    {
                                        vert.pos = new Vector3 {
                                            X = f.readFloat(), Y = f.readFloat(), Z = f.readFloat()
                                        }
                                    }
                                    ;
                                    break;

                                case "_c0":
                                    if (AttrArr[attr].vertType == 1301)
                                    {
                                        vert.col = new Vector4(f.readHalfFloat(), f.readHalfFloat(), f.readHalfFloat(), f.readHalfFloat());
                                    }
                                    if (AttrArr[attr].vertType == 2067)
                                    {
                                        vert.col = new Vector4 {
                                            X = f.readFloat(), Y = f.readFloat(), Z = f.readFloat(), W = f.readFloat()
                                        }
                                    }
                                    ;
                                    if (AttrArr[attr].vertType == 267)
                                    {
                                        vert.col = new Vector4(f.readByte() / 255f, f.readByte() / 255f, f.readByte() / 255f, f.readByte() / 255f);
                                    }
                                    break;

                                case "_n0":
                                    if (AttrArr[attr].vertType == 526)
                                    {
                                        int normVal = (int)f.readInt();
                                        //Thanks RayKoopa!
                                        vert.nrm = new Vector3 {
                                            X = sign10Bit((normVal) & 0x3FF) / (float)511, Y = sign10Bit((normVal >> 10) & 0x3FF) / (float)511, Z = sign10Bit((normVal >> 20) & 0x3FF) / (float)511
                                        };
                                    }
                                    break;

                                case "_u0":
                                case "color":
                                case "_t0":
                                case "_b0":
                                case "_u1":
                                case "_u2":
                                case "_u3":
                                    if (AttrArr[attr].vertType == 265 || AttrArr[attr].vertType == 521)
                                    {
                                        vert.tx.Add(new Vector2 {
                                            X = ((float)f.readByte()) / 255, Y = ((float)f.readByte()) / 255
                                        });
                                    }
                                    if (AttrArr[attr].vertType == 274)
                                    {
                                        vert.tx.Add(new Vector2 {
                                            X = ((float)f.readShort()) / 65535, Y = ((float)f.readShort()) / 65535
                                        });
                                    }
                                    if (AttrArr[attr].vertType == 530)
                                    {
                                        vert.tx.Add(new Vector2 {
                                            X = ((float)f.readShort()) / 32767, Y = ((float)f.readShort()) / 32767
                                        });
                                    }
                                    if (AttrArr[attr].vertType == 1298)
                                    {
                                        vert.tx.Add(new Vector2 {
                                            X = f.readHalfFloat(), Y = f.readHalfFloat()
                                        });
                                    }
                                    if (AttrArr[attr].vertType == 1303)
                                    {
                                        vert.tx.Add(new Vector2 {
                                            X = f.readFloat(), Y = f.readFloat()
                                        });
                                    }
                                    break;

                                case "_i0":
                                    if (AttrArr[attr].vertType == 770)
                                    {
                                        vert.node.Add(f.readByte());
                                        vert.weight.Add((float)1.0);
                                    }
                                    if (AttrArr[attr].vertType == 777)
                                    {
                                        vert.node.Add(f.readByte());
                                        vert.node.Add(f.readByte());
                                    }
                                    if (AttrArr[attr].vertType == 779)
                                    {
                                        vert.node.Add(f.readByte());
                                        vert.node.Add(f.readByte());
                                        vert.node.Add(f.readByte());
                                        vert.node.Add(f.readByte());
                                    }
                                    if (AttrArr[attr].vertType == 523)
                                    {
                                        vert.node.Add(f.readByte());
                                        vert.node.Add(f.readByte());
                                        vert.node.Add(f.readByte());
                                        vert.node.Add(f.readByte());
                                    }
                                    break;

                                case "_w0":
                                    if (AttrArr[attr].vertType == 258)
                                    {
                                        vert.weight.Add((f.readByte()) / (float)255);
                                    }
                                    if (AttrArr[attr].vertType == 265)
                                    {
                                        vert.weight.Add((f.readByte()) / (float)255);
                                        vert.weight.Add((f.readByte()) / (float)255);
                                    }
                                    if (AttrArr[attr].vertType == 267)
                                    {
                                        vert.weight.Add((f.readByte()) / (float)255);
                                        vert.weight.Add((f.readByte()) / (float)255);
                                        vert.weight.Add((f.readByte()) / (float)255);
                                        vert.weight.Add((f.readByte()) / (float)255);
                                    }
                                    if (AttrArr[attr].vertType == 274)
                                    {
                                        vert.weight.Add((f.readShort()) / (float)255);
                                        vert.weight.Add((f.readShort()) / (float)255);
                                    }
                                    break;

                                default:
                                    //     //Console.WriteLine(AttrArr[attr].attName + " Unknown type " + AttrArr[attr].vertType.ToString("x") + " 0x");
                                    break;
                                }
                            }
                            poly.vertices.Add(vert);
                        }
                        int LoadLOD = FSHPArr[m].lodMdlCount - 1;

                        f.seek((int)FSHPArr[m].lodMdlOff);
                        for (int lod = 0; lod < FSHPArr[m].lodMdlCount; lod++)
                        {
                            long SubMeshOff        = f.readInt64();
                            long unk1              = f.readInt64();
                            long unk2              = f.readInt64();
                            long indxBuffOff       = f.readInt64();
                            int  FaceBuffer        = f.readInt();
                            int  PrimativefaceType = f.readInt();
                            int  faceType          = f.readInt();
                            int  FaceCount         = f.readInt();
                            int  elmSkip           = f.readInt();
                            int  subMeshCount      = f.readInt();

                            int temp = f.pos();



                            f.seek(FaceBuffer + DataStart);
                            if (faceType == 1)
                            {
                                FaceCount = FaceCount / 3;
                            }
                            if (faceType == 2)
                            {
                                FaceCount = FaceCount / 6;
                            }


                            if (lod == LoadLOD)
                            {
                                for (int face = 0; face < FaceCount; face++)
                                {
                                    if (faceType == 1)
                                    {
                                        poly.faces.Add(new List <int> {
                                            elmSkip + f.readShort(), elmSkip + f.readShort(), elmSkip + f.readShort()
                                        });
                                    }
                                    else if (faceType == 2)
                                    {
                                        poly.faces.Add(new List <int> {
                                            elmSkip + f.readInt(), elmSkip + f.readInt(), elmSkip + f.readInt()
                                        });
                                    }
                                    else
                                    {
                                        Console.Write("UnkFaceFormat");
                                    }
                                }
                            }

                            f.seek(temp);
                        }



                        f.seek((int)FMATheaders[FSHPArr[m].fmatIndx].texSelOff);
                        List <string> MatTexList = new List <string>();
                        for (int tex = 0; FMATheaders[FSHPArr[m].fmatIndx].texAttSelCount > tex; tex++)
                        {
                            string TextureName = f.readString((int)f.readInt64() + 2, -1).ToLower();
                            MatTexList.Add(TextureName);
                        }

                        if (MatTexList.Count > 0)
                        {
                            poly.texNames.Add(MatTexList[0]);
                        }

                        //Console.WriteLine(String.Join(",",MatTexList));

                        model.poly.Add(poly);
                    }
                    models.Add(model);
                    f.seek(NextFMDL);
                }
            }
        }
Example #4
0
        public void ReadNTP3(FileData d)
        {
            d.seek(0x4);

            Version = d.readUShort();
            ushort count = d.readUShort();

            if (Version == 0x100)
            {
                count -= 1;
            }

            d.skip(0x8);
            int headerPtr = 0x10;

            for (ushort i = 0; i < count; ++i)
            {
                d.seek(headerPtr);

                NutTexture tex = new NutTexture();
                tex.isDds = true;
                tex.pixelInternalFormat = PixelInternalFormat.Rgba32ui;

                int totalSize = d.readInt();
                d.skip(4);
                int dataSize   = d.readInt();
                int headerSize = d.readUShort();
                d.skip(2);

                //It might seem that mipmapCount and pixelFormat would be shorts, but they're bytes because they stay in the same place regardless of endianness
                d.skip(1);
                byte mipmapCount = d.readByte();
                d.skip(1);
                tex.setPixelFormatFromNutFormat(d.readByte());
                tex.Width  = d.readUShort();
                tex.Height = d.readUShort();
                d.skip(4);
                uint caps2 = d.readUInt();

                bool isCubemap    = false;
                byte surfaceCount = 1;
                if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP) == (uint)DDS.DDSCAPS2.CUBEMAP)
                {
                    //Only supporting all six faces
                    if ((caps2 & (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES) == (uint)DDS.DDSCAPS2.CUBEMAP_ALLFACES)
                    {
                        isCubemap    = true;
                        surfaceCount = 6;
                    }
                    else
                    {
                        throw new NotImplementedException($"Unsupported cubemap face amount for texture {i} with hash 0x{tex.HashId:X}. Six faces are required.");
                    }
                }

                int dataOffset = d.readInt() + headerPtr;
                d.readInt();
                d.readInt();
                d.readInt();

                //The size of a single cubemap face (discounting mipmaps). I don't know why it is repeated. If mipmaps are present, this is also specified in the mipSize section anyway.
                int cmapSize1 = 0;
                int cmapSize2 = 0;
                if (isCubemap)
                {
                    cmapSize1 = d.readInt();
                    cmapSize2 = d.readInt();
                    d.skip(8);
                }

                int[] mipSizes = new int[mipmapCount];
                if (mipmapCount == 1)
                {
                    if (isCubemap)
                    {
                        mipSizes[0] = cmapSize1;
                    }
                    else
                    {
                        mipSizes[0] = dataSize;
                    }
                }
                else
                {
                    for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel)
                    {
                        mipSizes[mipLevel] = d.readInt();
                    }
                    d.align(0x10);
                }

                d.skip(0x10); //eXt data - always the same

                d.skip(4);    //GIDX
                d.readInt();  //Always 0x10
                tex.HashId = d.readInt();
                d.skip(4);    // padding align 8

                if (Version == 0x100)
                {
                    dataOffset = d.pos();
                }

                for (byte surfaceLevel = 0; surfaceLevel < surfaceCount; ++surfaceLevel)
                {
                    TextureSurface surface = new TextureSurface();
                    for (byte mipLevel = 0; mipLevel < mipmapCount; ++mipLevel)
                    {
                        byte[] texArray = d.getSection(dataOffset, mipSizes[mipLevel]);
                        surface.mipmaps.Add(texArray);
                        dataOffset += mipSizes[mipLevel];
                    }
                    tex.surfaces.Add(surface);
                }

                if (tex.getNutFormat() == 14 || tex.getNutFormat() == 17)
                {
                    tex.SwapChannelOrderUp();
                }

                headerPtr += headerSize;

                Nodes.Add(tex);
            }
        }
Example #5
0
        public void readKeyFrame(FileData d, int length, int dataoff, int valueFormat, int tanFormat, int keyframeCount, int boneId, int trackType)
        {
            int temp = d.pos();

            d.seek(dataoff);

            if (Debug)
            {
                Console.WriteLine("Start 0x" + d.pos() + " " + keyframeCount);
            }

            DATAnimTrack track = new DATAnimTrack();

            track.type = (AnimType)trackType;
            nodes[boneId].Add(track);

            while (d.pos() < dataoff + length)
            {
                int type = readExtendedByte(d);

                int interpolation = ((type) & 0x0F);
                int numOfKey      = ((type >> 4) & 0xFF) + 1;

                if (Debug)
                {
                    Console.WriteLine("Interpolation type: " + (InterpolationType)interpolation + "\tnumofkey: " + numOfKey);
                }

                for (int i = 0; i < numOfKey; i++)
                {
                    double value = -99, tan = -99;
                    int    time = 0;
                    if (interpolation == 1)
                    { // step
                        value = readVal(d, valueFormat);
                        time  = readExtendedByte(d);
                        if (Debug)
                        {
                            Console.WriteLine("\t" + value + "\t" + time);
                        }
                    }
                    if (interpolation == 2)
                    { // linear
                        value = readVal(d, valueFormat);
                        time  = readExtendedByte(d);
                        //Console.WriteLine("\t" + value + "\t" + time);
                    }
                    if (interpolation == 3)
                    { // hermite
                        value = readVal(d, valueFormat);
                        tan   = 0;
                        time  = readExtendedByte(d);
                        if (Debug)
                        {
                            Console.WriteLine("\t" + value + "\t" + time);
                        }
                    }
                    if (interpolation == 4)
                    { // hermite
                        value = readVal(d, valueFormat);
                        tan   = readVal(d, tanFormat);
                        time  = readExtendedByte(d);
                        if (Debug)
                        {
                            Console.WriteLine("\t" + value + "\t" + tan + "\t" + time);
                        }
                    }
                    if (interpolation == 5)
                    { // hermite
                        tan = readVal(d, tanFormat);
                        if (Debug)
                        {
                            Console.WriteLine("\t" + "Tan" + tan);
                        }
                    }
                    if (interpolation == 6)
                    { // constant
                        value = readVal(d, valueFormat);
                        time  = readExtendedByte(d);
                        //Console.WriteLine("\t" + value + "\t" + time);
                    }

                    KeyNode node = new KeyNode();
                    node.value             = (float)value;
                    node.frame             = time;
                    node.tan               = (float)tan;
                    node.interpolationType = (InterpolationType)interpolation;
                    track.keys.Add(node);
                    //node.boneID = boneId;
                }
                d.Endian = System.IO.Endianness.Big;
            }
            //Console.WriteLine("Ends at: " + (d.pos() + 8 - (d.pos() % 8)).ToString("x"));

            d.seek(temp);
        }
Example #6
0
        /**
         * Reading and saving --------------------
         **/

        public override void Read(string filename)
        {
            FileData d = new FileData(filename);

            d.seek(0);
            d.Endian = Endianness.Little;

            format = d.readShort();
            unkown = (ushort)d.readShort();
            flags  = d.readInt();
            mode   = d.readInt();
            bool hasNameTable = (flags & 2) > 0;

            int polyCount = d.readInt();

            mesh     = new List <Mesh>();
            descript = new List <Descriptor>();
            List <List <int> > prim = new List <List <int> >();

            for (int i = 0; i < polyCount; i++)
            {
                if (i == 0 && mode == 1)
                {
                    Descriptor des = new Descriptor();
                    des.ReadDescription(d);
                    descript.Add(des);
                }

                Mesh m = new Mesh();
                mesh.Add(m);

                int        faceCount = d.readInt();
                List <int> prims     = new List <int>();
                prim.Add(prims);
                for (int j = 0; j < faceCount; j++)
                {
                    int        nodeCount = d.readInt();
                    List <int> nodeList  = new List <int>();
                    m.nodeList.Add(nodeList);

                    for (int k = 0; k < nodeCount; k++)
                    {
                        nodeList.Add(d.readInt()); // for a node list?
                    }
                    int primitiveCount = d.readInt();
                    prims.Add(primitiveCount);

                    if (hasNameTable)
                    {
                        int nameId = d.readInt();
                    }

                    if (mode == 0)
                    {
                        if (format == 4)
                        {
                            int[] buffer = new int[primitiveCount];
                            for (int k = 0; k < primitiveCount; k++)
                            {
                                buffer[k] = d.readShort();
                            }
                            d.align(4);
                            List <int> buf = new List <int>();
                            buf.AddRange(buffer);
                            m.faces.Add(buf);
                        }
                        else
                        {
                            Descriptor des = new Descriptor();
                            des.ReadDescription(d);
                            descript.Add(des);
                        }
                    }
                }
            }

            if (mode == 0)
            {
                //Console.WriteLine("Extra!");
            }

            // TODO: STRING TABLE
            if (hasNameTable)
            {
                for (int i = 0; i < mesh.Count; i++)
                {
                    int index = d.readByte();
                    nameTable.Add(d.readString());
                }
            }


            if (format != 4)
            {
                d.align(32);
            }

            // Vertex Bank
            int start = d.pos();

            for (int i = 0; i < 1; i++)
            {
                if (mode == 0 || i == 0)
                {
                    Descriptor des = descript[i];

                    if (format != 4)
                    {
                        while (d.pos() < start + des.length)
                        {
                            Vertex v = new Vertex();
                            vertices.Add(v);

                            for (int k = 0; k < des.type.Length; k++)
                            {
                                d.align(2);
                                switch (des.type[k])
                                {
                                case 0:     //Position
                                    v.pos.X = readType(d, des.format[k], des.scale[k]);
                                    v.pos.Y = readType(d, des.format[k], des.scale[k]);
                                    v.pos.Z = readType(d, des.format[k], des.scale[k]);
                                    break;

                                case 1:     //Normal
                                    v.nrm.X = readType(d, des.format[k], des.scale[k]);
                                    v.nrm.Y = readType(d, des.format[k], des.scale[k]);
                                    v.nrm.Z = readType(d, des.format[k], des.scale[k]);
                                    break;

                                case 2:     //Color
                                    v.col.X = (int)(readType(d, des.format[k], des.scale[k]));
                                    v.col.Y = (int)(readType(d, des.format[k], des.scale[k]));
                                    v.col.Z = (int)(readType(d, des.format[k], des.scale[k]));
                                    v.col.W = (int)(readType(d, des.format[k], des.scale[k]));
                                    break;

                                case 3:     //Tex0
                                    v.tx.Add(new Vector2(readType(d, des.format[k], des.scale[k]), readType(d, des.format[k], des.scale[k])));
                                    break;

                                case 4:     //Tex1
                                    v.tx.Add(new Vector2(readType(d, des.format[k], des.scale[k]), readType(d, des.format[k], des.scale[k])));
                                    break;

                                case 5:     //Bone Index
                                    v.node.Add(d.readByte());
                                    v.node.Add(d.readByte());
                                    break;

                                case 6:     //Bone Weight
                                    v.weight.Add(readType(d, des.format[k], des.scale[k]));
                                    v.weight.Add(readType(d, des.format[k], des.scale[k]));
                                    break;
                                    //default:
                                    //    Console.WriteLine("WTF is this");
                                }
                            }
                        }
                        d.align(32);
                    }
                }

                for (int j = 0; j < mesh.Count; j++)
                {
                    foreach (int l in prim[j])
                    {
                        List <int> face = new List <int>();
                        mesh[j].faces.Add(face);
                        for (int k = 0; k < l; k++)
                        {
                            face.Add(d.readShort());
                        }
                        d.align(32);
                    }
                }
            }

            PreRender();
        }
Example #7
0
        public void ReadNTP3(FileData d)
        {
            Version = d.readShort();
            int count = d.readShort();

            d.skip(0x8);
            if (Version == 0x100)
            {
                count -= 1;
            }

            int dataPtr = 0;

            for (int i = 0; i < count; i++)
            {
                //Debug.WriteLine(d.pos().ToString("x"));
                NutTexture tex = new NutTexture();
                tex.type = PixelInternalFormat.Rgba32ui;

                int totalSize = d.readInt();
                d.skip(4); // padding

                int dataSize   = d.readInt();
                int headerSize = d.readShort();
                d.skip(3);
                int numMips = d.readByte();
                //Debug.WriteLine(numMips);
                d.skip(1);
                tex.setPixelFormatFromNutFormat(d.readByte());
                tex.Width  = d.readShort();
                tex.Height = d.readShort();

                d.skip(8); // padding?

                int dataOffset = d.readInt() + dataPtr + 0x10;
                d.skip(0x0C);

                int[] mipSizes = new int[numMips];

                if (numMips == 1)
                {
                    mipSizes[0] = dataSize;
                }
                else
                {
                    for (int j = 0; j < numMips; j++)
                    {
                        mipSizes[j] = d.readInt();
                    }
                }
                d.align(16);

                d.skip(0x18);
                tex.HASHID = d.readInt();
                d.skip(4); // padding align 8

                if (Version == 0x100)
                {
                    dataOffset = d.pos();
                }

                // add mipmap data
                for (int miplevel = 0; miplevel < numMips; miplevel++)
                {
                    byte[] texArray = d.getSection(dataOffset, mipSizes[miplevel]);
                    //Debug.WriteLine(texArray.Length.ToString("x"));
                    tex.mipmaps.Add(texArray);
                    dataOffset += mipSizes[miplevel];
                }

                dataPtr += headerSize;

                if (tex.getNutFormat() == 14 || tex.getNutFormat() == 17)
                {
                    Console.WriteLine("Endian swap");
                    // swap
                    foreach (byte[] mip in tex.mipmaps)
                    {
                        for (int t = 0; t < mip.Length; t += 4)
                        {
                            byte t1 = mip[t];
                            mip[t]     = mip[t + 1];
                            mip[t + 1] = mip[t + 2];
                            mip[t + 2] = mip[t + 3];
                            mip[t + 3] = t1;

                            /*byte t1 = mip[t];
                             * byte t2 = mip[t+1];
                             * mip[t] = mip[t + 3];
                             * mip[t + 1] = mip[t + 2];
                             * mip[t + 2] = t2;
                             * mip[t + 3] = t1;*/
                        }
                    }
                }

                Nodes.Add(tex);

                /*for (int miplevel = 0; miplevel < numMips; miplevel++)
                 * {
                 *  byte[] texArray = d.getSection(dataOffset, mipSizes[miplevel]);
                 *
                 *  if (tex.getNutFormat() == 14)
                 *  {
                 *      byte[] oldArray = texArray;
                 *      for (int pos = 0; pos < mipSizes[miplevel]; pos+=4)
                 *      {
                 *
                 *          for (int p = 0; p < 4; p++)
                 *          {
                 *              if (p == 0)
                 *                  texArray[pos + 3] = oldArray[pos];
                 *              else
                 *                  texArray[pos + p - 1] = oldArray[pos + p];
                 *          }
                 *
                 *      }
                 *  }
                 *  tex.mipmaps.Add(texArray);
                 *  dataOffset += mipSizes[miplevel];
                 * }*/
            }

            foreach (NutTexture tex in Nodes)
            {
                if (!draw.ContainsKey(tex.HASHID))
                {
                    draw.Add(tex.HASHID, loadImage(tex, true));
                }
            }
        }
Example #8
0
        public void Read(FileData f)
        {
            f.Endian = Endianness.Little;
            f.seek(4);
            int count = f.readInt();
            f.skip(12);
            int dataCount = f.readInt();
            int boneCount = f.readInt();
            int hashCount = f.readInt();
            int hashOffset = f.readInt() + 0x28;
            f.skip(4);

            Console.WriteLine("Count " + count);

            for (int i = 0; i < dataCount; i++)
            {
                Console.WriteLine("Bone " + i + " start at " + f.pos().ToString("x"));
                // 3 sections
                int secLength = f.readInt();
                int someCount = f.readInt(); // usually 2?

                int size1 = f.readInt();
                Console.Write(size1 + "\t");
                for (int j = 0; j < (size1 / 4) - 1; j++)
                    Console.Write(f.readShort() + " " + f.readShort() + "\t");
                Console.WriteLine();

                int size2 = f.readInt();
                Console.Write(size2 + "\t");
                for (int j = 0; j < (size2 / 4) - 1; j++)
                    Console.Write(f.readShort() + " " + f.readShort() + "\t");
                Console.WriteLine();

                int size3 = f.readInt();
                Console.Write(size3 + "\t");
                for (int j = 0; j < (size3 / 4) - 1; j++)
                    Console.Write(f.readShort() + " " + f.readShort() + "\t");
                Console.WriteLine();

                int size4 = f.readInt();
                Console.Write(size4 + "\t");
                for (int j = 0; j < (size4 / 4) - 1; j++)
                    Console.Write(f.readShort() + " " + f.readShort() + "\t");
                Console.WriteLine();

                int size5 = f.readInt();
                Console.Write(size5 + "\t");
                for (int j = 0; j < (size5 / 4) - 1; j++)
                    Console.Write(f.readShort() + " " + f.readShort() + "\t");
                Console.WriteLine();

                f.skip(8);
            }

            Console.WriteLine("0x" + f.pos().ToString("X"));
            f.skip(8);
            int hashSize = f.readInt();
            int unk = f.readInt();

            for (int i = 0; i < hashCount; i++)
            {
                Console.WriteLine(f.readInt().ToString("X"));
            }
        }
Example #9
0
        public override void Read(string filename)
        {
            FileData f = new FileData(filename);

            header.magic = f.readInt();
            header.unk0  = f.readInt();

            if (header.unk0 == 0x10000000)
            {
                f.Endian = Endianness.Little;

                f.skip(f.pos() - 4);
                header.unk0 = f.readInt();
            }

            header.unk1     = f.readInt();
            header.unk2     = f.readInt();
            header.unk3     = f.readInt();
            header.unk4     = f.readInt();
            header.unk5     = f.readInt();
            header.filesize = f.readInt();
            header.unk6     = f.readInt();
            header.unk7     = f.readInt();
            header.unk8     = f.readInt();
            header.unk9     = f.readInt();
            header.unk10    = f.readInt();
            header.unk11    = f.readInt();
            header.unk12    = f.readInt();
            header.unk13    = f.readInt();

            bool done = false;

            while (!done)
            {
                int tagOffset = f.pos();

                TagType tagType = (TagType)f.readInt();
                int     tagSize = f.readInt(); // in dwords!

                switch (tagType)
                {
                case TagType.Invalid:
                {
                    // uhhh. i think there's a specific exception for this
                    throw new Exception("Malformed file");
                }

                case TagType.Symbols:
                {
                    int numSymbols = f.readInt();

                    while (Strings.Count < numSymbols)
                    {
                        int len = f.readInt();

                        Strings.Add(f.readString());
                        f.skip(4 - (f.pos() % 4));
                    }

                    break;
                }

                case TagType.Colors:
                {
                    int numColors = f.readInt();

                    for (int i = 0; i < numColors; i++)
                    {
                        AddColor(new Vector4(f.readShort() / 256f, f.readShort() / 256f, f.readShort() / 256f, f.readShort() / 256f));
                    }

                    break;
                }

                case TagType.Fonts:
                {
                    unk000A = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.UnkF00A:
                {
                    unkF00A = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.UnkF00B:
                {
                    unkF00B = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.UnkF008:
                {
                    unkF008 = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.UnkF009:
                {
                    unkF009 = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.Defines:
                {
                    Defines = new Properties2(f);
                    break;
                }

                case TagType.ActionScript:
                {
                    Actionscript = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.ActionScript2:
                {
                    Actionscript2 = new UnhandledTag(tagType, tagSize, f);
                    break;
                }

                case TagType.End:
                {
                    done = true;
                    break;
                }

                case TagType.Transforms:
                {
                    int numTransforms = f.readInt();

                    for (int i = 0; i < numTransforms; i++)
                    {
                        float a = f.readFloat();
                        float b = f.readFloat();
                        float c = f.readFloat();
                        float d = f.readFloat();
                        float x = f.readFloat();
                        float y = f.readFloat();

                        var mat = new Matrix4(
                            a, b, 0, 0,
                            c, d, 0, 0,
                            0, 0, 1, 0,
                            x, y, 0, 1
                            );

                        Transforms.Add(mat);
                    }

                    break;
                }

                case TagType.Positions:
                {
                    int numPositions = f.readInt();

                    for (int i = 0; i < numPositions; i++)
                    {
                        Positions.Add(new Vector2(f.readFloat(), f.readFloat()));
                    }

                    break;
                }

                case TagType.Bounds:
                {
                    int numBounds = f.readInt();

                    for (int i = 0; i < numBounds; i++)
                    {
                        Bounds.Add(new Rect(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()));
                    }
                    break;
                }

                case TagType.Properties:
                {
                    properties = new Properties(f);
                    break;
                }

                case TagType.TextureAtlases:
                {
                    int numAtlases = f.readInt();

                    for (int i = 0; i < numAtlases; i++)
                    {
                        TextureAtlas atlas = new TextureAtlas();
                        atlas.id     = f.readInt();
                        atlas.nameId = f.readInt();
                        atlas.width  = f.readFloat();
                        atlas.height = f.readFloat();

                        Atlases.Add(atlas);
                    }

                    break;
                }

                case TagType.Shape:
                {
                    Shapes.Add(new Shape(f));
                    break;
                }

                case TagType.DynamicText:
                {
                    Texts.Add(new DynamicText(f));
                    break;
                }

                case TagType.DefineSprite:
                {
                    Sprites.Add(new Sprite(f));
                    break;
                }

                default:
                {
                    throw new NotImplementedException($"Unhandled tag id: 0x{(uint)tagType:X} @ 0x{tagOffset:X}");
                }
                }
            }
        } // Read()
Example #10
0
        public override void Read(string filename)
        {
            bchHeader header = new bchHeader();
            FileData  f      = new FileData(filename);

            f.Endian = System.IO.Endianness.Little;

            f.skip(4);
            header.backwardCompatibility = f.readByte();
            header.forwardCompatibility  = f.readByte();
            header.version = f.readShort();

            header.mainHeaderOffset  = f.readInt();
            header.stringTableOffset = f.readInt();
            header.gpuCommandsOffset = f.readInt();
            header.dataOffset        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedOffset = f.readInt();
            }
            header.relocationTableOffset = f.readInt();

            header.mainHeaderLength  = f.readInt();
            header.stringTableLength = f.readInt();
            header.gpuCommandsLength = f.readInt();
            header.dataLength        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedLength = f.readInt();
            }
            header.relocationTableLength = f.readInt();

            header.uninitializedDataSectionLength        = f.readInt();
            header.uninitializedDescriptionSectionLength = f.readInt();

            if (header.backwardCompatibility > 7)
            {
                header.flags        = f.readShort();
                header.addressCount = f.readShort();
            }

            // TODO: Finished Relocation table stuff
            for (int i = 0; i < header.relocationTableLength; i += 4)
            {
                f.seek(header.relocationTableOffset + i);
                int  val  = f.readInt();
                int  off  = val & 0x1FFFFFF;
                byte flag = (byte)(val >> 25);

                switch (flag)
                {
                case 0:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset);
                    break;

                case 1:
                    f.seek(off + header.mainHeaderOffset);
                    f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset);
                    break;

                case 2:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset);
                    break;

                case 0xc:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset);
                    break;
                }

                /*f.seek((off * 4) + header.gpuCommandsOffset);
                 * if (header.backwardCompatibility < 6)
                 * {
                 *  switch (flag)
                 *  {
                 *      case 0x23: f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; //Texture
                 *      case 0x25: f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset); break; //Vertex
                 *      // Trying to understand the mess first
                 *      case 0x26: f.writeInt((off * 4) + header.mainHeaderOffset, Convert.ToInt32(((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000)); break; //Index 16 bits mode
                 *                                                                                                                                                           //case 0x27: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode
                 *  }
                 * }
                 *              else if (header.backwardCompatibility < 8)
                 *              {
                 *                  switch (flag)
                 *                  {
                 *                      case 0x24: writer.Write(peek(input) + header.dataOffset); break; //Texture
                 *                      case 0x26: writer.Write(peek(input) + header.dataOffset); break; //Vertex
                 *                      case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                 *                      case 0x28: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode
                 *                  }
                 *              }
                 *              else if (header.backwardCompatibility < 0x21)
                 *              {
                 *                  switch (flag)
                 *                  {
                 *                      case 0x25: writer.Write(peek(input) + header.dataOffset); break; //Texture
                 *                      case 0x27: writer.Write(peek(input) + header.dataOffset); break; //Vertex
                 *                      case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                 *                      case 0x29: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode
                 *                  }
                 *              }
                 *              else
                 *              {
                 *                  switch (flag)
                 *                  {
                 *                      case 0x25: writer.Write(peek(input) + header.dataOffset); break; //Texture
                 *                      case 0x26: writer.Write(peek(input) + header.dataOffset); break; //Vertex relative to Data Offset
                 *                      case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset
                 *                      case 0x28: writer.Write((peek(input) + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset
                 *                      case 0x2b: writer.Write(peek(input) + header.dataExtendedOffset); break; //Vertex relative to Data Extended Offset
                 *                      case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset
                 *                      case 0x2d: writer.Write((peek(input) + header.dataExtendedOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Extended Offset
                 *                  }
                 *              }
                 */
            }


            // Content Header
            f.seek(header.mainHeaderOffset);
            bchContentHeader content = new bchContentHeader();

            {
                content.modelsPointerTableOffset        = f.readInt();
                content.modelsPointerTableEntries       = f.readInt();
                content.modelsNameOffset                = f.readInt();
                content.materialsPointerTableOffset     = f.readInt();
                content.materialsPointerTableEntries    = f.readInt();
                content.materialsNameOffset             = f.readInt();
                content.shadersPointerTableOffset       = f.readInt();
                content.shadersPointerTableEntries      = f.readInt();
                content.shadersNameOffset               = f.readInt();
                content.texturesPointerTableOffset      = f.readInt();
                content.texturesPointerTableEntries     = f.readInt();
                content.texturesNameOffset              = f.readInt();
                content.materialsLUTPointerTableOffset  = f.readInt();
                content.materialsLUTPointerTableEntries = f.readInt();
                content.materialsLUTNameOffset          = f.readInt();
                content.lightsPointerTableOffset        = f.readInt();
                content.lightsPointerTableEntries       = f.readInt();
                content.lightsNameOffset                = f.readInt();
                content.camerasPointerTableOffset       = f.readInt();
                content.camerasPointerTableEntries      = f.readInt();
                content.camerasNameOffset               = f.readInt();
                content.fogsPointerTableOffset          = f.readInt();
                content.fogsPointerTableEntries         = f.readInt();
                content.fogsNameOffset = f.readInt();
                content.skeletalAnimationsPointerTableOffset    = f.readInt();
                content.skeletalAnimationsPointerTableEntries   = f.readInt();
                content.skeletalAnimationsNameOffset            = f.readInt();
                content.materialAnimationsPointerTableOffset    = f.readInt();
                content.materialAnimationsPointerTableEntries   = f.readInt();
                content.materialAnimationsNameOffset            = f.readInt();
                content.visibilityAnimationsPointerTableOffset  = f.readInt();
                content.visibilityAnimationsPointerTableEntries = f.readInt();
                content.visibilityAnimationsNameOffset          = f.readInt();
                content.lightAnimationsPointerTableOffset       = f.readInt();
                content.lightAnimationsPointerTableEntries      = f.readInt();
                content.lightAnimationsNameOffset           = f.readInt();
                content.cameraAnimationsPointerTableOffset  = f.readInt();
                content.cameraAnimationsPointerTableEntries = f.readInt();
                content.cameraAnimationsNameOffset          = f.readInt();
                content.fogAnimationsPointerTableOffset     = f.readInt();
                content.fogAnimationsPointerTableEntries    = f.readInt();
                content.fogAnimationsNameOffset             = f.readInt();
                content.scenePointerTableOffset             = f.readInt();
                content.scenePointerTableEntries            = f.readInt();
                content.sceneNameOffset = f.readInt();
            }

            //Shaders (unused for now, until someone wants to add them)
            for (int index = 0; index < content.shadersPointerTableEntries; index++)
            {
                f.seek(content.shadersPointerTableOffset + (index * 4));
                int dataOffset = f.readInt();
                f.seek(dataOffset);

                int shaderDataOffset = f.readInt();
                int shaderDataLength = f.readInt();
            }

            // Textures
            // WIP Section
            for (int index = 0; index < content.texturesPointerTableEntries; index++)
            {
                f.seek(content.texturesPointerTableOffset + (index * 4));
                int dOffset = f.readInt();
                f.seek(dOffset);
                Debug.WriteLine("dOffset: " + dOffset.ToString("X"));
                int textureCommandsOffset    = f.readInt();
                int textureCommandsWordCount = f.readInt();

                f.seek(f.pos() + 0x14);
                String textureName = f.readString(f.readInt(), -1);
                //Debug.WriteLine("gpuCommandOffset: " + header.gpuCommandsOffset.ToString("X"));
                f.seek(textureCommandsOffset);
                //Debug.WriteLine("textureCommandOffset: " + textureCommandsOffset.ToString("X"));
                BCH_Texture tex = new BCH_Texture();
                textures.Add(textureName, tex);

                tex.height = f.readShort();
                tex.width  = f.readShort();
                f.skip(12);
                int doffset = f.readInt();
                //Debug.WriteLine("doffset: " + doffset.ToString("X"));
                f.skip(4);
                tex.type = f.readInt();
                tex.data = f.getSection(doffset, f.size() - doffset);

                if (tex.type == 12)
                {
                    tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height));
                }
            }

            // Model data

            for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++)
            {
                f.seek(content.modelsPointerTableOffset + (modelIndex * 4));
                int objectsHeaderOffset = f.readInt();

                // Objects
                f.seek(objectsHeaderOffset);
                BCH_Model model = new BCH_Model();
                models.Add(model);

                model.flags                     = f.readByte();
                model.skeletonScaleType         = f.readByte();
                model.silhouetteMaterialEntries = f.readShort();

                model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , 0, 0, 0, 1);

                model.materialsTableOffset  = f.readInt();
                model.materialsTableEntries = f.readInt();
                model.materialsNameOffset   = f.readInt();
                model.verticesTableOffset   = f.readInt();
                //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X"));
                model.verticesTableEntries = f.readInt();
                f.skip(0x28);
                model.skeletonOffset              = f.readInt();
                model.skeletonEntries             = f.readInt();
                model.skeletonNameOffset          = f.readInt();
                model.objectsNodeVisibilityOffset = f.readInt();
                model.objectsNodeCount            = f.readInt();
                model.name = f.readString(f.readInt(), -1);
                model.objectsNodeNameEntries = f.readInt();
                model.objectsNodeNameOffset  = f.readInt();
                f.readInt(); //0x0
                model.metaDataPointerOffset = f.readInt();

                f.seek(model.objectsNodeVisibilityOffset);
                int nodeVisibility = f.readInt();

                string[] objectName = new string[model.objectsNodeNameEntries];
                f.seek(model.objectsNodeNameOffset);
                int rootReferenceBit = f.readInt(); //Radix tree
                int rootLeftNode     = f.readShort();
                int rootRightNode    = f.readShort();
                int rootNameOffset   = f.readInt() + header.mainHeaderOffset;

                for (int i = 0; i < model.objectsNodeNameEntries; i++)
                {
                    int   referenceBit = f.readInt();
                    short leftNode     = (short)f.readShort();
                    short rightNode    = (short)f.readShort();
                    objectName[i] = f.readString(f.readInt(), -1);
                    //Debug.WriteLine(objectName[i]);
                }

                // Materials
                // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM

                String[] materialNames = new String[model.materialsTableEntries];
                for (int index = 0; index < model.materialsTableEntries; index++)
                {
                    f.seek(model.materialsTableOffset + (index * 0x2c));

                    int materialParametersOffset = f.readInt();
                    f.readInt();
                    f.readInt();
                    f.readInt();
                    int textureCommandsOffset    = f.readInt();
                    int textureCommandsWordCount = f.readInt();

                    int materialMapperOffset = f.readInt();
                    materialNames[index] = f.readString(f.readInt(), -1);
                }

                // Object Descriptions...
                // Assumes MBN is already loaded for now
                f.seek(model.verticesTableOffset);
                List <objDes> objDescriptors = new List <objDes>();
                Debug.WriteLine(model.name);
                if (mbn == null)
                {
                    mbn = new Smash_Forge.MBN();
                    for (int index = 0; index < model.verticesTableEntries; index++)
                    {
                        mbn.mesh.Add(new MBN.Mesh());
                    }
                    mbn.PreRender();
                }
                for (int index = 0; index < mbn.mesh.Count; index++)
                {
                    int i = f.readShort();
                    if (index > mbn.mesh.Count)
                    {
                        break;
                    }
                    if (i > materialNames.Length)
                    {
                        break;
                    }
                    mbn.mesh[index].texId = textures[materialNames[i]].display;
                    Console.WriteLine("Tex index" + mbn.mesh[index].texId);
                    f.skip(2); // flags
                    int nameId = f.readShort();
                    mbn.mesh[index].name = objectName[nameId];

                    // node visibility TODO: finish...
                    //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0);

                    mbn.mesh[index].renderPriority = f.readShort();

                    objDes des = new objDes();
                    objDescriptors.Add(des);
                    des.vshAttBufferCommandOffset = f.readInt();
                    des.vshAttBufferCommandCount  = f.readInt();
                    des.faceOffset = f.readInt();
                    des.faceCount  = f.readInt();
                    des.vshAttBufferCommandOffsetEx = f.readInt();
                    des.vshAttBufferCommandCountEx  = f.readInt();

                    f.skip(12);  // center vector
                    f.skip(4);   // flagsOffset
                    f.skip(4);   // 0?
                    f.readInt(); //bbOffsets[i] =  + mainheaderOffset

                    //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X"));
                }


                //Skeleton
                f.seek(model.skeletonOffset);
                for (int index = 0; index < model.skeletonEntries; index++)
                {
                    Bone bone      = new Smash_Forge.Bone(model.skeleton);
                    int  boneFlags = f.readInt();
                    bone.parentIndex = (short)f.readShort();
                    short boneSpace = (short)f.readShort();
                    bone.scale       = new float[3];
                    bone.rotation    = new float[3];
                    bone.position    = new float[3];
                    bone.scale[0]    = f.readFloat();
                    bone.scale[1]    = f.readFloat();
                    bone.scale[2]    = f.readFloat();
                    bone.rotation[0] = f.readFloat();
                    bone.rotation[1] = f.readFloat();
                    bone.rotation[2] = f.readFloat();
                    bone.position[0] = f.readFloat();
                    bone.position[1] = f.readFloat();
                    bone.position[2] = f.readFloat();

                    // bone matrix... not really needed to be stored per say
                    f.skip(4 * 4 * 3);

                    bone.boneName = f.readString(f.readInt(), -1).ToCharArray();

                    f.skip(4); // Meta data

                    model.skeleton.bones.Add(bone);
                }
                model.skeleton.reset();

/*                //Skeletal Animations
 *
 *              SkelAnimation anim = new SkelAnimation();
 *
 *              for (int index = 0; index < content.skeletalAnimationsPointerTableEntries; index++)
 *               {
 *                  f.seek(content.skeletalAnimationsPointerTableOffset + (index * 4));
 *                  int dataOffset = f.readInt();
 *                  f.seek(dataOffset);
 *
 *                  RenderBase.OSkeletalAnimation skeletalAnimation = new RenderBase.OSkeletalAnimation();
 *
 *                  skeletalAnimation.name = f.readString(f.readInt(), -1);
 *                  int animationFlags = f.readInt();
 *                  skeletalAnimation.loopMode = (RenderBase.OLoopMode)(animationFlags & 1);
 *                  skeletalAnimation.frameSize = f.readFloat();
 *                  int boneTableOffset = f.readInt();
 *                  int boneTableEntries = f.readInt();
 *                  int metaDataPointerOffset = f.readInt();
 *
 * //                    /*if (metaDataPointerOffset != 0)
 * //                    {
 * //                        data.Seek(metaDataPointerOffset, SeekOrigin.Begin);
 * //                        skeletalAnimation.userData = getMetaData(input);
 * //                    }
 *
 *                  for (int i = 0; i < boneTableEntries; i++)
 *                  {
 *                      f.seek(boneTableOffset + (i * 4));
 *                      int offset = f.readInt();
 *
 *                      RenderBase.OSkeletalAnimationBone bone = new RenderBase.OSkeletalAnimationBone();
 *
 *                      f.seek(offset);
 *                      bone.name = f.readString(f.readInt(), -1);
 *                      int animationTypeFlags = f.readInt();
 *
 *                      int flags = f.readInt();
 *
 *                      RenderBase.OSegmentType segmentType = (RenderBase.OSegmentType)((animationTypeFlags >> 16) & 0xf);
 *                                      switch (segmentType)
 *                                      {
 *                          case RenderBase.OSegmentType.transform:
 *                              f.seek(offset + 0x18);
 *
 *                              uint notExistMask = 0x80000;
 *                              uint constantMask = 0x200;
 *
 *                              for (int j = 0; j < 2; j++)
 *                              {
 *                                  for (int axis = 0; axis < 3; axis++)
 *                                  {
 *                                      bool notExist = (flags & notExistMask) > 0;
 *                                      bool constant = (flags & constantMask) > 0;
 *
 *                                      RenderBase.OAnimationKeyFrameGroup frame = new RenderBase.OAnimationKeyFrameGroup();
 *                                      frame.exists = !notExist;
 *                                      if (frame.exists)
 *                                      {
 *                                          if (constant)
 *                                          {
 *                                              frame.interpolation = RenderBase.OInterpolationMode.linear;
 *                                              frame.keyFrames.Add(new RenderBase.OAnimationKeyFrame(input.ReadSingle(), 0));
 *                                          }
 *                                          else
 *                                          {
 *                                              int frameOffset = f.readInt();
 *                                              long position = data.Position;
 *                                              f.seek(frameOffset);
 *                                              getAnimationKeyFrame(input, frame);
 *                                              f.seek(position);
 *                                          }
 *                                      }
 *                                      else
 *                                          data.Seek(4, SeekOrigin.Current);
 *
 *                                      if (j == 0)
 *                                      {
 *                                          switch (axis)
 *                                          {
 *                                              case 0: bone.rotationX = frame; break;
 *                                              case 1: bone.rotationY = frame; break;
 *                                              case 2: bone.rotationZ = frame; break;
 *                                          }
 *                                      }
 *                                      else
 *                                      {
 *                                          switch (axis)
 *                                          {
 *                                              case 0: bone.translationX = frame; break;
 *                                              case 1: bone.translationY = frame; break;
 *                                              case 2: bone.translationZ = frame; break;
 *                                          }
 *                                      }
 *
 *                                      notExistMask <<= 1;
 *                                      constantMask <<= 1;
 *                                  }
 *
 *                                  constantMask <<= 1;
 *                              }
 *
 *                              break;
 *                          case RenderBase.OSegmentType.transformQuaternion:
 *                              bone.isFrameFormat = true;
 *
 *                              uint scaleOffset = input.ReadUInt32();
 *                              uint rotationOffset = input.ReadUInt32();
 *                              uint translationOffset = input.ReadUInt32();
 *
 *                              if ((flags & 0x20) == 0)
 *                              {
 *                                  bone.scale.exists = true;
 *                                  data.Seek(scaleOffset, SeekOrigin.Begin);
 *
 *                                  if ((flags & 4) > 0)
 *                                  {
 *                                      bone.scale.vector.Add(new RenderBase.OVector4(
 *                                          input.ReadSingle(),
 *                                          input.ReadSingle(),
 *                                          input.ReadSingle(),
 *                                          0));
 *                                  }
 *                                  else
 *                                  {
 *                                      bone.scale.startFrame = input.ReadSingle();
 *                                      bone.scale.endFrame = input.ReadSingle();
 *
 *                                      uint scaleFlags = input.ReadUInt32();
 *                                      uint scaleDataOffset = input.ReadUInt32();
 *                                      uint scaleEntries = input.ReadUInt32();
 *
 *                                      data.Seek(scaleDataOffset, SeekOrigin.Begin);
 *                                      for (int j = 0; j < scaleEntries; j++)
 *                                      {
 *                                          bone.scale.vector.Add(new RenderBase.OVector4(
 *                                              input.ReadSingle(),
 *                                              input.ReadSingle(),
 *                                              input.ReadSingle(),
 *                                              0));
 *                                      }
 *                                  }
 *                              }
 *
 *                              if ((flags & 0x10) == 0)
 *                                              {
 *                                                  bone.rotationQuaternion.exists = true;
 *                                                  data.Seek(rotationOffset, SeekOrigin.Begin);
 *
 *                                                  if ((flags & 2) > 0)
 *                                                  {
 *                                                      bone.rotationQuaternion.vector.Add(new RenderBase.OVector4(
 *                                                          input.ReadSingle(),
 *                                                          input.ReadSingle(),
 *                                                          input.ReadSingle(),
 *                                                          input.ReadSingle()));
 *                                                  }
 *                                                  else
 *                                                  {
 *                                                      bone.rotationQuaternion.startFrame = input.ReadSingle();
 *                                                      bone.rotationQuaternion.endFrame = input.ReadSingle();
 *
 *                                                      uint rotationFlags = input.ReadUInt32();
 *                                                      uint rotationDataOffset = input.ReadUInt32();
 *                                                      uint rotationEntries = input.ReadUInt32();
 *
 *                                                      data.Seek(rotationDataOffset, SeekOrigin.Begin);
 *                                                      for (int j = 0; j < rotationEntries; j++)
 *                                                      {
 *                                                          bone.rotationQuaternion.vector.Add(new RenderBase.OVector4(
 *                                                              input.ReadSingle(),
 *                                                              input.ReadSingle(),
 *                                                              input.ReadSingle(),
 *                                                              input.ReadSingle()));
 *                                                      }
 *                                                  }
 *                                              }
 *
 *                                              if ((flags & 8) == 0)
 *                                              {
 *                                                  bone.translation.exists = true;
 *                                                  data.Seek(translationOffset, SeekOrigin.Begin);
 *
 *                                                  if ((flags & 1) > 0)
 *                                                  {
 *                                                      bone.translation.vector.Add(new RenderBase.OVector4(
 *                                                          input.ReadSingle(),
 *                                                          input.ReadSingle(),
 *                                                          input.ReadSingle(),
 *                                                          0));
 *                                                  }
 *                                                  else
 *                                                  {
 *                                                      bone.translation.startFrame = input.ReadSingle();
 *                                                      bone.translation.endFrame = input.ReadSingle();
 *
 *                                                      uint translationFlags = input.ReadUInt32();
 *                                                      uint translationDataOffset = input.ReadUInt32();
 *                                                      uint translationEntries = input.ReadUInt32();
 *
 *                                                      data.Seek(translationDataOffset, SeekOrigin.Begin);
 *                                                      for (int j = 0; j < translationEntries; j++)
 *                                                      {
 *                                                          bone.translation.vector.Add(new RenderBase.OVector4(
 *                                                              input.ReadSingle(),
 *                                                              input.ReadSingle(),
 *                                                              input.ReadSingle(),
 *                                                              0));
 *                                                      }
 *                                                  }
 *                                              }
 *
 *                                              break;
 *                                          case RenderBase.OSegmentType.transformMatrix:
 *                                              bone.isFullBakedFormat = true;
 *
 *                                              input.ReadUInt32();
 *                                              input.ReadUInt32();
 *                                              uint matrixOffset = input.ReadUInt32();
 *                                              uint entries = input.ReadUInt32();
 *
 *                                              data.Seek(matrixOffset, SeekOrigin.Begin);
 *                                              for (int j = 0; j < entries; j++)
 *                                              {
 *                                                  RenderBase.OMatrix transform = new RenderBase.OMatrix();
 *                                                  transform.M11 = input.ReadSingle();
 *                                                  transform.M21 = input.ReadSingle();
 *                                                  transform.M31 = input.ReadSingle();
 *                                                  transform.M41 = input.ReadSingle();
 *
 *                                                  transform.M12 = input.ReadSingle();
 *                                                  transform.M22 = input.ReadSingle();
 *                                                  transform.M32 = input.ReadSingle();
 *                                                  transform.M42 = input.ReadSingle();
 *
 *                                                  transform.M13 = input.ReadSingle();
 *                                                  transform.M23 = input.ReadSingle();
 *                                                  transform.M33 = input.ReadSingle();
 *                                                  transform.M43 = input.ReadSingle();
 *
 *                                                  bone.transform.Add(transform);
 *                                              }
 *
 *                                              break;
 *                                          default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.name));
 *                                      }
 *
 *                                      skeletalAnimation.bone.Add(bone);
 *                                  }
 *
 *                                  models.skeletalAnimation.list.Add(skeletalAnimation);
 *                              }
 *
 *                              //Material Animations
 *                              for (int index = 0; index < contentHeader.materialAnimationsPointerTableEntries; index++)
 *                              {
 *                                  data.Seek(contentHeader.materialAnimationsPointerTableOffset + (index * 4), SeekOrigin.Begin);
 *                                  uint dataOffset = input.ReadUInt32();
 *                                  data.Seek(dataOffset, SeekOrigin.Begin);
 *
 *                                  RenderBase.OMaterialAnimation materialAnimation = new RenderBase.OMaterialAnimation();
 *
 *                                  materialAnimation.name = readString(input);
 *                                  uint animationFlags = input.ReadUInt32();
 *                                  materialAnimation.loopMode = (RenderBase.OLoopMode)(animationFlags & 1);
 *                                  materialAnimation.frameSize = input.ReadSingle();
 *                                  uint dataTableOffset = input.ReadUInt32();
 *                                  uint dataTableEntries = input.ReadUInt32();
 *                                  input.ReadUInt32();
 *                                  uint textureNameTableOffset = input.ReadUInt32();
 *                                  uint textureNameTableEntries = input.ReadUInt32();
 *
 *                                  data.Seek(textureNameTableOffset, SeekOrigin.Begin);
 *                                  for (int i = 0; i < textureNameTableEntries; i++)
 *                                  {
 *                                      string name = readString(input);
 *                                      materialAnimation.textureName.Add(name);
 *                                  }
 *
 *                                  for (int i = 0; i < dataTableEntries; i++)
 *                                  {
 *                                      data.Seek(dataTableOffset + (i * 4), SeekOrigin.Begin);
 *                                      uint offset = input.ReadUInt32();
 *
 *                                      RenderBase.OMaterialAnimationData animationData = new RenderBase.OMaterialAnimationData();
 *
 *                                      data.Seek(offset, SeekOrigin.Begin);
 *                                      animationData.name = readString(input);
 *                                      uint animationTypeFlags = input.ReadUInt32();
 *                                      uint flags = input.ReadUInt32();
 *
 *                                      animationData.type = (RenderBase.OMaterialAnimationType)(animationTypeFlags & 0xff);
 *                                      RenderBase.OSegmentType segmentType = (RenderBase.OSegmentType)((animationTypeFlags >> 16) & 0xf);
 *
 *                                      int segmentCount = 0;
 *                                      switch (segmentType)
 *                                      {
 *                                          case RenderBase.OSegmentType.rgbaColor: segmentCount = 4; break;
 *                                          case RenderBase.OSegmentType.vector2: segmentCount = 2; break;
 *                                          case RenderBase.OSegmentType.single: segmentCount = 1; break;
 *                                          case RenderBase.OSegmentType.integer: segmentCount = 1; break;
 *                                      }
 *
 *                                      for (int j = 0; j < segmentCount; j++)
 *                                      {
 *                                          RenderBase.OAnimationKeyFrameGroup frame = new RenderBase.OAnimationKeyFrameGroup();
 *
 *                                          data.Seek(offset + 0xc + (j * 4), SeekOrigin.Begin);
 *
 *                                          frame.exists = (flags & (0x100 << j)) == 0;
 *                                          bool constant = (flags & (1 << j)) > 0;
 *
 *                                          if (frame.exists)
 *                                          {
 *                                              if (constant)
 *                                              {
 *                                                  frame.interpolation = RenderBase.OInterpolationMode.linear;
 *                                                  frame.keyFrames.Add(new RenderBase.OAnimationKeyFrame(input.ReadSingle(), 0));
 *                                              }
 *                                              else
 *                                              {
 *                                                  uint frameOffset = input.ReadUInt32();
 *                                                  data.Seek(frameOffset, SeekOrigin.Begin);
 *                                                  getAnimationKeyFrame(input, frame);
 *                                              }
 *                                          }
 *
 *                                          animationData.frameList.Add(frame);
 *                                      }
 *
 *                                      materialAnimation.data.Add(animationData);
 *                                  }
 *
 *                                  models.materialAnimation.list.Add(materialAnimation);
 *                              }
 *
 */
            }
        }
Example #11
0
        public VBN GetVBN(FileData d)
        {
            VBN v = new VBN();

            d.Endian = Endianness.Big;
            d.seek(8);
            int ver = d.readInt();

            d.skip(4);             //outer offset to brres

            int boneHeader = 0x40; // for version 9 only

            int dlist   = d.readInt();
            int boneSec = d.readInt();
            int vertSec = d.readInt();
            int normSec = d.readInt();
            int colrSec = d.readInt();
            int texcSec = d.readInt();

            d.skip(8);
            int polySec = d.readInt();

            d.seek(0x40);
            d.skip(16);
            int vertCount = d.readInt();
            int faceCount = d.readInt();

            d.skip(4);
            int boneCount = d.readInt();

            v.totalBoneCount = (uint)boneCount;
            for (int i = 0; i < 3; i++)
            {
                v.boneCountPerType[i + 1] = 0;
            }
            d.skip(4);
            int bonetableoff = d.readInt() + boneHeader;

            d.seek(bonetableoff);
            int bcount = d.readInt();

            int[] nodeIndex = new int[bcount];
            for (int i = 0; i < bcount; i++)
            {
                nodeIndex[i] = d.readInt();
            }

            Random rng    = new Random();
            uint   boneID = (uint)rng.Next(1, 0xFFFFFF);

            // BONES-----------------------------------------------
            d.seek(boneSec);
            d.skip(4); // length
            int bseccount = d.readInt();

            for (int i = 0; i < bseccount; i++)
            {
                Debug.Write(i);
                d.skip(4); // entry id and unknown
                d.skip(4); // left and right index
                int name = d.readInt() + boneSec;
                int data = d.readInt() + boneSec;

                int temp = d.pos();
                if (name != boneSec && data != boneSec)
                {
                    // read bone data
                    d.seek(data);
                    d.skip(8);
                    int nameOff = d.readInt() + data;
                    int index   = d.readInt(); // id
                    d.skip(4);                 // index
                    d.skip(8);                 // idk billboard settings and padding
                    Bone n = new Bone(v);

                    n.scale    = new float[3];
                    n.position = new float[3];
                    n.rotation = new float[3];
                    d.skip(4);                     // index

                    n.scale[0]    = d.readFloat();
                    n.scale[1]    = d.readFloat();
                    n.scale[2]    = d.readFloat();
                    n.rotation[0] = toRadians(d.readFloat());
                    n.rotation[1] = toRadians(d.readFloat());
                    n.rotation[2] = toRadians(d.readFloat());
                    n.position[0] = d.readFloat();
                    n.position[1] = d.readFloat();
                    n.position[2] = d.readFloat();

                    n.pos = new Vector3(n.position[0], n.position[1], n.position[2]);
                    n.sca = new Vector3(n.scale[0], n.scale[1], n.scale[2]);
                    n.rot = (VBN.FromEulerAngles(n.rotation [2], n.rotation [1], n.rotation [0]));

                    d.skip(24);

                    d.seek(data + 0x5C);
                    d.seek(d.readInt() + data + 12);
                    int parentid = 0x0FFFFFFF;
                    if (d.pos() != data + 12)
                    {
                        parentid = d.readInt();
                    }
                    n.parentIndex = (int)parentid;

                    n.boneName = d.readString(nameOff, -1).ToCharArray();
                    n.boneId   = boneID;
                    boneID++;

                    v.bones.Add(n);
                }
                else
                {
                    bseccount++;
                }

                d.seek(temp);
            }
            v.update();
            //v.updateChildren();
            v.boneCountPerType[0] = (uint)v.bones.Count;

            return(v);
        }
Example #12
0
        public void read(FileData f)
        {
            base.read(f);

            f.skip(1);
            type = f.readInt(); //2 = sphere, 3 = capsule
            if ((type != 2) && (type != 3))
            {
                throw new NotImplementedException($"Unknown damage shape type {type} at offset {f.pos()-4}");
            }

            x = f.readFloat();
            y = f.readFloat();
            z = f.readFloat();
            if (type == 2)
            {
                radius = f.readFloat();
                dx     = f.readFloat();
                dy     = f.readFloat();
                dz     = f.readFloat();
            }
            else if (type == 3)
            {
                dx     = f.readFloat();
                dy     = f.readFloat();
                dz     = f.readFloat();
                radius = f.readFloat();
            }
            unk = f.readFloat();
            f.skip(0x1);
        }
Example #13
0
        public void read(FileData f)
        {
            base.read(f);

            f.readByte();
            type = f.readInt(); //3 = rect, 4 = path
            if ((type != 3) && (type != 4))
            {
                throw new NotImplementedException($"Unknown general shape type {type} at offset {f.pos()-4}");
            }

            x1 = f.readFloat();
            y1 = f.readFloat();
            x2 = f.readFloat();
            y2 = f.readFloat();

            f.skip(1);
            f.skip(1);
            int pointCount = f.readInt();

            for (int i = 0; i < pointCount; i++)
            {
                f.skip(1);
                points.Add(new Vector2D()
                {
                    x = f.readFloat(), y = f.readFloat()
                });
            }
        }
Example #14
0
        public override void Read(string filename)
        {
            FileData f = new FileData(filename);

            f.Endian = System.IO.Endianness.Little;
            f.skip(4);
            int backwardCompatibility = f.readByte();
            int forwardCompatibility  = f.readByte();
            int version = f.readUShort();

            int mainHeaderOffset   = f.readInt();
            int stringTableOffset  = f.readInt();
            int gpuCommandsOffset  = f.readInt();
            int dataOffset         = f.readInt();
            int dataExtendedOffset = 0;
            int dataExtendedLength = 0;

            if (backwardCompatibility > 0x20)
            {
                dataExtendedOffset = f.readInt();
            }
            int relocationTableOffset = f.readInt();

            int mainHeaderLength  = f.readInt();
            int stringTableLength = f.readInt();
            int gpuCommandsLength = f.readInt();
            int dataLength        = f.readInt();

            if (backwardCompatibility > 0x20)
            {
                dataExtendedLength = f.readInt();
            }
            int relocationTableLength = f.readInt();

            int uninitializedDataSectionLength        = f.readInt();
            int uninitializedDescriptionSectionLength = f.readInt();

            if (backwardCompatibility > 7)
            {
                int flags        = f.readUShort();
                int addressCount = f.readUShort();
            }

            // Relocation table
            for (int i = 0; i < relocationTableLength; i += 4)
            {
                f.seek(relocationTableOffset + i);
                int  val  = f.readInt();
                int  off  = val & 0x1FFFFFF;
                byte flag = (byte)(val >> 25);

                switch (flag)
                {
                case 0:
                    f.seek((off * 4) + mainHeaderOffset);
                    f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + mainHeaderOffset);
                    break;

                case 1:
                    f.seek(off + mainHeaderOffset);
                    f.writeInt((off) + mainHeaderOffset, f.readInt() + stringTableOffset);
                    break;

                case 2:
                    f.seek((off * 4) + mainHeaderOffset);
                    f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + gpuCommandsOffset);
                    break;

                case 0xc:
                    f.seek((off * 4) + mainHeaderOffset);
                    f.writeInt((off * 4) + mainHeaderOffset, f.readInt() + dataOffset);
                    break;
                }

                f.seek((off * 4) + gpuCommandsOffset);
                if (backwardCompatibility < 6)
                {
                    switch (flag)
                    {
                    case 0x23: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Texture

                    case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Vertex

                    //case 0x26: f.writeInt((off * 4) + int gpuCommandsOffset, ((f.readInt() + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x27: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (backwardCompatibility < 8)
                {
                    switch (flag)
                    {
                    case 0x24: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Vertex

                    //case 0x27: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x28: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (backwardCompatibility < 0x21)
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Texture

                    case 0x27: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Vertex

                    //case 0x28: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x29: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataOffset); break;     //Vertex relative to Data Offset

                    //case 0x27: writer.Write(((peek(input) + int dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset
                    case 0x28: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset

                    case 0x2b: f.writeInt((off * 4) + gpuCommandsOffset, f.readInt() + dataExtendedOffset); break;        //Vertex relative to Data Extended Offset

                    //case 0x2c: writer.Write(((peek(input) + int dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset
                    case 0x2d: f.writeInt((off * 4) + gpuCommandsOffset, (f.readInt() + dataExtendedOffset) & 0x7fffffff); break;     //Index 8 bits mode relative to Data Extended Offset
                    }
                }
            }

            //File.WriteAllBytes(filename + "_offset", f.getSection(0, f.size()));

            f.seek(mainHeaderOffset);
            int modelsPointerTableOffset        = f.readInt();
            int modelsPointerTableEntries       = f.readInt();
            int modelsNameOffset                = f.readInt();
            int materialsPointerTableOffset     = f.readInt();
            int materialsPointerTableEntries    = f.readInt();
            int materialsNameOffset             = f.readInt();
            int shadersPointerTableOffset       = f.readInt();
            int shadersPointerTableEntries      = f.readInt();
            int shadersNameOffset               = f.readInt();
            int texturesPointerTableOffset      = f.readInt();
            int texturesPointerTableEntries     = f.readInt();
            int texturesNameOffset              = f.readInt();
            int materialsLUTPointerTableOffset  = f.readInt();
            int materialsLUTPointerTableEntries = f.readInt();
            int materialsLUTNameOffset          = f.readInt();
            int lightsPointerTableOffset        = f.readInt();
            int lightsPointerTableEntries       = f.readInt();
            int lightsNameOffset                = f.readInt();
            int camerasPointerTableOffset       = f.readInt();
            int camerasPointerTableEntries      = f.readInt();
            int camerasNameOffset               = f.readInt();
            int fogsPointerTableOffset          = f.readInt();
            int fogsPointerTableEntries         = f.readInt();
            int fogsNameOffset = f.readInt();
            int skeletalAnimationsPointerTableOffset    = f.readInt();
            int skeletalAnimationsPointerTableEntries   = f.readInt();
            int skeletalAnimationsNameOffset            = f.readInt();
            int materialAnimationsPointerTableOffset    = f.readInt();
            int materialAnimationsPointerTableEntries   = f.readInt();
            int materialAnimationsNameOffset            = f.readInt();
            int visibilityAnimationsPointerTableOffset  = f.readInt();
            int visibilityAnimationsPointerTableEntries = f.readInt();
            int visibilityAnimationsNameOffset          = f.readInt();
            int lightAnimationsPointerTableOffset       = f.readInt();
            int lightAnimationsPointerTableEntries      = f.readInt();
            int lightAnimationsNameOffset           = f.readInt();
            int cameraAnimationsPointerTableOffset  = f.readInt();
            int cameraAnimationsPointerTableEntries = f.readInt();
            int cameraAnimationsNameOffset          = f.readInt();
            int fogAnimationsPointerTableOffset     = f.readInt();
            int fogAnimationsPointerTableEntries    = f.readInt();
            int fogAnimationsNameOffset             = f.readInt();
            int scenePointerTableOffset             = f.readInt();
            int scenePointerTableEntries            = f.readInt();
            int sceneNameOffset = f.readInt();

            Console.WriteLine(modelsPointerTableEntries > 0 ? "Has Models" : "");
            Console.WriteLine(shadersPointerTableEntries > 0 ? "Has Shaders" : "");
            Console.WriteLine(texturesPointerTableEntries > 0 ? "Has Textures" : "");
            Console.WriteLine(materialsPointerTableEntries > 0 ? "Has Materials" : "");
            Console.WriteLine(materialsLUTPointerTableEntries > 0 ? "Has Material LUT" : "");
            Console.WriteLine(materialAnimationsPointerTableEntries > 0 ? "Has Material Animation" : "");
            Console.WriteLine(lightsPointerTableEntries > 0 ? "Has Lights" : "");
            Console.WriteLine(lightAnimationsPointerTableEntries > 0 ? "Has LightAnimations" : "");
            Console.WriteLine(camerasPointerTableEntries > 0 ? "Has Camera" : "");
            Console.WriteLine(cameraAnimationsPointerTableEntries > 0 ? "Has CameraAnimation" : "");
            Console.WriteLine(fogsPointerTableEntries > 0 ? "Has Fog" : "");
            Console.WriteLine(fogAnimationsPointerTableEntries > 0 ? "Has FogAnimation" : "");
            Console.WriteLine(skeletalAnimationsPointerTableEntries > 0 ? "Has Skeletal Animations" : "");
            Console.WriteLine(visibilityAnimationsPointerTableEntries > 0 ? "Has Visibility" : "");
            Console.WriteLine(scenePointerTableEntries > 0 ? "Has Scene" : "");

            // Textures
            for (int index = 0; index < texturesPointerTableEntries; index++)
            {
                f.seek(texturesPointerTableOffset + (index * 4));
                int dOffset = f.readInt();
                f.seek(dOffset);

                // one for each mip I assume
                int textureCommandsOffset     = f.readInt();
                int textureCommandsWordCount  = f.readInt();
                int textureCommandsOffset2    = f.readInt();
                int textureCommandsWordCount2 = f.readInt();
                int textureCommandsOffset3    = f.readInt();
                int textureCommandsWordCount3 = f.readInt();

                int unk = f.readInt();

                BCH_Texture tex = new BCH_Texture();
                tex.Text = f.readString(f.readInt(), -1);
                Textures.Nodes.Add(tex);

                f.seek(textureCommandsOffset);
                tex.ReadParameters(f, textureCommandsWordCount);
            }


            //Models

            for (int index = 0; index < modelsPointerTableEntries; index++)
            {
                f.seek(modelsPointerTableOffset + (index * 4));

                f.seek(f.readInt());

                BCH_Model model = new BCH_Model();
                Models.Nodes.Add(model);
                model.flags                     = f.readByte();
                model.skeletonScaleType         = f.readByte();
                model.silhouetteMaterialEntries = f.readUShort();
                model.worldTransform            = new OpenTK.Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                                     , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                                     , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                                     , 0, 0, 0, 1);

                int materialsTableOffset  = f.readInt();
                int materialsTableEntries = f.readInt();
                int materialNameOffset    = f.readInt();
                int verticesTableOffset   = f.readInt();
                int verticesTableEntries  = f.readInt();
                f.skip(0x28);
                int skeletonOffset              = f.readInt();
                int skeletonEntries             = f.readInt();
                int skeletonNameOffset          = f.readInt();
                int objectsNodeVisibilityOffset = f.readInt();
                int objectsNodeCount            = f.readInt();
                model.Text = f.readString(f.readInt(), -1);
                int objectsNodeNameEntries = f.readInt();
                int objectsNodeNameOffset  = f.readInt();
                f.readInt(); //0x0
                int metaDataPointerOffset = f.readInt();

                f.seek(objectsNodeVisibilityOffset);
                int nodeVisibility = f.readInt();

                string[] objectName = new string[objectsNodeNameEntries];
                f.seek(objectsNodeNameOffset);
                int rootReferenceBit = f.readInt();
                int rootLeftNode     = f.readUShort();
                int rootRightNode    = f.readUShort();
                int rootNameOffset   = f.readInt();

                //Console.WriteLine(rootReferenceBit.ToString("x") + " " + f.readString(rootNameOffset, -1) + " " + rootLeftNode + " " + rootRightNode);
                // Object name tree Radix Tree
                for (int i = 0; i < objectsNodeNameEntries; i++)
                {
                    int   referenceBit = f.readInt();
                    short leftNode     = f.readShort();
                    short rightNode    = f.readShort();
                    objectName[i] = f.readString(f.readInt(), -1);
                    Console.WriteLine((referenceBit >> 3) + " " + (referenceBit & 0x7) + " " + objectName[i] + " " + leftNode + " " + rightNode);
                }

                //TODO: Metadata, boundingbox, normal mesh, materials
                f.seek(verticesTableOffset);
                Dictionary <int, BCH_Mesh> MeshIndex = new Dictionary <int, BCH_Mesh>();
                int nim = 0;
                for (int i = 0; i < verticesTableEntries; i++)
                {
                    BCH_Mesh Mesh = new BCH_Mesh();
                    Mesh.MaterialIndex = f.readUShort();
                    int mflags = f.readUShort();
                    int meshId = f.readUShort();
                    if (!MeshIndex.ContainsKey(meshId))
                    {
                        MeshIndex.Add(meshId, Mesh);
                        Mesh.Text = nim < objectName.Length ? objectName[nim++] : i + "";
                        model.Nodes.Add(Mesh);
                    }
                    else
                    {
                        BCH_Mesh m = MeshIndex[meshId];
                        Mesh.Text = m.Text;
                        model.Nodes.Insert(model.Nodes.IndexOf(m) - 1, Mesh);
                    }

                    // node visibility TODO: finish...
                    Mesh.Checked = ((nodeVisibility & (1 << i)) > 0);

                    Mesh.renderPriority = f.readUShort();

                    int vshAttBufferCommandOffset = f.readInt();
                    int vshAttBufferCommandCount  = f.readInt();
                    int faceOffset = f.readInt();
                    int faceCount  = f.readInt();
                    int vshAttBufferCommandOffsetEx = f.readInt();
                    int vshAttBufferCommandCountEx  = f.readInt();

                    Vector3 Center     = new Vector3(f.readFloat(), f.readFloat(), f.readFloat());
                    int     flagoffset = f.readInt(); // flagsOffset
                    f.skip(4);                        // 0?
                    int boundingBoxOffset = f.readInt();
                }


                //Materials
                Console.WriteLine(materialsTableOffset.ToString("x") + " " + materialsPointerTableOffset.ToString("x"));
                for (int i = 0; i < materialsTableEntries; i++)
                {
                    f.seek(materialsTableOffset + (i * 0x2c));
                    int paramOffset = f.readInt();
                    f.skip(12); // other offsets
                    int texCommandOffset = f.readInt();
                    int texCommandCount  = f.readInt();
                    int mapperOffset     = f.readInt();

                    BCH_Material mat = new BCH_Material();
                    Materials.Nodes.Add(mat);
                    mat.Text = f.readString(f.readInt(), -1);
                    Console.WriteLine(mat.Text);
                    //Console.WriteLine(f.readString(f.readInt(), -1));
                    //Console.WriteLine(f.readString(f.readInt(), -1));
                    //Console.WriteLine(f.readString(f.readInt(), -1));

                    // TODO: Parameters
                }


                //Skeleton
                f.seek(skeletonOffset);
                for (int bindex = 0; bindex < skeletonEntries; bindex++)
                {
                    Bone bone      = new Bone(model.skeleton);
                    int  boneFlags = f.readInt();
                    bone.parentIndex = f.readShort();
                    short boneSpace = f.readShort();
                    bone.scale       = new float[3];
                    bone.rotation    = new float[3];
                    bone.position    = new float[3];
                    bone.scale[0]    = f.readFloat();
                    bone.scale[1]    = f.readFloat();
                    bone.scale[2]    = f.readFloat();
                    bone.rotation[0] = f.readFloat();
                    bone.rotation[1] = f.readFloat();
                    bone.rotation[2] = f.readFloat();
                    bone.position[0] = f.readFloat();
                    bone.position[1] = f.readFloat();
                    bone.position[2] = f.readFloat();

                    // bone matrix... not really needed to be stored per say
                    f.skip(4 * 4 * 3);

                    bone.Text = f.readString(f.readInt(), -1);

                    int metaDataPointerOffset2 = f.readInt();
                    if (metaDataPointerOffset2 != 0)
                    {
                        int position = f.pos();
                        f.seek(metaDataPointerOffset2);
                        //bone.userData = getMetaData(input);
                        f.seek(position);
                    }

                    model.skeleton.bones.Add(bone);
                }
                model.skeleton.reset();
                model.skeleton.update();
            }
        }
Example #15
0
        public override void Read(string filename)
        {
            bchHeader header = new bchHeader();
            FileData  f      = new FileData(filename);

            f.Endian = System.IO.Endianness.Little;

            f.skip(4);
            header.backwardCompatibility = f.readByte();
            header.forwardCompatibility  = f.readByte();
            header.version = f.readShort();

            header.mainHeaderOffset  = f.readInt();
            header.stringTableOffset = f.readInt();
            header.gpuCommandsOffset = f.readInt();
            header.dataOffset        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedOffset = f.readInt();
            }
            header.relocationTableOffset = f.readInt();

            header.mainHeaderLength  = f.readInt();
            header.stringTableLength = f.readInt();
            header.gpuCommandsLength = f.readInt();
            header.dataLength        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedLength = f.readInt();
            }
            header.relocationTableLength = f.readInt();

            header.uninitializedDataSectionLength        = f.readInt();
            header.uninitializedDescriptionSectionLength = f.readInt();

            if (header.backwardCompatibility > 7)
            {
                header.flags        = f.readShort();
                header.addressCount = f.readShort();
            }

            // Relocation table
            for (int i = 0; i < header.relocationTableLength; i += 4)
            {
                f.seek(header.relocationTableOffset + i);
                int  val  = f.readInt();
                int  off  = val & 0x1FFFFFF;
                byte flag = (byte)(val >> 25);

                switch (flag)
                {
                case 0:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset);
                    break;

                case 1:
                    f.seek(off + header.mainHeaderOffset);
                    f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset);
                    break;

                case 2:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset);
                    break;

                case 0xc:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset);
                    break;
                }

                f.seek((off * 4) + header.gpuCommandsOffset);
                if (header.backwardCompatibility < 6)
                {
                    switch (flag)
                    {
                    case 0x23: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex

                    //case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, ((f.readInt() + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (header.backwardCompatibility < 8)
                {
                    switch (flag)
                    {
                    case 0x24: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex

                    //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else if (header.backwardCompatibility < 0x21)
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x27: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex

                    //case 0x28: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode
                    case 0x29: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break;     //Index 8 bits mode
                    }
                }
                else
                {
                    switch (flag)
                    {
                    case 0x25: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Texture

                    case 0x26: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataOffset); break;     //Vertex relative to Data Offset

                    //case 0x27: writer.Write(((peek(input) + header.dataOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Offset
                    case 0x28: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataOffset) & 0x7fffffff); break; //Index 8 bits mode relative to Data Offset

                    case 0x2b: f.writeInt((off * 4) + header.gpuCommandsOffset, f.readInt() + header.dataExtendedOffset); break;        //Vertex relative to Data Extended Offset

                    //case 0x2c: writer.Write(((peek(input) + header.dataExtendedOffset) & 0x7fffffff) | 0x80000000); break; //Index 16 bits mode relative to Data Extended Offset
                    case 0x2d: f.writeInt((off * 4) + header.gpuCommandsOffset, (f.readInt() + header.dataExtendedOffset) & 0x7fffffff); break;     //Index 8 bits mode relative to Data Extended Offset
                    }
                }
            }


            // Content Header
            f.seek(header.mainHeaderOffset);
            bchContentHeader content = new bchContentHeader();

            {
                content.modelsPointerTableOffset        = f.readInt();
                content.modelsPointerTableEntries       = f.readInt();
                content.modelsNameOffset                = f.readInt();
                content.materialsPointerTableOffset     = f.readInt();
                content.materialsPointerTableEntries    = f.readInt();
                content.materialsNameOffset             = f.readInt();
                content.shadersPointerTableOffset       = f.readInt();
                content.shadersPointerTableEntries      = f.readInt();
                content.shadersNameOffset               = f.readInt();
                content.texturesPointerTableOffset      = f.readInt();
                content.texturesPointerTableEntries     = f.readInt();
                content.texturesNameOffset              = f.readInt();
                content.materialsLUTPointerTableOffset  = f.readInt();
                content.materialsLUTPointerTableEntries = f.readInt();
                content.materialsLUTNameOffset          = f.readInt();
                content.lightsPointerTableOffset        = f.readInt();
                content.lightsPointerTableEntries       = f.readInt();
                content.lightsNameOffset                = f.readInt();
                content.camerasPointerTableOffset       = f.readInt();
                content.camerasPointerTableEntries      = f.readInt();
                content.camerasNameOffset               = f.readInt();
                content.fogsPointerTableOffset          = f.readInt();
                content.fogsPointerTableEntries         = f.readInt();
                content.fogsNameOffset = f.readInt();
                content.skeletalAnimationsPointerTableOffset    = f.readInt();
                content.skeletalAnimationsPointerTableEntries   = f.readInt();
                content.skeletalAnimationsNameOffset            = f.readInt();
                content.materialAnimationsPointerTableOffset    = f.readInt();
                content.materialAnimationsPointerTableEntries   = f.readInt();
                content.materialAnimationsNameOffset            = f.readInt();
                content.visibilityAnimationsPointerTableOffset  = f.readInt();
                content.visibilityAnimationsPointerTableEntries = f.readInt();
                content.visibilityAnimationsNameOffset          = f.readInt();
                content.lightAnimationsPointerTableOffset       = f.readInt();
                content.lightAnimationsPointerTableEntries      = f.readInt();
                content.lightAnimationsNameOffset           = f.readInt();
                content.cameraAnimationsPointerTableOffset  = f.readInt();
                content.cameraAnimationsPointerTableEntries = f.readInt();
                content.cameraAnimationsNameOffset          = f.readInt();
                content.fogAnimationsPointerTableOffset     = f.readInt();
                content.fogAnimationsPointerTableEntries    = f.readInt();
                content.fogAnimationsNameOffset             = f.readInt();
                content.scenePointerTableOffset             = f.readInt();
                content.scenePointerTableEntries            = f.readInt();
                content.sceneNameOffset = f.readInt();
            }

            //Shaders (unused for now, until someone wants to add them)
            for (int index = 0; index < content.shadersPointerTableEntries; index++)
            {
                f.seek(content.shadersPointerTableOffset + (index * 4));
                int dataOffset = f.readInt();
                f.seek(dataOffset);

                int shaderDataOffset = f.readInt();
                int shaderDataLength = f.readInt();
            }

            // Textures
            // WIP Section
            for (int index = 0; index < content.texturesPointerTableEntries; index++)
            {
                f.seek(content.texturesPointerTableOffset + (index * 4));
                int dOffset = f.readInt();
                f.seek(dOffset);

                int textureCommandsOffset    = f.readInt();
                int textureCommandsWordCount = f.readInt();

                f.seek(f.pos() + 0x14);
                String textureName = f.readString(f.readInt(), -1);
                //Debug.WriteLine("gpuCommandOffset: " + header.gpuCommandsOffset.ToString("X"));
                f.seek(textureCommandsOffset);
                //Debug.WriteLine("textureCommandOffset: " + textureCommandsOffset.ToString("X"));
                BCH_Texture tex = new BCH_Texture();
                textures.Add(textureName, tex);

                tex.height = f.readShort();
                tex.width  = f.readShort();
                f.skip(12);
                int doffset = f.readInt();
                //Debug.WriteLine("doffset: " + doffset.ToString("X"));
                f.skip(4);
                tex.type = f.readInt();
                tex.data = f.getSection(doffset, f.size() - doffset);

                if (tex.type == 12)
                {
                    tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height));
                }
            }

            // Model data

            for (int modelIndex = 0; modelIndex < content.modelsPointerTableEntries; modelIndex++)
            {
                f.seek(content.modelsPointerTableOffset + (modelIndex * 4));
                int objectsHeaderOffset = f.readInt();

                // Objects
                f.seek(objectsHeaderOffset);
                BCH_Model model = new BCH_Model();
                models.Add(model);

                model.flags                     = f.readByte();
                model.skeletonScaleType         = f.readByte();
                model.silhouetteMaterialEntries = f.readShort();

                model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , 0, 0, 0, 1);

                model.materialsTableOffset  = f.readInt();
                model.materialsTableEntries = f.readInt();
                model.materialsNameOffset   = f.readInt();
                model.verticesTableOffset   = f.readInt();
                //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X"));
                model.verticesTableEntries = f.readInt();
                f.skip(0x28);
                model.skeletonOffset              = f.readInt();
                model.skeletonEntries             = f.readInt();
                model.skeletonNameOffset          = f.readInt();
                model.objectsNodeVisibilityOffset = f.readInt();
                model.objectsNodeCount            = f.readInt();
                model.name = f.readString(f.readInt(), -1);
                model.objectsNodeNameEntries = f.readInt();
                model.objectsNodeNameOffset  = f.readInt();
                f.readInt(); //0x0
                model.metaDataPointerOffset = f.readInt();

                f.seek(model.objectsNodeVisibilityOffset);
                int nodeVisibility = f.readInt();

                string[] objectName = new string[model.objectsNodeNameEntries];
                f.seek(model.objectsNodeNameOffset);
                int rootReferenceBit = f.readInt(); //Radix tree
                int rootLeftNode     = f.readShort();
                int rootRightNode    = f.readShort();
                int rootNameOffset   = f.readInt();

                for (int i = 0; i < model.objectsNodeNameEntries; i++)
                {
                    int   referenceBit = f.readInt();
                    short leftNode     = (short)f.readShort();
                    short rightNode    = (short)f.readShort();
                    objectName[i] = f.readString(f.readInt(), -1);
                    //Debug.WriteLine(objectName[i]);
                }

                // Materials
                // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM

                String[] materialNames = new String[model.materialsTableEntries];
                for (int index = 0; index < model.materialsTableEntries; index++)
                {
                    f.seek(model.materialsTableOffset + (index * 0x2c));

                    int materialParametersOffset = f.readInt();
                    f.readInt();
                    f.readInt();
                    f.readInt();
                    int textureCommandsOffset    = f.readInt();
                    int textureCommandsWordCount = f.readInt();

                    int materialMapperOffset = f.readInt();
                    materialNames[index] = f.readString(f.readInt(), -1);
                }

                // Object Descriptions...
                // Assumes MBN is already loaded for now
                f.seek(model.verticesTableOffset);
                List <objDes> objDescriptors = new List <objDes>();
                Debug.WriteLine(model.name);
                if (mbn == null)
                {
                    mbn = new Smash_Forge.MBN();
                    for (int index = 0; index < model.verticesTableEntries; index++)
                    {
                        mbn.mesh.Add(new MBN.Mesh());
                    }
                    mbn.PreRender();
                }
                for (int index = 0; index < mbn.mesh.Count; index++)
                {
                    int i = f.readShort();
                    if (index > mbn.mesh.Count)
                    {
                        break;
                    }
                    if (i > materialNames.Length)
                    {
                        break;
                    }
                    mbn.mesh[index].texId = textures[materialNames[i]].display;
                    Console.WriteLine("Tex index" + mbn.mesh[index].texId);
                    f.skip(2); // flags
                    int nameId = f.readShort();
                    mbn.mesh[index].name = objectName[nameId];

                    // node visibility TODO: finish...
                    //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0);

                    mbn.mesh[index].renderPriority = f.readShort();

                    objDes des = new objDes();
                    objDescriptors.Add(des);
                    des.vshAttBufferCommandOffset = f.readInt();
                    des.vshAttBufferCommandCount  = f.readInt();
                    des.faceOffset = f.readInt();
                    des.faceCount  = f.readInt();
                    des.vshAttBufferCommandOffsetEx = f.readInt();
                    des.vshAttBufferCommandCountEx  = f.readInt();

                    f.skip(12);  // center vector
                    f.skip(4);   // flagsOffset
                    f.skip(4);   // 0?
                    f.readInt(); //bbOffsets[i]

                    //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X"));
                }

                for (int index1 = 0; index1 < content.skeletalAnimationsPointerTableEntries; index1++)
                {
                    f.seek(content.skeletalAnimationsPointerTableOffset + (index1 * 4));
                    int dataOffset = f.readInt();
                    f.seek(dataOffset);


                    string skeletalAnimationName      = f.readString();
                    int    animationFlags             = f.readInt();
                    int    skeletalAnimationloopMode  = f.readByte();
                    float  skeletalAnimationframeSize = f.readFloat();
                    int    boneTableOffset            = f.readInt();
                    int    boneTableEntries           = f.readInt();
                    int    metaDataPointerOffset      = f.readInt();

                    Console.WriteLine("Animation Name: " + skeletalAnimationName);
                }



                //Skeleton
                f.seek(model.skeletonOffset);
                for (int index = 0; index < model.skeletonEntries; index++)
                {
                    Bone bone      = new Smash_Forge.Bone(model.skeleton);
                    int  boneFlags = f.readInt();
                    bone.parentIndex = (short)f.readShort();
                    short boneSpace = (short)f.readShort();
                    bone.scale       = new float[3];
                    bone.rotation    = new float[3];
                    bone.position    = new float[3];
                    bone.scale[0]    = f.readFloat();
                    bone.scale[1]    = f.readFloat();
                    bone.scale[2]    = f.readFloat();
                    bone.rotation[0] = f.readFloat();
                    bone.rotation[1] = f.readFloat();
                    bone.rotation[2] = f.readFloat();
                    bone.position[0] = f.readFloat();
                    bone.position[1] = f.readFloat();
                    bone.position[2] = f.readFloat();

                    // bone matrix... not really needed to be stored per say
                    f.skip(4 * 4 * 3);

                    bone.Text = f.readString(f.readInt(), -1);

                    f.skip(4); // Meta data

                    model.skeleton.bones.Add(bone);
                }
                model.skeleton.reset();
            }
        }
Example #16
0
        public static Animation readAnim(FileData d, VBN m)
        {
            int offset  = d.readInt();
            int nameoff = d.readInt();

            d.skip(4);
            int fCount        = d.readShort();
            int animDataCount = d.readShort();

            d.skip(8);

            Animation anim = new Animation("CHR0 Import");

            //anim.setModel(m);

            d.seek(offset);
            int sectionOffset = d.readInt() + offset;
            int size          = d.readInt();    // size again

            for (int i = 0; i < size; i++)
            {
                //			System.out.print(d.readShort()); // id
                d.skip(4);                 // id and unknown
                d.readShort();             //left
                d.readShort();             //right
                int nameOffset = d.readInt() + offset;
                int dataOffset = d.readInt() + offset;
                if (dataOffset == offset)
                {
                    i--;
                    continue;
                    //				d.skip(8);
                    //				nameOffset = d.readInt() + 4;
                    //				dataOffset = d.readInt() + offset;
                }


                int temp = d.pos();

                d.seek(dataOffset);

                int pos     = d.pos();
                int nameOff = d.readInt() + sectionOffset + (d.pos() - sectionOffset) - 4;
                int flags   = d.readInt();

                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;

                Animation.KeyNode node = new Animation.KeyNode(d.readString(nameOff, -1));
                anim.Bones.Add(node);
                node.RotType = Animation.RotationType.EULER;

                if (hasS == 1)
                {
                    if (Siso == 1)
                    {
                        float iss = d.readFloat();
                        node.XSCA.Keys.Add(new Animation.KeyFrame()
                        {
                            Frame = 0, Value = iss
                        });
                        node.YSCA.Keys.Add(new Animation.KeyFrame()
                        {
                            Frame = 0, Value = iss
                        });
                        node.ZSCA.Keys.Add(new Animation.KeyFrame()
                        {
                            Frame = 0, Value = iss
                        });
                    }
                    else
                    {
                        if (SXfixed == 1)
                        {
                            node.XSCA.Keys.Add(new Animation.KeyFrame()
                            {
                                Frame = 0, Value = d.readFloat()
                            });
                        }
                        else
                        {
                            process(d, s_type, pos, node, "SX", false, anim);
                        }
                        if (SYfixed == 1)
                        {
                            node.YSCA.Keys.Add(new Animation.KeyFrame()
                            {
                                Frame = 0, Value = d.readFloat()
                            });
                        }
                        else
                        {
                            process(d, s_type, pos, node, "SY", false, anim);
                        }
                        if (SZfixed == 1)
                        {
                            node.ZSCA.Keys.Add(new Animation.KeyFrame()
                            {
                                Frame = 0, Value = d.readFloat()
                            });
                        }
                        else
                        {
                            process(d, s_type, pos, node, "SZ", false, anim);
                        }
                    }
                }

                if (hasR == 1)
                {
                    if (Riso == 1)
                    {
                        float iss = (float)((d.readFloat()) * Math.PI / 180f);
                        node.XROT.Keys.Add(new Animation.KeyFrame()
                        {
                            Frame = 0, Value = iss
                        });
                        node.YROT.Keys.Add(new Animation.KeyFrame()
                        {
                            Frame = 0, Value = iss
                        });
                        node.ZROT.Keys.Add(new Animation.KeyFrame()
                        {
                            Frame = 0, Value = iss
                        });
                    }
                    else
                    {
                        if (RXfixed == 1)
                        {
                            node.XROT.Keys.Add(new Animation.KeyFrame()
                            {
                                Frame = 0, Value = (float)(Math.PI / 180f) * (d.readFloat())
                            });
                        }
                        else
                        {
                            process(d, r_type, pos, node, "RX", false, anim);
                        }
                        if (RYfixed == 1)
                        {
                            node.YROT.Keys.Add(new Animation.KeyFrame()
                            {
                                Frame = 0, Value = (float)(Math.PI / 180f) * (d.readFloat())
                            });
                        }
                        else
                        {
                            process(d, r_type, pos, node, "RY", false, anim);
                        }
                        if (RZfixed == 1)
                        {
                            node.ZROT.Keys.Add(new Animation.KeyFrame()
                            {
                                Frame = 0, Value = (float)(Math.PI / 180f) * (d.readFloat())
                            });
                        }
                        else
                        {
                            process(d, r_type, pos, node, "RZ", false, anim);
                        }
                    }
                }

                if (hasT == 1)
                {
                    if (Tiso == 1)
                    {
                        float iss = d.readFloat();
                        node.XPOS.Keys.Add(new Animation.KeyFrame()
                        {
                            Frame = 0, Value = iss
                        });
                        node.YPOS.Keys.Add(new Animation.KeyFrame()
                        {
                            Frame = 0, Value = iss
                        });
                        node.ZPOS.Keys.Add(new Animation.KeyFrame()
                        {
                            Frame = 0, Value = iss
                        });
                    }
                    else
                    {
                        if (Xfixed == 1)
                        {
                            node.XPOS.Keys.Add(new Animation.KeyFrame()
                            {
                                Frame = 0, Value = d.readFloat()
                            });
                        }
                        else
                        {
                            process(d, t_type, pos, node, "X", false, anim);
                        }
                        if (Yfixed == 1)
                        {
                            node.YPOS.Keys.Add(new Animation.KeyFrame()
                            {
                                Frame = 0, Value = d.readFloat()
                            });
                        }
                        else
                        {
                            process(d, t_type, pos, node, "Y", false, anim);
                        }
                        if (Zfixed == 1)
                        {
                            node.ZPOS.Keys.Add(new Animation.KeyFrame()
                            {
                                Frame = 0, Value = d.readFloat()
                            });
                        }
                        else
                        {
                            process(d, t_type, pos, node, "Z", false, anim);
                        }
                    }
                }

                d.seek(temp);
            }

            return(anim);
        }
Example #17
0
        public override void Read(string filename)
        {
            FileData f = new FileData(filename);

            f.Endian = System.IO.Endianness.Little;

            f.skip(8);
            int mainHeaderOffset      = f.readInt();
            int stringTableOffset     = f.readInt();
            int gpuCommandOffset      = f.readInt();
            int dataOffset            = f.readInt();
            int dataExtendOffset      = f.readInt();
            int relocationTableOffset = f.readInt();

            int mainHeaderLength      = f.readInt();
            int stringTableLength     = f.readInt();
            int gpuCommandLength      = f.readInt();
            int dataLength            = f.readInt();
            int dataExtendLength      = f.readInt();
            int relocationTableLength = f.readInt();

            int datsSecLength = f.readInt();
            int desSecLength  = f.readInt();

            int flags        = f.readShort();
            int addressCount = f.readShort();

            // TODO: Finished Relocation table stuff
            for (int i = 0; i < relocationTableLength; i += 4)
            {
                f.seek(relocationTableOffset + i);
                int  val  = f.readInt();
                int  off  = val & 0x1FFFFFF;
                byte flag = (byte)(val >> 25);

                switch (flag)
                {
                case 0:
                    f.seek((off * 4) + mainHeaderOffset);

                    break;
                }
            }

            // Content Header
            f.seek(mainHeaderOffset);
            int modelsPointerTableOffset        = f.readInt() + mainHeaderOffset;
            int modelsPointerTableEntries       = f.readInt();
            int modelsNameOffset                = f.readInt() + mainHeaderOffset;
            int materialsPointerTableOffset     = f.readInt() + mainHeaderOffset;
            int materialsPointerTableEntries    = f.readInt();
            int materialsNameOffset             = f.readInt() + mainHeaderOffset;
            int shadersPointerTableOffset       = f.readInt() + mainHeaderOffset;
            int shadersPointerTableEntries      = f.readInt();
            int shadersNameOffset               = f.readInt() + mainHeaderOffset;
            int texturesPointerTableOffset      = f.readInt() + mainHeaderOffset;
            int texturesPointerTableEntries     = f.readInt();
            int texturesNameOffset              = f.readInt() + mainHeaderOffset;
            int materialsLUTPointerTableOffset  = f.readInt() + mainHeaderOffset;
            int materialsLUTPointerTableEntries = f.readInt();
            int materialsLUTNameOffset          = f.readInt() + mainHeaderOffset;
            int lightsPointerTableOffset        = f.readInt() + mainHeaderOffset;
            int lightsPointerTableEntries       = f.readInt();
            int lightsNameOffset                = f.readInt() + mainHeaderOffset;
            int camerasPointerTableOffset       = f.readInt() + mainHeaderOffset;
            int camerasPointerTableEntries      = f.readInt();
            int camerasNameOffset               = f.readInt() + mainHeaderOffset;
            int fogsPointerTableOffset          = f.readInt() + mainHeaderOffset;
            int fogsPointerTableEntries         = f.readInt();
            int fogsNameOffset = f.readInt() + mainHeaderOffset;
            int skeletalAnimationsPointerTableOffset    = f.readInt() + mainHeaderOffset;
            int skeletalAnimationsPointerTableEntries   = f.readInt();
            int skeletalAnimationsNameOffset            = f.readInt() + mainHeaderOffset;
            int materialAnimationsPointerTableOffset    = f.readInt() + mainHeaderOffset;
            int materialAnimationsPointerTableEntries   = f.readInt();
            int materialAnimationsNameOffset            = f.readInt() + mainHeaderOffset;
            int visibilityAnimationsPointerTableOffset  = f.readInt() + mainHeaderOffset;
            int visibilityAnimationsPointerTableEntries = f.readInt();
            int visibilityAnimationsNameOffset          = f.readInt() + mainHeaderOffset;
            int lightAnimationsPointerTableOffset       = f.readInt() + mainHeaderOffset;
            int lightAnimationsPointerTableEntries      = f.readInt();
            int lightAnimationsNameOffset           = f.readInt() + mainHeaderOffset;
            int cameraAnimationsPointerTableOffset  = f.readInt() + mainHeaderOffset;
            int cameraAnimationsPointerTableEntries = f.readInt();
            int cameraAnimationsNameOffset          = f.readInt() + mainHeaderOffset;
            int fogAnimationsPointerTableOffset     = f.readInt() + mainHeaderOffset;
            int fogAnimationsPointerTableEntries    = f.readInt();
            int fogAnimationsNameOffset             = f.readInt() + mainHeaderOffset;
            int scenePointerTableOffset             = f.readInt() + mainHeaderOffset;
            int scenePointerTableEntries            = f.readInt();
            int sceneNameOffset = f.readInt() + mainHeaderOffset;

            // Textures
            // WIP Section
            for (int index = 0; index < texturesPointerTableEntries; index++)
            {
                f.seek(texturesPointerTableOffset + (index * 4));
                int dOffset = f.readInt();
                f.seek(dOffset + mainHeaderOffset);

                int textureCommandsOffset    = f.readInt() + gpuCommandOffset;
                int textureCommandsWordCount = f.readInt();

                f.seek(f.pos() + 0x14);
                String textureName = f.readString(f.readInt() + stringTableOffset, -1);

                f.seek(textureCommandsOffset);

                BCH_Texture tex = new BCH_Texture();
                textures.Add(textureName, tex);

                tex.height = f.readShort();
                tex.width  = f.readShort();
                f.skip(12);
                int doffset = f.readInt() + dataOffset;
                f.skip(4);
                tex.type = f.readInt();
                tex.data = f.getSection(doffset, f.size() - doffset);
                if (tex.type == 12)
                {
                    tex.display = NUT.loadImage(Pixel.decodeETC(tex.data, tex.width, tex.height));
                }
            }

            // Model data
            for (int modelIndex = 0; modelIndex < modelsPointerTableEntries; modelIndex++)
            {
                f.seek(modelsPointerTableOffset + (modelIndex * 4));
                int objectsHeaderOffset = f.readInt() + mainHeaderOffset;

                // Objects
                f.seek(objectsHeaderOffset);
                BCH_Model model = new BCH_Model();
                models.Add(model);

                model.flags                     = f.readByte();
                model.skeletonScaleType         = f.readByte();
                model.silhouetteMaterialEntries = f.readShort();

                model.worldTransform = new Matrix4(f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , f.readFloat(), f.readFloat(), f.readFloat(), f.readFloat()
                                                   , 0, 0, 0, 1);

                int materialsTableOffset  = f.readInt() + mainHeaderOffset;
                int materialsTableEntries = f.readInt();
                int materialsNamesOffset  = f.readInt() + mainHeaderOffset;
                int verticesTableOffset   = f.readInt() + mainHeaderOffset;
                //Debug.WriteLine("Mesh Count: " + f.pos().ToString("X"));
                int verticesTableEntries = f.readInt();
                f.skip(0x28);
                int skeletonOffset              = f.readInt() + mainHeaderOffset;
                int skeletonEntries             = f.readInt();
                int skeletonNameOffset          = f.readInt() + mainHeaderOffset;
                int objectsNodeVisibilityOffset = f.readInt() + mainHeaderOffset;
                int objectsNodeCount            = f.readInt();
                model.name = f.readString(f.readInt() + stringTableOffset, -1);
                int objectsNodeNameEntries = f.readInt();
                int objectsNodeNameOffset  = f.readInt() + mainHeaderOffset;
                f.readInt(); //0x0
                int metaDataPointerOffset = f.readInt() + mainHeaderOffset;

                f.seek(objectsNodeVisibilityOffset);
                int nodeVisibility = f.readInt();

                string[] objectName = new string[objectsNodeNameEntries];
                f.seek(objectsNodeNameOffset);
                int rootReferenceBit = f.readInt(); //Radix tree
                int rootLeftNode     = f.readShort();
                int rootRightNode    = f.readShort();
                int rootNameOffset   = f.readInt() + mainHeaderOffset;

                for (int i = 0; i < objectsNodeNameEntries; i++)
                {
                    int   referenceBit = f.readInt();
                    short leftNode     = (short)f.readShort();
                    short rightNode    = (short)f.readShort();
                    objectName[i] = f.readString(f.readInt() + stringTableOffset, -1);
                    //Debug.WriteLine(objectName[i]);
                }

                // Materials
                // NOTE: MATERIALS AND OBJECT SECTIONS ARE REALLY MESSY ATM

                String[] materialNames = new String[materialsTableEntries];
                for (int index = 0; index < materialsTableEntries; index++)
                {
                    f.seek(materialsTableOffset + (index * 0x2c));

                    int materialParametersOffset = f.readInt();
                    f.readInt();
                    f.readInt();
                    f.readInt();
                    int textureCommandsOffset    = f.readInt();
                    int textureCommandsWordCount = f.readInt();

                    int materialMapperOffset = f.readInt();
                    materialNames[index] = f.readString(f.readInt() + stringTableOffset, -1);
                }

                // Object Descriptions...
                // Assumes MBN is already loaded for now
                f.seek(verticesTableOffset);
                List <objDes> objDescriptors = new List <objDes>();
                Debug.WriteLine(model.name);
                if (mbn == null)
                {
                    mbn = new Smash_Forge.MBN();
                    for (int index = 0; index < verticesTableEntries; index++)
                    {
                        mbn.mesh.Add(new MBN.Mesh());
                    }
                    mbn.PreRender();
                }
                for (int index = 0; index < mbn.mesh.Count; index++)
                {
                    int i = f.readShort();
                    if (index > mbn.mesh.Count)
                    {
                        break;
                    }
                    if (i > materialNames.Length)
                    {
                        break;
                    }
                    mbn.mesh[index].texId = textures[materialNames[i]].display;
                    f.skip(2); // flags
                    int nameId = f.readShort();
                    mbn.mesh[index].name = objectName[nameId];

                    // node visibility TODO: finish...
                    //mbn.mesh[index].isVisible = ((nodeVisibility & (1 << nameId)) > 0);

                    mbn.mesh[index].renderPriority = f.readShort();

                    objDes des = new objDes();
                    objDescriptors.Add(des);
                    des.vshAttBufferCommandOffset = f.readInt() + mainHeaderOffset;
                    des.vshAttBufferCommandCount  = f.readInt();
                    des.faceOffset = f.readInt() + mainHeaderOffset;
                    des.faceCount  = f.readInt();
                    des.vshAttBufferCommandOffsetEx = f.readInt() + mainHeaderOffset;
                    des.vshAttBufferCommandCountEx  = f.readInt();

                    f.skip(12);  // center vector
                    f.skip(4);   // flagsOffset
                    f.skip(4);   // 0?
                    f.readInt(); //bbOffsets[i] =  + mainheaderOffset

                    //Debug.WriteLine(des.vshAttBufferCommandOffset.ToString("X"));
                }


                //Skeleton
                f.seek(skeletonOffset);
                for (int index = 0; index < skeletonEntries; index++)
                {
                    Bone bone      = new Smash_Forge.Bone(model.skeleton);
                    int  boneFlags = f.readInt();
                    bone.parentIndex = (short)f.readShort();
                    short boneSpace = (short)f.readShort();
                    bone.scale       = new float[3];
                    bone.rotation    = new float[3];
                    bone.position    = new float[3];
                    bone.scale[0]    = f.readFloat();
                    bone.scale[1]    = f.readFloat();
                    bone.scale[2]    = f.readFloat();
                    bone.rotation[0] = f.readFloat();
                    bone.rotation[1] = f.readFloat();
                    bone.rotation[2] = f.readFloat();
                    bone.position[0] = f.readFloat();
                    bone.position[1] = f.readFloat();
                    bone.position[2] = f.readFloat();

                    // bone matrix... not really needed to be stored per say
                    f.skip(4 * 4 * 3);

                    bone.boneName = f.readString(f.readInt() + stringTableOffset, -1).ToCharArray();

                    f.skip(4); // Meta data

                    model.skeleton.bones.Add(bone);
                }
                model.skeleton.reset();
            }
        }
Example #18
0
        public static void process(FileData d, int type, int secOff, Animation.KeyNode node, String part, bool debug, Animation a)
        {
            int offset = d.readInt() + secOff;
            int temp   = d.pos();

            d.seek(offset);

            int   max    = 0;
            int   fCount = -1;
            float scale  = 0;

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

            if (type == 0x1)
            {
                fCount = d.readShort();
                d.skip(2);
                scale = d.readFloat();
                float stepb = d.readFloat();
                float base2 = d.readFloat();

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

                for (int i = 0; i < fCount; i++)
                {
                    frame[i] = d.readByte();
                    int th = d.readThree();
                    step[i] = base2 + ((th >> 12) & 0xfff) * stepb;
                    tan[i]  = (FileData.sign12Bit(th & 0xfff) / 32f);

                    if (frame[i] > max)
                    {
                        max = (int)frame[i];
                    }
                }
            }

            if (type == 0x2)
            {
                fCount = d.readShort();
                d.skip(2);
                scale = d.readFloat();
                float stepb = d.readFloat();
                float base2 = d.readFloat();

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

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

                    if (frame[i] > max)
                    {
                        max = (int)frame[i];
                    }
                }
            }

            if (type == 0x3)
            {
                //if(debug)
                //System.out.println(part + "\tInterpolated 12 " + Integer.toHexString(offset));

                fCount = d.readShort();
                d.skip(2);
                scale = d.readFloat();

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

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

                    if (frame[i] > max)
                    {
                        max = (int)frame[i];
                    }
                }
            }

            a.FrameCount = max;

            float degrad = (float)(Math.PI / 180f);

            if (frame != null)
            {
                for (int i = 0; i < frame.Length; i++)
                {
                    Animation.KeyFrame f = new Animation.KeyFrame();
                    f.InterType = Animation.InterpolationType.HERMITE;
                    f.Value     = step[i];
                    f.Frame     = frame[i] - 1;
                    f.In        = tan[i];
                    switch (part)
                    {
                    case "RX":
                        f.Value = step[i] * degrad;
                        node.XROT.Keys.Add(f);
                        break;

                    case "RY":
                        f.Value = step[i] * degrad;
                        node.YROT.Keys.Add(f);
                        break;

                    case "RZ":
                        f.Value = step[i] * degrad;
                        node.ZROT.Keys.Add(f);
                        break;

                    case "X":
                        node.XPOS.Keys.Add(f);
                        break;

                    case "Y":
                        node.YPOS.Keys.Add(f);
                        break;

                    case "Z":
                        node.ZPOS.Keys.Add(f);
                        break;

                    case "SX":
                        node.XSCA.Keys.Add(f);
                        break;

                    case "SY":
                        node.YSCA.Keys.Add(f);
                        break;

                    case "SZ":
                        node.ZSCA.Keys.Add(f);
                        break;
                    }
                }
            }

            if (type == 0x4)
            {
                float stepb = d.readFloat();
                float base2 = d.readFloat();
                for (int i = 0; i < a.FrameCount; i++)
                {
                    float v = base2 + stepb * (d.readByte());

                    Animation.KeyFrame f = new Animation.KeyFrame();
                    f.InterType = Animation.InterpolationType.LINEAR;
                    f.Value     = v;
                    f.Frame     = i;

                    switch (part)
                    {
                    case "RX":
                        f.Value = step[i] * degrad;
                        node.XROT.Keys.Add(f);
                        break;

                    case "RY":
                        f.Value = step[i] * degrad;
                        node.YROT.Keys.Add(f);
                        break;

                    case "RZ":
                        f.Value = step[i] * degrad;
                        node.ZROT.Keys.Add(f);
                        break;

                    case "X":
                        node.XPOS.Keys.Add(f);
                        break;

                    case "Y":
                        node.YPOS.Keys.Add(f);
                        break;

                    case "Z":
                        node.ZPOS.Keys.Add(f);
                        break;

                    case "SX":
                        node.XSCA.Keys.Add(f);
                        break;

                    case "SY":
                        node.YSCA.Keys.Add(f);
                        break;

                    case "SZ":
                        node.ZSCA.Keys.Add(f);
                        break;
                    }
                }
            }

            if (type == 0x6)
            {
                for (int i = 0; i < a.FrameCount; i++)
                {
                    float v = d.readFloat();

                    Animation.KeyFrame f = new Animation.KeyFrame();
                    f.InterType = Animation.InterpolationType.LINEAR;
                    f.Value     = v;
                    f.Frame     = i;
                    switch (part)
                    {
                    case "RX":
                        f.Value = step[i] * degrad;
                        node.XROT.Keys.Add(f);
                        break;

                    case "RY":
                        f.Value = step[i] * degrad;
                        node.YROT.Keys.Add(f);
                        break;

                    case "RZ":
                        f.Value = step[i] * degrad;
                        node.ZROT.Keys.Add(f);
                        break;

                    case "X":
                        node.XPOS.Keys.Add(f);
                        break;

                    case "Y":
                        node.YPOS.Keys.Add(f);
                        break;

                    case "Z":
                        node.ZPOS.Keys.Add(f);
                        break;

                    case "SX":
                        node.XSCA.Keys.Add(f);
                        break;

                    case "SY":
                        node.YSCA.Keys.Add(f);
                        break;

                    case "SZ":
                        node.ZSCA.Keys.Add(f);
                        break;
                    }
                }
            }

            d.seek(temp);
        }
Example #19
0
        public void ReadNTWU(FileData d)
        {
            d.skip(0x02);
            int count = d.readShort();

            d.skip(0x10);
            int headerPtr       = d.pos();
            int dataPtr         = 0;
            int gtxHeaderOffset = 0;

            for (int i = 0; i < count; i++)
            {
                NUD_Texture tex = new NUD_Texture();
                tex.type = PixelInternalFormat.Rgba32ui;

                d.seek(headerPtr);
                int totalSize  = d.readInt();
                int headerSize = d.readShort();
                int numMips    = d.readInt();
                tex.setPixelFormatFromNutFormat(d.readShort());
                tex.width  = d.readShort();
                tex.height = d.readShort();

                d.skip(8); // mipmaps and padding
                int dataOffset = d.readInt() + dataPtr + 0x10;

                headerPtr += headerSize;
                dataPtr   += headerSize;

                d.skip(0x04);
                if (i == 0)
                {
                    gtxHeaderOffset = d.readInt() + 0x10;
                }
                else
                {
                    gtxHeaderOffset += 0x80;
                    d.skip(0x04);
                }

                d.skip(0x04);

                // check for cubemap
                bool cmap = (d.readInt() == d.readInt());
                d.seek(d.pos() - 8);
                if (cmap)
                {
                    Console.WriteLine("cubemap detected");
                }

                d.skip(headerSize - 0x50);

                d.skip(0x18);
                tex.id = d.readInt();

                d.seek(gtxHeaderOffset);
                d.skip(0x04); // dim
                d.skip(0x04); // width
                d.skip(0x04); // height
                d.skip(0x04); // depth
                d.skip(0x04); // numMips
                int format = d.readInt();
                d.skip(0x04); // aa
                d.skip(0x04); // use
                int imageSize = d.readInt();
                d.skip(0x04); // imagePtr
                d.skip(0x04); // mipSize
                d.skip(0x04); // mipPtr
                int tileMode = d.readInt();
                int swizzle  = d.readInt();
                d.skip(0x04); // alignment
                int pitch = d.readInt();

                for (int mipLevel = 0; mipLevel < numMips; mipLevel++)
                {
                    // Maybe this is the problem?
                    int mipSize = imageSize >> (mipLevel * 2);
                    int p       = pitch >> mipLevel;

                    //Console.WriteLine(tex.id.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + swizzle);
                    //Console.WriteLine((tex.width >> mipLevel) + " " + (tex.height >> mipLevel));

                    //if (cmap) tex.height *= 2;

                    int w = (tex.width >> mipLevel);
                    int h = (tex.height >> mipLevel);

                    //if (mipSize % 0x10 != 0) mipSize += mipSize % 0x10;
                    //if (cmap) mipSize /= 6;

                    //if (p <= 16) p = 64;
                    {
                        tex.mipmaps.Add(GTX.swizzleBC(
                                            d.getSection(dataOffset, mipSize),
                                            w,
                                            h,
                                            format,
                                            tileMode,
                                            p,
                                            swizzle
                                            ));
                    }
                    dataOffset += mipSize;

                    /*if (cmap)
                     * {
                     *  for(int k = 0; k < 5; k++)
                     *  {
                     *      p = pitch >> (mipLevel + k + 1);
                     *      tex.mipmaps.Add(GTX.swizzleBC(
                     *          d.getSection(dataOffset, mipSize),
                     *          w,
                     *          h,
                     *          format,
                     *          tileMode,
                     *          p,
                     *          swizzle
                     *      ));
                     *
                     *      dataOffset += mipSize;
                     *  }
                     * }*/

                    //while (dataOffset % 1024 != 0) dataOffset++;
                    //if (mipSize == 0x4000) dataOffset += 0x400;
                }

                // fix mipmap swizzle for rgba types
                if (tex.getNutFormat() == 14 || tex.getNutFormat() == 17)
                {
                    Console.WriteLine("Endian swap");
                    // swap
                    foreach (byte[] mip in tex.mipmaps)
                    {
                        for (int t = 0; t < mip.Length; t += 4)
                        {
                            /*byte t1 = mip[t];
                             * byte t2 = mip[t+1];
                             * mip[t] = mip[t + 3];
                             * mip[t + 1] = mip[t + 2];
                             * mip[t + 2] = t2;
                             * mip[t + 3] = t1;*/
                        }
                    }
                }

                textures.Add(tex);
            }

            foreach (var tex in textures)
            {
                if (!draw.ContainsKey(tex.id))
                {
                    draw.Add(tex.id, loadImage(tex));
                }
            }
        }
Example #20
0
        public static SkelAnimation readAnim(FileData d, VBN m)
        {
            int offset  = d.readInt();
            int nameoff = d.readInt();

            d.skip(4);
            int fCount        = d.readShort();
            int animDataCount = d.readShort();

            d.skip(8);

            SkelAnimation anim = new SkelAnimation();

            //anim.setModel(m);

            d.seek(offset);
            int sectionOffset = d.readInt() + offset;
            int size          = d.readInt();    // size again

            for (int i = 0; i < size; i++)
            {
                //			System.out.print(d.readShort()); // id
                d.skip(4);                 // id and unknown
                d.readShort();             //left
                d.readShort();             //right
                int nameOffset = d.readInt() + offset;
                int dataOffset = d.readInt() + offset;
                if (dataOffset == offset)
                {
                    i--;
                    continue;
                    //				d.skip(8);
                    //				nameOffset = d.readInt() + 4;
                    //				dataOffset = d.readInt() + offset;
                }


                int temp = d.pos();

                d.seek(dataOffset);

                int pos     = d.pos();
                int nameOff = d.readInt() + sectionOffset + (d.pos() - sectionOffset) - 4;
                int flags   = d.readInt();

                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;


                if (hasS == 1)
                {
                    if (Siso == 1)
                    {
                        //System.out.println("S is ISO");

                        int     nid  = anim.getNodeIndex(d.readString(nameOff, -1), m);
                        KeyNode node = anim.getNode(0, nid);
                        node.s_type = 1;
                        float iss = d.readFloat();
                        node.s = new OpenTK.Vector3(iss, iss, iss);
                    }
                    else
                    {
                        int     nid  = anim.getNodeIndex(d.readString(nameOff, -1), m);
                        KeyNode node = anim.getNode(0, nid);
                        node.s_type = 1;

                        //					System.out.println("Scale: " + SXfixed + " " + SYfixed + " " + SZfixed + " " + s_type);
                        node.s = new OpenTK.Vector3(-99, -99, -99);
                        if (SXfixed == 1)
                        {
                            node.s.X = d.readFloat();
                        }
                        else
                        {
                            process(d, s_type, pos, anim, "SX", nid, false, m);
                        }
                        if (SYfixed == 1)
                        {
                            node.s.Y = d.readFloat();
                        }
                        else
                        {
                            process(d, s_type, pos, anim, "SY", nid, false, m);
                        }
                        if (SZfixed == 1)
                        {
                            node.s.Z = d.readFloat();
                        }
                        else
                        {
                            process(d, s_type, pos, anim, "SZ", nid, false, m);
                        }
                    }
                }

                if (hasR == 1)
                {
                    if (Riso == 1)
                    {
                        //System.out.println("R is ISO");

                        int     nid  = anim.getNodeIndex(d.readString(nameOff, -1), m);
                        KeyNode node = anim.getNode(0, nid);
                        node.r_type = 1;
                        float iss = (float)((d.readFloat()) * Math.PI / 180f);
                        node.r = VBN.FromEulerAngles(iss, iss, iss);
                    }
                    else
                    {
                        int     nid  = anim.getNodeIndex(d.readString(nameOff, -1), m);
                        KeyNode node = anim.getNode(0, nid);

                        //				System.out.println("Rot: " + RXfixed + " " + RYfixed + " " + RZfixed);

                        node.r = new OpenTK.Quaternion(-99, -99, -99, 0);

                        if (RXfixed == 1)
                        {
                            node.r.X = (float)(Math.PI / 180f) * (d.readFloat());
                        }
                        else
                        {
                            process(d, r_type, pos, anim, "RX", nid, false, m);
                        }
                        if (RYfixed == 1)
                        {
                            node.r.Y = (float)(Math.PI / 180f) * (d.readFloat());
                        }
                        else
                        {
                            process(d, r_type, pos, anim, "RY", nid, false, m);
                        }
                        if (RZfixed == 1)
                        {
                            node.r.Z = (float)(Math.PI / 180f) * (d.readFloat());
                        }
                        else
                        {
                            process(d, r_type, pos, anim, "RZ", nid, false, m);
                        }
                    }
                }

                if (hasT == 1)
                {
                    if (Tiso == 1)
                    {
                        //System.out.println("T is ISO");

                        int     nid  = anim.getNodeIndex(d.readString(nameOff, -1), m);
                        KeyNode node = anim.getNode(0, nid);
                        node.t_type = 1;
                        float iss = d.readFloat();
                        node.t = new OpenTK.Vector3(iss, iss, iss);
                    }
                    else
                    {
                        int     nid  = anim.getNodeIndex(d.readString(nameOff, -1), m);
                        KeyNode node = anim.getNode(0, nid);
                        node.t_type = 1;

                        //					System.out.println("Trans: " + Xfixed + " " + Yfixed + " " + Zfixed);

                        node.t = new OpenTK.Vector3(-99, -99, -99);
                        if (Xfixed == 1)
                        {
                            node.t.X = d.readFloat();
                        }
                        else
                        {
                            process(d, t_type, pos, anim, "X", nid, false, m);
                        }
                        if (Yfixed == 1)
                        {
                            node.t.Y = d.readFloat();
                        }
                        else
                        {
                            process(d, t_type, pos, anim, "Y", nid, false, m);
                        }
                        if (Zfixed == 1)
                        {
                            node.t.Z = d.readFloat();
                        }
                        else
                        {
                            process(d, t_type, pos, anim, "Z", nid, false, m);
                        }
                    }
                }

                d.seek(temp);
            }

            // keynode rotations need caluclation
            foreach (KeyFrame f in anim.frames)
            {
                foreach (KeyNode n in f.nodes)
                {
                    n.r = VBN.FromEulerAngles(n.r.Z, n.r.Y, n.r.X);
                }
            }
            //anim.calcMax();

            return(anim);
        }
Example #21
0
        public void ReadNTWU(FileData d)
        {
            d.skip(0x02);
            int count = d.readShort();

            d.skip(0x10);
            int headerPtr       = d.pos();
            int dataPtr         = 0;
            int gtxHeaderOffset = 0;

            for (int i = 0; i < count; i++)
            {
                NutTexture tex = new NutTexture();
                tex.type = PixelInternalFormat.Rgba32ui;

                d.seek(headerPtr);
                int totalSize  = d.readInt();
                int headerSize = d.readShort();
                int numMips    = d.readInt();
                tex.setPixelFormatFromNutFormat(d.readShort());
                tex.Width  = d.readShort();
                tex.Height = d.readShort();

                d.skip(8); // mipmaps and padding
                int dataOffset = d.readInt() + dataPtr + 0x10;

                headerPtr += headerSize;
                dataPtr   += headerSize;

                d.skip(0x04);
                if (i == 0)
                {
                    gtxHeaderOffset = d.readInt() + 0x10;
                }
                else
                {
                    gtxHeaderOffset += 0x80;
                    d.skip(0x04);
                }

                d.skip(0x04);

                // check for cubemap
                bool cmap = (d.readInt() == d.readInt());
                d.seek(d.pos() - 8);
                if (cmap)
                {
                    Console.WriteLine("cubemap detected");
                }

                d.skip(headerSize - 0x50);

                d.skip(0x18);
                tex.HASHID = d.readInt();

                Console.WriteLine(gtxHeaderOffset.ToString("x"));
                d.seek(gtxHeaderOffset);
                d.skip(0x04);              // dim
                d.skip(0x04);              // width
                d.skip(0x04);              // height
                d.skip(0x04);              // depth
                d.skip(0x04);              // numMips
                int format = d.readInt();
                d.skip(0x04);              // aa
                d.skip(0x04);              // use
                int imageSize = d.readInt();
                d.skip(0x04);              // imagePtr
                int maxSize = d.readInt(); // mipSize
                d.skip(0x04);              // mipPtr
                int tileMode = d.readInt();
                int swizzle  = d.readInt();
                d.skip(0x04); // alignment
                int pitch = d.readInt();

                int ds   = dataOffset;
                int s1   = 0;
                int size = 0;
                Console.WriteLine(totalSize.ToString("x"));
                for (int mipLevel = 0; mipLevel < numMips; mipLevel++)
                {
                    // Maybe this is the problem?
                    int mipSize = imageSize >> (mipLevel * 2);
                    int p       = pitch >> mipLevel;

                    size = d.readInt();
                    //Console.WriteLine("\tMIP: " + size.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + (size == 0 ? ds + totalSize - dataOffset : size));

                    //Console.WriteLine(tex.id.ToString("x") + " " + dataOffset.ToString("x") + " " + mipSize.ToString("x") + " " + p + " " + swizzle);
                    //Console.WriteLine((tex.width >> mipLevel) + " " + (tex.height >> mipLevel));

                    //if (cmap) tex.height *= 2;

                    int w = (tex.Width >> mipLevel);
                    int h = (tex.Height >> mipLevel);

                    {
                        byte[] deswiz = GTX.swizzleBC(
                            d.getSection(dataOffset, d.size() - dataOffset),
                            w,
                            h,
                            format,
                            tileMode,
                            p,
                            swizzle
                            );
                        tex.mipmaps.Add(new FileData(deswiz).getSection(0, mipSize));
                    }
                    if (mipLevel == 0)
                    {
                        s1         = size;
                        dataOffset = ds + size;
                    }
                    else
                    {
                        dataOffset = ds + s1 + size;
                    }
                    //dataOffset += mipSize;

                    /*if (cmap)
                     * {
                     *  for(int k = 0; k < 5; k++)
                     *  {
                     *      p = pitch >> (mipLevel + k + 1);
                     *      tex.mipmaps.Add(GTX.swizzleBC(
                     *          d.getSection(dataOffset, mipSize),
                     *          w,
                     *          h,
                     *          format,
                     *          tileMode,
                     *          p,
                     *          swizzle
                     *      ));
                     *
                     *      dataOffset += mipSize;
                     *  }
                     * }*/

                    //while (dataOffset % 1024 != 0) dataOffset++;
                    //if (mipSize == 0x4000) dataOffset += 0x400;
                }

                Nodes.Add(tex);
            }

            foreach (NutTexture tex in Nodes)
            {
                if (!draw.ContainsKey(tex.HASHID))
                {
                    draw.Add(tex.HASHID, loadImage(tex, false));
                }

                // redo mipmaps

                /*GL.BindTexture(TextureTarget.Texture2D, draw[tex.id]);
                 * for (int k = 1; k < tex.mipmaps.Count; k++)
                 * {
                 *  tex.mipmaps[k] = new byte[tex.mipmaps[k].Length];
                 *  GCHandle pinnedArray = GCHandle.Alloc(tex.mipmaps[k], GCHandleType.Pinned);
                 *  IntPtr pointer = pinnedArray.AddrOfPinnedObject();
                 *  GL.GetCompressedTexImage(TextureTarget.Texture2D, 0, pointer);
                 *  pinnedArray.Free();
                 * }*/
            }


            //File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\mip1.bin", bytearray);

            //Console.WriteLine(GL.GetError());

            /*int j = 0;
             * foreach(byte[] b in textures[0].mipmaps)
             * {
             *  if (j == 3)
             *  {
             *      for(int w = 3; w < 8; w++)
             *      {
             *          for (int p = 3; p < 6; p++)
             *          {
             *              byte[] deswiz = GTX.swizzleBC(
             *                  b,
             *                  (int)Math.Pow(2, w),
             *                  64,
             *                  51,
             *                  4,
             *                   (int)Math.Pow(2, p),
             *                  197632
             *              );
             *              File.WriteAllBytes("C:\\s\\Smash\\extract\\data\\fighter\\duckhunt\\model\\body\\chunk_" + (int)Math.Pow(2, p) + "_" + (int)Math.Pow(2, w), deswiz);
             *          }
             *      }
             *
             *  }
             *  j++;
             * }*/
        }
Example #22
0
        public static void process(FileData d, int type, int secOff, SkelAnimation anim, String part, int nid, bool debug, VBN vbn)
        {
            int offset = d.readInt() + secOff;
            int temp   = d.pos();

            d.seek(offset);
            //		System.out.println(d.pos());

            int   max    = 0;
            int   fCount = -1;
            float scale  = 0;

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

            if (type == 0x1)
            {
                fCount = d.readShort();
                d.skip(2);
                scale = d.readFloat();
                float stepb = d.readFloat();
                float base2 = d.readFloat();

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

                for (int i = 0; i < fCount; i++)
                {
                    frame[i] = d.readByte();
                    int th = d.readThree();
                    step[i] = base2 + ((th >> 12) & 0xfff) * stepb;
                    tan[i]  = (FileData.sign12Bit(th & 0xfff) / 32f);

                    if (frame[i] > max)
                    {
                        max = (int)frame[i];
                    }
                }
            }

            if (type == 0x2)
            {
                //if(debug)
                //System.out.println(part + "\tInterpolated 6\t" + Integer.toHexString(offset));

                fCount = d.readShort();
                d.skip(2);
                scale = d.readFloat();
                float stepb = d.readFloat();
                float base2 = d.readFloat();

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

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

                    if (frame[i] > max)
                    {
                        max = (int)frame[i];
                    }
                }
            }

            if (type == 0x3)
            {
                //if(debug)
                //System.out.println(part + "\tInterpolated 12 " + Integer.toHexString(offset));

                fCount = d.readShort();
                d.skip(2);
                scale = d.readFloat();

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

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

                    if (frame[i] > max)
                    {
                        max = (int)frame[i];
                    }
                }
            }

            if (frame != null)
            {
                generateInter(anim, max, nid, part, frame, tan, step, vbn);
            }

            if (type == 0x4)
            {
                //if(debug)
                //System.out.println(part + "\tLkin 1 " + Integer.toHexString(offset) + " " + anim.size());
                float stepb = d.readFloat();
                float base2 = d.readFloat();
                for (int i = 0; i < anim.size(); i++)
                {
                    KeyNode n = anim.getNode(i, nid);

                    if (part.Contains("R"))
                    {
                        n.r_type = 1;
                    }
                    else
                    if (part.Contains("S"))
                    {
                        n.s_type = 1;
                    }
                    else
                    {
                        n.t_type = 1;
                    }

                    float v = base2 + stepb * (d.readByte());
                    //				float f = d.readFloat();
                    //				System.out.println(stepb + " " + base + " " + (byte)d.readByte());

                    switch (part)
                    {
                    case "RX":
                        n.r.X = (float)(Math.PI / 180f) * (v);
                        break;

                    case "RY":
                        n.r.Y = (float)(Math.PI / 180f) * (v);
                        break;

                    case "RZ":
                        n.r.Z = (float)(Math.PI / 180f) * (v);
                        break;

                    case "X":
                        n.t.X = v;
                        break;

                    case "Y":
                        n.t.Y = v;
                        break;

                    case "Z":
                        n.t.Z = v;
                        break;

                    case "SX":
                        n.s.X = v;
                        break;

                    case "SY":
                        n.s.Y = v;
                        break;

                    case "SZ":
                        n.s.Z = v;
                        break;
                    }
                }

                //			System.out.println(d.pos());
            }

            if (type == 0x6)
            {
                //if(debug)
                //System.out.println(part + "\tLin 4");
                for (int i = 0; i < anim.size(); i++)
                {
                    KeyNode n = anim.getNode(i, nid);

                    if (part.Contains("R"))
                    {
                        n.r_type = 1;
                    }
                    else
                    if (part.Contains("S"))
                    {
                        n.s_type = 1;
                    }
                    else
                    {
                        n.t_type = 1;
                    }

                    float v = d.readFloat();

                    switch (part)
                    {
                    case "RX":
                        n.r.X = (float)(Math.PI / 180) * (v);
                        break;

                    case "RY":
                        n.r.Y = (float)(Math.PI / 180) * (v);
                        break;

                    case "RZ":
                        n.r.Z = (float)(Math.PI / 180) * (v);
                        break;

                    case "X":
                        n.t.X = v;
                        break;

                    case "Y":
                        n.t.Y = v;
                        break;

                    case "Z":
                        n.t.Z = v;
                        break;

                    case "SX":
                        n.s.X = v;
                        break;

                    case "SY":
                        n.s.Y = v;
                        break;

                    case "SZ":
                        n.s.Z = v;
                        break;
                    }
                }
            }

            d.seek(temp);
        }
Example #23
0
        public void Read(FileData d)
        {
            d.Endian = System.IO.Endianness.Big;
            d.seek(4); // skip filesize
            int dataSize         = d.readInt();
            int offsetTableCount = d.readInt();
            int rootA            = d.readInt();
            int headerSize       = 0x20;

            int rootOffset = headerSize + dataSize + offsetTableCount * 4;

            d.seek(rootOffset);
            int figtree = d.readInt() + headerSize;

            d.skip(4);
            String name = d.readString(d.pos(), -1);

            this.Name = name;

            d.seek(figtree);
            d.skip(8);
            float frameCount = d.readFloat();
            int   keyOffset  = d.readInt();

            if (Debug)
            {
                Console.WriteLine(name + "\tCount: " + frameCount);
            }
            this.frameCount = (int)frameCount;

            int temp = d.pos();

            d.seek(keyOffset + 0x20);
            //int boneCount = 0x2E; // TODO: Use actual bone count 0x35
            List <int> keyFrameCount = new List <int>();
            int        bid           = d.readByte();

            while (bid != 0xFF)
            {
                keyFrameCount.Add(bid);
                bid = d.readByte();
                nodes.Add(new List <DATAnimTrack>());
            }
            int boneCount = keyFrameCount.Count;

            if (Debug)
            {
                Console.WriteLine(boneCount);
            }

            d.seek(temp);

            int animDataOffset = 0;

            int[] trackcount = new int[offsetTableCount];
            for (int i = 0; i < offsetTableCount; i++)
            {
                trackcount[i] = d.readInt();
                if (i == 0)
                {
                    animDataOffset = trackcount[i];
                }
            }

            d.seek(animDataOffset + 0x20);
            for (int i = 0; i < boneCount; i++)
            { // bonecount
                if (Debug)
                {
                    Console.WriteLine("Bone " + i + ": " + keyFrameCount[i] + "\t" + d.pos().ToString("x"));
                }

                for (int j = 0; j < keyFrameCount[i]; j++)
                {
                    int length = d.readShort();
                    d.skip(2);
                    int trackType   = d.readByte();
                    int valueFormat = d.readByte();
                    int tanFormat   = d.readByte();
                    d.skip(1);
                    int dataoff = d.readInt() + 0x20;

                    if (Debug)
                    {
                        Console.WriteLine((AnimType)trackType + "\tLength: " + length + "\tOffset: " + dataoff.ToString("x") + " " + valueFormat.ToString("x") + " " + tanFormat.ToString("x"));
                    }
                    // System.out.println(valueFormat + " " + tanFormat);
                    readKeyFrame(d, length, dataoff, valueFormat, tanFormat, keyFrameCount[i], i, trackType);
                }
            }
        }
Example #24
0
        public static SkelAnimation read(FileData d)
        {
            d.Endian = Endianness.Big;

            d.skip(4); // header OMO
            d.skip(4); // two shorts, idk

            d.skip(4); //flags?

            d.skip(2);
            int numOfBones = d.readShort();
            int frameSize  = d.readShort();
            int frameStart = d.readShort();

            int offset1 = d.readInt();
            int offset2 = d.readInt();
            int offset3 = d.readInt();

            SkelAnimation anim = new SkelAnimation();

            anim.Tag = d;
            //anim.setModel(m);

            // base frames
            // These are linked to bones somehow, hash??
            d.seek(offset1); //
            int[]     framekey = new int[numOfBones];
            KeyNode[] baseNode = new KeyNode[numOfBones];

            for (int i = 0; i < numOfBones; i++)
            {
                flagsused = flagsused | d.readInt(); d.seek(d.pos() - 4);
                //Console.WriteLine(flagsused.ToString("x"));

                int flags = d.readByte();
                int tFlag = d.readByte();
                int rFlag = d.readByte();
                int sFlag = d.readByte();
                int hash  = d.readInt(); // used to find the identifying bone
                int off1  = d.readInt() + offset2;
                framekey[i] = d.readInt();

                bool hasTrans = (flags & 0x01) == 0x01;
                bool hasScale = (flags & 0x04) == 0x04;
                bool hasRot   = (flags & 0x02) == 0x02;

                KeyNode node = new KeyNode();
                baseNode[i] = node;

                node.hash = (uint)hash;

                int temp = d.pos();
                d.seek(off1);

                if (hasTrans)
                {
                    if (tFlag == 0x8)
                    { // interpolated
                        node.t_type = KeyNode.INTERPOLATED;
                        node.t      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.t2     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                    else if (tFlag == 0x20)
                    {
                        node.t_type = KeyNode.CONSTANT;
                        node.t      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                }
                if (hasRot)
                {
                    if ((rFlag & 0xF) != 0x50 && (rFlag & 0xF0) != 0x70 && (rFlag & 0xF0) != 0x60 && (rFlag & 0xF0) != 0xA0)
                    {
                        //Console.WriteLine(rFlag);
                    }

                    if ((rFlag & 0xF0) == 0xA0)
                    {
                        node.r_type = 3;
                    }

                    if ((rFlag & 0xF0) == 0x50)
                    { // interpolated
                        node.r_type = KeyNode.INTERPOLATED;
                        node.rv     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.rv2    = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                    if ((rFlag & 0xF0) == 0x70 || (rFlag & 0xF0) == 0x60)
                    { // constant
                        node.r_type = KeyNode.CONSTANT;
                        node.rv     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        if ((rFlag & 0xF0) == 0x60)
                        {
                            d.skip(4);
                        }
                    }
                }

                if (hasScale)
                {
                    if ((sFlag & 0xF0) == 0x80)
                    { // interpolated
                        node.s_type = KeyNode.INTERPOLATED;
                        node.s      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.s2     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                    if ((rFlag & 0x0F) == 0x02 || (rFlag & 0x0F) == 0x03)
                    { // constant
                        node.s_type = KeyNode.CONSTANT;
                        node.s      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                }
                d.seek(temp);
            }

            d.seek(offset3);
            for (int i = 0; i < frameSize; i++)
            {
                KeyFrame key = new KeyFrame();
                key.frame = i;

                int off = d.pos();

                for (int j = 0; j < numOfBones; j++)
                {
                    KeyNode node = new KeyNode();

                    node.t_type = baseNode[j].t_type;
                    node.r_type = baseNode[j].r_type;
                    node.s_type = baseNode[j].s_type;

                    node.id   = baseNode[j].id;
                    node.hash = baseNode[j].hash;

                    d.seek(off + framekey[j]);

                    if (baseNode[j].t_type == KeyNode.INTERPOLATED)
                    {
                        float i1 = ((float)d.readShort() / 0xffff);
                        float i2 = ((float)d.readShort() / 0xffff);
                        float i3 = ((float)d.readShort() / 0xffff);

                        float x = baseNode[j].t.X + (baseNode[j].t2.X * (i1));
                        float y = baseNode[j].t.Y + (baseNode[j].t2.Y * (i2));
                        float z = baseNode[j].t.Z + (baseNode[j].t2.Z * (i3));

                        node.t = new Vector3(x, y, z);
                    }
                    else
                    {
                        node.t = baseNode[j].t;
                    }

                    if (baseNode[j].r_type == 3)
                    {
                        int   v  = short.MaxValue;
                        float i1 = ((float)((short)d.readShort()) / v);
                        float i2 = ((float)((short)d.readShort()) / v);
                        float i3 = ((float)((short)d.readShort()) / v);
                        float i4 = ((float)((short)d.readShort()) / v);

                        node.r = new Quaternion(new Vector3(i1, i2, i3), i4);
                        //Console.WriteLine(node.r.ToString());
                        //node.r = VBN.FromEulerAngles(i4 * i1, i4 * i2, i4 * i3);
                        node.r_type = KeyNode.INTERPOLATED;
                        //node.r.Normalize();
                    }
                    else
                    if (baseNode[j].r_type == KeyNode.INTERPOLATED)
                    {
                        float i1 = ((float)d.readShort() / (0xffff));
                        float i2 = ((float)d.readShort() / (0xffff));
                        float i3 = ((float)d.readShort() / (0xffff));

                        float x = baseNode[j].rv.X + (baseNode[j].rv2.X * (i1));
                        float y = baseNode[j].rv.Y + (baseNode[j].rv2.Y * (i2));
                        float z = baseNode[j].rv.Z + (baseNode[j].rv2.Z * (i3));

                        float w = (float)Math.Sqrt(Math.Abs(1 - (x * x + y * y + z * z)));

                        node.r = new Quaternion(new Vector3(x, y, z), w);
                        node.r.Normalize();
                    }
                    else
                    {
                        float x = baseNode[j].rv.X;
                        float y = baseNode[j].rv.Y;
                        float z = baseNode[j].rv.Z;

                        float w = (float)Math.Sqrt(1 - (x * x + y * y + z * z));

                        node.r = new Quaternion(baseNode[j].rv, w);
                    }

                    if (baseNode[j].s_type == KeyNode.INTERPOLATED)
                    {
                        float i1 = ((float)d.readShort() / (0xffff));
                        float i2 = ((float)d.readShort() / (0xffff));
                        float i3 = ((float)d.readShort() / (0xffff));

                        float x = baseNode[j].s.X + (baseNode[j].s2.X * (i1));
                        float y = baseNode[j].s.Y + (baseNode[j].s2.Y * (i2));
                        float z = baseNode[j].s.Z + (baseNode[j].s2.Z * (i3));

                        node.s = new Vector3(x, y, z);
                    }
                    else
                    {
                        node.s = baseNode[j].s;
                    }

                    key.addNode(node);
                }
                d.seek(off + frameStart);

                anim.addKeyframe(key);
            }

            return(anim);
        }
Example #25
0
        public static Animation read(FileData d)
        {
            d.Endian = Endianness.Big;

            d.skip(4); // header OMO
            d.skip(4); // two shorts, idk

            d.skip(4); //flags?

            d.skip(2);
            int boneCount  = d.readShort();
            int frameCount = d.readShort();
            int frameSize  = d.readShort();

            int offset1 = d.readInt();  // nodeOffset
            int offset2 = d.readInt();  // interOffset
            int offset3 = d.readInt();  // keyOffset

            SkelAnimation anim = new SkelAnimation();

            anim.Tag = d;

            if (boneCount > offset2 / 0x10)
            {
                boneCount = offset2 / 0x10;
                anim.Tag  = null;
            }

            // base frames
            // These are linked to bones via hashes
            d.seek(offset1); //
            int[]     framekey = new int[boneCount];
            KeyNode[] baseNode = new KeyNode[boneCount];

            // Start positions for bones/nodes
            for (int i = 0; i < boneCount; i++)
            {
                flagsused = flagsused | d.readInt(); d.seek(d.pos() - 4);
                //Console.WriteLine(flagsused.ToString("x"));

                int flags = d.readByte();
                int tFlag = d.readByte();
                int rFlag = d.readByte();
                int sFlag = d.readByte();
                int hash  = d.readInt(); // used to find the identifying bone
                int off1  = d.readInt() + offset2;
                framekey[i] = d.readInt();

                bool hasTrans = (flags & 0x01) == 0x01;
                bool hasScale = (flags & 0x04) == 0x04;
                bool hasRot   = (flags & 0x02) == 0x02;

                KeyNode node = new KeyNode();
                baseNode[i] = node;

                node.hash = (uint)hash;

                int temp = d.pos();
                d.seek(off1);

                if (hasTrans)
                {
                    if (tFlag == 0x8)
                    { // interpolated
                        node.t_type = KeyNode.INTERPOLATED;
                        node.t      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.t2     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                    else if (tFlag == 0x20)
                    {
                        node.t_type = KeyNode.CONSTANT;
                        node.t      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                    else if (tFlag == 0x4)
                    {
                        // entire Vector3 provided in keyframe data i.e. KEYFRAME type
                        node.t_type = KeyNode.KEYFRAME;
                    }
                }
                if (hasRot)
                {
                    if ((rFlag & 0xF0) != 0x50 && (rFlag & 0xF0) != 0x70 && (rFlag & 0xF0) != 0x60 && (rFlag & 0xF0) != 0xA0)
                    {
                        //Console.WriteLine(rFlag);
                    }

                    if ((rFlag & 0xF0) == 0xA0)
                    {
                        // All data is in the keyframe for this type
                        node.r_type = KeyNode.COMPRESSED;
                    }

                    if ((rFlag & 0xF0) == 0x50)
                    { // interpolated
                        node.r_type = KeyNode.INTERPOLATED;
                        node.rv     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.rv2    = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }

                    if ((rFlag & 0xF0) == 0x60)
                    {
                        node.r_type  = KeyNode.KEYFRAME;
                        node.rv      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.r_extra = d.readFloat() / 65535;
                    }

                    if ((rFlag & 0xF0) == 0x70)
                    {
                        node.r_type = KeyNode.CONSTANT;
                        node.rv     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                }

                if (hasScale)
                {
                    if ((sFlag & 0xF0) == 0x80)
                    { // interpolated
                        node.s_type = KeyNode.INTERPOLATED;
                        node.s      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                        node.s2     = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                    // TODO: investigate the difference between these
                    if ((rFlag & 0x0F) == 0x02 || (rFlag & 0x0F) == 0x03)
                    { // constant
                        node.s_type = KeyNode.CONSTANT;
                        node.s      = new Vector3(d.readFloat(), d.readFloat(), d.readFloat());
                    }
                }
                d.seek(temp);
            }

            // Interpolated type below here is always a set translation/rotation/scale
            // from the coords specified with the bone node above

            Animation a = new Animation("Anim");

            a.Tag        = anim.Tag;
            a.FrameCount = frameCount;

            d.seek(offset3);

            for (int j = 0; j < boneCount; j++)
            {
                string bid  = "";
                int    hash = -1;
                if (!MainForm.Hashes.ids.TryGetValue(baseNode[j].hash, out bid))
                {
                    hash = (int)baseNode[j].hash;
                }
                Animation.KeyNode n = new Animation.KeyNode(bid);
                n.Hash = hash;
                a.Bones.Add(n);
                n.Type = Animation.BoneType.NORMAL;

                /*foreach (ModelContainer con in Runtime.ModelContainers)
                 *  if (con.VBN != null)
                 *      bid = con.VBN.getBone(baseNode[j].hash) == null ? "" : con.VBN.getBone(baseNode[j].hash).Text;*/

                for (int i = 0; i < a.FrameCount; i++)
                {
                    d.seek(offset3 + frameSize * i + framekey[j]);

                    if (baseNode[j].t_type == KeyNode.INTERPOLATED)
                    {
                        float i1 = ((float)d.readShort() / 0xffff);
                        float i2 = ((float)d.readShort() / 0xffff);
                        float i3 = ((float)d.readShort() / 0xffff);

                        float x = baseNode[j].t.X + (baseNode[j].t2.X * (i1));
                        float y = baseNode[j].t.Y + (baseNode[j].t2.Y * (i2));
                        float z = baseNode[j].t.Z + (baseNode[j].t2.Z * (i3));

                        //node.t = new Vector3(x, y, z);  // Translation
                        n.XPOS.Keys.Add(new Animation.KeyFrame(x, i));
                        n.YPOS.Keys.Add(new Animation.KeyFrame(y, i));
                        n.ZPOS.Keys.Add(new Animation.KeyFrame(z, i));
                    }
                    else if (baseNode[j].t_type == KeyNode.CONSTANT)
                    {
                        //node.t = baseNode[j].t;
                        n.XPOS.Keys.Add(new Animation.KeyFrame(baseNode[j].t.X, i));
                        n.YPOS.Keys.Add(new Animation.KeyFrame(baseNode[j].t.Y, i));
                        n.ZPOS.Keys.Add(new Animation.KeyFrame(baseNode[j].t.Z, i));
                    }
                    else if (baseNode[j].t_type == 2)
                    {
                        float x = d.readFloat();
                        float y = d.readFloat();
                        float z = d.readFloat();

                        //node.t = new Vector3(x, y, z);
                        n.XPOS.Keys.Add(new Animation.KeyFrame(x, i));
                        n.YPOS.Keys.Add(new Animation.KeyFrame(y, i));
                        n.ZPOS.Keys.Add(new Animation.KeyFrame(z, i));
                    }

                    if (baseNode[j].r_type == KeyNode.COMPRESSED)
                    {
                        // There are 64 bits present for each node of this rot type
                        // The format is: 20bits * 3 of encoded floats, and 4 bits of flags
                        // The flags describe which 3 components of the quaternion are being presented
                        int b1 = d.readByte();
                        int b2 = d.readByte();
                        int b3 = d.readByte();
                        int b4 = d.readByte();
                        int b5 = d.readByte();
                        int b6 = d.readByte();
                        int b7 = d.readByte();
                        int b8 = d.readByte();

                        // Capture 20 bits at a time of the raw data
                        int f1    = (b1 << 12) | (b2 << 4) | ((b3 & 0xF0) >> 4);
                        int f2    = ((b3 & 0xF) << 16) | (b4 << 8) | b5;
                        int f3    = (b6 << 12) | (b7 << 4) | ((b8 & 0xF0) >> 4);
                        int flags = b8 & 0xF;

                        Quaternion r = new Quaternion();
                        switch (flags)
                        {
                        case 0:      // y, z, w provided
                            r.Y = encodedRot10ToQuaternionComponent(f1);
                            r.Z = encodedRot10ToQuaternionComponent(f2);
                            r.W = encodedRot10ToQuaternionComponent(f3);

                            r.X = (float)Math.Sqrt(Math.Abs(1 - (r.Y * r.Y + r.Z * r.Z + r.W * r.W)));
                            break;

                        case 1:      // x, z, w provided
                            r.X = encodedRot10ToQuaternionComponent(f1);
                            r.Z = encodedRot10ToQuaternionComponent(f2);
                            r.W = encodedRot10ToQuaternionComponent(f3);

                            r.Y = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Z * r.Z + r.W * r.W)));
                            break;

                        case 2:      // x, y, w provided
                            r.X = encodedRot10ToQuaternionComponent(f1);
                            r.Y = encodedRot10ToQuaternionComponent(f2);
                            r.W = encodedRot10ToQuaternionComponent(f3);

                            r.Z = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Y * r.Y + r.W * r.W)));
                            break;

                        case 3:      // x, y, z, provided
                            r.X = encodedRot10ToQuaternionComponent(f1);
                            r.Y = encodedRot10ToQuaternionComponent(f2);
                            r.Z = encodedRot10ToQuaternionComponent(f3);

                            r.W = (float)Math.Sqrt(Math.Abs(1 - (r.X * r.X + r.Y * r.Y + r.Z * r.Z)));
                            break;

                        default:
                            Console.WriteLine("Unknown rotation type3 flags: " + flags);
                            break;
                        }
                        n.RotType = Animation.RotationType.QUATERNION;
                        n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i));
                        n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i));
                        n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i));
                        n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i));
                    }
                    else if (baseNode[j].r_type == KeyNode.INTERPOLATED)
                    {
                        float i1 = ((float)d.readShort() / (0xffff));
                        float i2 = ((float)d.readShort() / (0xffff));
                        float i3 = ((float)d.readShort() / (0xffff));

                        float x = baseNode[j].rv.X + (baseNode[j].rv2.X * (i1));
                        float y = baseNode[j].rv.Y + (baseNode[j].rv2.Y * (i2));
                        float z = baseNode[j].rv.Z + (baseNode[j].rv2.Z * (i3));

                        float w = (float)Math.Sqrt(Math.Abs(1 - (x * x + y * y + z * z)));

                        Quaternion r = new Quaternion(new Vector3(x, y, z), w);
                        r.Normalize();

                        n.RotType = Animation.RotationType.QUATERNION;
                        n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i));
                        n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i));
                        n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i));
                        n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i));
                    }
                    else if (baseNode[j].r_type == KeyNode.KEYFRAME)
                    {
                        float scale = d.readShort() * baseNode[j].r_extra;
                        float x     = baseNode[j].rv.X;
                        float y     = baseNode[j].rv.Y;
                        float z     = baseNode[j].rv.Z + scale;
                        float w     = rot6CalculateW(x, y, z);

                        Quaternion r = new Quaternion(x, y, z, w);
                        n.RotType = Animation.RotationType.QUATERNION;
                        n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i));
                        n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i));
                        n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i));
                        n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i));
                    }
                    else
                    {
                        float x = baseNode[j].rv.X;
                        float y = baseNode[j].rv.Y;
                        float z = baseNode[j].rv.Z;
                        float w = (float)Math.Sqrt(Math.Abs(1 - (x * x + y * y + z * z)));

                        Quaternion r = new Quaternion(baseNode[j].rv, w);
                        r.Normalize();
                        n.RotType = Animation.RotationType.QUATERNION;
                        n.XROT.Keys.Add(new Animation.KeyFrame(r.X, i));
                        n.YROT.Keys.Add(new Animation.KeyFrame(r.Y, i));
                        n.ZROT.Keys.Add(new Animation.KeyFrame(r.Z, i));
                        n.WROT.Keys.Add(new Animation.KeyFrame(r.W, i));
                    }

                    if (baseNode[j].s_type == KeyNode.INTERPOLATED)
                    {
                        float i1 = ((float)d.readShort() / (0xffff));
                        float i2 = ((float)d.readShort() / (0xffff));
                        float i3 = ((float)d.readShort() / (0xffff));

                        float x = baseNode[j].s.X + (baseNode[j].s2.X * (i1));
                        float y = baseNode[j].s.Y + (baseNode[j].s2.Y * (i2));
                        float z = baseNode[j].s.Z + (baseNode[j].s2.Z * (i3));

                        //node.s = new Vector3(x, y, z);
                        n.XSCA.Keys.Add(new Animation.KeyFrame(x, i));
                        n.YSCA.Keys.Add(new Animation.KeyFrame(y, i));
                        n.ZSCA.Keys.Add(new Animation.KeyFrame(z, i));
                    }
                    else
                    {
                        //node.s = baseNode[j].s;
                        n.XSCA.Keys.Add(new Animation.KeyFrame(baseNode[j].s.X, i));
                        n.YSCA.Keys.Add(new Animation.KeyFrame(baseNode[j].s.Y, i));
                        n.ZSCA.Keys.Add(new Animation.KeyFrame(baseNode[j].s.Z, i));
                    }
                }
            }

            return(a);
        }
Example #26
0
        public static AnimationGroupNode Read(string filename)
        {
            bchHeader header = new bchHeader();
            FileData  f      = new FileData(filename);

            f.Endian = System.IO.Endianness.Little;

            f.skip(4);
            header.backwardCompatibility = f.readByte();
            header.forwardCompatibility  = f.readByte();
            header.version = f.readUShort();

            header.mainHeaderOffset  = f.readInt();
            header.stringTableOffset = f.readInt();
            header.gpuCommandsOffset = f.readInt();
            header.dataOffset        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedOffset = f.readInt();
            }
            header.relocationTableOffset = f.readInt();

            header.mainHeaderLength  = f.readInt();
            header.stringTableLength = f.readInt();
            header.gpuCommandsLength = f.readInt();
            header.dataLength        = f.readInt();
            if (header.backwardCompatibility > 0x20)
            {
                header.dataExtendedLength = f.readInt();
            }
            header.relocationTableLength = f.readInt();

            header.uninitializedDataSectionLength        = f.readInt();
            header.uninitializedDescriptionSectionLength = f.readInt();

            if (header.backwardCompatibility > 7)
            {
                header.flags        = f.readUShort();
                header.addressCount = f.readUShort();
            }

            // Relocation table
            for (int i = 0; i < header.relocationTableLength; i += 4)
            {
                f.seek(header.relocationTableOffset + i);
                int  val  = f.readInt();
                int  off  = val & 0x1FFFFFF;
                byte flag = (byte)(val >> 25);

                switch (flag)
                {
                case 0:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.mainHeaderOffset);
                    break;

                case 1:
                    f.seek(off + header.mainHeaderOffset);
                    f.writeInt((off) + header.mainHeaderOffset, f.readInt() + header.stringTableOffset);
                    break;

                case 2:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.gpuCommandsOffset);
                    break;

                case 0xc:
                    f.seek((off * 4) + header.mainHeaderOffset);
                    f.writeInt((off * 4) + header.mainHeaderOffset, f.readInt() + header.dataOffset);
                    break;
                }
            }


            // Content Header
            f.seek(header.mainHeaderOffset);
            bchContentHeader content = new bchContentHeader();
            {
                content.modelsPointerTableOffset        = f.readInt();
                content.modelsPointerTableEntries       = f.readInt();
                content.modelsNameOffset                = f.readInt();
                content.materialsPointerTableOffset     = f.readInt();
                content.materialsPointerTableEntries    = f.readInt();
                content.materialsNameOffset             = f.readInt();
                content.shadersPointerTableOffset       = f.readInt();
                content.shadersPointerTableEntries      = f.readInt();
                content.shadersNameOffset               = f.readInt();
                content.texturesPointerTableOffset      = f.readInt();
                content.texturesPointerTableEntries     = f.readInt();
                content.texturesNameOffset              = f.readInt();
                content.materialsLUTPointerTableOffset  = f.readInt();
                content.materialsLUTPointerTableEntries = f.readInt();
                content.materialsLUTNameOffset          = f.readInt();
                content.lightsPointerTableOffset        = f.readInt();
                content.lightsPointerTableEntries       = f.readInt();
                content.lightsNameOffset                = f.readInt();
                content.camerasPointerTableOffset       = f.readInt();
                content.camerasPointerTableEntries      = f.readInt();
                content.camerasNameOffset               = f.readInt();
                content.fogsPointerTableOffset          = f.readInt();
                content.fogsPointerTableEntries         = f.readInt();
                content.fogsNameOffset = f.readInt();
                content.skeletalAnimationsPointerTableOffset    = f.readInt();
                content.skeletalAnimationsPointerTableEntries   = f.readInt();
                content.skeletalAnimationsNameOffset            = f.readInt();
                content.materialAnimationsPointerTableOffset    = f.readInt();
                content.materialAnimationsPointerTableEntries   = f.readInt();
                content.materialAnimationsNameOffset            = f.readInt();
                content.visibilityAnimationsPointerTableOffset  = f.readInt();
                content.visibilityAnimationsPointerTableEntries = f.readInt();
                content.visibilityAnimationsNameOffset          = f.readInt();
                content.lightAnimationsPointerTableOffset       = f.readInt();
                content.lightAnimationsPointerTableEntries      = f.readInt();
                content.lightAnimationsNameOffset           = f.readInt();
                content.cameraAnimationsPointerTableOffset  = f.readInt();
                content.cameraAnimationsPointerTableEntries = f.readInt();
                content.cameraAnimationsNameOffset          = f.readInt();
                content.fogAnimationsPointerTableOffset     = f.readInt();
                content.fogAnimationsPointerTableEntries    = f.readInt();
                content.fogAnimationsNameOffset             = f.readInt();
                content.scenePointerTableOffset             = f.readInt();
                content.scenePointerTableEntries            = f.readInt();
                content.sceneNameOffset = f.readInt();
            }


            //Skeletal animation
            AnimationGroupNode ThisAnimation = new AnimationGroupNode()
            {
                Text = filename
            };

            for (int index1 = 0; index1 < content.skeletalAnimationsPointerTableEntries; index1++)//
            {
                f.seek(content.skeletalAnimationsPointerTableOffset + (index1 * 4));
                int dataOffset = f.readInt();
                f.seek(dataOffset);


                string skeletalAnimationName = f.readString(f.readInt(), -1);
                int    animationFlags        = f.readInt();
                //int skeletalAnimationloopMode = f.readByte();  //pas ça du tout
                float skeletalAnimationframeSize = f.readFloat();
                int   boneTableOffset            = f.readInt();
                int   boneTableEntries           = f.readInt();
                int   metaDataPointerOffset      = f.readInt();

                //Runtime.Animations.Add(skeletalAnimationName, a);
                //MainForm.animNode.Nodes.Add(skeletalAnimationName);

                Animation a = new Animation(skeletalAnimationName);
                ThisAnimation.Nodes.Add(a);

                for (int i = 0; i < boneTableEntries; i++)
                {
                    f.seek(boneTableOffset + (i * 4));
                    int offset = f.readInt();

                    Animation.KeyNode bone = new Animation.KeyNode("");
                    a.Bones.Add(bone);
                    f.seek(offset);
                    bone.Text = f.readString(f.readInt(), -1);
                    //Console.WriteLine("Bone Name: " + bone.name);
                    int  animationTypeFlags = f.readInt();
                    uint flags = (uint)f.readInt();

                    OSegmentType segmentType = (OSegmentType)((animationTypeFlags >> 16) & 0xf);
                    //Debug.WriteLine(bone.Text + " " + flags.ToString("x"));
                    switch (segmentType)
                    {
                    case OSegmentType.transform:
                        f.seek(offset + 0xC);
                        //Console.WriteLine(f.pos().ToString("x") + " " + flags.ToString("x"));

                        uint notExistMask = 0x10000;
                        uint constantMask = 0x40;

                        for (int j = 0; j < 3; j++)
                        {
                            for (int axis = 0; axis < 3; axis++)
                            {
                                bool notExist = (flags & notExistMask) > 0;
                                bool constant = (flags & constantMask) > 0;
                                //Console.WriteLine(notExist + " " + constant);

                                Animation.KeyGroup group = new Animation.KeyGroup();
                                //frame.exists = !notExist;
                                if (!notExist)
                                {
                                    if (constant)
                                    {
                                        Animation.KeyFrame frame = new Animation.KeyFrame();
                                        frame.InterType = Animation.InterpolationType.LINEAR;
                                        frame.Value     = f.readFloat();
                                        frame.Frame     = 0;
                                        group.Keys.Add(frame);
                                    }
                                    else
                                    {
                                        int frameOffset = f.readInt();
                                        int position    = f.pos();
                                        f.seek(frameOffset);
                                        float c = 0;
                                        //Debug.WriteLine(j + " " + axis + " " + bone.Text);
                                        getAnimationKeyFrame(f, group, out c);
                                        if (c > a.FrameCount)
                                        {
                                            a.FrameCount = (int)c;
                                        }
                                        f.seek(position);
                                    }
                                }
                                else
                                {
                                    f.seek(f.pos() + 0x04);
                                }
                                bone.RotType = Animation.RotationType.EULER;

                                if (j == 0)
                                {
                                    switch (axis)
                                    {
                                    case 0: bone.XSCA = group; break;

                                    case 1: bone.YSCA = group; break;

                                    case 2: bone.ZSCA = group; break;
                                    }
                                }
                                else
                                if (j == 1)
                                {
                                    switch (axis)
                                    {
                                    case 0: bone.XROT = group; break;

                                    case 1: bone.YROT = group; break;

                                    case 2: bone.ZROT = group; break;
                                    }
                                }
                                else
                                if (j == 2)
                                {
                                    switch (axis)
                                    {
                                    case 0: bone.XPOS = group; break;

                                    case 1: bone.YPOS = group; break;

                                    case 2: bone.ZPOS = group; break;
                                    }
                                }

                                notExistMask <<= 1;
                                constantMask <<= 1;
                            }
                            if (j == 1)
                            {
                                constantMask <<= 1;
                            }
                        }

                        break;

                    /*case OSegmentType.transformQuaternion:
                     *  bone.isFrameFormat = true;
                     *
                     *  int scaleOffset = f.readInt();
                     *  int rotationOffset = f.readInt();
                     *  int translationOffset = f.readInt();
                     *
                     *  if ((flags & 0x20) == 0)
                     *  {
                     *      bone.scale.exists = true;
                     *      f.seek(scaleOffset);
                     *
                     *      if ((flags & 4) > 0)
                     *      {
                     *          bone.scale.vector.Add(new Vector4(
                     *              f.readFloat(),
                     *              f.readFloat(),
                     *              f.readFloat(),
                     *              0));
                     *      }
                     *      else
                     *      {
                     *          bone.scale.startFrame = f.readFloat();
                     *          bone.scale.endFrame = f.readFloat();
                     *
                     *          int scaleFlags = f.readInt();
                     *          int scaleDataOffset = f.readInt();
                     *          int scaleEntries = f.readInt();
                     *
                     *          f.seek(scaleDataOffset);
                     *          for (int j = 0; j < scaleEntries; j++)
                     *          {
                     *              bone.scale.vector.Add(new Vector4(
                     *                  f.readFloat(),
                     *                  f.readFloat(),
                     *                  f.readFloat(),
                     *                  0));
                     *          }
                     *      }
                     *  }
                     *
                     *  if ((flags & 0x10) == 0)
                     *  {
                     *      bone.rotationQuaternion.exists = true;
                     *      f.seek(rotationOffset);
                     *
                     *      if ((flags & 2) > 0)
                     *      {
                     *          bone.rotationQuaternion.vector.Add(new Vector4(
                     *              f.readFloat(),
                     *              f.readFloat(),
                     *              f.readFloat(),
                     *              f.readFloat()));
                     *      }
                     *      else
                     *      {
                     *          bone.rotationQuaternion.startFrame = f.readFloat();
                     *          bone.rotationQuaternion.endFrame = f.readFloat();
                     *
                     *          int rotationFlags = f.readInt();
                     *          int rotationDataOffset = f.readInt();
                     *          int rotationEntries = f.readInt();
                     *
                     *          f.seek(rotationDataOffset);
                     *          for (int j = 0; j < rotationEntries; j++)
                     *          {
                     *              bone.rotationQuaternion.vector.Add(new Vector4(
                     *                  f.readFloat(),
                     *                  f.readFloat(),
                     *                  f.readFloat(),
                     *                  f.readFloat()));
                     *          }
                     *      }
                     *  }
                     *
                     *  if ((flags & 8) == 0)
                     *  {
                     *      bone.translation.exists = true;
                     *      f.seek(translationOffset);
                     *
                     *      if ((flags & 1) > 0)
                     *      {
                     *          bone.translation.vector.Add(new Vector4(
                     *              f.readFloat(),
                     *              f.readFloat(),
                     *              f.readFloat(),
                     *              0));
                     *      }
                     *      else
                     *      {
                     *          bone.translation.startFrame = f.readFloat();
                     *          bone.translation.endFrame = f.readFloat();
                     *
                     *          int translationFlags = f.readInt();
                     *          int translationDataOffset = f.readInt();
                     *          int translationEntries = f.readInt();
                     *
                     *          f.seek(translationDataOffset);
                     *          for (int j = 0; j < translationEntries; j++)
                     *          {
                     *              bone.translation.vector.Add(new Vector4(
                     *                  f.readFloat(),
                     *                  f.readFloat(),
                     *                  f.readFloat(),
                     *                  0));
                     *          }
                     *      }
                     *  }
                     *
                     *  break;
                     * case OSegmentType.transformMatrix:
                     *  bone.isFullBakedFormat = true;
                     *
                     *  f.readInt();
                     *  f.readInt();
                     *  int matrixOffset = f.readInt();
                     *  int entries = f.readInt();
                     *
                     *  f.seek(matrixOffset);
                     *  for (int j = 0; j < entries; j++)
                     *  {
                     *      OMatrix transform = new OMatrix();
                     *      transform.M11 = f.readFloat();
                     *      transform.M21 = f.readFloat();
                     *      transform.M31 = f.readFloat();
                     *      transform.M41 = f.readFloat();
                     *
                     *      transform.M12 = f.readFloat();
                     *      transform.M22 = f.readFloat();
                     *      transform.M32 = f.readFloat();
                     *      transform.M42 = f.readFloat();
                     *
                     *      transform.M13 = f.readFloat();
                     *      transform.M23 = f.readFloat();
                     *      transform.M33 = f.readFloat();
                     *      transform.M43 = f.readFloat();
                     *
                     *      bone.transform.Add(transform);
                     *  }
                     *
                     *  break;*/
                    default: throw new Exception(string.Format("BCH: Unknow Segment Type {0} on Skeletal Animation bone {1}! STOP!", segmentType, bone.Text));
                    }

                    //skeletalAnimation.bone.Add(bone);
                }
            }
            //return a;
            return(ThisAnimation);
        }
Example #27
0
 public int readOffset(FileData f)
 {
     return(f.pos() + f.readInt());
 }
Example #28
0
        public override void Read(string filename)
        {
            FileData file = new FileData(filename);

            if (file != null)
            {
                file.Endian = Endianness.Little;
                Endian      = Endianness.Little;
                string magic = file.readString(0, 4);
                if (magic == "VBN ")
                {
                    file.Endian = Endianness.Big;
                    Endian      = Endianness.Big;
                }

                file.seek(4);

                unk_1               = file.readShort();
                unk_2               = file.readShort();
                totalBoneCount      = (UInt32)file.readInt();
                boneCountPerType[0] = (UInt32)file.readInt();
                boneCountPerType[1] = (UInt32)file.readInt();
                boneCountPerType[2] = (UInt32)file.readInt();
                boneCountPerType[3] = (UInt32)file.readInt();

                int[] pi = new int[totalBoneCount];
                for (int i = 0; i < totalBoneCount; i++)
                {
                    Bone temp = new Bone(this);
                    temp.Text = file.readString(file.pos(), -1);
                    file.skip(64);
                    temp.boneType = (UInt32)file.readInt();
                    pi[i]         = file.readInt();
                    temp.boneId   = (UInt32)file.readInt();
                    temp.position = new float[3];
                    temp.rotation = new float[3];
                    temp.scale    = new float[3];
                    //temp.isSwingBone = temp.Text.Contains("__swing");
                    bones.Add(temp);
                }

                for (int i = 0; i < bones.Count; i++)
                {
                    bones[i].position[0] = file.readFloat();
                    bones[i].position[1] = file.readFloat();
                    bones[i].position[2] = file.readFloat();
                    bones[i].rotation[0] = file.readFloat();
                    bones[i].rotation[1] = file.readFloat();
                    bones[i].rotation[2] = file.readFloat();
                    bones[i].scale[0]    = file.readFloat();
                    bones[i].scale[1]    = file.readFloat();
                    bones[i].scale[2]    = file.readFloat();
                    Bone temp = bones[i];
                    temp.parentIndex = pi[i];
                    //Debug.Write(temp.parentIndex);
                    //if (temp.parentIndex != 0x0FFFFFFF && temp.parentIndex > -1)
                    //    bones[temp.parentIndex].children.Add(i);
                    bones[i] = temp;
                }
                reset();
            }
        }
Example #29
0
        public void Read(FileData f)
        {
            f.Endian = Endianness.Little;
            f.seek(4);
            int count = f.readInt();

            f.skip(12);
            int dataCount  = f.readInt();
            int boneCount  = f.readInt();
            int hashCount  = f.readInt();
            int hashOffset = f.readInt() + 0x28;

            f.skip(4);

            int pos = f.pos();

            f.seek(hashOffset);

            csvHashes     csv      = new csvHashes(Path.Combine(MainForm.executableDir, "hashTable.csv"));
            List <string> bonename = new List <string>();

            for (int i = 0; i < hashCount; i++)
            {
                uint hash = (uint)f.readInt();
                Console.WriteLine(csv.ids[hash]);
                bonename.Add(csv.ids[hash]);
            }

            f.seek(pos);
            Console.WriteLine("Count " + count);

            for (int i = 0; i < dataCount; i++)
            {
                Console.WriteLine("Bone " + i + " start at " + f.pos().ToString("x"));
                // 3 sections
                int secLength = f.readInt();
                int someCount = f.readInt(); // usually 2?

                for (int sec = 0; sec < 5; sec++)
                {
                    int size = f.readInt();
                    int id   = f.readInt();
                    Console.WriteLine(id + ":\t" + size.ToString("x"));
                    for (int j = 0; j < ((size - 1) / 4) - 1; j++)
                    {
                        if (id == 4)
                        {
                            short b1 = f.readShort();
                            short b2 = f.readShort();
                            Console.Write("\t" + (b1 == -1 ? b1 + "" : bonename[b1]) + " " + b2 + "\t");
                        }
                        else
                        if (id == 5)
                        {
                            short b1 = f.readShort();
                            short b2 = f.readShort();
                            Console.Write("\t" + (b1 == -1 ? b1 + "" : bonename[b1]) + " " + (b2 == -1 ? b2 + "" : bonename[b2]) + "\t");
                        }
                        else
                        {
                            Console.Write("\t" + (f.readUShort() / (id == 7 ? (float)0xffff : 1)) + " " + (f.readUShort() / (id == 7 ? (float)0xffff : 1)) + "\t");
                        }
                    }
                    Console.WriteLine();
                }

                f.skip(8);
            }

            Console.WriteLine("0x" + f.pos().ToString("X"));
            f.skip(8);
            int hashSize = f.readInt();
            int unk      = f.readInt();
        }
Example #30
0
        public void read(FileData f)
        {
            f.skip(0xD);
            name = f.readString(f.pos(), 0x38);
            f.skip(0x38);
            f.skip(1);//Seperation char
            subname = f.readString(f.pos(), 0x40);
            f.skip(0x40);
            f.skip(1);//Seperation char
            startPos[0] = f.readFloat();
            startPos[1] = f.readFloat();
            startPos[2] = f.readFloat();
            useStartPos = (f.readByte() != 0);
            f.skip(1);//Seperation char
            unk2 = f.readInt();
            f.skip(1);
            unk3 = f.read(0xC);
            f.skip(4); //FF FF FF FF
            f.skip(1); //Seperation char
            unk4 = new char[0x40];
            for (int i = 0; i < 0x40; i++)
            {
                unk4[i] = (char)f.readByte();
            }

            flag1 = Convert.ToBoolean(f.readByte());
            flag2 = Convert.ToBoolean(f.readByte());
            flag3 = Convert.ToBoolean(f.readByte());
            flag4 = Convert.ToBoolean(f.readByte());
            f.skip(1);//Seperation char
            //f.skip(0xAA);
            //Console.WriteLine(f.pos());
            int vertCount = f.readInt();

            for (int i = 0; i < vertCount; i++)
            {
                f.skip(1);//Seperation char
                Vector2D temp = new Vector2D();
                temp.x = f.readFloat();
                temp.y = f.readFloat();
                verts.Add(temp);
            }
            f.skip(1);//Seperation char

            int normalCount = f.readInt();

            for (int i = 0; i < normalCount; i++)
            {
                f.skip(1);//Seperation char
                Vector2D temp = new Vector2D();
                temp.x = f.readFloat();
                temp.y = f.readFloat();
                normals.Add(temp);
            }
            f.skip(1);                    //Seperation char

            int cliffCount = f.readInt(); //CLIFFS tend to be useless

            f.skip(0xFC * cliffCount);    //Standard CLIFFS are 0xFC in length, just skip em all
            f.skip(1);                    //Seperation char

            int materialCount = f.readInt();

            for (int i = 0; i < materialCount; i++)
            {
                f.skip(1);                   //Seperation char
                CollisionMat temp = new CollisionMat();
                temp.material = f.read(0xC); //Temporary, will work on fleshing out material more later

                materials.Add(temp);
            }
        }