public scenario_structure_bsp(CacheBase Cache, CacheBase.IndexItem Tag)
        {
            cache = Cache;
            int          Address = Tag.Offset;
            EndianReader Reader  = Cache.Reader;

            Reader.SeekTo(Address);

            Reader.SeekTo(Address + 68);
            XBounds = new Range <float>(Reader.ReadSingle(), Reader.ReadSingle());
            YBounds = new Range <float>(Reader.ReadSingle(), Reader.ReadSingle());
            ZBounds = new Range <float>(Reader.ReadSingle(), Reader.ReadSingle());

            #region Clusters Block
            Reader.SeekTo(Address + 172);
            int iCount  = Reader.ReadInt32();
            int iOffset = Reader.ReadInt32() - Tag.Magic;
            for (int i = 0; i < iCount; i++)
            {
                ModelSections.Add(new ModelSection(Cache, Tag, iOffset + 176 * i, null)
                {
                    FacesIndex = i, VertsIndex = i, NodeIndex = 255
                });
                Clusters.Add(new Cluster(i));
            }
            #endregion

            #region Shaders Block
            Reader.SeekTo(Address + 180);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Tag.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Shaders.Add(new Halo2Xbox.render_model.Shader(Cache, iOffset + 32 * i));
            }
            #endregion

            #region ModelParts Block
            Reader.SeekTo(Address + 328);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Tag.Magic;
            for (int i = 0; i < iCount; i++)
            {
                ModelSections.Add(new ModelSection(Cache, Tag, iOffset + 200 * i, BoundingBoxes)
                {
                    FacesIndex = i + Clusters.Count, VertsIndex = i + Clusters.Count, NodeIndex = 255
                });
            }
            #endregion

            #region GeometryInstances Block
            Reader.SeekTo(Address + 336);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Tag.Magic;
            for (int i = 0; i < iCount; i++)
            {
                GeomInstances.Add(new InstancedGeometry(Cache, iOffset + 88 * i, Clusters.Count));
            }
            #endregion
        }
示例#2
0
        public scenario_structure_bsp(CacheBase Cache, CacheBase.IndexItem Tag)
        {
            cache = Cache;
            int          Address = Tag.Offset;
            EndianReader Reader  = Cache.Reader;

            Reader.SeekTo(Address + 0xE0);
            XBounds = new Range <float>(Reader.ReadSingle(), Reader.ReadSingle());
            YBounds = new Range <float>(Reader.ReadSingle(), Reader.ReadSingle());
            ZBounds = new Range <float>(Reader.ReadSingle(), Reader.ReadSingle());

            Reader.SeekTo(Address + 0x110);
            indexCount  = Reader.ReadInt32() * 3;
            indexOffset = Reader.ReadInt32() - Tag.Magic;

            #region Lightmaps Block
            Reader.SeekTo(Address + 0x11C);
            int iCount  = Reader.ReadInt32();
            int iOffset = Reader.ReadInt32() - Tag.Magic;
            for (int i = 0; i < iCount; i++)
            {
                ModelSections.Add(new Lightmap(cache, iOffset + 32 * i, Tag.Magic)
                {
                    VertsIndex = i, FacesIndex = i, NodeIndex = 255
                });
            }
            #endregion

            #region Create Shader List
            var sIDs = new List <int>();
            for (int i = 0; i < ModelSections.Count; i++)
            {
                var section = ModelSections[i];
                for (int j = 0; j < section.Submeshes.Count; j++)
                {
                    var mesh = (Lightmap.Material)section.Submeshes[j];

                    if (!sIDs.Contains(mesh.shaderID))
                    {
                        sIDs.Add(mesh.shaderID);
                    }
                    mesh.ShaderIndex = sIDs.IndexOf(mesh.shaderID);
                }
            }
            foreach (int ID in sIDs)
            {
                Shaders.Add(new Shader(ID));
            }
            for (int i = 0; i < ModelSections.Count; i++)
            {
                Clusters.Add(new Cluster(i));
            }
            #endregion
        }
