コード例 #1
0
        private void Mod_LoadVisibility(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            int pos_visdata = 0;

            br.BaseStream.Seek(header.lumps[LUMP_VISIBILITY].fileofs, System.IO.SeekOrigin.Begin);

            if (header.lumps[LUMP_VISIBILITY].filelen == 0)
            {
                _SModel.vis.numclusters = 0;
                _SModel.vis.bitofs      = null;
                _SModel.visdata         = null;

                return;
            }

            _SModel.vis.numclusters = br.ReadInt32();
            _SModel.vis.bitofs      = new int[_SModel.vis.numclusters, 2];

            for (int i = 0; i < _SModel.vis.numclusters; i++)
            {
                _SModel.vis.bitofs[i, DVIS_PVS] = br.ReadInt32();
                _SModel.vis.bitofs[i, DVIS_PHS] = br.ReadInt32();

                // decrement the offsets, because the data is stored in a seperate byte array
                _SModel.vis.bitofs[i, DVIS_PVS] -= 4 + ((4 * _SModel.vis.numclusters * 2));
                _SModel.vis.bitofs[i, DVIS_PHS] -= 4 + ((4 * _SModel.vis.numclusters * 2));
            }

            _SModel.visdata = new byte[(header.lumps[LUMP_VISIBILITY].fileofs + header.lumps[LUMP_VISIBILITY].filelen) - br.BaseStream.Position];
            while (br.BaseStream.Position < (header.lumps[LUMP_VISIBILITY].fileofs + header.lumps[LUMP_VISIBILITY].filelen))
            {
                _SModel.visdata[pos_visdata++] = br.ReadByte();
            }
        }
コード例 #2
0
        /// <summary>
        /// CreateSurfaceLightmap
        /// ---------------------
        /// Creates a lightmap surface
        /// </summary>
        public void CreateSurfaceLightmap(CModel.SModel _SModel, ref CModel.SMSurface surf)
        {
            int smax;
            int tmax;
            int bytepos;

            if (
                (surf.flags & CModel.EMSurface.SURF_DRAWSKY) == CModel.EMSurface.SURF_DRAWSKY
                | (surf.flags & CModel.EMSurface.SURF_DRAWTURB) == CModel.EMSurface.SURF_DRAWTURB
                )
            {
                return;
            }

            smax = (surf.extents[0] >> 4) + 1;
            tmax = (surf.extents[1] >> 4) + 1;

            if (LM_AllocBlock(smax, tmax, ref surf.light_s, ref surf.light_t) == false)
            {
                LM_UploadBlock(false);
                LM_InitBlock();

                if (LM_AllocBlock(smax, tmax, ref surf.light_s, ref surf.light_t) == false)
                {
                    CMain.Error(CMain.EErrorParm.ERR_FATAL, "Consecutive calls to LM_AllocBlock(" + smax + "," + tmax + ") failed\n");
                }
            }

            surf.lightmaptexturenum = CProgram.gQ2Game.gCMain.gCImage.current_lightmap_texture;

            bytepos = (surf.light_t * BLOCK_WIDTH + surf.light_s) * LIGHTMAP_BYTES;

            CProgram.gQ2Game.gCMain.gCLight.SetCacheState(ref surf);
            CProgram.gQ2Game.gCMain.gCLight.BuildLightMap(_SModel, ref surf, bytepos, ref lms.lightmap_buffer, BLOCK_WIDTH * LIGHTMAP_BYTES);
        }
コード例 #3
0
        private void Mod_LoadAreas(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            List <SDArea>        DArea = new List <SDArea>();
            List <CModel.SMArea> MArea = new List <CModel.SMArea>();

            br.BaseStream.Seek(header.lumps[LUMP_AREAS].fileofs, System.IO.SeekOrigin.Begin);
            while (br.BaseStream.Position < (header.lumps[LUMP_AREAS].fileofs + header.lumps[LUMP_AREAS].filelen))
            {
                SDArea _DArea;

                _DArea.numareaportals  = br.ReadInt32();
                _DArea.firstareaportal = br.ReadInt32();

                DArea.Add(_DArea);
            }

            for (int i = 0; i < DArea.Count; i++)
            {
                CModel.SMArea _MArea;

                _MArea.numareaportals  = DArea[i].numareaportals;
                _MArea.firstareaportal = DArea[i].firstareaportal;
                _MArea.floodvalid      = 0;
                _MArea.floodnum        = 0;

                MArea.Add(_MArea);
            }

            _SModel.numareas = MArea.Count;
            _SModel.areas    = MArea.ToArray();
        }
コード例 #4
0
        private void Mod_LoadAreaPortals(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            List <SDAreaPortal>        DAreaPortal = new List <SDAreaPortal>();
            List <CModel.SMAreaPortal> MAreaPortal = new List <CModel.SMAreaPortal>();

            br.BaseStream.Seek(header.lumps[LUMP_AREAPORTALS].fileofs, System.IO.SeekOrigin.Begin);
            while (br.BaseStream.Position < (header.lumps[LUMP_AREAPORTALS].fileofs + header.lumps[LUMP_AREAPORTALS].filelen))
            {
                SDAreaPortal _DAreaPortal;

                _DAreaPortal.portalnum = br.ReadInt32();
                _DAreaPortal.otherarea = br.ReadInt32();

                DAreaPortal.Add(_DAreaPortal);
            }

            for (int i = 0; i < DAreaPortal.Count; i++)
            {
                CModel.SMAreaPortal _MAreaPortal;

                _MAreaPortal.portalnum = DAreaPortal[i].portalnum;
                _MAreaPortal.otherarea = DAreaPortal[i].otherarea;

                MAreaPortal.Add(_MAreaPortal);
            }

            _SModel.numareaportals = MAreaPortal.Count;
            _SModel.areaportals    = MAreaPortal.ToArray();
        }
