diff --git a/src/g_levellocals.h b/src/g_levellocals.h index 7f7be16fc..e4d87934c 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -33,6 +33,7 @@ struct FLevelLocals TStaticArray sectors; TStaticArray lines; TStaticArray sides; + TStaticArray segs; TArray sectorPortals; @@ -109,6 +110,11 @@ inline int line_t::Index() const return int(this - &level.lines[0]); } +inline int seg_t::Index() const +{ + return int(this - &level.segs[0]); +} + inline FSectorPortal *line_t::GetTransferredPortal() { return portaltransferred >= level.sectorPortals.Size() ? (FSectorPortal*)nullptr : &level.sectorPortals[portaltransferred]; diff --git a/src/gl/data/gl_data.cpp b/src/gl/data/gl_data.cpp index 1515842b9..b83ced72c 100644 --- a/src/gl/data/gl_data.cpp +++ b/src/gl/data/gl_data.cpp @@ -389,13 +389,12 @@ CCMD(dumpgeometry) { Printf(PRINT_LOG, " (%4.4f, %4.4f), (%4.4f, %4.4f) - seg %d, linedef %d, side %d", seg->v1->fX(), seg->v1->fY(), seg->v2->fX(), seg->v2->fY(), - int(seg-segs), seg->linedef->Index(), seg->sidedef != seg->linedef->sidedef[0]); + seg->Index(), seg->linedef->Index(), seg->sidedef != seg->linedef->sidedef[0]); } else { Printf(PRINT_LOG, " (%4.4f, %4.4f), (%4.4f, %4.4f) - seg %d, miniseg", - seg->v1->fX(), seg->v1->fY(), seg->v2->fX(), seg->v2->fY(), - int(seg-segs)); + seg->v1->fX(), seg->v1->fY(), seg->v2->fX(), seg->v2->fY(), seg->Index()); } if (seg->PartnerSeg) { diff --git a/src/gl/data/gl_setup.cpp b/src/gl/data/gl_setup.cpp index 6c314cdb7..1ecd74057 100644 --- a/src/gl/data/gl_setup.cpp +++ b/src/gl/data/gl_setup.cpp @@ -115,7 +115,7 @@ static int MergeMapSections(int num) TArray sectvalid; sectmap.Resize(num); sectvalid.Resize(num); - for(int i=0;iSubsector->mapsection; - for(int j=0;j<2;j++) + int section = seg.Subsector->mapsection; + for (int j = 0; j < 2; j++) { - vt = j==0? seg->v1:seg->v2; + vt = j == 0 ? seg.v1 : seg.v2; vmap[vt] = section; } } // second step: Check if any seg references more than one mapsection, either by subsector or by vertex - for(uint32_t i=0;i<(uint32_t)numsegs;i++) + for (auto &seg : level.segs) { - seg_t * seg = &segs[i]; - int section = seg->Subsector->mapsection; - for(int j=0;j<2;j++) + int section = seg.Subsector->mapsection; + for (int j = 0; j < 2; j++) { - vt = j==0? seg->v1:seg->v2; + vt = j == 0 ? seg.v1 : seg.v2; int vsection = vmap[vt]; if (vsection != section) { // These 2 sections should be merged - for(int k=0;kValue == vsection) pair->Value = section; } - sectvalid[vsection-1] = false; + sectvalid[vsection - 1] = false; } } } - for(int i=0;isidedef == NULL) continue; // miniseg - int sidenum = seg->sidedef->Index(); + if (seg.sidedef == NULL) continue; // miniseg + int sidenum = seg.sidedef->Index(); realsegs++; segcount[sidenum]++; - DVector2 sidestart, sideend, segend = seg->v2->fPos(); + DVector2 sidestart, sideend, segend = seg.v2->fPos(); GetSideVertices(sidenum, &sidestart, &sideend); sideend -=sidestart; segend -= sidestart; - seg->sidefrac = float(segend.Length() / sideend.Length()); + seg.sidefrac = float(segend.Length() / sideend.Length()); } // allocate memory @@ -521,10 +517,9 @@ static void PrepareSegs() delete [] segcount; // assign the segs - for(int i=0;isidedef != NULL) seg->sidedef->segs[seg->sidedef->numsegs++] = seg; + if (seg.sidedef != NULL) seg.sidedef->segs[seg.sidedef->numsegs++] = &seg; } // sort the segs diff --git a/src/gl/dynlights/gl_shadowmap.cpp b/src/gl/dynlights/gl_shadowmap.cpp index 9a23e4114..c9223082d 100644 --- a/src/gl/dynlights/gl_shadowmap.cpp +++ b/src/gl/dynlights/gl_shadowmap.cpp @@ -32,6 +32,7 @@ #include "gl/renderer/gl_renderbuffers.h" #include "gl/shaders/gl_shadowmapshader.h" #include "r_state.h" +#include "g_levellocals.h" /* The 1D shadow maps are stored in a 1024x1024 texture as float depth values (R32F). @@ -157,7 +158,9 @@ void FShadowMap::UploadLights() void FShadowMap::UploadAABBTree() { - if (numnodes != mLastNumNodes || numsegs != mLastNumSegs) // To do: there is probably a better way to detect a map change than this.. + // Just comparing the level info is not enough. If two MAPINFO-less levels get played after each other, + // they can both refer to the same default level info. + if (level.info != mLastLevel && numnodes != mLastNumNodes || level.segs.Size() != mLastNumSegs) Clear(); if (mAABBTree) @@ -201,6 +204,7 @@ void FShadowMap::Clear() mAABBTree.reset(); + mLastLevel = level.info; mLastNumNodes = numnodes; - mLastNumSegs = numsegs; + mLastNumSegs = level.segs.Size(); } diff --git a/src/gl/dynlights/gl_shadowmap.h b/src/gl/dynlights/gl_shadowmap.h index e2b5b371f..45a3f6798 100644 --- a/src/gl/dynlights/gl_shadowmap.h +++ b/src/gl/dynlights/gl_shadowmap.h @@ -6,6 +6,7 @@ #include class ADynamicLight; +struct level_info_t; class FShadowMap { @@ -49,8 +50,9 @@ private: int mLinesBuffer = 0; // Used to detect when a level change requires the AABB tree to be regenerated + level_info_t *mLastLevel = nullptr; int mLastNumNodes = 0; - int mLastNumSegs = 0; + unsigned mLastNumSegs = 0; // AABB-tree of the level, used for ray tests std::unique_ptr mAABBTree; diff --git a/src/nodebuild.h b/src/nodebuild.h index c5297190d..09298ac19 100644 --- a/src/nodebuild.h +++ b/src/nodebuild.h @@ -194,7 +194,7 @@ public: ~FNodeBuilder (); void Extract(node_t *&nodes, int &nodeCount, - seg_t *&segs, int &segCount, + TStaticArray &segs, subsector_t *&ssecs, int &subCount, TStaticArray &vertexes); const int *GetOldVertexTable(); diff --git a/src/nodebuild_extract.cpp b/src/nodebuild_extract.cpp index 98ade3f78..f16b75524 100644 --- a/src/nodebuild_extract.cpp +++ b/src/nodebuild_extract.cpp @@ -53,7 +53,7 @@ #endif void FNodeBuilder::Extract (node_t *&outNodes, int &nodeCount, - seg_t *&outSegs, int &segCount, + TStaticArray &outSegs, subsector_t *&outSubs, int &subCount, TStaticArray &outVerts) { @@ -114,10 +114,10 @@ void FNodeBuilder::Extract (node_t *&outNodes, int &nodeCount, outSubs[i].firstline = (seg_t *)(size_t)(segs.Size() - numsegs); } - segCount = segs.Size (); - outSegs = new seg_t[segCount]; + auto segCount = segs.Size (); + outSegs.Alloc(segCount); - for (i = 0; i < segCount; ++i) + for (unsigned i = 0; i < segCount; ++i) { outSegs[i] = *(seg_t *)&segs[i]; @@ -135,9 +135,9 @@ void FNodeBuilder::Extract (node_t *&outNodes, int &nodeCount, else { memcpy (outSubs, &Subsectors[0], subCount*sizeof(subsector_t)); - segCount = Segs.Size (); - outSegs = new seg_t[segCount]; - for (i = 0; i < segCount; ++i) + auto segCount = Segs.Size (); + outSegs.Alloc(segCount); + for (unsigned i = 0; i < segCount; ++i) { const FPrivSeg *org = &Segs[SegList[i].SegNum]; seg_t *out = &outSegs[i]; diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index 2da9a0457..153c20949 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -135,25 +135,23 @@ static int CheckForMissingSegs() int missing = 0; memset(added_seglen, 0, sizeof(double)*numsides); - for(int i=0;isidedef!=NULL) + if (seg.sidedef != nullptr) { // check all the segs and calculate the length they occupy on their sidedef - DVector2 vec1(seg->v2->fX() - seg->v1->fX(), seg->v2->fY() - seg->v1->fY()); - added_seglen[seg->sidedef->Index()] += vec1.Length(); + DVector2 vec1(seg.v2->fX() - seg.v1->fX(), seg.v2->fY() - seg.v1->fY()); + added_seglen[seg.sidedef->Index()] += vec1.Length(); } } - for(unsigned i=0;iDelta().Length(); missing += (added_seglen[i] < linelen - 1.); } - delete [] added_seglen; + delete[] added_seglen; return missing; } @@ -183,7 +181,7 @@ bool P_CheckForGLNodes() { for(uint32_t j=0;jnumlines;j++) { - if (segs[j].linedef==NULL) // miniseg + if (level.segs[j].linedef==NULL) // miniseg { // We already have GL nodes. Great! return true; @@ -304,11 +302,11 @@ static bool LoadGLSegs(FileReader * lump) int i; line_t *ldef=NULL; - numsegs = lump->GetLength(); + int numsegs = lump->GetLength(); data= new char[numsegs]; lump->Seek(0, SEEK_SET); lump->Read(data, numsegs); - segs=NULL; + auto &segs = level.segs; #ifdef _MSC_VER __try @@ -317,12 +315,13 @@ static bool LoadGLSegs(FileReader * lump) if (!format5 && memcmp(data, "gNd3", 4)) { numsegs/=sizeof(glseg_t); - segs = new seg_t[numsegs]; - memset(segs,0,sizeof(seg_t)*numsegs); + level.segs.Alloc(numsegs); + memset(&segs[0],0,sizeof(seg_t)*numsegs); glseg_t * ml = (glseg_t*)data; for(i = 0; i < numsegs; i++) - { // check for gl-vertices + { + // check for gl-vertices segs[i].v1 = &level.vertexes[checkGLVertex(LittleShort(ml->v1))]; segs[i].v2 = &level.vertexes[checkGLVertex(LittleShort(ml->v2))]; segs[i].PartnerSeg = ml->partner == 0xFFFF ? nullptr : &segs[LittleShort(ml->partner)]; @@ -368,8 +367,8 @@ static bool LoadGLSegs(FileReader * lump) { if (!format5) numsegs-=4; numsegs/=sizeof(glseg3_t); - segs = new seg_t[numsegs]; - memset(segs,0,sizeof(seg_t)*numsegs); + level.segs.Alloc(numsegs); + memset(&segs[0],0,sizeof(seg_t)*numsegs); glseg3_t * ml = (glseg3_t*)(data+ (format5? 0:4)); for(i = 0; i < numsegs; i++) @@ -428,8 +427,7 @@ static bool LoadGLSegs(FileReader * lump) // (at least under MSVC. GCC can't do SEH even for Windows... :( ) Printf("Invalid GL segs. The BSP will have to be rebuilt.\n"); delete [] data; - delete [] segs; - segs = NULL; + level.segs.Clear(); return false; } #endif @@ -468,7 +466,7 @@ static bool LoadGLSubsectors(FileReader * lump) for (i=0; ifile, id); return true; @@ -876,11 +870,7 @@ bool P_LoadGLNodes(MapData * map) delete[] subsectors; subsectors = NULL; } - if (segs != NULL) - { - delete[] segs; - segs = NULL; - } + level.segs.Clear(); if (nodes != NULL) { delete[] nodes; @@ -984,9 +974,7 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) numnodes = 0; subsectors = NULL; numsubsectors = 0; - if (segs) delete [] segs; - segs = NULL; - numsegs = 0; + level.segs.Clear(); // Try to load GL nodes (cached or GWA) loaded = P_LoadGLNodes(map); @@ -1009,11 +997,11 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) FNodeBuilder builder (leveldata, polyspots, anchors, true); builder.Extract (nodes, numnodes, - segs, numsegs, + level.segs, subsectors, numsubsectors, level.vertexes); endTime = I_FPSTime (); - DPrintf (DMSG_NOTIFY, "BSP generation took %.3f sec (%d segs)\n", (endTime - startTime) * 0.001, numsegs); + DPrintf (DMSG_NOTIFY, "BSP generation took %.3f sec (%u segs)\n", (endTime - startTime) * 0.001, level.segs.Size()); buildtime = endTime - startTime; } } @@ -1106,15 +1094,15 @@ static void CreateCachedNodes(MapData *map) WriteLong(ZNodes, subsectors[i].numlines); } - WriteLong(ZNodes, numsegs); - for(int i=0;iIndex()); - WriteLong(ZNodes, segs[i].PartnerSeg == nullptr? 0xffffffffu : uint32_t(segs[i].PartnerSeg - segs)); - if (segs[i].linedef) + WriteLong(ZNodes, seg.v1->Index()); + WriteLong(ZNodes, seg.PartnerSeg == nullptr? 0xffffffffu : uint32_t(seg.PartnerSeg->Index())); + if (seg.linedef) { - WriteLong(ZNodes, uint32_t(segs[i].linedef->Index())); - WriteByte(ZNodes, segs[i].sidedef == segs[i].linedef->sidedef[0]? 0:1); + WriteLong(ZNodes, uint32_t(seg.linedef->Index())); + WriteByte(ZNodes, seg.sidedef == seg.linedef->sidedef[0]? 0:1); } else { @@ -1247,11 +1235,7 @@ static bool CheckCachedNodes(MapData *map) delete[] subsectors; subsectors = NULL; } - if (segs != NULL) - { - delete[] segs; - segs = NULL; - } + level.segs.Clear(); if (nodes != NULL) { delete[] nodes; @@ -1438,30 +1422,30 @@ void P_SetRenderSector() // Check for incorrect partner seg info so that the following code does not crash. - for (i = 0; i < numsegs; i++) + for (auto &seg : level.segs) { - auto p = segs[i].PartnerSeg; + auto p = seg.PartnerSeg; if (p != nullptr) { - int partner = (int)(p - segs); + int partner = p->Index(); - if (partner < 0 || partner >= numsegs || &segs[partner] != p) + if (partner < 0 || partner >= (int)level.segs.Size() || &level.segs[partner] != p) { - segs[i].PartnerSeg = nullptr; + seg.PartnerSeg = nullptr; } // glbsp creates such incorrect references for Strife. - if (segs[i].linedef && segs[i].PartnerSeg != nullptr && !segs[i].PartnerSeg->linedef) + if (seg.linedef && seg.PartnerSeg != nullptr && !seg.PartnerSeg->linedef) { - segs[i].PartnerSeg = segs[i].PartnerSeg->PartnerSeg = nullptr; + seg.PartnerSeg = seg.PartnerSeg->PartnerSeg = nullptr; } } } - for (i = 0; i < numsegs; i++) + for (auto &seg : level.segs) { - if (segs[i].PartnerSeg != nullptr && segs[i].PartnerSeg->PartnerSeg != &segs[i]) + if (seg.PartnerSeg != nullptr && seg.PartnerSeg->PartnerSeg != &seg) { - segs[i].PartnerSeg = nullptr; + seg.PartnerSeg = nullptr; } } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 4793dd7ea..908306a25 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -3914,7 +3914,7 @@ void P_SetupLevel (const char *lumpname, int position) // if the different machines' am_textured setting differs. FNodeBuilder builder (leveldata, polyspots, anchors, BuildGLNodes); builder.Extract (nodes, numnodes, - segs, numsegs, + level.segs, subsectors, numsubsectors, level.vertexes); endTime = I_FPSTime (); diff --git a/src/r_defs.h b/src/r_defs.h index 74c08e266..eeb2931a6 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -1375,9 +1375,11 @@ struct seg_t subsector_t* Subsector; float sidefrac; // relative position of seg's ending vertex on owning sidedef + + int Index() const; }; -extern seg_t *segs; +//extern seg_t *segs; // diff --git a/src/r_state.h b/src/r_state.h index 6223c40b4..780a2767c 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -46,8 +46,8 @@ extern uint32_t NumStdSprites; extern TArray vertexdatas; -extern int numsegs; -extern seg_t* segs; +//extern int numsegs; +//extern seg_t* segs; extern int numsubsectors; extern subsector_t* subsectors;