示例#3
0
        public scenario_structure_bsp(CacheBase Cache, int Address)
        {
            cache = Cache;
            EndianReader Reader = Cache.Reader;

            Reader.SeekTo(Address);

            #region sldt ID
            //sldt's sections address will be used instead of the one in sbsp
            int sectionAddress = 0;
            foreach (var item in Cache.IndexItems)
            {
                if (item.ClassCode == "scnr")
                {
                    Reader.SeekTo(item.Offset + 20);
                    int cnt = Reader.ReadInt32();
                    int ptr = Reader.ReadInt32() - Cache.Magic;

                    int bspIndex = 0;

                    for (int i = 0; i < cnt; i++)
                    {
                        Reader.SeekTo(ptr + 108 * i + 12);
                        if (Cache.IndexItems.GetItemByID(Reader.ReadInt32()).Offset == Address)
                        {
                            bspIndex = i;
                            break;
                        }
                    }

                    Reader.SeekTo(item.Offset + 1776 + 12);
                    int sldtID      = Reader.ReadInt32();
                    int sldtAddress = Cache.IndexItems.GetItemByID(sldtID).Offset;

                    Reader.SeekTo(sldtAddress + 4);
                    cnt = Reader.ReadInt32();
                    ptr = Reader.ReadInt32() - Cache.Magic;

                    for (int i = 0; i < cnt; i++)
                    {
                        Reader.SeekTo(ptr + 436 * i + 2);

                        if (Reader.ReadInt16() != bspIndex)
                        {
                            continue;
                        }

                        Reader.SeekTo(ptr + 436 * i + 312);
                        sectionAddress = Reader.ReadInt32() - Cache.Magic;

                        Reader.SeekTo(ptr + 436 * i + 428);
                        geomRawID = Reader.ReadInt32();
                    }

                    break;
                }
            }
            #endregion

            Reader.SeekTo(Address + 60);
            XBounds = new RealBounds(Reader.ReadSingle(), Reader.ReadSingle());
            YBounds = new RealBounds(Reader.ReadSingle(), Reader.ReadSingle());
            ZBounds = new RealBounds(Reader.ReadSingle(), Reader.ReadSingle());

            #region Clusters Block
            Reader.SeekTo(Address + 180);
            int iCount  = Reader.ReadInt32();
            int iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Clusters.Add(new Cluster(Cache, iOffset + 220 * i));
            }
            #endregion

            #region Shaders Block
            Reader.SeekTo(Address + 192);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Shaders.Add(new Halo3Beta.render_model.Shader(Cache, iOffset + 36 * i));
            }
            #endregion

            #region GeometryInstances Block
            Reader.SeekTo(Address + 432);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                GeomInstances.Add(new InstancedGeometry(Cache, iOffset + 120 * i));
            }
            #endregion

            Reader.SeekTo(Address + 580);
            RawID1 = Reader.ReadInt32();

            #region ModelSections Block
            Reader.SeekTo(Address + 740);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                ModelSections.Add(new Halo3Beta.render_model.ModelSection(Cache, sectionAddress + 76 * i));
            }
            #endregion

            #region Bounding Boxes Block
            Reader.SeekTo(Address + 752);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                BoundingBoxes.Add(new Halo3Beta.render_model.BoundingBox(Cache, iOffset + 44 * i));
            }
            #endregion

            Reader.SeekTo(Address + 860);
            RawID2 = Reader.ReadInt32();

            Reader.SeekTo(Address + 892);
            RawID3 = Reader.ReadInt32();
        }