コード例 #5
0
        /// <summary>
        /// BeginBuildingLightmaps
        /// ----------------------
        /// Initializes the lightmap building process
        /// </summary>
        public void BeginBuildingLightmaps(ref CModel.SModel _SModel)
        {
            CLocal.SLightStyle[] _LightStyle;

            // no dlightcache
            CMain.r_framecount = 1;

            // setup the base lightstyles so the lightmaps won't have to be regenerated
            // the first time they're seen
            _LightStyle = new CLocal.SLightStyle[CLocal.MAX_LIGHTSTYLES];
            for (int i = 0; i < CLocal.MAX_LIGHTSTYLES; i++)
            {
                _LightStyle[i].rgb    = new float[3];
                _LightStyle[i].rgb[0] = 1.0f;
                _LightStyle[i].rgb[1] = 1.0f;
                _LightStyle[i].rgb[2] = 1.0f;
                _LightStyle[i].white  = 3.0f;
            }

            CClient.cl.RefDef.lightstyles = _LightStyle;

            // jkrige ??
            //if (!gl_state.lightmap_textures)
            //{
            //    gl_state.lightmap_textures = TEXNUM_LIGHTMAPS;
            //}
            // jkrige ??

            CProgram.gQ2Game.gCMain.gCImage.StartLightmaps(ref _SModel);
            LM_InitBlock();
        }
コード例 #6
0
        private void Mod_LoadLighting(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            if (header.lumps[LUMP_LIGHTING].filelen == 0)
            {
                _SModel.lightdata = null;
                return;
            }

            br.BaseStream.Seek(header.lumps[LUMP_LIGHTING].fileofs, System.IO.SeekOrigin.Begin);
            _SModel.lightdata = br.ReadBytes(header.lumps[LUMP_LIGHTING].filelen);
        }
コード例 #7
0
        private void Mod_SetParent(ref CModel.SModel _SModel, int idx_node, int idx_parent)
        {
            _SModel.nodes[idx_node].parent = idx_parent;

            if (_SModel.nodes[idx_node].contents != -1)
            {
                return;
            }

            Mod_SetParent(ref _SModel, _SModel.nodes[idx_node].children[0], idx_node);
            Mod_SetParent(ref _SModel, _SModel.nodes[idx_node].children[1], idx_node);
        }
コード例 #8
0
        private void Mod_LoadSurfedges(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            List <int> DSurfEdge = new List <int>();

            br.BaseStream.Seek(header.lumps[LUMP_SURFEDGES].fileofs, System.IO.SeekOrigin.Begin);
            while (br.BaseStream.Position < (header.lumps[LUMP_SURFEDGES].fileofs + header.lumps[LUMP_SURFEDGES].filelen))
            {
                DSurfEdge.Add(br.ReadInt32());
            }

            _SModel.numsurfedges = DSurfEdge.Count;
            _SModel.surfedges    = DSurfEdge.ToArray();
        }
コード例 #9
0
        private void Mod_LoadPlanes(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            int bits;

            float[] normal = new float[3];
            List <CShared.SCPlane> CPlane = new List <CShared.SCPlane>();

            br.BaseStream.Seek(header.lumps[LUMP_PLANES].fileofs, System.IO.SeekOrigin.Begin);
            while (br.BaseStream.Position < (header.lumps[LUMP_PLANES].fileofs + header.lumps[LUMP_PLANES].filelen))
            {
                CShared.SCPlane _CPlane;

                normal[0] = 0.0f;
                normal[1] = 0.0f;
                normal[2] = 0.0f;

                bits = 0;

                for (int j = 0; j < 3; j++)
                {
                    normal[j] = br.ReadSingle();

                    if (normal[j] < 0)
                    {
                        bits |= 1 << j;
                    }
                }

                _CPlane.normal.X = normal[0];
                _CPlane.normal.Y = normal[1];
                _CPlane.normal.Z = normal[2];

                _CPlane.dist     = br.ReadSingle();
                _CPlane.type     = (byte)br.ReadInt32();
                _CPlane.signbits = (byte)bits;

                _CPlane.pad = new byte[2];

                CPlane.Add(_CPlane);
            }

            _SModel.planes    = CPlane.ToArray();
            _SModel.numplanes = _SModel.planes.Length;
        }
コード例 #10
0
        public void FloodAreaConnections(ref CModel.SModel _SModel)
        {
            int floodnum;

            // all current floods are now invalid
            floodvalid++;
            floodnum = 0;

            // area 0 is not used
            for (int i = 1; i < _SModel.numareas; i++)
            {
                if (_SModel.areas[i].floodvalid == floodvalid)
                {
                    continue; // already flooded into
                }
                floodnum++;
                FloodArea_r(_SModel, ref _SModel.areas[i], floodnum);
            }
        }
コード例 #11
0
        private void Mod_LoadVertexes(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            List <CModel.SMVertex> MVertex = new List <CModel.SMVertex>();

            br.BaseStream.Seek(header.lumps[LUMP_VERTEXES].fileofs, System.IO.SeekOrigin.Begin);
            while (br.BaseStream.Position < (header.lumps[LUMP_VERTEXES].fileofs + header.lumps[LUMP_VERTEXES].filelen))
            {
                CModel.SMVertex _MVertex;

                _MVertex.Position.X = br.ReadSingle();
                _MVertex.Position.Y = br.ReadSingle();
                _MVertex.Position.Z = br.ReadSingle();

                MVertex.Add(_MVertex);
            }

            _SModel.numvertexes = MVertex.Count;
            _SModel.vertexes    = MVertex.ToArray();
        }
コード例 #12
0
        private void Mod_LoadEntityString(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            if (header.lumps[LUMP_ENTITIES].filelen > MAX_MAP_ENTSTRING)
            {
                // entity string exceeds maximum
                _SModel.map_entitystring = null;
                return;
            }

            br.BaseStream.Seek(header.lumps[LUMP_ENTITIES].fileofs, System.IO.SeekOrigin.Begin);
            if (br.BaseStream.Position < (header.lumps[LUMP_ENTITIES].fileofs + header.lumps[LUMP_ENTITIES].filelen))
            {
                _SModel.map_entitystring = CShared.Com_ToString(br.ReadChars(header.lumps[LUMP_ENTITIES].filelen));
                _SModel.map_entitystring = _SModel.map_entitystring.Replace("\r", "").Replace("\n", "\r\n");
            }
            else
            {
                _SModel.map_entitystring = null;
            }
        }
コード例 #13
0
        private void Mod_LoadMarksurfaces(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            List <int> MarkSurface = new List <int>();

            br.BaseStream.Seek(header.lumps[LUMP_LEAFFACES].fileofs, System.IO.SeekOrigin.Begin);
            while (br.BaseStream.Position < (header.lumps[LUMP_LEAFFACES].fileofs + header.lumps[LUMP_LEAFFACES].filelen))
            {
                int msurf = br.ReadInt16();

                if (msurf < 0 || msurf >= _SModel.numsurfaces)
                {
                    CMain.Error(CMain.EErrorParm.ERR_FATAL, "Mod_ParseMarksurfaces: bad surface number");
                }

                MarkSurface.Add(msurf);
            }

            _SModel.nummarksurfaces = MarkSurface.Count;
            _SModel.marksurfaces    = MarkSurface.ToArray();
        }
