public SceneData(PakFile Pak, PakFile.PakTag Item)
        {
            var reader = Pak.Reader;
            reader.EndianType = EndianFormat.LittleEndian;
            reader.SeekTo(Item.Offset);

            unmapped0 = reader.ReadBytes(16);
            x0700 = reader.ReadInt16(); //0700
            xADDE = reader.ReadInt16(); //ADDE

            var min = new Vector(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
            var max = new Vector(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
            unkBounds = new BoundingBox()
            {
                XBounds = new Range<float>(min.X, max.X),
                YBounds = new Range<float>(min.Y, max.Y),
                ZBounds = new Range<float>(min.Z, max.Z),
            };

            var count = reader.ReadInt32(); //always bsp object count + 1
            indices = new List<int>();
            for (int i = 0; i < count; i++)
                indices.Add(reader.ReadInt32()); //last value is always struct0 count

            count = reader.ReadInt32();
            unkS0 = new List<struct0>();
            for (int i = 0; i < count; i++)
                unkS0.Add(new struct0(Pak, Item));

            unmapped1 = reader.ReadBytes(13); //always the same
        }
        public Block_2002(EndianReader reader)
            : base(reader, 0x2002)
        {
            unk0 = reader.ReadInt32(); // ]
            unk1 = reader.ReadInt32(); // ] unknown purpose, often all 60
            unk2 = reader.ReadInt32(); // ]

            var min = new Vector(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
            var max = new Vector(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
            Bounds = new BoundingBox()
            {
                XBounds = new Range<float>(min.X, max.X),
                YBounds = new Range<float>(min.Y, max.Y),
                ZBounds = new Range<float>(min.Z, max.Z),
            };
            unkPos0 = new Vector(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
        }
        public Template(PakFile Pak, PakFile.PakTag Item, bool loadMesh)
        {
            var reader = Pak.Reader;
            reader.EndianType = EndianFormat.LittleEndian;
            reader.StreamOrigin = Item.Offset;
            reader.SeekTo(0);

            reader.ReadInt16(); //E402
            reader.ReadInt32(); //filesize (EOB offset?)

            #region Block E502
            reader.ReadInt16(); //E502
            reader.ReadInt32(); //EOB offset
            reader.ReadInt32(); //LPTA (probs part of the string)
            Name = reader.ReadNullTerminatedString();
            reader.ReadByte(); //00
            #endregion

            #region Block 1603
            reader.ReadInt16(); //1603
            reader.ReadInt32(); //EOB offset
            reader.ReadBytes(3); //02 01 01
            #endregion

            #region Block 5501
            reader.ReadInt16(); //5501
            reader.ReadInt32(); //address

            int count = reader.ReadInt32();
            Materials = new List<MatRefBlock_5601>();
            for (int i = 0; i < count; i++)
                Materials.Add(new MatRefBlock_5601(reader));
            #endregion

            reader.ReadInt16(); //0100
            reader.ReadInt32(); //address

            #region Block F000
            xF000 = reader.ReadInt16();
            reader.ReadInt32(); //EOB offset
            x2C01 = reader.ReadInt16();
            reader.ReadInt32(); //EOB offset

            count = reader.ReadInt32();
            Objects = new List<Node>();
            for (int i = 0; i < count; i++)
                Objects.Add(new Node(reader, loadMesh));

            foreach (var obj in Objects)
                if (obj.isInheritor)
                    Objects[obj._2901.InheritID].isInherited = true;
            #endregion

            reader.ReadInt16(); //0100
            reader.ReadInt32(); //address

            #region Block E802
            reader.ReadInt16(); //E802
            reader.ReadInt32(); //address

            count = reader.ReadInt32();
            for (int i = 0; i < count; i++)
                Bones.Add(new BoneBlock_E902(reader));
            #endregion

            //havent mapped this block, assumed anim/sound related
            _E602 = new unkBlock_XXXX(reader, 0xE602);

            reader.ReadInt16(); //0100
            reader.ReadInt32(); //address

            if (reader.PeekUInt16() == 0xBA01)
                unkStrBlk = new StringBlock_BA01(reader);

            //contains data count, havent seen used
            _1D02 = new unkBlock_XXXX(reader, 0x1D02);

            //int16 count, [int16, int16] * count
            if (reader.PeekUInt16() == 0x1103)
                _1103 = new unkBlock_XXXX(reader, 0x1103);

            //contains null term string, used on IGA models
            _0403 = new unkBlock_XXXX(reader, 0x0403);

            if (reader.PeekUInt16() == 0x0503)
                _0503 = new Block_0503(reader);

            #region Block 0803
            reader.ReadInt16(); //0803
            reader.ReadInt32(); //address to end of bounds values
            reader.ReadInt32(); //bounds count?
            var min = new Vector(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
            var max = new Vector(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());

            RenderBounds = new BoundingBox();
            RenderBounds.XBounds = new Range<float>(min.X, max.X);
            RenderBounds.YBounds = new Range<float>(min.Y, max.Y);
            RenderBounds.ZBounds = new Range<float>(min.Z, max.Z);
            #endregion

            _0E03 = new Block_0E03(reader);

            //contains length prefixed string
            if (reader.PeekUInt16() == 0x1203)
                _1203 = new unkBlock_XXXX(reader, 0x1203);

            reader.ReadInt16(); //0100
            reader.ReadInt32(); //address to EOF

            reader.StreamOrigin = 0;
        }
        public static Matrix4x3 FromBounds(BoundingBox bb)
        {
            var bbXLength = bb.XBounds.Max - bb.XBounds.Min;
            var bbYLength = bb.YBounds.Max - bb.YBounds.Min;
            var bbZLength = bb.ZBounds.Max - bb.ZBounds.Min;

            return new Matrix4x3(
                bbXLength != 0.0f ? bbXLength : 1.0f, 0.0f, 0.0f,
                0.0f, bbYLength != 0.0f ? bbYLength : 1.0f, 0.0f,
                0.0f, 0.0f, bbZLength != 0.0f ? bbZLength : 1.0f,
                bbXLength, bbYLength, bbZLength);
        }