示例#4
0
        public render_model(CacheBase Cache, int Address)
        {
            cache = Cache;
            EndianReader Reader = Cache.Reader;

            Reader.SeekTo(Address);

            Name  = Cache.Strings.GetItemByID(Reader.ReadInt32());
            Flags = new Bitmask(Reader.ReadInt32());

            #region Regions Block
            Reader.SeekTo(Address + 12);
            int iCount  = Reader.ReadInt32();
            int iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Regions.Add(new Region(Cache, iOffset + 16 * i));
            }
            #endregion

            Reader.SeekTo(Address + 28);
            InstancedGeometryIndex = Reader.ReadInt32();

            #region Instanced Geometry Block
            Reader.SeekTo(Address + 32);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                GeomInstances.Add(new InstancedGeometry(Cache, iOffset + 60 * i));
            }
            #endregion

            #region Nodes Block
            Reader.SeekTo(Address + 48);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Nodes.Add(new Node(Cache, iOffset + 96 * i));
            }
            #endregion

            #region MarkerGroups Block
            Reader.SeekTo(Address + 60);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                MarkerGroups.Add(new MarkerGroup(Cache, iOffset + 16 * i));
            }
            #endregion

            #region Shaders Block
            Reader.SeekTo(Address + 72);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Shaders.Add(new Shader(Cache, iOffset + 44 * i));
            }
            #endregion

            #region ModelSections Block
            Reader.SeekTo(Address + 104);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                ModelSections.Add(new ModelSection(Cache, iOffset + 92 * i));
            }
            #endregion

            #region BoundingBox Block
            Reader.SeekTo(Address + 116);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                BoundingBoxes.Add(new BoundingBox(Cache, iOffset + 52 * i));
            }
            #endregion

            #region NodeMapGroup Block
            Reader.SeekTo(Address + 176);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                NodeIndexGroups.Add(new NodeIndexGroup(Cache, iOffset + 12 * i));
            }
            #endregion

            Reader.SeekTo(Address + 236);
            RawID = Reader.ReadInt32();
        }
示例#5
0
        public gbxmodel(CacheBase Cache, int Address)
        {
            cache = Cache;
            EndianReader Reader = Cache.Reader;

            Reader.SeekTo(Address);

            Name  = "gbxmodel";
            Flags = new Bitmask(Reader.ReadInt16());

            Reader.SeekTo(Address + 0x30);
            uScale = Reader.ReadSingle();
            vScale = Reader.ReadSingle();


            #region MarkerGroups Block
            Reader.SeekTo(Address + 0xAC);
            int iCount  = Reader.ReadInt32();
            int iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                MarkerGroups.Add(new MarkerGroup(Cache, iOffset + 64 * i));
            }
            #endregion

            #region Nodes Block
            Reader.SeekTo(Address + 0xB8);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Nodes.Add(new Node(Cache, iOffset + 156 * i));
            }
            #endregion

            #region Regions Block
            Reader.SeekTo(Address + 0xC4);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Regions.Add(new Region(Cache, iOffset + 76 * i));
            }
            #endregion

            #region ModelParts Block
            Reader.SeekTo(Address + 0xD0);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                ModelSections.Add(new ModelSection(Cache, iOffset + 48 * i)
                {
                    FacesIndex = i, VertsIndex = i, NodeIndex = 255
                });
            }
            #endregion

            #region Shaders Block
            Reader.SeekTo(Address + 0xDC);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Shaders.Add(new Shader(Cache, iOffset + 32 * i));
            }
            #endregion

            #region BoundingBox Block
            BoundingBoxes.Add(new BoundingBox());
            #endregion
        }