コード例 #14
0
        private void Mod_LoadEdges(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            List <CModel.SMEdge> MEdge = new List <CModel.SMEdge>();

            br.BaseStream.Seek(header.lumps[LUMP_EDGES].fileofs, System.IO.SeekOrigin.Begin);
            while (br.BaseStream.Position < (header.lumps[LUMP_EDGES].fileofs + header.lumps[LUMP_EDGES].filelen))
            {
                CModel.SMEdge _MEdge;

                _MEdge.v    = new ushort[2];
                _MEdge.v[0] = br.ReadUInt16();
                _MEdge.v[1] = br.ReadUInt16();

                _MEdge.cachededgeoffset = 0;

                MEdge.Add(_MEdge);
            }

            _SModel.numedges = MEdge.Count;
            _SModel.edges    = MEdge.ToArray();
        }
コード例 #15
0
        // ================================================================
        //
        // AREAPORTALS
        //
        // ================================================================

        public void FloodArea_r(CModel.SModel _SModel, ref CModel.SMArea area, int floodnum)
        {
            if (area.floodvalid == floodvalid)
            {
                if (area.floodnum == floodnum)
                {
                    return;
                }

                System.Diagnostics.Debug.WriteLine("FloodArea_r: reflooded");
                return;
            }

            area.floodnum   = floodnum;
            area.floodvalid = floodvalid;

            for (int i = 0; i < area.numareaportals; i++)
            {
                if (portalopen[_SModel.areaportals[area.firstareaportal + i].portalnum] == true)
                {
                    FloodArea_r(_SModel, ref _SModel.areas[_SModel.areaportals[area.firstareaportal + i].otherarea], floodnum);
                }
            }
        }
コード例 #16
0
        public void Mod_LoadBrushModel(ref CModel.SModel _SModel, MemoryStream ms)
        {
            SDHeader     header;
            List <SLump> lumps;
            BinaryReader br;

            ms.Seek(0, System.IO.SeekOrigin.Begin);
            br = new BinaryReader(ms);

            if (worldMapLoaded == true)
            {
                CMain.Error(CMain.EErrorParm.ERR_FATAL, "ERROR: attempted to redundantly load world map");
                return;
            }

            worldMapLoaded = true;

            _SModel.ModType = CModel.EModType.MOD_BRUSH;

            header.ident = br.ReadInt32();
            if (header.ident != IDBSPHEADER)
            {
                CMain.Error(CMain.EErrorParm.ERR_WARNING, "RE_LoadWorldMap: " + _SModel.name + " has wrong identity.");
                return;
            }

            header.version = br.ReadInt32();
            if (header.version != BSP_VERSION)
            {
                CMain.Error(CMain.EErrorParm.ERR_FATAL, "RE_LoadWorldMap: " + _SModel.name + " has wrong version number (" + header.version.ToString() + " should be " + BSP_VERSION.ToString() + ")");
                return;
            }

            lumps = new List <SLump>();
            for (int i = 0; i < HEADER_LUMPS; i++)
            {
                SLump _lump;
                _lump.fileofs = br.ReadInt32();
                _lump.filelen = br.ReadInt32();

                lumps.Add(_lump);
            }
            header.lumps = lumps.ToArray();

            CProgram.gQ2Game.gCMain.gCImage.StartWAL(ref _SModel);

            // load into heap
            Mod_LoadVertexes(header, ref _SModel, ref br);
            Mod_LoadEdges(header, ref _SModel, ref br);
            Mod_LoadSurfedges(header, ref _SModel, ref br);
            Mod_LoadLighting(header, ref _SModel, ref br);
            Mod_LoadPlanes(header, ref _SModel, ref br);
            Mod_LoadTexinfo(header, ref _SModel, ref br);
            Mod_LoadFaces(header, ref _SModel, ref br);
            Mod_LoadMarksurfaces(header, ref _SModel, ref br);
            Mod_LoadVisibility(header, ref _SModel, ref br);
            Mod_LoadNodesAndLeafs(header, ref _SModel, ref br);
            Mod_LoadSubmodels(header, ref _SModel, ref br);
            Mod_LoadAreas(header, ref _SModel, ref br);
            Mod_LoadAreaPortals(header, ref _SModel, ref br);
            Mod_LoadEntityString(header, ref _SModel, ref br);
            _SModel.numframes = 2;


            // set up the submodels
            for (int i = 0; i < _SModel.numsubmodels; i++)
            {
                CModel.SMModel bm;
                CModel.SModel  starmod;

                bm      = _SModel.submodels[i];
                starmod = CProgram.gQ2Game.gCMain.gCModel.mod_inline[i];

                starmod.ModType           = CModel.EModType.MOD_BRUSH;
                starmod.firstmodelsurface = bm.firstface;
                starmod.nummodelsurfaces  = bm.numfaces;
                starmod.firstnode         = bm.headnode;

                if (starmod.firstnode >= _SModel.numnodes)
                {
                    System.Diagnostics.Debug.WriteLine("Inline model " + i.ToString() + " has bad firstnode");
                }

                starmod.maxs     = bm.bounds.Max;
                starmod.mins     = bm.bounds.Min;
                starmod.radius   = bm.radius;
                starmod.numleafs = bm.visleafs;

                CProgram.gQ2Game.gCMain.gCModel.mod_inline[i] = starmod;
            }

            CProgram.gQ2Game.gCMain.gCImage.FinalizeWAL(ref _SModel);

            portalopen = new bool[MAX_MAP_AREAPORTALS];
            FloodAreaConnections(ref _SModel);
        }
コード例 #17
0
 /// <summary>
 /// EndBuildingLightmaps
 /// --------------------
 /// Finalizes the processed lightmaps
 /// </summary>
 public void EndBuildingLightmaps(ref CModel.SModel _SModel)
 {
     LM_UploadBlock(false);
     CProgram.gQ2Game.gCMain.gCImage.FinalizeLightmaps(ref _SModel);
 }
