From 6b5b426636e66b191023bb51d79c82e35112a406 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Mon, 7 Feb 2022 00:02:51 -0700 Subject: [PATCH] qbsp: remove internal list in face_t --- include/qbsp/csg4.hh | 3 +- include/qbsp/qbsp.hh | 4 +- qbsp/brush.cc | 15 ------ qbsp/csg4.cc | 124 +++++++++++++++++++------------------------ qbsp/exportobj.cc | 2 +- qbsp/outside.cc | 4 +- qbsp/solidbsp.cc | 24 ++++----- qbsp/surfaces.cc | 26 +++------ qbsp/tjunc.cc | 12 ++--- 9 files changed, 84 insertions(+), 130 deletions(-) diff --git a/include/qbsp/csg4.hh b/include/qbsp/csg4.hh index c9446fcf..5b76c2fa 100644 --- a/include/qbsp/csg4.hh +++ b/include/qbsp/csg4.hh @@ -22,11 +22,12 @@ #pragma once #include +#include extern int csgmergefaces; // build surfaces is also used by GatherNodeFaces std::vector BuildSurfaces(std::map> &planefaces); face_t *NewFaceFromFace(face_t *in); -void SplitFace(face_t *in, const qplane3d &split, face_t **front, face_t **back); +std::tuple SplitFace(face_t *in, const qplane3d &split); void UpdateFaceSphere(face_t *in); diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index 525dd6d3..25cb20c9 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -211,8 +211,6 @@ struct face_fragment_t struct face_t : face_fragment_t { - face_t *next; - int planenum; int planeside; // which side is the front of the face int texinfo; @@ -301,7 +299,7 @@ struct node_t int firstface; // decision node only int numfaces; // decision node only node_t *children[2]; // children[0] = front side, children[1] = back side of plane. only valid for decision nodes - face_t *faces; // decision nodes only, list for both sides + std::list facelist; // decision nodes only, list for both sides // information for leafs contentflags_t contents; // leaf nodes (0 for decision nodes) diff --git a/qbsp/brush.cc b/qbsp/brush.cc index 0fa39012..16d6d3b8 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -404,21 +404,6 @@ static std::vector CreateBrushFaces(const mapentity_t *src, hullbrush_t return { std::make_move_iterator(facelist.begin()), std::make_move_iterator(facelist.end()) }; } -/* -================= -FreeBrushFaces -================= -*/ -static void FreeBrushFaces(face_t *facelist) -{ - face_t *face, *next; - - for (face = facelist; face; face = next) { - next = face->next; - delete face; - } -} - /* ===================== FreeBrushes diff --git a/qbsp/csg4.cc b/qbsp/csg4.cc index d42ace43..4fc783ea 100644 --- a/qbsp/csg4.cc +++ b/qbsp/csg4.cc @@ -101,10 +101,10 @@ void UpdateFaceSphere(face_t *in) ================== SplitFace -Frees in. +Frees in. Returns {front, back} ================== */ -void SplitFace(face_t *in, const qplane3d &split, face_t **front, face_t **back) +std::tuple SplitFace(face_t *in, const qplane3d &split) { vec_t *dists = (vec_t *)alloca(sizeof(vec_t) * (in->w.size() + 1)); side_t *sides = (side_t *)alloca(sizeof(side_t) * (in->w.size() + 1)); @@ -131,18 +131,14 @@ void SplitFace(face_t *in, const qplane3d &split, face_t **front, face_t **back) // Plane doesn't split this face after all if (!counts[SIDE_FRONT]) { - *front = NULL; - *back = in; - return; + return {nullptr, in}; } if (!counts[SIDE_BACK]) { - *front = in; - *back = NULL; - return; + return {in, nullptr}; } - *back = newf = NewFaceFromFace(in); - *front = new2 = NewFaceFromFace(in); + newf = NewFaceFromFace(in); + new2 = NewFaceFromFace(in); // distribute the points and generate splits for (i = 0; i < in->w.size(); i++) { @@ -187,6 +183,9 @@ void SplitFace(face_t *in, const qplane3d &split, face_t **front, face_t **back) /* free the original face now that it is represented by the fragments */ delete in; + + // {front, back} + return {new2, newf}; } /* @@ -198,13 +197,14 @@ outside the brush to the outside list, without splitting them. This saves us time in mergefaces later on (and sometimes a lot of memory) ================= */ -static void RemoveOutsideFaces(const brush_t &brush, face_t **inside, face_t **outside) +static void RemoveOutsideFaces(const brush_t &brush, std::list *inside, std::list *outside) { - face_t *face = *inside; - face_t *next = nullptr; - *inside = NULL; - while (face) { - next = face->next; + std::list oldinside; + + // clear `inside`, transfer it to `oldinside` + std::swap(*inside, oldinside); + + for (face_t *face : oldinside) { std::optional w = face->w; for (auto &clipface : brush.faces) { qbsp_plane_t clipplane = map.planes[clipface.planenum]; @@ -216,14 +216,11 @@ static void RemoveOutsideFaces(const brush_t &brush, face_t **inside, face_t **o break; } if (!w) { - /* The face is completely outside this brush */ - face->next = *outside; - *outside = face; + /* The face is completely outside this brush */ + outside->push_front(face); } else { - face->next = *inside; - *inside = face; + inside->push_front(face); } - face = next; } } @@ -237,17 +234,17 @@ outside list or spliting it into a piece in each list. Faces exactly on the plane will stay inside unless overdrawn by later brush ================= */ -static void ClipInside(const face_t *clipface, bool precedence, face_t **inside, face_t **outside) +static void ClipInside(const face_t *clipface, bool precedence, std::list *inside, + std::list *outside) { - face_t *face, *next, *frags[2]; + std::list oldinside; + + // effectively make a copy of `inside`, and clear it + std::swap(*inside, oldinside); const qbsp_plane_t &splitplane = map.planes[clipface->planenum]; - face = *inside; - *inside = NULL; - while (face) { - next = face->next; - + for (face_t *face : oldinside) { /* HACK: Check for on-plane but not the same planenum ( https://github.com/ericwa/ericw-tools/issues/174 ) */ @@ -260,6 +257,8 @@ static void ClipInside(const face_t *clipface, bool precedence, face_t **inside, } } + std::array frags; + /* Handle exactly on-plane faces */ if (face->planenum == clipface->planenum || spurious_onplane) { const qplane3d faceplane = Face_Plane(face); @@ -269,27 +268,24 @@ static void ClipInside(const face_t *clipface, bool precedence, face_t **inside, if (opposite || precedence) { /* always clip off opposite facing */ - frags[clipface->planeside] = NULL; - frags[!clipface->planeside] = face; + frags[clipface->planeside] = {}; + frags[!clipface->planeside] = {face}; } else { /* leave it on the outside */ - frags[clipface->planeside] = face; - frags[!clipface->planeside] = NULL; + frags[clipface->planeside] = {face}; + frags[!clipface->planeside] = {}; } } else { /* proper split */ - SplitFace(face, splitplane, &frags[0], &frags[1]); + std::tie(frags[0], frags[1]) = SplitFace(face, splitplane); } if (frags[clipface->planeside]) { - frags[clipface->planeside]->next = *outside; - *outside = frags[clipface->planeside]; + outside->push_front(frags[clipface->planeside]); } if (frags[!clipface->planeside]) { - frags[!clipface->planeside]->next = *inside; - *inside = frags[!clipface->planeside]; + inside->push_front(frags[!clipface->planeside]); } - face = next; } } @@ -303,13 +299,10 @@ This plane map is later used to build up the surfaces for creating the BSP. Not parallel. ================== */ -static void SaveFacesToPlaneList(face_t *facelist, bool mirror, std::map> &planefaces) +static void SaveFacesToPlaneList(std::list facelist, bool mirror, std::map> &planefaces) { - face_t *face, *next; - - for (face = facelist; face; face = next) { + for (face_t *face : facelist) { const int plane = face->planenum; - next = face->next; // Handy for debugging CSGFaces issues, throw out detail faces and export obj. #if 0 @@ -355,39 +348,33 @@ static void SaveFacesToPlaneList(face_t *facelist, bool mirror, std::map &facelist) { - face_t *next; - - while (face) { - next = face->next; + for (face_t *face : facelist) { delete face; - face = next; } + facelist.clear(); } /* ================== SaveInsideFaces -`face` is the list of faces from `brush` (solid) that are inside `clipbrush` (nonsolid) +`faces` is the list of faces from `brush` (solid) that are inside `clipbrush` (nonsolid) Save the list of faces onto the output list, modifying the outside contents to match given brush. If the inside contents are empty, the given brush's contents override the face inside contents. ================== */ -static void SaveInsideFaces(face_t *face, const brush_t &clipbrush, face_t **savelist) +static void SaveInsideFaces(const std::list &faces, const brush_t &clipbrush, std::list *savelist) { Q_assert(!clipbrush.contents.is_solid(options.target_game)); - face_t *next; - - while (face) { + for (face_t *face : faces) { // the back side of `face` is a solid // Q_assert(face->contents[1] == CONTENTS_SOLID); - next = face->next; face->contents[0] = clipbrush.contents; if ((face->contents[1].is_solid(options.target_game) || face->contents[1].is_sky(options.target_game)) && @@ -434,9 +421,7 @@ static void SaveInsideFaces(face_t *face, const brush_t &clipbrush, face_t **sav } } - face->next = *savelist; - *savelist = face; - face = next; + savelist->push_front(face); } } @@ -484,18 +469,16 @@ std::vector BuildSurfaces(std::map> &planefa CopyBrushFaces ================== */ -static face_t *CopyBrushFaces(const brush_t &brush) +static std::list CopyBrushFaces(const brush_t &brush) { - face_t *facelist, *newface; + std::list facelist; - facelist = NULL; for (auto &face : brush.faces) { brushfaces++; - newface = new face_t(face); + auto *newface = new face_t(face); newface->contents = { options.target_game->create_empty_contents(), brush.contents }; newface->lmshift = { brush.lmshift, brush.lmshift }; - newface->next = facelist; - facelist = newface; + facelist.push_back(newface); } return facelist; @@ -524,7 +507,7 @@ std::vector CSGFaces(const mapentity_t *entity) #endif // output vector for the parallel_for - std::vector brushvec_outsides; + std::vector> brushvec_outsides; brushvec_outsides.resize(entity->brushes.size()); /* @@ -537,7 +520,7 @@ std::vector CSGFaces(const mapentity_t *entity) */ tbb::parallel_for(static_cast(0), entity->brushes.size(), [entity, &brushvec_outsides](const size_t i) { auto &brush = entity->brushes[i]; - face_t *outside = CopyBrushFaces(brush); + std::list outside = CopyBrushFaces(brush); bool overwrite = false; for (auto &clipbrush : entity->brushes) { @@ -586,8 +569,9 @@ std::vector CSGFaces(const mapentity_t *entity) */ // divide faces by the planes of the new brush - face_t *inside = outside; - outside = NULL; + std::list inside; + + std::swap(inside, outside); RemoveOutsideFaces(clipbrush, &inside, &outside); for (auto &clipface : clipbrush.faces) @@ -632,7 +616,7 @@ std::vector CSGFaces(const mapentity_t *entity) std::map> planefaces; for (size_t i = 0; i < entity->brushes.size(); ++i) { const brush_t &brush = entity->brushes[i]; - face_t *outside = brushvec_outsides[i]; + std::list outside = brushvec_outsides[i]; /* * All of the faces left on the outside list are real surface faces diff --git a/qbsp/exportobj.cc b/qbsp/exportobj.cc index 14535ebc..e73400c6 100644 --- a/qbsp/exportobj.cc +++ b/qbsp/exportobj.cc @@ -145,7 +145,7 @@ static void ExportObj_Nodes_r(const node_t *node, std::vector *d return; } - for (face_t *face = node->faces; face; face = face->next) { + for (face_t *face : node->facelist) { dest->push_back(face); } diff --git a/qbsp/outside.cc b/qbsp/outside.cc index 9c35bbf1..c06ce29a 100644 --- a/qbsp/outside.cc +++ b/qbsp/outside.cc @@ -324,7 +324,7 @@ static void ResetFacesTouchingOccupiedLeafs(node_t *node) return; } - for (face_t *face = node->faces; face; face = face->next) { + for (face_t *face : node->facelist) { face->touchesOccupiedLeaf = false; } @@ -383,7 +383,7 @@ static void ClearOutFaces(node_t *node) } // FIXME: Shouldn't be needed here - node->faces = NULL; + node->facelist = {}; } static void OutLeafsToSolid_r(node_t *node, int *outleafs_count) diff --git a/qbsp/solidbsp.cc b/qbsp/solidbsp.cc index 9153561b..e0a7673f 100644 --- a/qbsp/solidbsp.cc +++ b/qbsp/solidbsp.cc @@ -548,16 +548,13 @@ static twosided> DividePlane(surface_t &in, const qplan std::list frontlist, backlist; for (auto face : in.faces) { - face_t *frontfrag = nullptr; - face_t *backfrag = nullptr; - - SplitFace(face, split, &frontfrag, &backfrag); + auto [frontfrag, backfrag] = SplitFace(face, split); if (frontfrag) { - frontlist.emplace_back(frontfrag); + frontlist.push_back(frontfrag); } if (backfrag) { - backlist.emplace_back(backfrag); + backlist.push_back(backfrag); } } @@ -606,7 +603,7 @@ Called in parallel. */ static void LinkConvexFaces(std::vector &planelist, node_t *leafnode) { - leafnode->faces = NULL; + leafnode->facelist.clear(); leafnode->planenum = PLANENUM_LEAF; int count = 0; @@ -688,7 +685,7 @@ is returned here (why?). Called in parallel. ================== */ -static face_t *LinkNodeFaces(surface_t &surface) +static std::list LinkNodeFaces(surface_t &surface) { // subdivide large faces for (auto it = surface.faces.begin(); it != surface.faces.end(); it++) { @@ -699,14 +696,15 @@ static face_t *LinkNodeFaces(surface_t &surface) nodefaces += surface.faces.size(); - face_t *list = NULL; - + std::list list; + // copy for (auto &f : surface.faces) { face_t *newf = new face_t(*f); + Q_assert(newf->original == nullptr); + + list.push_front(newf); f->original = newf; - newf->next = list; - list = newf; } return list; @@ -735,7 +733,7 @@ static void PartitionSurfaces(std::vector &surfaces, node_t *node) splitnodes++; LogPercent(splitnodes.load(), csgmergefaces); - node->faces = LinkNodeFaces(*split); + node->facelist = LinkNodeFaces(*split); node->children[0] = new node_t{}; node->children[1] = new node_t{}; node->planenum = split->planenum; diff --git a/qbsp/surfaces.cc b/qbsp/surfaces.cc index e06f6325..38a88957 100644 --- a/qbsp/surfaces.cc +++ b/qbsp/surfaces.cc @@ -110,7 +110,7 @@ std::list::iterator SubdivideFace(std::list::iterator it, st // plane.dist = (mins + subdiv) / v; plane.dist = (mins + subdiv - 16) / v; - SplitFace(f, plane, &front, &back); + std::tie(front, back) = SplitFace(f, plane); if (!front || !back) { LogPrintLocked("didn't split\n"); break; @@ -128,13 +128,8 @@ std::list::iterator SubdivideFace(std::list::iterator it, st static void FreeNode(node_t* node) { - if (node->faces) { - face_t *f, *next; - for (f = node->faces; f; f = next) { - next = f->next; - delete f; - } - node->faces = nullptr; + for (face_t *f : node->facelist) { + delete f; } delete node; } @@ -159,12 +154,9 @@ have inside faces. static void GatherNodeFaces_r(node_t *node, std::map> &planefaces) { - face_t *f, *next; - if (node->planenum != PLANENUM_LEAF) { // decision node - for (f = node->faces; f; f = next) { - next = f->next; + for (face_t *f : node->facelist) { if (!f->w.size()) { // face was removed outside delete f; } else { @@ -172,7 +164,7 @@ static void GatherNodeFaces_r(node_t *node, std::map> & } } // don't attempt to free node->faces again as ownership has moved to the planefaces map - node->faces = nullptr; + node->facelist = {}; GatherNodeFaces_r(node->children[0], planefaces); GatherNodeFaces_r(node->children[1], planefaces); } @@ -367,7 +359,7 @@ static int MakeFaceEdges_r(mapentity_t *entity, node_t *node, int progress) if (node->planenum == PLANENUM_LEAF) return progress; - for (face_t *f = node->faces; f; f = f->next) { + for (face_t *f : node->facelist) { FindFaceEdges(entity, f); } @@ -443,7 +435,7 @@ static void GrowNodeRegion(mapentity_t *entity, node_t *node) node->firstface = static_cast(map.bsp.dfaces.size()); - for (face_t *face = node->faces; face; face = face->next) { + for (face_t *face : node->facelist) { Q_assert(face->planenum == node->planenum); // emit a region @@ -477,12 +469,10 @@ CountData_r */ static void CountData_r(mapentity_t *entity, node_t *node, size_t &facesCount, size_t &vertexesCount) { - face_t *f; - if (node->planenum == PLANENUM_LEAF) return; - for (f = node->faces; f; f = f->next) { + for (face_t *f : node->facelist) { CountFace(entity, f, facesCount, vertexesCount); } diff --git a/qbsp/tjunc.cc b/qbsp/tjunc.cc index 6537c16c..1c0badd3 100644 --- a/qbsp/tjunc.cc +++ b/qbsp/tjunc.cc @@ -363,13 +363,12 @@ static void FixFaceEdges(face_t *face) static void tjunc_count_r(node_t *node) { - face_t *f; - if (node->planenum == PLANENUM_LEAF) return; - for (f = node->faces; f; f = f->next) + for (face_t *f : node->facelist) { cWVerts += f->w.size(); + } tjunc_count_r(node->children[0]); tjunc_count_r(node->children[1]); @@ -377,13 +376,12 @@ static void tjunc_count_r(node_t *node) static void tjunc_find_r(node_t *node) { - face_t *f; - if (node->planenum == PLANENUM_LEAF) return; - for (f = node->faces; f; f = f->next) + for (face_t *f : node->facelist) { AddFaceEdges(f); + } tjunc_find_r(node->children[0]); tjunc_find_r(node->children[1]); @@ -394,7 +392,7 @@ static void tjunc_fix_r(node_t *node) if (node->planenum == PLANENUM_LEAF) return; - for (face_t *face = node->faces; face; face = face->next) { + for (face_t *face : node->facelist) { FixFaceEdges(face); }