From fea4079b7cc97ac8362d86d56f8332e7f4824f98 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 17 Mar 2017 01:42:37 +0100 Subject: [PATCH] - moved nodes into FLevelLocals. --- src/g_levellocals.h | 16 +++ src/gl/data/gl_portaldata.cpp | 14 +-- src/gl/dynlights/gl_shadowmap.cpp | 4 +- src/gl/dynlights/gl_shadowmap.h | 2 +- src/gl/scene/gl_bsp.cpp | 4 +- src/gl/scene/gl_drawinfo.cpp | 2 +- src/gl/scene/gl_portal.cpp | 6 +- src/gl/scene/gl_scene.cpp | 2 +- src/nodebuild.h | 6 +- src/nodebuild_extract.cpp | 20 ++-- src/p_glnodes.cpp | 137 ++++++++----------------- src/p_maputl.cpp | 34 +++++- src/p_setup.cpp | 89 +++++++--------- src/po_man.cpp | 10 +- src/polyrenderer/scene/poly_cull.cpp | 4 +- src/polyrenderer/scene/poly_scene.cpp | 4 +- src/r_defs.h | 2 + src/r_state.h | 8 +- src/r_utility.cpp | 4 +- src/swrenderer/scene/r_opaque_pass.cpp | 4 +- 20 files changed, 164 insertions(+), 208 deletions(-) diff --git a/src/g_levellocals.h b/src/g_levellocals.h index a7bd53ed1..48f852902 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -36,6 +36,8 @@ struct FLevelLocals TStaticArray segs; TStaticPointableArray subsectors; TStaticPointableArray gamesubsectors; + TStaticPointableArray nodes; + TStaticPointableArray gamenodes; TArray sectorPortals; @@ -93,6 +95,15 @@ struct FLevelLocals bool IsJumpingAllowed() const; bool IsCrouchingAllowed() const; bool IsFreelookAllowed() const; + + node_t *HeadNode() const + { + return &nodes[nodes.Size() - 1]; + } + node_t *HeadGamenode() const + { + return &gamenodes[gamenodes.Size() - 1]; + } }; extern FLevelLocals level; @@ -122,6 +133,11 @@ inline int subsector_t::Index() const return int(this - &level.subsectors[0]); } +inline int node_t::Index() const +{ + return int(this - &level.nodes[0]); +} + inline FSectorPortal *line_t::GetTransferredPortal() { return portaltransferred >= level.sectorPortals.Size() ? (FSectorPortal*)nullptr : &level.sectorPortals[portaltransferred]; diff --git a/src/gl/data/gl_portaldata.cpp b/src/gl/data/gl_portaldata.cpp index 99ab17413..a51d20430 100644 --- a/src/gl/data/gl_portaldata.cpp +++ b/src/gl/data/gl_portaldata.cpp @@ -324,7 +324,7 @@ void gl_BuildPortalCoverage(FPortalCoverage *coverage, subsector_t *subsector, c build.center.x = xs_CRoundToInt(centerx / subsector->numlines); build.center.y = xs_CRoundToInt(centery / subsector->numlines); - build.CollectNode(nodes + numnodes - 1, shape); + build.CollectNode(level.HeadNode(), shape); coverage->subsectors = new uint32_t[build.collect.Size()]; coverage->sscount = build.collect.Size(); memcpy(coverage->subsectors, &build.collect[0], build.collect.Size() * sizeof(uint32_t)); @@ -359,17 +359,9 @@ void gl_InitPortals() { FPortalMap collection; - if (numnodes == 0) return; - - for(int i=0;idx); - double fdy = FIXED2DBL(no->dy); - no->len = (float)sqrt(fdx * fdx + fdy * fdy); - } + if (level.nodes.Size() == 0) return; + CollectPortalSectors(collection); glSectorPortals.Clear(); diff --git a/src/gl/dynlights/gl_shadowmap.cpp b/src/gl/dynlights/gl_shadowmap.cpp index c9223082d..3ef764821 100644 --- a/src/gl/dynlights/gl_shadowmap.cpp +++ b/src/gl/dynlights/gl_shadowmap.cpp @@ -160,7 +160,7 @@ void FShadowMap::UploadAABBTree() { // 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) + if (level.info != mLastLevel && level.nodes.Size() != mLastNumNodes || level.segs.Size() != mLastNumSegs) Clear(); if (mAABBTree) @@ -205,6 +205,6 @@ void FShadowMap::Clear() mAABBTree.reset(); mLastLevel = level.info; - mLastNumNodes = numnodes; + mLastNumNodes = level.nodes.Size(); mLastNumSegs = level.segs.Size(); } diff --git a/src/gl/dynlights/gl_shadowmap.h b/src/gl/dynlights/gl_shadowmap.h index 45a3f6798..281936f80 100644 --- a/src/gl/dynlights/gl_shadowmap.h +++ b/src/gl/dynlights/gl_shadowmap.h @@ -51,7 +51,7 @@ private: // Used to detect when a level change requires the AABB tree to be regenerated level_info_t *mLastLevel = nullptr; - int mLastNumNodes = 0; + unsigned mLastNumNodes = 0; unsigned mLastNumSegs = 0; // AABB-tree of the level, used for ray tests diff --git a/src/gl/scene/gl_bsp.cpp b/src/gl/scene/gl_bsp.cpp index 3112b716a..804311bc6 100644 --- a/src/gl/scene/gl_bsp.cpp +++ b/src/gl/scene/gl_bsp.cpp @@ -554,7 +554,7 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub) void GLSceneDrawer::RenderBSPNode (void *node) { - if (numnodes == 0) + if (level.nodes.Size() == 0) { DoSubsector (&level.subsectors[0]); return; @@ -575,7 +575,7 @@ void GLSceneDrawer::RenderBSPNode (void *node) // It is not necessary to use the slower precise version here if (!clipper.CheckBox(bsp->bbox[side])) { - if (!(gl_drawinfo->no_renderflags[bsp-nodes] & SSRF_SEEN)) + if (!(gl_drawinfo->no_renderflags[bsp->Index()] & SSRF_SEEN)) return; } diff --git a/src/gl/scene/gl_drawinfo.cpp b/src/gl/scene/gl_drawinfo.cpp index dbc646464..84da70596 100644 --- a/src/gl/scene/gl_drawinfo.cpp +++ b/src/gl/scene/gl_drawinfo.cpp @@ -1052,7 +1052,7 @@ void FDrawInfo::StartScene() memset(§orrenderflags[0], 0, level.sectors.Size() * sizeof(sectorrenderflags[0])); memset(&ss_renderflags[0], 0, level.subsectors.Size() * sizeof(ss_renderflags[0])); - memset(&no_renderflags[0], 0, numnodes * sizeof(no_renderflags[0])); + memset(&no_renderflags[0], 0, level.nodes.Size() * sizeof(no_renderflags[0])); next = gl_drawinfo; gl_drawinfo = this; diff --git a/src/gl/scene/gl_portal.cpp b/src/gl/scene/gl_portal.cpp index 9968d2350..38ce80799 100644 --- a/src/gl/scene/gl_portal.cpp +++ b/src/gl/scene/gl_portal.cpp @@ -692,7 +692,7 @@ GLSectorStackPortal::~GLSectorStackPortal() static uint8_t SetCoverage(void *node) { - if (numnodes == 0) + if (level.nodes.Size() == 0) { return 0; } @@ -700,7 +700,7 @@ static uint8_t SetCoverage(void *node) { node_t *bsp = (node_t *)node; uint8_t coverage = SetCoverage(bsp->children[0]) | SetCoverage(bsp->children[1]); - gl_drawinfo->no_renderflags[bsp-nodes] = coverage; + gl_drawinfo->no_renderflags[bsp->Index()] = coverage; return coverage; } else @@ -723,7 +723,7 @@ void GLSectorStackPortal::SetupCoverage() gl_drawinfo->ss_renderflags[dsub->Index()] |= SSRF_SEEN; } } - SetCoverage(&nodes[numnodes-1]); + SetCoverage(::level.HeadNode()); } //----------------------------------------------------------------------------- diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 1eecd0dff..6538da9cb 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -271,7 +271,7 @@ void GLSceneDrawer::CreateScene() GLRenderer->mVBO->Map(); SetView(); validcount++; // used for processing sidedefs only once by the renderer. - RenderBSPNode (nodes + numnodes - 1); + RenderBSPNode (level.HeadNode()); if (GLRenderer->mCurrentPortal != NULL) GLRenderer->mCurrentPortal->RenderAttached(); Bsp.Unclock(); diff --git a/src/nodebuild.h b/src/nodebuild.h index 72e301be1..5e22032f7 100644 --- a/src/nodebuild.h +++ b/src/nodebuild.h @@ -5,6 +5,7 @@ struct FPolySeg; struct FMiniBSP; +struct FLevelLocals; struct FEventInfo { @@ -193,10 +194,7 @@ public: bool makeGLNodes); ~FNodeBuilder (); - void Extract(node_t *&nodes, int &nodeCount, - TStaticArray &segs, - TStaticPointableArray &ssecs, - TStaticArray &vertexes); + void Extract(FLevelLocals &level); const int *GetOldVertexTable(); // These are used for building sub-BSP trees for polyobjects. diff --git a/src/nodebuild_extract.cpp b/src/nodebuild_extract.cpp index 6d1f13303..089303fbe 100644 --- a/src/nodebuild_extract.cpp +++ b/src/nodebuild_extract.cpp @@ -43,6 +43,7 @@ #include "nodebuild.h" #include "templates.h" +#include "g_levellocals.h" #if 0 #define D(x) x @@ -52,13 +53,11 @@ #undef DD #endif -void FNodeBuilder::Extract (node_t *&outNodes, int &nodeCount, - TStaticArray &outSegs, - TStaticPointableArray &outSubs, - TStaticArray &outVerts) +void FNodeBuilder::Extract (FLevelLocals &level) { int i; + auto &outVerts = level.vertexes; int vertCount = Vertices.Size (); outVerts.Alloc(vertCount); @@ -67,15 +66,17 @@ void FNodeBuilder::Extract (node_t *&outNodes, int &nodeCount, outVerts[i].set(Vertices[i].x, Vertices[i].y); } + auto &outSubs = level.subsectors; auto subCount = Subsectors.Size(); outSubs.Alloc(subCount); memset(&outSubs[0], 0, subCount * sizeof(subsector_t)); - nodeCount = Nodes.Size (); - outNodes = new node_t[nodeCount]; + auto &outNodes = level.nodes; + auto nodeCount = Nodes.Size (); + outNodes.Alloc(nodeCount); - memcpy (outNodes, &Nodes[0], nodeCount*sizeof(node_t)); - for (i = 0; i < nodeCount; ++i) + memcpy (&outNodes[0], &Nodes[0], nodeCount*sizeof(node_t)); + for (unsigned i = 0; i < nodeCount; ++i) { D(Printf(PRINT_LOG, "Node %d: Splitter[%08x,%08x] [%08x,%08x]\n", i, outNodes[i].x, outNodes[i].y, outNodes[i].dx, outNodes[i].dy)); @@ -91,7 +92,7 @@ void FNodeBuilder::Extract (node_t *&outNodes, int &nodeCount, else { D(Printf(PRINT_LOG, " node %d\n", outNodes[i].intchildren[j])); - outNodes[i].children[j] = outNodes + outNodes[i].intchildren[j]; + outNodes[i].children[j] = &outNodes[outNodes[i].intchildren[j]]; } } for (int j = 0; j < 2; ++j) @@ -103,6 +104,7 @@ void FNodeBuilder::Extract (node_t *&outNodes, int &nodeCount, } } + auto &outSegs = level.segs; if (GLNodes) { TArray segs (Segs.Size()*5/4); diff --git a/src/p_glnodes.cpp b/src/p_glnodes.cpp index b7c03d46c..d0f39536a 100644 --- a/src/p_glnodes.cpp +++ b/src/p_glnodes.cpp @@ -526,7 +526,6 @@ static bool LoadNodes (FileReader * lump) const int NF_SUBSECTOR = 0x8000; const int GL5_NF_SUBSECTOR = (1 << 31); - int i; int j; int k; node_t* no; @@ -535,11 +534,11 @@ static bool LoadNodes (FileReader * lump) if (!format5) { mapnode_t* mn, * basemn; - numnodes = lump->GetLength() / sizeof(mapnode_t); + unsigned numnodes = unsigned(lump->GetLength() / sizeof(mapnode_t)); if (numnodes == 0) return false; - nodes = new node_t[numnodes]; + level.nodes.Alloc(numnodes); lump->Seek(0, SEEK_SET); basemn = mn = new mapnode_t[numnodes]; @@ -548,9 +547,9 @@ static bool LoadNodes (FileReader * lump) used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes); memset (used, 0, sizeof(uint16_t)*numnodes); - no = nodes; + no = &level.nodes[0]; - for (i = 0; i < numnodes; i++, no++, mn++) + for (unsigned i = 0; i < numnodes; i++, no++, mn++) { no->x = LittleShort(mn->x)<y = LittleShort(mn->y)<children[j] = &nodes[child]; + no->children[j] = &level.nodes[child]; used[child] = j + 1; } for (k = 0; k < 4; k++) @@ -595,11 +594,11 @@ static bool LoadNodes (FileReader * lump) else { gl5_mapnode_t* mn, * basemn; - numnodes = lump->GetLength() / sizeof(gl5_mapnode_t); + auto numnodes = unsigned(lump->GetLength() / sizeof(gl5_mapnode_t)); if (numnodes == 0) return false; - nodes = new node_t[numnodes]; + level.nodes.Alloc(numnodes); lump->Seek(0, SEEK_SET); basemn = mn = new gl5_mapnode_t[numnodes]; @@ -608,9 +607,9 @@ static bool LoadNodes (FileReader * lump) used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes); memset (used, 0, sizeof(uint16_t)*numnodes); - no = nodes; + no = &level.nodes[0]; - for (i = 0; i < numnodes; i++, no++, mn++) + for (unsigned i = 0; i < numnodes; i++, no++, mn++) { no->x = LittleShort(mn->x)<y = LittleShort(mn->y)<children[j] = (uint8_t *)&level.subsectors[child] + 1; } - else if (child >= numnodes) + else if ((unsigned)child >= numnodes) { delete [] basemn; return false; @@ -641,7 +640,7 @@ static bool LoadNodes (FileReader * lump) } else { - no->children[j] = &nodes[child]; + no->children[j] = &level.nodes[child]; used[child] = j + 1; } for (k = 0; k < 4; k++) @@ -663,28 +662,12 @@ static bool LoadNodes (FileReader * lump) static bool DoLoadGLNodes(FileReader ** lumps) { - if (!LoadGLVertexes(lumps[0])) + if (!LoadGLVertexes(lumps[0]) || + !LoadGLSegs(lumps[1]) || + !LoadGLSubsectors(lumps[2]) || + !LoadNodes(lumps[3])) { - return false; - } - if (!LoadGLSegs(lumps[1])) - { - level.segs.Clear(); - return false; - } - if (!LoadGLSubsectors(lumps[2])) - { - level.subsectors.Clear(); - level.segs.Clear(); - return false; - } - if (!LoadNodes(lumps[3])) - { - delete [] nodes; - nodes = NULL; - level.subsectors.Clear(); - level.segs.Clear(); - return false; + goto fail; } // Quick check for the validity of the nodes @@ -696,11 +679,7 @@ static bool DoLoadGLNodes(FileReader ** lumps) if (!seg->sidedef) { Printf("GL nodes contain invalid data. The BSP has to be rebuilt.\n"); - delete [] nodes; - nodes = NULL; - level.subsectors.Clear(); - level.segs.Clear(); - return false; + goto fail; } } @@ -711,6 +690,12 @@ static bool DoLoadGLNodes(FileReader ** lumps) Printf("%d missing segs counted in GL nodes.\nThe BSP has to be rebuilt.\n", missing); } return missing == 0; + +fail: + level.nodes.Clear(); + level.subsectors.Clear(); + level.segs.Clear(); + return false; } @@ -855,7 +840,7 @@ bool P_LoadGLNodes(MapData * map) { level.subsectors.Clear(); level.segs.Clear(); - nodes = NULL; + level.nodes.Clear(); P_LoadZNodes (*map->file, id); return true; } @@ -863,11 +848,7 @@ bool P_LoadGLNodes(MapData * map) { level.subsectors.Clear(); level.segs.Clear(); - if (nodes != NULL) - { - delete[] nodes; - nodes = NULL; - } + level.nodes.Clear(); } } } @@ -962,8 +943,7 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) sub.sector = sub.firstline->sidedef->sector; } - nodes = NULL; - numnodes = 0; + level.nodes.Clear(); level.subsectors.Clear(); level.segs.Clear(); @@ -987,10 +967,7 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) leveldata.FindMapBounds (); FNodeBuilder builder (leveldata, polyspots, anchors, true); - builder.Extract (nodes, numnodes, - level.segs, - level.subsectors, - level.vertexes); + builder.Extract (level); endTime = I_FPSTime (); DPrintf (DMSG_NOTIFY, "BSP generation took %.3f sec (%u segs)\n", (endTime - startTime) * 0.001, level.segs.Size()); buildtime = endTime - startTime; @@ -1014,10 +991,9 @@ bool P_CheckNodes(MapData * map, bool rebuilt, int buildtime) } } - if (!gamenodes) + if (level.gamenodes.Size() == 0) { - gamenodes = nodes; - numgamenodes = numnodes; + level.gamenodes.Point(level.nodes); level.gamesubsectors.Point(level.subsectors); } return ret; @@ -1101,31 +1077,31 @@ static void CreateCachedNodes(MapData *map) } } - WriteLong(ZNodes, numnodes); - for(int i=0;iIndex()); + child = 0x80000000 | uint32_t(((subsector_t *)((uint8_t *)node.children[j] - 1))->Index()); } else { - child = uint32_t((node_t *)nodes[i].children[j] - nodes); + child = ((node_t *)node.children[j])->Index(); } WriteLong(ZNodes, child); } @@ -1222,11 +1198,7 @@ static bool CheckCachedNodes(MapData *map) level.subsectors.Clear(); level.segs.Clear(); - if (nodes != NULL) - { - delete[] nodes; - nodes = NULL; - } + level.nodes.Clear(); goto errorout; } @@ -1297,35 +1269,6 @@ CCMD(clearnodecache) //========================================================================== -//========================================================================== -// -// P_PointInSubsector -// -//========================================================================== - -subsector_t *P_PointInSubsector (double x, double y) -{ - node_t *node; - int side; - - // single subsector is a special case - if (numgamenodes == 0) - return &level.gamesubsectors[0]; - - node = gamenodes + numgamenodes - 1; - - fixed_t xx = FLOAT2FIXED(x); - fixed_t yy = FLOAT2FIXED(y); - do - { - side = R_PointOnSide (xx, yy, node); - node = (node_t *)node->children[side]; - } - while (!((size_t)node & 1)); - - return (subsector_t *)((uint8_t *)node - 1); -} - //========================================================================== // // PointOnLine diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 86183a8fc..25d23ff9f 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -426,7 +426,7 @@ void AActor::LinkToWorld(FLinkContext *ctx, bool spawningmapthing, sector_t *sec if (sector == NULL) { - if (!spawning || numgamenodes == 0) + if (!spawning) { sector = P_PointInSector(Pos()); } @@ -2093,6 +2093,34 @@ int P_VanillaPointOnLineSide(double x, double y, const line_t* line) return 1; // back side } +//========================================================================== +// +// P_PointInSubsector +// +//========================================================================== + +subsector_t *P_PointInSubsector(double x, double y) +{ + node_t *node; + int side; + + // single subsector is a special case + if (level.gamenodes.Size() == 0) + return &level.gamesubsectors[0]; + + node = level.HeadGamenode(); + + fixed_t xx = FLOAT2FIXED(x); + fixed_t yy = FLOAT2FIXED(y); + do + { + side = R_PointOnSide(xx, yy, node); + node = (node_t *)node->children[side]; + } while (!((size_t)node & 1)); + + return (subsector_t *)((uint8_t *)node - 1); +} + //========================================================================== // // Use buggy PointOnSide and fix actors that lie on @@ -2103,10 +2131,10 @@ int P_VanillaPointOnLineSide(double x, double y, const line_t* line) sector_t *P_PointInSectorBuggy(double x, double y) { // single subsector is a special case - if (numgamenodes == 0) + if (level.gamenodes.Size() == 0) return level.gamesubsectors[0].sector; - node_t *node = gamenodes + numgamenodes - 1; + auto node = level.HeadGamenode(); do { diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 278b67c7f..04987fe61 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -125,13 +125,13 @@ inline bool P_LoadBuildMap(uint8_t *mapdata, size_t len, FMapThing **things, int // TArray vertexdatas; -int numnodes; -node_t* nodes; +//int numnodes; +//node_t* nodes; TArray Zones; -node_t * gamenodes; -int numgamenodes; +//node_t * gamenodes; +//int numgamenodes; bool hasglnodes; @@ -1049,9 +1049,9 @@ void LoadZNodes(FileReaderBase &data, int glnodes) uint32_t numNodes; data >> numNodes; - numnodes = numNodes; - nodes = new node_t[numNodes]; - memset (nodes, 0, sizeof(node_t)*numNodes); + auto &nodes = level.nodes; + nodes.Alloc(numNodes); + memset (&nodes[0], 0, sizeof(node_t)*numNodes); for (i = 0; i < numNodes; ++i) { @@ -1211,7 +1211,7 @@ void P_LoadSegs (MapData * map) { Printf ("This map has no segs.\n"); level.subsectors.Clear(); - delete[] nodes; + level.nodes.Clear(); delete[] vertchanged; ForceNodeBuild = true; return; @@ -1357,7 +1357,7 @@ void P_LoadSegs (MapData * map) Printf ("The BSP will be rebuilt.\n"); level.segs.Clear(); level.subsectors.Clear(); - delete[] nodes; + level.nodes.Clear(); ForceNodeBuild = true; } @@ -1382,7 +1382,7 @@ void P_LoadSubsectors (MapData * map) if (numsubsectors == 0 || maxseg == 0 ) { Printf ("This map has an incomplete BSP tree.\n"); - delete[] nodes; + level.nodes.Clear(); ForceNodeBuild = true; return; } @@ -1403,7 +1403,7 @@ void P_LoadSubsectors (MapData * map) { Printf ("Subsector %i is empty.\n", i); level.subsectors.Clear(); - delete[] nodes; + level.nodes.Clear(); ForceNodeBuild = true; return; } @@ -1417,7 +1417,7 @@ void P_LoadSubsectors (MapData * map) "The BSP will be rebuilt.\n", i, (unsigned)((size_t)subsectors[i].firstline), (unsigned)((size_t)subsectors[i].firstline) + subsectors[i].numlines - 1); ForceNodeBuild = true; - delete[] nodes; + level.nodes.Clear(); level.subsectors.Clear(); break; } @@ -1427,7 +1427,7 @@ void P_LoadSubsectors (MapData * map) "The BSP will be rebuilt.\n", i, maxseg, (unsigned)((size_t)subsectors[i].firstline) + subsectors[i].numlines - 1); ForceNodeBuild = true; - delete[] nodes; + level.nodes.Clear(); level.subsectors.Clear(); break; } @@ -1538,7 +1538,6 @@ template void P_LoadNodes (MapData * map) { FMemLump data; - int i; int j; int k; char *mnp; @@ -1548,7 +1547,7 @@ void P_LoadNodes (MapData * map) int lumplen = map->Size(ML_NODES); int maxss = map->Size(ML_SSECTORS) / sizeof(subsectortype); - numnodes = (lumplen - nodetype::NF_LUMPOFFSET) / sizeof(nodetype); + unsigned numnodes = (lumplen - nodetype::NF_LUMPOFFSET) / sizeof(nodetype); if ((numnodes == 0 && maxss != 1) || maxss == 0) { @@ -1556,16 +1555,17 @@ void P_LoadNodes (MapData * map) return; } - nodes = new node_t[numnodes]; + auto &nodes = level.nodes; + nodes.Alloc(numnodes); used = (uint16_t *)alloca (sizeof(uint16_t)*numnodes); memset (used, 0, sizeof(uint16_t)*numnodes); mnp = new char[lumplen]; mn = (nodetype*)(mnp + nodetype::NF_LUMPOFFSET); map->Read(ML_NODES, mnp); - no = nodes; + no = &nodes[0]; - for (i = 0; i < numnodes; i++, no++, mn++) + for (unsigned i = 0; i < numnodes; i++, no++, mn++) { no->x = LittleShort(mn->x)<y = LittleShort(mn->y)<children[j] = (uint8_t *)&level.subsectors[child] + 1; } - else if (child >= numnodes) + else if ((unsigned)child >= numnodes) { Printf ("BSP node %d references invalid node %td.\n" - "The BSP will be rebuilt.\n", i, (node_t *)no->children[j] - nodes); + "The BSP will be rebuilt.\n", i, ((node_t *)no->children[j])->Index()); ForceNodeBuild = true; - delete[] nodes; + level.nodes.Clear(); delete[] mnp; return; } @@ -1603,7 +1603,7 @@ void P_LoadNodes (MapData * map) "which is already used by node %d.\n" "The BSP will be rebuilt.\n", i, child, used[child]-1); ForceNodeBuild = true; - delete[] nodes; + level.nodes.Clear(); delete[] mnp; return; } @@ -3451,19 +3451,10 @@ void P_FreeLevelData () level.lines.Clear(); level.sides.Clear(); level.vertexes.Clear(); - - if (gamenodes != NULL && gamenodes != nodes) - { - delete[] gamenodes; - } + level.nodes.Clear(); + level.gamenodes.Clear(); level.subsectors.Clear(); level.gamesubsectors.Clear(); - if (nodes != NULL) - { - delete[] nodes; - } - nodes = gamenodes = NULL; - numnodes = numgamenodes = 0; if (blockmaplump != NULL) { @@ -3799,11 +3790,7 @@ void P_SetupLevel (const char *lumpname, int position) ForceNodeBuild = true; level.subsectors.Clear(); level.segs.Clear(); - if (nodes != NULL) - { - delete[] nodes; - nodes = NULL; - } + level.nodes.Clear(); } } else if (!map->isText) // regular nodes are not supported for text maps @@ -3879,10 +3866,7 @@ void P_SetupLevel (const char *lumpname, int position) // In case a sync critical game mode is started, also build GL nodes to avoid problems // if the different machines' am_textured setting differs. FNodeBuilder builder (leveldata, polyspots, anchors, BuildGLNodes); - builder.Extract (nodes, numnodes, - level.segs, - level.subsectors, - level.vertexes); + builder.Extract (level); endTime = I_FPSTime (); DPrintf (DMSG_NOTIFY, "BSP generation took %.3f sec (%d segs)\n", (endTime - startTime) * 0.001, level.segs.Size()); oldvertextable = builder.GetOldVertexTable(); @@ -3911,19 +3895,12 @@ void P_SetupLevel (const char *lumpname, int position) } } - // Copy pointers to the old nodes so that R_PointInSubsector can use them - if (nodes) - { - gamenodes = nodes; - numgamenodes = numnodes; - } - else - { - gamenodes=NULL; - } + // duplicate the nodes in the game* arrays so that replacement nodes do not overwrite them. // let the game data take ownership, because that is guaranteed to remain intact after here. level.gamesubsectors = std::move(level.subsectors); level.subsectors.Point(level.gamesubsectors); + level.gamenodes = std::move(level.nodes); + level.nodes.Point(level.gamenodes); if (RequireGLNodes) { @@ -4018,6 +3995,12 @@ void P_SetupLevel (const char *lumpname, int position) if (sec.floorplane.isSlope()) sec.reflect[sector_t::floor] = 0; if (sec.ceilingplane.isSlope()) sec.reflect[sector_t::ceiling] = 0; } + for (auto &node : level.nodes) + { + double fdx = FIXED2DBL(node.dx); + double fdy = FIXED2DBL(node.dy); + node.len = (float)g_sqrt(fdx * fdx + fdy * fdy); + } // This must be done BEFORE the PolyObj Spawn!!! Renderer->PreprocessLevel(); diff --git a/src/po_man.cpp b/src/po_man.cpp index 5a0405a43..5baa90be6 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -1741,14 +1741,6 @@ void PO_Init (void) // [RH] Don't need the side lists anymore KillSideLists (); - for(int i=0;idx); - double fdy = FIXED2DBL(no->dy); - no->len = (float)g_sqrt(fdx * fdx + fdy * fdy); - } - // mark all subsectors which have a seg belonging to a polyobj // These ones should not be rendered on the textured automap. for (auto &ss : level.subsectors) @@ -2128,7 +2120,7 @@ void FPolyObj::CreateSubsectorLinks() } if (!(i_compatflags & COMPATF_POLYOBJ)) { - SplitPoly(node, nodes + numnodes - 1, dummybbox); + SplitPoly(node, level.HeadNode(), dummybbox); } else { diff --git a/src/polyrenderer/scene/poly_cull.cpp b/src/polyrenderer/scene/poly_cull.cpp index 246da6187..325571ad6 100644 --- a/src/polyrenderer/scene/poly_cull.cpp +++ b/src/polyrenderer/scene/poly_cull.cpp @@ -37,10 +37,10 @@ void PolyCull::CullScene(const TriMatrix &worldToClip, const Vec4f &portalClipPl // Cull front to back MaxCeilingHeight = 0.0; MinFloorHeight = 0.0; - if (numnodes == 0) + if (level.nodes.Size() == 0) CullSubsector(&level.subsectors[0]); else - CullNode(nodes + numnodes - 1); // The head node is the last node output. + CullNode(level.HeadNode()); } void PolyCull::CullNode(void *node) diff --git a/src/polyrenderer/scene/poly_scene.cpp b/src/polyrenderer/scene/poly_scene.cpp index 830f68c25..be615a3a0 100644 --- a/src/polyrenderer/scene/poly_scene.cpp +++ b/src/polyrenderer/scene/poly_scene.cpp @@ -134,7 +134,7 @@ void RenderPolyScene::RenderSubsector(subsector_t *sub) void RenderPolyScene::RenderSprite(AActor *thing, double sortDistance, const DVector2 &left, const DVector2 &right) { - if (numnodes == 0) + if (level.nodes.Size() == 0) { subsector_t *sub = &level.subsectors[0]; auto it = SubsectorDepths.find(sub); @@ -143,7 +143,7 @@ void RenderPolyScene::RenderSprite(AActor *thing, double sortDistance, const DVe } else { - RenderSprite(thing, sortDistance, left, right, 0.0, 1.0, nodes + numnodes - 1); // The head node is the last node output. + RenderSprite(thing, sortDistance, left, right, 0.0, 1.0, level.HeadNode()); } } diff --git a/src/r_defs.h b/src/r_defs.h index f3c28ee84..6e8e9c161 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -1447,6 +1447,8 @@ struct node_t void *children[2]; // If bit 0 is set, it's a subsector. int intchildren[2]; // Used by nodebuilder. }; + + int Index() const; }; diff --git a/src/r_state.h b/src/r_state.h index 56b53cad5..56e377d3a 100644 --- a/src/r_state.h +++ b/src/r_state.h @@ -46,13 +46,13 @@ extern uint32_t NumStdSprites; extern TArray vertexdatas; -extern int numnodes; -extern node_t* nodes; +//extern int numnodes; +//extern node_t* nodes; extern TArray Zones; -extern node_t * gamenodes; -extern int numgamenodes; +//extern node_t * gamenodes; +//extern int numgamenodes; // diff --git a/src/r_utility.cpp b/src/r_utility.cpp index f76b6fb89..df6c1e3dd 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -301,10 +301,10 @@ subsector_t *R_PointInSubsector (fixed_t x, fixed_t y) int side; // single subsector is a special case - if (numnodes == 0) + if (level.nodes.Size() == 0) return &level.subsectors[0]; - node = nodes + numnodes - 1; + node = level.HeadNode(); do { diff --git a/src/swrenderer/scene/r_opaque_pass.cpp b/src/swrenderer/scene/r_opaque_pass.cpp index dec5f8e17..23876235f 100644 --- a/src/swrenderer/scene/r_opaque_pass.cpp +++ b/src/swrenderer/scene/r_opaque_pass.cpp @@ -777,7 +777,7 @@ namespace swrenderer SeenActors.clear(); InSubsector = nullptr; - RenderBSPNode(nodes + numnodes - 1); // The head node is the last node output. + RenderBSPNode(level.HeadNode()); // The head node is the last node output. } // @@ -788,7 +788,7 @@ namespace swrenderer void RenderOpaquePass::RenderBSPNode(void *node) { - if (numnodes == 0) + if (level.nodes.Size() == 0) { RenderSubsector(&level.subsectors[0]); return;