コード例 #18
0
        private void Mod_LoadSubmodels(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            List <SDModel>        DModel = new List <SDModel>();
            List <CModel.SMModel> MModel = new List <CModel.SMModel>();

            br.BaseStream.Seek(header.lumps[LUMP_MODELS].fileofs, System.IO.SeekOrigin.Begin);
            while (br.BaseStream.Position < (header.lumps[LUMP_MODELS].fileofs + header.lumps[LUMP_MODELS].filelen))
            {
                SDModel _DModel;

                _DModel.mins    = new float[3];
                _DModel.mins[0] = br.ReadSingle();
                _DModel.mins[1] = br.ReadSingle();
                _DModel.mins[2] = br.ReadSingle();

                _DModel.maxs    = new float[3];
                _DModel.maxs[0] = br.ReadSingle();
                _DModel.maxs[1] = br.ReadSingle();
                _DModel.maxs[2] = br.ReadSingle();

                _DModel.origin    = new float[3];
                _DModel.origin[0] = br.ReadSingle();
                _DModel.origin[1] = br.ReadSingle();
                _DModel.origin[2] = br.ReadSingle();

                _DModel.headnode = br.ReadInt32();

                _DModel.firstface = br.ReadInt32();
                _DModel.numfaces  = br.ReadInt32();

                DModel.Add(_DModel);
            }

            for (int i = 0; i < DModel.Count; i++)
            {
                CModel.SMModel _MModel;

                _MModel.bounds.Min.X = DModel[i].mins[0] - 1;
                _MModel.bounds.Min.Y = DModel[i].mins[1] - 1;
                _MModel.bounds.Min.Z = DModel[i].mins[2] - 1;
                _MModel.bounds.Max.X = DModel[i].maxs[0] + 1;
                _MModel.bounds.Max.Y = DModel[i].maxs[1] + 1;
                _MModel.bounds.Max.Z = DModel[i].maxs[2] + 1;

                _MModel.origin.X = DModel[i].origin[0];
                _MModel.origin.Y = DModel[i].origin[1];
                _MModel.origin.Z = DModel[i].origin[2];

                _MModel.radius = RadiusFromBounds(_MModel.bounds);

                _MModel.headnode  = DModel[i].headnode;
                _MModel.firstface = DModel[i].firstface;
                _MModel.numfaces  = DModel[i].numfaces;

                _MModel.visleafs = 0;

                MModel.Add(_MModel);
            }

            _SModel.numsubmodels = MModel.Count;
            _SModel.submodels    = MModel.ToArray();
        }
コード例 #19
0
        /// <summary>
        /// R_BuildLightMap
        /// ---------------
        /// Combine and scale multiple lightmaps into the floating format in blocklights
        /// </summary>
        public void BuildLightMap(CModel.SModel _SModel, ref CModel.SMSurface surf, int dest_pos, ref byte[] dest, int stride)
        {
            int smax, tmax;
            int r, g, b, a, max;
            int size;
            int lightmap;

            float[] scale;
            int     nummaps;

            float[]            bl;
            CLocal.SLightStyle style;

            int   bl_pos;
            float modulate = 1.0f;

            if (
                (_SModel.texinfo[surf.texinfo].flags & CQ2BSP.ESurface.SURF_SKY) == CQ2BSP.ESurface.SURF_SKY
                | (_SModel.texinfo[surf.texinfo].flags & CQ2BSP.ESurface.SURF_TRANS33) == CQ2BSP.ESurface.SURF_TRANS33
                | (_SModel.texinfo[surf.texinfo].flags & CQ2BSP.ESurface.SURF_TRANS66) == CQ2BSP.ESurface.SURF_TRANS66
                | (_SModel.texinfo[surf.texinfo].flags & CQ2BSP.ESurface.SURF_WARP) == CQ2BSP.ESurface.SURF_WARP
                )
            {
                CMain.Error(CMain.EErrorParm.ERR_WARNING, "BuildLightMap called for non-lit surface");
            }

            smax = (surf.extents[0] >> 4) + 1;
            tmax = (surf.extents[1] >> 4) + 1;
            size = smax * tmax;

            if (size > ((sizeof(float) * s_blocklights.Length) >> 4))
            {
                CMain.Error(CMain.EErrorParm.ERR_WARNING, "Bad s_blocklights size");
            }

            // set to full bright if no light data
            if (surf.samples == -1)
            {
                for (int i = 0; i < size * 3; i++)
                {
                    s_blocklights[i] = 255;
                }

                for (int maps = 0; maps < CQ2BSP.MAXLIGHTMAPS && surf.styles[maps] != 255; maps++)
                {
                    style = CClient.cl.RefDef.lightstyles[surf.styles[maps]];
                }

                goto store;
            }

            // count the # of maps
            for (nummaps = 0; nummaps < CQ2BSP.MAXLIGHTMAPS && surf.styles[nummaps] != 255; nummaps++)
            {
                ;
            }

            lightmap = surf.samples;

            // add all the lightmaps
            if (nummaps == 1)
            {
                scale = new float[3];

                for (int maps = 0; maps < CQ2BSP.MAXLIGHTMAPS && surf.styles[maps] != 255; maps++)
                {
                    bl     = s_blocklights;
                    bl_pos = 0;

                    for (int i = 0; i < 3; i++)
                    {
                        scale[i] = modulate * CClient.cl.RefDef.lightstyles[surf.styles[maps]].rgb[i];
                    }

                    if (scale[0] == 1.0f && scale[1] == 1.0f && scale[2] == 1.0f)
                    {
                        for (int i = 0; i < size; i++, bl_pos += 3)
                        {
                            bl[bl_pos + 0] = _SModel.lightdata[lightmap + (i * 3) + 0];
                            bl[bl_pos + 1] = _SModel.lightdata[lightmap + (i * 3) + 1];
                            bl[bl_pos + 2] = _SModel.lightdata[lightmap + (i * 3) + 2];
                        }
                    }
                    else
                    {
                        for (int i = 0; i < size; i++, bl_pos += 3)
                        {
                            bl[bl_pos + 0] = _SModel.lightdata[lightmap + (i * 3) + 0] * scale[0];
                            bl[bl_pos + 1] = _SModel.lightdata[lightmap + (i * 3) + 1] * scale[1];
                            bl[bl_pos + 2] = _SModel.lightdata[lightmap + (i * 3) + 2] * scale[2];
                        }
                    }

                    // skip to next lightmap
                    lightmap += size * 3;
                }
            }
            else
            {
                scale = new float[3];

                for (int i = 0; i < (sizeof(float) * size * 3); i++)
                {
                    s_blocklights[i] = 0;
                }

                for (int maps = 0; maps < CQ2BSP.MAXLIGHTMAPS && surf.styles[maps] != 255; maps++)
                {
                    bl     = s_blocklights;
                    bl_pos = 0;

                    for (int i = 0; i < 3; i++)
                    {
                        scale[i] = modulate * CClient.cl.RefDef.lightstyles[surf.styles[maps]].rgb[i];
                    }

                    if (scale[0] == 1.0f && scale[1] == 1.0f && scale[2] == 1.0f)
                    {
                        for (int i = 0; i < size; i++, bl_pos += 3)
                        {
                            bl[bl_pos + 0] += _SModel.lightdata[lightmap + (i * 3) + 0];
                            bl[bl_pos + 1] += _SModel.lightdata[lightmap + (i * 3) + 1];
                            bl[bl_pos + 2] += _SModel.lightdata[lightmap + (i * 3) + 2];
                        }
                    }
                    else
                    {
                        for (int i = 0; i < size; i++, bl_pos += 3)
                        {
                            bl[bl_pos + 0] += _SModel.lightdata[lightmap + (i * 3) + 0] * scale[0];
                            bl[bl_pos + 1] += _SModel.lightdata[lightmap + (i * 3) + 1] * scale[1];
                            bl[bl_pos + 2] += _SModel.lightdata[lightmap + (i * 3) + 2] * scale[2];
                        }
                    }

                    // skip to next lightmap
                    lightmap += size * 3;
                }
            }

            // add all the dynamic lights
            //if (surf.dlightframe == CMain.r_framecount)
            //    R_AddDynamicLights(surf);

            // put into texture format
store:
            stride -= (smax << 2);
            bl      = s_blocklights;
            bl_pos  = 0;

            for (int i = 0; i < tmax; i++, dest_pos += stride)
            {
                for (int j = 0; j < smax; j++)
                {
                    r = Convert.ToInt32(bl[bl_pos + 0]);
                    g = Convert.ToInt32(bl[bl_pos + 1]);
                    b = Convert.ToInt32(bl[bl_pos + 2]);

                    // catch negative lights
                    if (r < 0)
                    {
                        r = 0;
                    }
                    if (g < 0)
                    {
                        g = 0;
                    }
                    if (b < 0)
                    {
                        b = 0;
                    }

                    // determine the brightest of the three color components
                    if (r > g)
                    {
                        max = r;
                    }
                    else
                    {
                        max = g;
                    }
                    if (b > max)
                    {
                        max = b;
                    }

                    // alpha is ONLY used for the mono lightmap case.  For this reason
                    // we set it to the brightest of the color components so that
                    // things don't get too dim.
                    a = max;

                    // rescale all the color components if the intensity of the greatest
                    // channel exceeds 1.0
                    if (max > 255)
                    {
                        float t = 255.0f / max;

                        r = (int)(r * t);
                        g = (int)(g * t);
                        b = (int)(b * t);
                        a = (int)(a * t);
                    }

                    dest[dest_pos + 0] = (byte)r;
                    dest[dest_pos + 1] = (byte)g;
                    dest[dest_pos + 2] = (byte)b;
                    dest[dest_pos + 3] = (byte)a;

                    bl_pos   += 3;
                    dest_pos += 4;
                }
            }
        }