示例#6
0
        static NJS_OBJECT ProcessModel(byte[] file, int verbose = 0, int startaddress = 0)
        {
            int curaddr = 0;

            do
            {
                int temp = BitConverter.ToInt16(file, curaddr);
                if (temp < 0 || temp > 7)
                {
                    if (verbose > 1)
                    {
                        Console.WriteLine("Skipping two padding bytes at {0}", curaddr.ToString("X"));
                    }
                    curaddr += 2;
                }
                ModelSections section_type = (ModelSections)BitConverter.ToInt16(file, curaddr);
                int           itemnum      = BitConverter.ToInt16(file, curaddr + 2);
                int           section_size = BitConverter.ToInt32(file, curaddr + 4);
                int           section_addr = curaddr + 8;
                if (verbose > 1)
                {
                    Console.Write("Subsection type {0}, size {1}, data begins at {2}", section_type.ToString(), section_size, section_addr.ToString("X"));
                }
                switch (section_type)
                {
                case ModelSections.POLY:
                    if (verbose > 1)
                    {
                        Console.Write(", calculated item count: {0}\n", (float)section_size / 2.0f);
                    }
                    break;

                case ModelSections.VERTEX:
                    if (verbose > 1)
                    {
                        Console.Write(", calculated item count: {0}\n", (float)section_size / 12.0f);
                    }
                    break;

                case ModelSections.NORMAL:
                    if (verbose > 1)
                    {
                        Console.Write(", calculated item count: {0}\n", (float)section_size / 12.0f);
                    }
                    break;

                case ModelSections.UV:
                    if (verbose > 1)
                    {
                        Console.Write(", calculated item count: {0}\n", (float)section_size / 4.0f);
                    }
                    break;

                case ModelSections.MATERIAL:
                    if (verbose > 1)
                    {
                        Console.Write(", item count: {0} (calculated {1})\n", itemnum, (float)section_size / 20.0f);
                    }
                    break;

                case ModelSections.MESHSET:
                    if (verbose > 1)
                    {
                        Console.Write(", item count: {0} (calculated {1})\n", itemnum, (float)section_size / 24.0f);
                    }
                    break;

                case ModelSections.MODEL:
                    if (verbose > 1)
                    {
                        Console.Write(", item count: {0} (calculated {1})\n", itemnum, (float)section_size / 40.0f);
                    }
                    break;

                case ModelSections.OBJECT:
                    if (verbose > 1)
                    {
                        Console.Write(", item count: {0} (calculated {1})\n", itemnum, (float)section_size / 52.0f);
                    }
                    break;
                }
                curaddr += 8 + section_size;
            }while (curaddr < file.Length);
            if (verbose > 0)
            {
                Console.WriteLine("Model at {0}", (file.Length - 52 + startaddress).ToString("X"));
            }
            return(new NJS_OBJECT(file, file.Length - 52, 0, ModelFormat.Basic, null));
        }
