/// <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(); }
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(); }
/// <summary> /// SubdivideSurface /// ---------------- /// Breaks a polygon up along axial 64 unit boundaries /// so that turbulent and sky warps can be done reasonably. /// </summary> public void SubdivideSurface(ref CModel.SMSurface surf) { float[] verts; int numverts; List<CModel.SGLPoly> polys; if ((surf.flags & CModel.EMSurface.SURF_DRAWTURB) != CModel.EMSurface.SURF_DRAWTURB) return; verts = new float[64 * 3]; numverts = surf.polys[0].numverts; for (int i = 0; i < surf.polys[0].numverts; i++) { verts[(i * 3) + 0] = surf.polys[0].verts[i].vertex.Position.X; verts[(i * 3) + 1] = surf.polys[0].verts[i].vertex.Position.Y; verts[(i * 3) + 2] = surf.polys[0].verts[i].vertex.Position.Z; } surf.polys = null; polys = new List<CModel.SGLPoly>(); SubdividePolygon(surf, ref polys, numverts, verts); surf.polys = polys.ToArray(); polys.Clear(); }
/// <summary> /// EndBuildingLightmaps /// -------------------- /// Finalizes the processed lightmaps /// </summary> public void EndBuildingLightmaps(ref CModel.SModel _SModel) { LM_UploadBlock(false); CProgram.gQ2Game.gCMain.gCImage.FinalizeLightmaps(ref _SModel); }
/// <summary> /// BuildSurfaceIndex /// ------------------ /// Convert the surface's vertex format from triangle fan to triangle list /// This is used to speed up surface warping by using an index buffer /// </summary> public int[] BuildSurfaceIndex(CModel.SMSurface surf) { List<int> ib = new List<int>(); ib.Clear(); for (int i = 0; i < surf.polys.Length; i++) { for (int j = 2; j < surf.polys[i].verts.Length; j++) { ib.Add(surf.polys[i].verts[0].offset); ib.Add(surf.polys[i].verts[j - 1].offset); ib.Add(surf.polys[i].verts[j].offset); } } return ib.ToArray(); }
public void BuildPolygonFromSurface(ref CModel.SMSurface surf) { // most parts of the BuildWorld() function in CMain could be done here // if so, the polygons needs to be subdivided first most likely // see the function calling this function }
public void SetCacheState(ref CModel.SMSurface surf) { surf.cached_light = new float[CQ2BSP.MAXLIGHTMAPS]; for(int maps = 0; maps < CQ2BSP.MAXLIGHTMAPS && surf.styles[maps] != 255; maps++) { surf.cached_light[maps] = CClient.cl.RefDef.lightstyles[surf.styles[maps]].white; } }
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(); }
public void R_DrawBrushModel(CModel.SEntities _CurrentEntity) { Matrix wMatrix; //EffectParameter EP; Vector3 mins; Vector3 maxs; bool rotated; // update HLSL variables CProgram.gQ2Game.gCMain.UpdateHLSL(-1); // sort textures and surfaces if (CProgram.gQ2Game.gCMain.MarkSurfaceSetupStatic(ref _CurrentEntity.Model) == false) return; // set vertex buffer CProgram.gQ2Game.gGraphicsDevice.SetVertexBuffer(_CurrentEntity.Model.vbWorldSolid); if (_CurrentEntity.Angles.X != 0.0f || _CurrentEntity.Angles.Y != 0.0f || _CurrentEntity.Angles.Z != 0.0f) { rotated = true; mins.X = _CurrentEntity.Origin.X - _CurrentEntity.Model.radius; mins.Y = _CurrentEntity.Origin.Y - _CurrentEntity.Model.radius; mins.Z = _CurrentEntity.Origin.Z - _CurrentEntity.Model.radius; maxs.X = _CurrentEntity.Origin.X + _CurrentEntity.Model.radius; maxs.Y = _CurrentEntity.Origin.Y + _CurrentEntity.Model.radius; maxs.Z = _CurrentEntity.Origin.Z + _CurrentEntity.Model.radius; } else { rotated = false; mins.X = _CurrentEntity.Origin.X + _CurrentEntity.Model.mins.X; mins.Y = _CurrentEntity.Origin.Y + _CurrentEntity.Model.mins.Y; mins.Z = _CurrentEntity.Origin.Z + _CurrentEntity.Model.mins.Z; maxs.X = _CurrentEntity.Origin.X + _CurrentEntity.Model.maxs.X; maxs.Y = _CurrentEntity.Origin.Y + _CurrentEntity.Model.maxs.Y; maxs.Z = _CurrentEntity.Origin.Z + _CurrentEntity.Model.maxs.Z; } //if (R_CullBox(mins, maxs)) // return; CMain.ModelOrigin.X = CClient.cl.RefDef.ViewOrigin.X - _CurrentEntity.Origin.X; CMain.ModelOrigin.Y = CClient.cl.RefDef.ViewOrigin.Y - _CurrentEntity.Origin.Y; CMain.ModelOrigin.Z = CClient.cl.RefDef.ViewOrigin.Z - _CurrentEntity.Origin.Z; if (rotated == true) { Vector3 temp; Vector3 forward, right, up; temp.X = CMain.ModelOrigin.X; temp.Y = CMain.ModelOrigin.Y; temp.Z = CMain.ModelOrigin.Z; forward = Vector3.Zero; right = Vector3.Zero; up = Vector3.Zero; CShared.AngleVectors(_CurrentEntity.Angles, ref forward, ref right, ref up); CMain.ModelOrigin.X = Vector3.Dot(temp, forward); CMain.ModelOrigin.Y = -Vector3.Dot(temp, right); CMain.ModelOrigin.Z = Vector3.Dot(temp, up); } if (rotated == false) { wMatrix = Matrix.CreateFromYawPitchRoll(_CurrentEntity.Angles.Y, _CurrentEntity.Angles.X, _CurrentEntity.Angles.Z); wMatrix *= Matrix.CreateTranslation(_CurrentEntity.Origin); } else { wMatrix = Matrix.CreateTranslation(_CurrentEntity.Origin); } // update HLSL variables CProgram.gQ2Game.gEffect.Parameters["xWorld"].SetValue(wMatrix); // set a rendering technique if ((_CurrentEntity.Model.Flags & CQ2MD2.EModelFlags.RF_TRANSLUCENT) == CQ2MD2.EModelFlags.RF_TRANSLUCENT) CProgram.gQ2Game.gEffect.CurrentTechnique = CProgram.gQ2Game.gEffect.Techniques["TexturedTranslucent"]; else { if (CProgram.gQ2Game.gCMain.r_hardwarelight == false) CProgram.gQ2Game.gEffect.CurrentTechnique = CProgram.gQ2Game.gEffect.Techniques["TexturedLightmap"]; else CProgram.gQ2Game.gEffect.CurrentTechnique = CProgram.gQ2Game.gEffect.Techniques["TexturedLight"]; } // jkrige TODO - probably need to update this since most brushmodels can translate/rotate // save effect parameter collection shortcut //EP = CProgram.gQ2Game.gEffect.Parameters["lights"]; for (int i = 0; i < _CurrentEntity.Model.nummodelsurfaces; i++) { int surf = _CurrentEntity.Model.firstmodelsurface + i; // update surface HLSL variables CProgram.gQ2Game.gCMain.UpdateHLSL(surf); // set lights for current surface //for (int k = 0; k < CProgram.gQ2Game.gCMain.r_maxLights; k++) //{ // _CurrentEntity.Model.lights[CQ2BSP.SWorldData.surfaces[surf].lightIndex[k]].SetLight(EP.Elements[k]); //} } for (int i = 0; i < _CurrentEntity.Model.lSChainLightmap.Count; i++) { // bind new lightmap int lightmaptexturenum = _CurrentEntity.Model.lSChainLightmap[i].lightmaptexturenum; CProgram.gQ2Game.gEffect.Parameters["xTextureLightmap"].SetValue(CQ2BSP.SWorldData.WorldLightmaps[lightmaptexturenum]); for (int j = 0; j < _CurrentEntity.Model.lSChainLightmap[i].TexInfo.Count; j++) { // bind new texture int texanim = CProgram.gQ2Game.gCMain.TextureAnimation(_CurrentEntity.Model.lSChainLightmap[i].TexInfo[j].texinfo); int texinfo = _CurrentEntity.Model.lSChainLightmap[i].TexInfo[j].texinfo; CProgram.gQ2Game.gEffect.Parameters["xTextureDiffuse"].SetValue(CQ2BSP.SWorldData.WorldTextures[CQ2BSP.SWorldData.texinfo[texanim].image].Tex2D); // set the indices CProgram.gQ2Game.gGraphicsDevice.Indices = _CurrentEntity.Model.ibWorldSolid[lightmaptexturenum, texinfo].ibBuffer; foreach (EffectPass pass in CProgram.gQ2Game.gEffect.CurrentTechnique.Passes) { pass.Apply(); CProgram.gQ2Game.gGraphicsDevice.DrawIndexedPrimitives( PrimitiveType.TriangleList, 0, 0, _CurrentEntity.Model.vbWorldSolid.VertexCount, 0, _CurrentEntity.Model.ibWorldSolid[lightmaptexturenum, texinfo].PrimitiveCount); } CMain.c_brush_polys += _CurrentEntity.Model.ibWorldSolid[lightmaptexturenum, texinfo].PrimitiveCount; } } }
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); }
// ================================================================ // // 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); } }
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); } }
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); }
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(); } }
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(); }
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); }
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; }
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(); }
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(); }
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(); }
/// <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; } } }
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(); }
/// <summary> /// BuildSurfaceIndex /// ------------------ /// Convert the surface's vertex format from triangle fan to triangle list /// This is used to speed up surface warping by using an index buffer /// </summary> public void BuildSurfaceIndex(ref CModel.SMSurface surf) { List<int> ib; //if ((surf.flags & CModel.EMSurface.SURF_DRAWTURB) != CModel.EMSurface.SURF_DRAWTURB) // return; ib = new List<int>(); ib.Clear(); for (int i = 0; i < surf.polys.Length; i++) { for (int j = 2; j < surf.polys[i].verts.Length; j++) { ib.Add(surf.polys[i].verts[0].offset); ib.Add(surf.polys[i].verts[j - 1].offset); ib.Add(surf.polys[i].verts[j].offset); } } surf.ibData = ib.ToArray(); // setup the index buffer if (CProgram.gQ2Game.gGraphicsDevice.GraphicsProfile == GraphicsProfile.HiDef) { surf.ibSurface = new IndexBuffer(CProgram.gQ2Game.gGraphicsDevice, IndexElementSize.ThirtyTwoBits /*typeof(int)*/, surf.ibData.Length, BufferUsage.WriteOnly); surf.ibSurface.SetData(surf.ibData); } else { short[] ibData16 = new short[surf.ibData.Length]; for (int i = 0; i < surf.ibData.Length; i++) ibData16[i] = (short)surf.ibData[i]; surf.ibSurface = new IndexBuffer(CProgram.gQ2Game.gGraphicsDevice, IndexElementSize.SixteenBits, ibData16.Length, BufferUsage.WriteOnly); surf.ibSurface.SetData(ibData16); } //surf.ibSurface.SetData(surf.ibData); }
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; } }
/// <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); }
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(); }
/// <summary> /// SubdividePolygon /// ---------------- /// Breaks a polygon up along axial 64 unit boundaries /// so that turbulent and sky warps can be done reasonably. /// </summary> public void SubdividePolygon(CModel.SMSurface surf, ref List<CModel.SGLPoly> polys, int numverts, float[] verts) { float[] mins, maxs, dist; float m; float frac; int i, j, k, v; float[] Front, Back; int f, b; CModel.SGLPoly poly; Vector3 total; float total_s; float total_t; mins = new float[3]; maxs = new float[3]; dist = new float[64]; Front = new float[64 * 3]; Back = new float[64 * 3]; if (numverts > 60) CMain.Error(CMain.EErrorParm.ERR_WARNING, "(error) numverts = " + numverts); // Bind mins and maxs BoundPoly(numverts, verts, ref mins, ref maxs); for (i = 0; i < 3; i++) { m = (mins[i] + maxs[i]) * 0.5f; m = SUBDIVIDE_SIZE * (float)Math.Floor(m / (float)SUBDIVIDE_SIZE + 0.5f); if (maxs[i] - m < 8) continue; if (m - mins[i] < 8) continue; // cut it v = i; for (j = 0; j < numverts; j++, v += 3) { dist[j] = verts[v] - m; } // wrap cases dist[j] = dist[0]; v -= i; verts[v + 0] = verts[0 + 0]; verts[v + 1] = verts[0 + 1]; verts[v + 2] = verts[0 + 2]; f = 0; b = 0; v = 0; for (j = 0; j < numverts; j++, v += 3) { if (dist[j] >= 0) { Front[(f * 3) + 0] = verts[v + 0]; Front[(f * 3) + 1] = verts[v + 1]; Front[(f * 3) + 2] = verts[v + 2]; f++; } if (dist[j] <= 0) { Back[(b * 3) + 0] = verts[v + 0]; Back[(b * 3) + 1] = verts[v + 1]; Back[(b * 3) + 2] = verts[v + 2]; b++; } if (dist[j] == 0 || dist[j + 1] == 0) continue; if ((dist[j] > 0) != (dist[j + 1] > 0)) { // clip point frac = dist[j] / (dist[j] - dist[j + 1]); for (k = 0; k < 3; k++) { Front[(f * 3) + k] = Back[(b * 3) + k] = verts[v + k] + frac * (verts[3 + v + k] - verts[v + k]); } f++; b++; } } SubdividePolygon(surf, ref polys, f, Front); SubdividePolygon(surf, ref polys, b, Back); return; } // add a point in the center to help keep warp valid poly.next = 0; poly.chain = 0; poly.numverts = numverts + 2; poly.verts = new CModel.SPolyVerts[poly.numverts]; total = Vector3.Zero; total_s = 0.0f; total_t = 0.0f; v = 0; for (i = 0; i < numverts; i++, v += 3) { float s; float t; Vector3 vec0; Vector3 vec1; poly.verts[i + 1].vertex.Position.X = verts[v + 0]; poly.verts[i + 1].vertex.Position.Y = verts[v + 1]; poly.verts[i + 1].vertex.Position.Z = verts[v + 2]; vec0.X = CQ2BSP.SWorldData.texinfo[surf.texinfo].vecs[0].X; vec0.Y = CQ2BSP.SWorldData.texinfo[surf.texinfo].vecs[0].Y; vec0.Z = CQ2BSP.SWorldData.texinfo[surf.texinfo].vecs[0].Z; vec1.X = CQ2BSP.SWorldData.texinfo[surf.texinfo].vecs[1].X; vec1.Y = CQ2BSP.SWorldData.texinfo[surf.texinfo].vecs[1].Y; vec1.Z = CQ2BSP.SWorldData.texinfo[surf.texinfo].vecs[1].Z; s = Vector3.Dot(poly.verts[i + 1].vertex.Position, vec0); t = Vector3.Dot(poly.verts[i + 1].vertex.Position, vec1); total_s += s; total_t += t; total.X += verts[v + 0]; total.Y += verts[v + 1]; total.Z += verts[v + 2]; poly.verts[i + 1].vertex.TextureCoordinate.X = s; poly.verts[i + 1].vertex.TextureCoordinate.Y = t; poly.verts[i + 1].vertex.LightmapCoordinate.X = 0.0f; poly.verts[i + 1].vertex.LightmapCoordinate.Y = 0.0f; poly.verts[i + 1].vertex.Normal.X = 0.0f; poly.verts[i + 1].vertex.Normal.Y = 0.0f; poly.verts[i + 1].vertex.Normal.Z = 0.0f; } CShared.VectorScale(total, (1.0f / numverts), ref poly.verts[0].vertex.Position); poly.verts[0].vertex.TextureCoordinate.X = total_s / numverts; poly.verts[0].vertex.TextureCoordinate.Y = total_t / numverts; // copy first vertex to last poly.verts[i + 1] = poly.verts[1]; // insert centered point at first index polys.Insert(0, poly); }
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); }
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(); }
/// <summary> /// MarkSurfaceSetup /// ---------------- /// Sort surfaces according to texture /// </summary> public bool MarkSurfaceSetupStatic(ref CModel.SModel _SModel) { List<int> indices; if (_SModel.MarkSurfaceListStatic == null) return false; if (_SModel.MarkSurfaceListStatic.Count == 0) return false; // build lightmap/texture/surface chains _SModel.lSChainLightmap = new List<SChainLightmap>(); for (int i = 0; i < _SModel.MarkSurfaceListStatic.Count; i++) { int idxLightmap = -1; int idxTexture = -1; int idxSurface = -1; // check for lightmap modification gCLight.LightmapAnimation(_SModel.MarkSurfaceListStatic[i].surf); // generate lightmap list for (int j = 0; j < _SModel.lSChainLightmap.Count; j++) { if (_SModel.lSChainLightmap[j].lightmaptexturenum == _SModel.MarkSurfaceListStatic[i].lightmaptexturenum) { idxLightmap = j; break; } } if (idxLightmap == -1) { SChainLightmap _SCLM; _SCLM.lightmaptexturenum = _SModel.MarkSurfaceListStatic[i].lightmaptexturenum; _SCLM.TexInfo = new List<SChainTexture>(); _SModel.lSChainLightmap.Add(_SCLM); idxLightmap = _SModel.lSChainLightmap.Count - 1; } // generate texinfo list SChainLightmap _SChainLightmap = _SModel.lSChainLightmap[idxLightmap]; for (int j = 0; j < _SChainLightmap.TexInfo.Count; j++) { if (_SChainLightmap.TexInfo[j].texinfo == _SModel.MarkSurfaceListStatic[i].texinfo) { idxTexture = j; break; } } if (idxTexture == -1) { SChainTexture _SCT; _SCT.texinfo = _SModel.MarkSurfaceListStatic[i].texinfo; _SCT.surf = new List<int>(); _SChainLightmap.TexInfo.Add(_SCT); idxTexture = _SChainLightmap.TexInfo.Count - 1; } _SModel.lSChainLightmap[idxLightmap] = _SChainLightmap; // generate surface list SChainTexture _SChainTexture = _SModel.lSChainLightmap[idxLightmap].TexInfo[idxTexture]; for (int j = 0; j < _SChainTexture.surf.Count; j++) { if (_SChainTexture.surf[j] == _SModel.MarkSurfaceListStatic[i].surf) { idxSurface = j; break; } } if (idxSurface == -1) { _SChainTexture.surf.Add(_SModel.MarkSurfaceListStatic[i].surf); idxSurface = _SChainTexture.surf.Count - 1; } _SModel.lSChainLightmap[idxLightmap].TexInfo[idxTexture] = _SChainTexture; } // build cluster-based index buffer indices = new List<int>(); for (int i = 0; i < _SModel.lSChainLightmap.Count; i++) { for (int j = 0; j < _SModel.lSChainLightmap[i].TexInfo.Count; j++) { int[] idx1; int[] idx2; int lm = _SModel.lSChainLightmap[i].lightmaptexturenum; int tx = _SModel.lSChainLightmap[i].TexInfo[j].texinfo; bool isEqual = true; indices.Clear(); for (int k = 0; k < _SModel.lSChainLightmap[i].TexInfo[j].surf.Count; k++) { int[] idx = gCSurface.BuildSurfaceIndex(CQ2BSP.SWorldData.surfaces[_SModel.lSChainLightmap[i].TexInfo[j].surf[k]]); if (idx == null) continue; for (int l = 0; l < idx.Length; l++) { indices.Add(idx[l]); } } idx1 = indices.ToArray(); idx2 = _SModel.ibWorldSolid[lm, tx].ibIndices; if (idx2 != null) { if (idx1.Length == idx2.Length) { for (int k = 0; k < idx1.Length; k++) { if (idx1[k] != idx2[k]) { isEqual = false; break; } } } else { isEqual = false; } } else { isEqual = false; } // re-build the index buffer the indices doesn't match if(isEqual == false) { _SModel.ibWorldSolid[lm, tx].ibIndices = new int[idx1.Length]; for (int k = 0; k < idx1.Length; k++) { _SModel.ibWorldSolid[lm, tx].ibIndices[k] = idx1[k]; } _SModel.ibWorldSolid[lm, tx].PrimitiveCount = _SModel.ibWorldSolid[lm, tx].ibIndices.Length / 3; if (_SModel.ibWorldSolid[lm, tx].ibBuffer.IndexCount < idx1.Length) { _SModel.ibWorldSolid[lm, tx].ibBuffer.Dispose(); _SModel.ibWorldSolid[lm, tx].ibBuffer = null; if (CProgram.gQ2Game.gGraphicsDevice.GraphicsProfile == GraphicsProfile.HiDef) _SModel.ibWorldSolid[lm, tx].ibBuffer = new IndexBuffer(CProgram.gQ2Game.gGraphicsDevice, IndexElementSize.ThirtyTwoBits, idx1.Length, BufferUsage.WriteOnly); else _SModel.ibWorldSolid[lm, tx].ibBuffer = new IndexBuffer(CProgram.gQ2Game.gGraphicsDevice, IndexElementSize.SixteenBits, idx1.Length, BufferUsage.WriteOnly); } if (CProgram.gQ2Game.gGraphicsDevice.GraphicsProfile == GraphicsProfile.HiDef) { _SModel.ibWorldSolid[lm, tx].ibBuffer.SetData(_SModel.ibWorldSolid[lm, tx].ibIndices); } else { short[] ibData16 = new short[_SModel.ibWorldSolid[lm, tx].ibIndices.Length]; for (int k = 0; k < _SModel.ibWorldSolid[lm, tx].ibIndices.Length; k++) ibData16[k] = (short)_SModel.ibWorldSolid[lm, tx].ibIndices[k]; _SModel.ibWorldSolid[lm, tx].ibBuffer.SetData(ibData16); } } } } indices.Clear(); indices = null; return true; }