コード例 #20
0
        private void Mod_LoadTexinfo(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            List <CModel.SMTexInfo> MTexInfo = new List <CModel.SMTexInfo>();

            br.BaseStream.Seek(header.lumps[LUMP_TEXINFO].fileofs, System.IO.SeekOrigin.Begin);
            while (br.BaseStream.Position < (header.lumps[LUMP_TEXINFO].fileofs + header.lumps[LUMP_TEXINFO].filelen))
            {
                CModel.SMTexInfo _MTexInfo;
                string           texture;
                int next;

                _MTexInfo.vecs = new Microsoft.Xna.Framework.Vector4[2];
                for (int i = 0; i < 2; i++)
                {
                    _MTexInfo.vecs[i].X = br.ReadSingle();
                    _MTexInfo.vecs[i].Y = br.ReadSingle();
                    _MTexInfo.vecs[i].Z = br.ReadSingle();
                    _MTexInfo.vecs[i].W = br.ReadSingle();
                }

                _MTexInfo.flags = (ESurface)br.ReadInt32();
                br.ReadInt32(); // value
                texture = CShared.Com_ToString(br.ReadChars(32));
                texture = "textures/" + texture;

                next = br.ReadInt32();
                if (next > 0)
                {
                    _MTexInfo.next = next;
                }
                else
                {
                    _MTexInfo.next = 0;
                }

                _MTexInfo.image = CProgram.gQ2Game.gCMain.gCImage.FindImage(texture, out _MTexInfo.Width, out _MTexInfo.Height, CImage.EImageType.IT_WALL);

                // TODO
                //out->image = GL_FindImage (name, it_wall);
                //if (!out->image)
                //{
                //    ri.Con_Printf (PRINT_ALL, "Couldn't load %s\n", name);
                //    out->image = r_notexture;
                //}

                _MTexInfo.numframes = 0;

                MTexInfo.Add(_MTexInfo);
            }

            // count animation frames
            for (int i = 0; i < MTexInfo.Count; i++)
            {
                CModel.SMTexInfo _MTexInfo = MTexInfo[i];
                _MTexInfo.numframes = 1;

                for (int step = _MTexInfo.next; step != 0 && step != i; step = MTexInfo[step].next)
                {
                    _MTexInfo.numframes++;
                }

                MTexInfo[i] = _MTexInfo;
            }

            _SModel.numtexinfo = MTexInfo.Count;
            _SModel.texinfo    = MTexInfo.ToArray();
        }