示例#7
0
        public render_model(CacheBase Cache, int Address)
        {
            cache = Cache;
            EndianReader Reader = Cache.Reader;

            Reader.SeekTo(Address);

            Name = Cache.Strings.GetItemByID(Reader.ReadInt16());
            //Flags = new Bitmask(Reader.ReadInt32());

            #region BoundingBox Block
            Reader.SeekTo(Address + 20);
            int iCount  = Reader.ReadInt32();
            int iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                BoundingBoxes.Add(new BoundingBox(Cache, iOffset + 56 * i));
            }
            #endregion

            #region Regions Block
            Reader.SeekTo(Address + 28);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Regions.Add(new Region(Cache, iOffset + 16 * i));
            }
            #endregion

            #region ModelParts Block
            Reader.SeekTo(Address + 36);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                ModelSections.Add(new ModelSection(Cache, iOffset + 92 * i)
                {
                    FacesIndex = i, VertsIndex = i, NodeIndex = 255
                });
            }
            Reader.SeekTo(Address + 72);
            #endregion

            #region Nodes Block
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Nodes.Add(new Node(Cache, iOffset + 96 * i));
            }
            #endregion

            #region MarkerGroups Block
            Reader.SeekTo(Address + 88);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                MarkerGroups.Add(new MarkerGroup(Cache, iOffset + 12 * i));
            }
            #endregion

            #region Shaders Block
            Reader.SeekTo(Address + 96);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Shaders.Add(new Shader(Cache, iOffset + 32 * i));
            }
            #endregion
        }
        public scenario_structure_bsp(CacheBase Cache, int Address)
        {
            cache = Cache;
            EndianReader Reader = Cache.Reader;

            Reader.SeekTo(Address);

            #region sldt/lbsp ID
            //lbsp's sections address will be used instead of the one in sbsp
            int sectionAddress = 0;
            int sectionCount   = 0;
            foreach (var item in Cache.IndexItems)
            {
                if (item.ClassCode == "scnr")
                {
                    Reader.SeekTo(item.Offset + 76);
                    int cnt = Reader.ReadInt32();
                    int ptr = Reader.ReadInt32() - Cache.Magic;

                    int bspIndex = 0;

                    for (int i = 0; i < cnt; i++)
                    {
                        Reader.SeekTo(ptr + 172 * i + 12);
                        if (Cache.IndexItems.GetItemByID(Reader.ReadInt32()).Offset == Address)
                        {
                            bspIndex = i;
                            break;
                        }
                    }

                    Reader.SeekTo(item.Offset + 1844 + 12);
                    int sldtID      = Reader.ReadInt32();
                    int sldtAddress = Cache.IndexItems.GetItemByID(sldtID).Offset;

                    Reader.SeekTo(sldtAddress + 4);
                    cnt = Reader.ReadInt32();
                    ptr = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(ptr + 32 * bspIndex + 12);
                    int lbspID      = Reader.ReadInt32();
                    int lbspAddress = Cache.IndexItems.GetItemByID(lbspID).Offset;

                    Reader.SeekTo(lbspAddress + 124);
                    sectionCount   = Reader.ReadInt32();
                    sectionAddress = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(lbspAddress + 268);
                    geomRawID = Reader.ReadInt32();
                    break;
                }
            }
            #endregion

            Reader.SeekTo(Address + 236);
            XBounds = new RealBounds(Reader.ReadSingle(), Reader.ReadSingle());
            YBounds = new RealBounds(Reader.ReadSingle(), Reader.ReadSingle());
            ZBounds = new RealBounds(Reader.ReadSingle(), Reader.ReadSingle());

            #region Clusters Block
            Reader.SeekTo(Address + 308);
            int iCount  = Reader.ReadInt32();
            int iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Clusters.Add(new Cluster(Cache, iOffset + 140 * i));
            }
            #endregion

            #region Shaders Block
            Reader.SeekTo(Address + 320);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Shaders.Add(new ReachRetail.render_model.Shader(Cache, iOffset + 44 * i));
            }
            #endregion

            #region GeometryInstances Block
            Reader.SeekTo(Address + 608);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                GeomInstances.Add(new InstancedGeometry(Cache, iOffset + 4 * i));
            }

            #region Load Fixup Data
            Reader.SeekTo(Address + 1298);
            int id    = Reader.ReadUInt16();
            var entry = Cache.zone.RawEntries[id];
            var er    = new EndianReader(new MemoryStream(Cache.zone.FixupData), EndianFormat.BigEndian);
            int addr  = entry.Fixups[entry.Fixups.Count - 10].Offset;

            for (int i = 0; i < GeomInstances.Count; i++)
            {
                er.SeekTo(entry.FixupOffset + addr + 156 * i);
                var geom = GeomInstances[i];

                geom.TransformScale = er.ReadSingle();

                geom.TransformMatrix.m11 = er.ReadSingle();
                geom.TransformMatrix.m12 = er.ReadSingle();
                geom.TransformMatrix.m13 = er.ReadSingle();

                geom.TransformMatrix.m21 = er.ReadSingle();
                geom.TransformMatrix.m22 = er.ReadSingle();
                geom.TransformMatrix.m23 = er.ReadSingle();

                geom.TransformMatrix.m31 = er.ReadSingle();
                geom.TransformMatrix.m32 = er.ReadSingle();
                geom.TransformMatrix.m33 = er.ReadSingle();

                geom.TransformMatrix.m41 = er.ReadSingle();
                geom.TransformMatrix.m42 = er.ReadSingle();
                geom.TransformMatrix.m43 = er.ReadSingle();

                er.ReadUInt16();
                er.ReadUInt16();
                er.ReadUInt16();
                geom.SectionIndex = er.ReadUInt16();
            }
            er.Close();
            er.Dispose();
            #endregion
            #endregion

            Reader.SeekTo(Address + 796);
            RawID1 = Reader.ReadInt32();

            Reader.SeekTo(Address + 976);
            RawID2 = Reader.ReadInt32();

            #region ModelParts Block
            Reader.SeekTo(Address + 1100);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            if (sectionAddress == -Cache.Magic)
            {
                sectionAddress = iOffset;                                 //null address in lbsp
            }
            for (int i = 0; i < iCount; i++)
            {
                ModelSections.Add(new ReachRetail.render_model.ModelSection(Cache, sectionAddress + 92 * i));
            }
            #endregion

            #region Bounding Boxes Block
            Reader.SeekTo(Address + 1112);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                BoundingBoxes.Add(new ReachRetail.render_model.BoundingBox(Cache, iOffset + 52 * i));
            }
            #endregion

            Reader.SeekTo(Address + 1244);
            RawID3 = Reader.ReadInt32();
        }
        public scenario_structure_bsp(CacheBase Cache, int Address)
        {
            cache = Cache;
            EndianReader Reader = Cache.Reader;

            Reader.SeekTo(Address);

            #region sldt/lbsp ID
            //lbsp's sections address will be used instead of the one in sbsp
            int sectCount = 0, sectionAddress = 0, bbCount = 0, bbAddr = 0;
            foreach (var item in Cache.IndexItems)
            {
                if (item.ClassCode == "scnr")
                {
                    Reader.SeekTo(item.Offset + 160);
                    int cnt = Reader.ReadInt32();
                    int ptr = Reader.ReadInt32() - Cache.Magic;

                    int bspIndex = 0;

                    for (int i = 0; i < cnt; i++)
                    {
                        Reader.SeekTo(ptr + 336 * i + 12);
                        if (Cache.IndexItems.GetItemByID(Reader.ReadInt32()).Offset == Address)
                        {
                            bspIndex = i;
                            break;
                        }
                    }

                    Reader.SeekTo(item.Offset + 1896 + 12);
                    int sldtID      = Reader.ReadInt32();
                    int sldtAddress = Cache.IndexItems.GetItemByID(sldtID).Offset;

                    Reader.SeekTo(sldtAddress + 4);
                    cnt = Reader.ReadInt32();
                    ptr = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(ptr + 32 * bspIndex + 12);
                    int lbspID      = Reader.ReadInt32();
                    int lbspAddress = Cache.IndexItems.GetItemByID(lbspID).Offset;

                    Reader.SeekTo(lbspAddress + 320); //320, 512, 692
                    sectCount      = Reader.ReadInt32();
                    sectionAddress = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(lbspAddress + 344); //344, 536, 716
                    bbCount = Reader.ReadInt32();
                    bbAddr  = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(lbspAddress + 464); //464, 656, 836
                    geomRawID = Reader.ReadInt32();
                    break;
                }
            }
            #endregion

            Reader.SeekTo(Address + 268);
            XBounds = new Range <float>(Reader.ReadSingle(), Reader.ReadSingle());
            YBounds = new Range <float>(Reader.ReadSingle(), Reader.ReadSingle());
            ZBounds = new Range <float>(Reader.ReadSingle(), Reader.ReadSingle());

            #region Clusters Block
            Reader.SeekTo(Address + 340);
            int iCount  = Reader.ReadInt32();
            int iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < 1; i++)
            {
                Clusters.Add(new Cluster(Cache, iOffset + 140 * i));
            }
            #endregion

            #region Shaders Block
            Reader.SeekTo(Address + 352);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Shaders.Add(new Halo4Retail.render_model.Shader(Cache, iOffset + 44 * i));
            }
            #endregion

            #region GeometryInstances Block
            Reader.SeekTo(Address + 640);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                GeomInstances.Add(new InstancedGeometry(Cache, iOffset + 4 * i));
            }

            #region Load Fixup Data
            Reader.SeekTo(Address + 1364);
            int id    = Reader.ReadInt32();
            var entry = Cache.zone.RawEntries[id & 0xFFFF];
            var er    = new EndianReader(new MemoryStream(Cache.GetRawFromID(id)), EndianFormat.Big);
            int addr  = entry.Fixups[entry.Fixups.Count - 10].Offset;

            for (int i = 0; i < GeomInstances.Count; i++)
            {
                er.SeekTo(addr + 148 * i);
                var geom = GeomInstances[i];

                geom.TransformScale = er.ReadSingle();

                geom.TransformMatrix = Matrix4x3.Read(er);

                er.ReadUInt16();
                er.ReadUInt16();
                er.ReadInt32();
                er.ReadUInt16();
                geom.SectionIndex = er.ReadUInt16();
            }
            er.Close();
            er.Dispose();
            #endregion
            #endregion

            Reader.SeekTo(Address + 844);
            RawID1 = Reader.ReadInt32();

            Reader.SeekTo(Address + 1048);
            RawID2 = Reader.ReadInt32();

            #region ModelSections Block
            Reader.SeekTo(Address + 1144);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            if (sectionAddress == -Cache.Magic)
            {
                sectionAddress = iOffset;                                 //null address in lbsp
            }
            for (int i = 0; i < sectCount; i++)
            {
                ModelSections.Add(new Halo4Retail.render_model.ModelSection(Cache, sectionAddress + 112 * i));
            }
            #endregion

            #region Bounding Boxes Block
            Reader.SeekTo(Address + 1168);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < bbCount; i++)
            {
                BoundingBoxes.Add(new Halo4Retail.render_model.BoundingBox(Cache, bbAddr + 52 * i));
            }
            #endregion

            Reader.SeekTo(Address + 1288);
            RawID3 = Reader.ReadInt32();
        }
        public scenario_structure_bsp(CacheBase Cache, int Address)
        {
            cache = Cache;
            EndianReader Reader = Cache.Reader;

            Reader.SeekTo(Address);

            #region sldt/lbsp ID
            //lbsp's sections address will be used instead of the one in sbsp
            int sectionAddress = 0;
            foreach (var item in Cache.IndexItems)
            {
                if (item.ClassCode == "scnr")
                {
                    Reader.SeekTo(item.Offset + 68);
                    int cnt = Reader.ReadInt32();
                    int ptr = Reader.ReadInt32() - Cache.Magic;

                    int bspIndex = 0;

                    for (int i = 0; i < cnt; i++)
                    {
                        Reader.SeekTo(ptr + 168 * i + 12);
                        if (Cache.IndexItems.GetItemByID(Reader.ReadInt32()).Offset == Address)
                        {
                            bspIndex = i;
                            break;
                        }
                    }

                    Reader.SeekTo(item.Offset + 1828 + 12);
                    int sldtID      = Reader.ReadInt32();
                    var sldt        = Cache.IndexItems.GetItemByID(sldtID);
                    int sldtAddress = Cache.IndexItems.GetItemByID(sldtID).Offset;

                    Reader.SeekTo(sldtAddress + 4);
                    cnt = Reader.ReadInt32();
                    ptr = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(ptr + 32 * bspIndex + 12);
                    int lbspID      = Reader.ReadInt32();
                    var lbsp        = Cache.IndexItems.GetItemByID(lbspID);
                    int lbspAddress = Cache.IndexItems.GetItemByID(lbspID).Offset;

                    Reader.SeekTo(lbspAddress + 116);
                    sectionAddress = Reader.ReadInt32() - Cache.Magic;

                    Reader.SeekTo(lbspAddress + 244);
                    geomRawID = Reader.ReadInt32();
                    break;
                }
            }
            #endregion

            Reader.SeekTo(Address + 236);
            XBounds = new Range <float>(Reader.ReadSingle(), Reader.ReadSingle());
            YBounds = new Range <float>(Reader.ReadSingle(), Reader.ReadSingle());
            ZBounds = new Range <float>(Reader.ReadSingle(), Reader.ReadSingle());

            #region Clusters Block
            Reader.SeekTo(Address + 308);
            int iCount  = Reader.ReadInt32();
            int iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Clusters.Add(new Cluster(Cache, iOffset + 288 * i));
            }
            #endregion

            #region Shaders Block
            Reader.SeekTo(Address + 320);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                Shaders.Add(new ReachBeta.render_model.Shader(Cache, iOffset + 44 * i));
            }
            #endregion

            #region GeometryInstances Block
            Reader.SeekTo(Address + 620);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                GeomInstances.Add(new InstancedGeometry(Cache, iOffset + 168 * i));
            }
            #endregion

            Reader.SeekTo(Address + 796);
            RawID1 = Reader.ReadInt32();

            Reader.SeekTo(Address + 976);
            RawID2 = Reader.ReadInt32();

            #region ModelParts Block
            Reader.SeekTo(Address + 1112);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                ModelSections.Add(new ReachBeta.render_model.ModelSection(Cache, sectionAddress + 92 * i));
            }
            #endregion

            #region Bounding Boxes Block
            Reader.SeekTo(Address + 1124);
            iCount  = Reader.ReadInt32();
            iOffset = Reader.ReadInt32() - Cache.Magic;
            for (int i = 0; i < iCount; i++)
            {
                BoundingBoxes.Add(new ReachBeta.render_model.BoundingBox(Cache, iOffset + 52 * i));
            }
            #endregion

            Reader.SeekTo(Address + 1244);
            RawID3 = Reader.ReadInt32();
        }