コード例 #21
0
        private void Mod_LoadFaces(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            List <SDFace>           DFace    = new List <SDFace>();
            List <CModel.SMSurface> MSurface = new List <CModel.SMSurface>();

            br.BaseStream.Seek(header.lumps[LUMP_FACES].fileofs, System.IO.SeekOrigin.Begin);
            while (br.BaseStream.Position < (header.lumps[LUMP_FACES].fileofs + header.lumps[LUMP_FACES].filelen))
            {
                SDFace _DFace;

                _DFace.planenum = br.ReadUInt16();
                _DFace.side     = br.ReadInt16();

                _DFace.firstedge = br.ReadInt32();
                _DFace.numedges  = br.ReadInt16();
                _DFace.texinfo   = br.ReadInt16();

                _DFace.styles   = br.ReadBytes(MAXLIGHTMAPS);
                _DFace.lightofs = br.ReadInt32();

                DFace.Add(_DFace);
            }

            CProgram.gQ2Game.gCMain.gCSurface.BeginBuildingLightmaps(ref _SModel);

            for (int i = 0; i < DFace.Count; i++)
            {
                CModel.SMSurface _MSurface;
                int   side;
                short ti;

                _MSurface.firstedge = DFace[i].firstedge;
                _MSurface.numedges  = DFace[i].numedges;
                _MSurface.flags     = 0;
                _MSurface.polys     = null;
                _MSurface.ibSurface = null;
                _MSurface.ibData    = null;


                side = DFace[i].side;
                if (side != 0)
                {
                    _MSurface.flags |= CModel.EMSurface.SURF_PLANEBACK;
                }

                _MSurface.plane = DFace[i].planenum;

                _MSurface.plane2 = new Microsoft.Xna.Framework.Plane();

                ti = DFace[i].texinfo;
                if (ti < 0 || ti >= _SModel.numtexinfo)
                {
                    CMain.Error(CMain.EErrorParm.ERR_WARNING, "MOD_LoadBmodel: bad texinfo number");
                }
                _MSurface.texinfo = ti;

                _MSurface.bounds = CLocal.ClearBounds();

                _MSurface.boundsMid.X = 0.0f;
                _MSurface.boundsMid.Y = 0.0f;
                _MSurface.boundsMid.Z = 0.0f;

                _MSurface.lightIndex  = null;
                _MSurface.lightLength = null;

                _MSurface.texturechain = 0;
                _MSurface.visframe     = 0;

                // lighting info
                _MSurface.dlightframe        = 0;
                _MSurface.dlightbits         = 0;
                _MSurface.lightmaptexturenum = 0;
                _MSurface.styles             = new byte[MAXLIGHTMAPS];
                for (int j = 0; j < MAXLIGHTMAPS; j++)
                {
                    _MSurface.styles[j] = DFace[i].styles[j];
                }

                _MSurface.cached_light = null;
                _MSurface.samples      = DFace[i].lightofs;

                _MSurface.light_s  = 0;
                _MSurface.light_t  = 0;
                _MSurface.dlight_s = 0;
                _MSurface.dlight_t = 0;

                _MSurface.extents     = null;
                _MSurface.texturemins = null;
                CModel.CalcSurfaceExtents(ref _SModel, ref _MSurface);

                // set the drawing flags
                if ((_SModel.texinfo[_MSurface.texinfo].flags & ESurface.SURF_WARP) == ESurface.SURF_WARP)
                {
                    _MSurface.flags |= CModel.EMSurface.SURF_DRAWTURB;

                    for (int j = 0; j < 2; j++)
                    {
                        _MSurface.extents[j]     = 16384;
                        _MSurface.texturemins[j] = -8192;
                    }

                    // TODO
                    // cut up polygon for warps
                    //SubdivideSurface(i, ref _WorldModel.mfaces[i]);
                    //SubdivideSurface (out);
                }

                // create lightmaps and polygons
                if (
                    (_SModel.texinfo[_MSurface.texinfo].flags & ESurface.SURF_SKY) != ESurface.SURF_SKY &&
                    (_SModel.texinfo[_MSurface.texinfo].flags & ESurface.SURF_TRANS33) != ESurface.SURF_TRANS33 &&
                    (_SModel.texinfo[_MSurface.texinfo].flags & ESurface.SURF_TRANS66) != ESurface.SURF_TRANS66 &&
                    (_SModel.texinfo[_MSurface.texinfo].flags & ESurface.SURF_WARP) != ESurface.SURF_WARP
                    )
                {
                    CProgram.gQ2Game.gCMain.gCSurface.CreateSurfaceLightmap(_SModel, ref _MSurface);
                }

                if ((_SModel.texinfo[_MSurface.texinfo].flags & ESurface.SURF_WARP) == ESurface.SURF_WARP)
                {
                    CProgram.gQ2Game.gCMain.gCSurface.BuildPolygonFromSurface(ref _MSurface);
                }

                MSurface.Add(_MSurface);
            }

            CProgram.gQ2Game.gCMain.gCSurface.EndBuildingLightmaps(ref _SModel);

            _SModel.numsurfaces = MSurface.Count;
            _SModel.surfaces    = MSurface.ToArray();
        }
コード例 #22
0
        public void Mod_LoadAliasModel(ref CModel.SModel _SModel, MemoryStream ms)
        {
            BinaryReader                  br;
            List <string>                 skinnames;
            List <CQ2MD2.SSTVert>         st;
            List <CQ2MD2.SDTriangle>      triangles;
            List <CQ2MD2.SAliasFrameDesc> aliasframes;

            // HACK - prevent model loading if in Heretic II mode
            if (CProgram.gQ2Game.gCMain.r_htic2 == true)
            {
                return;
            }

            ms.Seek(0, System.IO.SeekOrigin.Begin);
            br = new BinaryReader(ms);


            // identity (header)
            _SModel.ModelMD2.md2.identification = br.ReadBytes(4);
            if (_SModel.ModelMD2.md2.identification[0] != 'I' ||
                _SModel.ModelMD2.md2.identification[1] != 'D' ||
                _SModel.ModelMD2.md2.identification[2] != 'P' ||
                _SModel.ModelMD2.md2.identification[3] != '2')
            {
                System.Diagnostics.Debug.WriteLine("MDL file " + _SModel.name + " doesn't have IDP2 id");

                br.Close();
                return;
            }


            // model version
            _SModel.ModelMD2.md2.version = br.ReadInt32();
            if (_SModel.ModelMD2.md2.version != ALIAS_VERSION)
            {
                System.Diagnostics.Debug.WriteLine(_SModel.name + " has wrong version number (" + _SModel.ModelMD2.md2.version + " should be " + ALIAS_VERSION + ")");

                br.Close();
                return;
            }


            // skin size
            _SModel.ModelMD2.md2.skinwidth  = br.ReadInt32();
            _SModel.ModelMD2.md2.skinheight = br.ReadInt32();
            if (_SModel.ModelMD2.md2.skinheight > CLocal.MAX_LBM_HEIGHT)
            {
                System.Diagnostics.Debug.WriteLine("model " + _SModel.name + " has a skin taller than " + CLocal.MAX_LBM_HEIGHT + ".");

                br.Close();
                return;
            }


            // frame size
            _SModel.ModelMD2.md2.framesize = br.ReadInt32();


            // number of skins
            _SModel.ModelMD2.md2.num_skins = br.ReadInt32();


            // number of vertices
            _SModel.ModelMD2.md2.num_xyz = br.ReadInt32();
            if (_SModel.ModelMD2.md2.num_xyz > MAX_VERTS)
            {
                System.Diagnostics.Debug.WriteLine("model " + _SModel.name + " has too many vertices");

                br.Close();
                return;
            }


            // number of st vertices
            _SModel.ModelMD2.md2.num_st = br.ReadInt32();
            if (_SModel.ModelMD2.md2.num_st <= 0)
            {
                System.Diagnostics.Debug.WriteLine("model " + _SModel.name + " has no st vertices");

                br.Close();
                return;
            }


            // number of triangles
            _SModel.ModelMD2.md2.num_tris = br.ReadInt32();
            if (_SModel.ModelMD2.md2.num_tris <= 0)
            {
                System.Diagnostics.Debug.WriteLine("model " + _SModel.name + " has no triangles");

                br.Close();
                return;
            }


            // number of gl commands
            _SModel.ModelMD2.md2.num_glcmds = br.ReadInt32();


            // number of frames
            _SModel.ModelMD2.md2.num_frames = br.ReadInt32();
            if (_SModel.ModelMD2.md2.num_frames <= 0)
            {
                System.Diagnostics.Debug.WriteLine("model " + _SModel.name + " has no frames");

                br.Close();
                return;
            }


            // load offsets
            _SModel.ModelMD2.md2.ofs_skins  = br.ReadInt32(); // each skin is a MAX_SKINNAME string
            _SModel.ModelMD2.md2.ofs_st     = br.ReadInt32(); // byte offset from start for stverts
            _SModel.ModelMD2.md2.ofs_tris   = br.ReadInt32(); // offset for dtriangles
            _SModel.ModelMD2.md2.ofs_frames = br.ReadInt32(); // offset for first frame
            _SModel.ModelMD2.md2.ofs_glcmds = br.ReadInt32(); // offset for strip/fan command list
            _SModel.ModelMD2.md2.ofs_end    = br.ReadInt32(); // end of file


            //
            // load the skin names
            //
            skinnames = new List <string>();
            for (int i = 0; i < _SModel.ModelMD2.md2.num_skins; i++)
            {
                skinnames.Add(CShared.Com_ToString(br.ReadChars(MAX_SKINNAME)));
            }

            if (skinnames.Count != 0)
            {
                _SModel.ModelMD2.skinnames = skinnames.ToArray();
                skinnames.Clear();
                skinnames = null;
            }


            //
            // load base s and t vertices (not used in gl version)
            //
            st = new List <SSTVert>();
            for (int i = 0; i < _SModel.ModelMD2.md2.num_st; i++)
            {
                SSTVert _SSTVert;

                _SSTVert.s = br.ReadInt16();
                _SSTVert.t = br.ReadInt16();

                st.Add(_SSTVert);
            }

            if (st.Count != 0)
            {
                _SModel.ModelMD2.st = st.ToArray();
                st.Clear();
                st = null;
            }


            //
            // load the triangles
            //
            triangles = new List <SDTriangle>();
            for (int i = 0; i < _SModel.ModelMD2.md2.num_tris; i++)
            {
                SDTriangle _SDTriangle;

                _SDTriangle.index_xyz    = new short[3];
                _SDTriangle.index_xyz[0] = br.ReadInt16();
                _SDTriangle.index_xyz[1] = br.ReadInt16();
                _SDTriangle.index_xyz[2] = br.ReadInt16();

                _SDTriangle.index_st    = new short[3];
                _SDTriangle.index_st[0] = br.ReadInt16();
                _SDTriangle.index_st[1] = br.ReadInt16();
                _SDTriangle.index_st[2] = br.ReadInt16();

                triangles.Add(_SDTriangle);
            }

            if (triangles.Count != 0)
            {
                _SModel.ModelMD2.triangles = triangles.ToArray();
                triangles.Clear();
                triangles = null;
            }


            //
            // load the frames
            //
            aliasframes = new List <SAliasFrameDesc>();
            for (int i = 0; i < _SModel.ModelMD2.md2.num_frames; i++)
            {
                SAliasFrameDesc _SAliasFrameDesc;

                _SAliasFrameDesc.scale    = new float[3];
                _SAliasFrameDesc.scale[0] = br.ReadSingle();
                _SAliasFrameDesc.scale[1] = br.ReadSingle();
                _SAliasFrameDesc.scale[2] = br.ReadSingle();

                _SAliasFrameDesc.translate    = new float[3];
                _SAliasFrameDesc.translate[0] = br.ReadSingle();
                _SAliasFrameDesc.translate[1] = br.ReadSingle();
                _SAliasFrameDesc.translate[2] = br.ReadSingle();

                _SAliasFrameDesc.name = br.ReadChars(16);

                _SAliasFrameDesc.verts = new STrivertx[_SModel.ModelMD2.md2.num_xyz];
                for (int j = 0; j < _SModel.ModelMD2.md2.num_xyz; j++)
                {
                    _SAliasFrameDesc.verts[j].v    = new byte[3];
                    _SAliasFrameDesc.verts[j].v[0] = br.ReadByte();
                    _SAliasFrameDesc.verts[j].v[1] = br.ReadByte();
                    _SAliasFrameDesc.verts[j].v[2] = br.ReadByte();

                    _SAliasFrameDesc.verts[j].lightnormalindex = br.ReadByte();
                }

                aliasframes.Add(_SAliasFrameDesc);
            }

            if (aliasframes.Count != 0)
            {
                _SModel.ModelMD2.aliasframes = aliasframes.ToArray();
                aliasframes.Clear();
                aliasframes = null;
            }


            //
            // load the gl commands
            //
            _SModel.ModelMD2.glcmds = br.ReadBytes(_SModel.ModelMD2.md2.num_glcmds * sizeof(int));



            // set the model type
            _SModel.ModType = CModel.EModType.MOD_ALIAS;


            // register all skins
            _SModel.ModelMD2.skins = new Microsoft.Xna.Framework.Graphics.Texture2D[_SModel.ModelMD2.md2.num_skins];
            for (int i = 0; i < _SModel.ModelMD2.md2.num_skins; i++)
            {
                _SModel.ModelMD2.skins[i] = CProgram.gQ2Game.gCMain.gCImage.LoadSkin(_SModel.ModelMD2.skinnames[i]);
            }

            // set default mins/maxs
            _SModel.mins.X = -32;
            _SModel.mins.Y = -32;
            _SModel.mins.Z = -32;
            _SModel.maxs.X = 32;
            _SModel.maxs.Y = 32;
            _SModel.maxs.Z = 32;

            // close the binary reader
            br.Close();
            br = null;

            // close the memory stream
            ms.Close();
            ms = null;

            BuildAliasModelBuffer(ref _SModel.ModelMD2);
        }
コード例 #23
0
        private void Mod_LoadNodesAndLeafs(SDHeader header, ref CModel.SModel _SModel, ref System.IO.BinaryReader br)
        {
            List <SDNode>        DNode = new List <SDNode>();
            List <SDLeaf>        DLeaf = new List <SDLeaf>();
            List <CModel.SMNode> MNode = new List <CModel.SMNode>();


            // load nodes
            br.BaseStream.Seek(header.lumps[LUMP_NODES].fileofs, System.IO.SeekOrigin.Begin);
            while (br.BaseStream.Position < (header.lumps[LUMP_NODES].fileofs + header.lumps[LUMP_NODES].filelen))
            {
                SDNode _DNode;

                _DNode.planenum = br.ReadInt32();

                _DNode.children    = new int[2];
                _DNode.children[0] = br.ReadInt32();
                _DNode.children[1] = br.ReadInt32();

                _DNode.mins    = new short[3];
                _DNode.mins[0] = br.ReadInt16();
                _DNode.mins[1] = br.ReadInt16();
                _DNode.mins[2] = br.ReadInt16();

                _DNode.maxs    = new short[3];
                _DNode.maxs[0] = br.ReadInt16();
                _DNode.maxs[1] = br.ReadInt16();
                _DNode.maxs[2] = br.ReadInt16();

                _DNode.firstface = br.ReadUInt16();
                _DNode.numfaces  = br.ReadUInt16();

                DNode.Add(_DNode);
            }

            for (int i = 0; i < DNode.Count; i++)
            {
                CModel.SMNode _MNode;
                int           p;

                _MNode.bounds.Min.X = DNode[i].mins[0];
                _MNode.bounds.Min.Y = DNode[i].mins[1];
                _MNode.bounds.Min.Z = DNode[i].mins[2];
                _MNode.bounds.Max.X = DNode[i].maxs[0];
                _MNode.bounds.Max.Y = DNode[i].maxs[1];
                _MNode.bounds.Max.Z = DNode[i].maxs[2];

                _MNode.plane = DNode[i].planenum;

                _MNode.firstsurface = DNode[i].firstface;
                _MNode.numsurfaces  = DNode[i].numfaces;
                _MNode.contents     = -1; // differentiate from leafs

                _MNode.children = new int[2];
                for (int j = 0; j < 2; j++)
                {
                    p = DNode[i].children[j];

                    if (p >= 0)
                    {
                        _MNode.children[j] = p;
                    }
                    else
                    {
                        _MNode.children[j] = DNode.Count + (-1 - p);
                    }
                }

                _MNode.parent   = 0;
                _MNode.visframe = 0;

                // leaf specific
                _MNode.cluster          = 0;
                _MNode.area             = 0;
                _MNode.firstmarksurface = 0;
                _MNode.nummarksurfaces  = 0;

                MNode.Add(_MNode);
            }


            // load leafs
            br.BaseStream.Seek(header.lumps[LUMP_LEAFS].fileofs, System.IO.SeekOrigin.Begin);
            while (br.BaseStream.Position < (header.lumps[LUMP_LEAFS].fileofs + header.lumps[LUMP_LEAFS].filelen))
            {
                SDLeaf _DLeaf;

                _DLeaf.contents = br.ReadInt32();

                _DLeaf.cluster = br.ReadInt16();
                _DLeaf.area    = br.ReadInt16();

                _DLeaf.mins    = new short[3];
                _DLeaf.mins[0] = br.ReadInt16();
                _DLeaf.mins[1] = br.ReadInt16();
                _DLeaf.mins[2] = br.ReadInt16();

                _DLeaf.maxs    = new short[3];
                _DLeaf.maxs[0] = br.ReadInt16();
                _DLeaf.maxs[1] = br.ReadInt16();
                _DLeaf.maxs[2] = br.ReadInt16();

                _DLeaf.firstleafface = br.ReadUInt16();
                _DLeaf.numleaffaces  = br.ReadUInt16();

                _DLeaf.firstleafbrush = br.ReadUInt16();
                _DLeaf.numleafbrushes = br.ReadUInt16();

                DLeaf.Add(_DLeaf);
            }

            for (int i = 0; i < DLeaf.Count; i++)
            {
                CModel.SMNode _MNode;

                _MNode.bounds.Min.X = DLeaf[i].mins[0];
                _MNode.bounds.Min.Y = DLeaf[i].mins[1];
                _MNode.bounds.Min.Z = DLeaf[i].mins[2];
                _MNode.bounds.Max.X = DLeaf[i].maxs[0];
                _MNode.bounds.Max.Y = DLeaf[i].maxs[1];
                _MNode.bounds.Max.Z = DLeaf[i].maxs[2];

                _MNode.contents = DLeaf[i].contents;

                _MNode.cluster = DLeaf[i].cluster;
                _MNode.area    = DLeaf[i].area;

                _MNode.firstmarksurface = DLeaf[i].firstleafface;
                _MNode.nummarksurfaces  = DLeaf[i].numleaffaces;

                _MNode.parent   = 0;
                _MNode.visframe = 0;

                // node specific
                _MNode.plane        = 0;
                _MNode.firstsurface = 0;
                _MNode.numsurfaces  = 0;
                _MNode.children     = null;

                MNode.Add(_MNode);
            }

            _SModel.numnodes         = DNode.Count + DLeaf.Count;
            _SModel.numDecisionNodes = DNode.Count;
            _SModel.numleafs         = DLeaf.Count;
            _SModel.nodes            = MNode.ToArray();

            // chain decendants
            Mod_SetParent(ref _SModel, 0, -1);
        }