From ed325eedea01510d0cb79d253f45ac0668638a28 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Fri, 28 Jan 2022 10:47:52 -0500 Subject: [PATCH] surface faces now use list/vector --- include/qbsp/csg4.hh | 2 +- include/qbsp/map.hh | 6 +- include/qbsp/merge.hh | 5 +- include/qbsp/qbsp.hh | 23 +++++-- include/qbsp/solidbsp.hh | 2 +- include/qbsp/surfaces.hh | 2 +- qbsp/brush.cc | 2 +- qbsp/csg4.cc | 33 ++++------ qbsp/exportobj.cc | 6 +- qbsp/merge.cc | 63 +++++------------- qbsp/qbsp.cc | 2 +- qbsp/solidbsp.cc | 138 ++++++++++++++++++--------------------- qbsp/surfaces.cc | 34 +++++----- 13 files changed, 144 insertions(+), 174 deletions(-) diff --git a/include/qbsp/csg4.hh b/include/qbsp/csg4.hh index 466759b0..c9446fcf 100644 --- a/include/qbsp/csg4.hh +++ b/include/qbsp/csg4.hh @@ -26,7 +26,7 @@ extern int csgmergefaces; // build surfaces is also used by GatherNodeFaces -std::list BuildSurfaces(const std::map &planefaces); +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); void UpdateFaceSphere(face_t *in); diff --git a/include/qbsp/map.hh b/include/qbsp/map.hh index e95e5bd8..5e21652d 100644 --- a/include/qbsp/map.hh +++ b/include/qbsp/map.hh @@ -221,10 +221,10 @@ constexpr int HULL_COLLISION = -1; /* Create BSP brushes from map brushes */ brush_stats_t Brush_LoadEntity(mapentity_t *entity, const int hullnum); -std::list CSGFaces(const mapentity_t *entity); +std::vector CSGFaces(const mapentity_t *entity); void PortalizeWorld(const mapentity_t *entity, node_t *headnode, const int hullnum); void TJunc(const mapentity_t *entity, node_t *headnode); -node_t *SolidBSP(const mapentity_t *entity, std::list &surfhead, bool midsplit); +node_t *SolidBSP(const mapentity_t *entity, std::vector &surfhead, bool midsplit); int MakeFaceEdges(mapentity_t *entity, node_t *headnode); void ExportClipNodes(mapentity_t *entity, node_t *headnode, const int hullnum); void ExportDrawNodes(mapentity_t *entity, node_t *headnode, int firstface); @@ -238,7 +238,7 @@ void BSPX_Brushes_Init(struct bspxbrushes_s *ctx); void ExportObj_Faces(const std::string &filesuffix, const std::vector &faces); void ExportObj_Brushes(const std::string &filesuffix, const std::vector &brushes); -void ExportObj_Surfaces(const std::string &filesuffix, const std::list &surfaces); +void ExportObj_Surfaces(const std::string &filesuffix, const std::vector &surfaces); void ExportObj_Nodes(const std::string &filesuffix, const node_t *nodes); void ExportObj_Marksurfaces(const std::string &filesuffix, const node_t *nodes); diff --git a/include/qbsp/merge.hh b/include/qbsp/merge.hh index fc544c66..26f78cc2 100644 --- a/include/qbsp/merge.hh +++ b/include/qbsp/merge.hh @@ -23,6 +23,5 @@ #include -face_t *MergeFaceToList(face_t *face, face_t *list); -face_t *FreeMergeListScraps(face_t *merged); -void MergeAll(std::list &surfhead); +void MergeFaceToList(face_t *face, std::list &list); +void MergeAll(std::vector &surfhead); diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index d1d00d81..525dd6d3 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -235,7 +235,7 @@ struct surface_t bool onnode; // true if surface has already been used // as a splitting node bool detail_separator; // true if ALL faces are detail - face_t *faces; // links to all faces on either side of the surf + std::list faces; // links to all faces on either side of the surf // bounds of all the face windings; calculated via calculateInfo aabb3d bounds; @@ -246,6 +246,19 @@ struct surface_t std::optional outputplanenum; // only valid after WriteSurfacePlanes + inline surface_t shallowCopy() + { + surface_t copy; + + copy.planenum = planenum; + copy.onnode = onnode; + copy.detail_separator = detail_separator; + copy.has_struct = has_struct; + copy.lmshift = lmshift; + + return copy; + } + // calculate bounds & info inline void calculateInfo() { @@ -253,10 +266,12 @@ struct surface_t lmshift = std::numeric_limits::max(); has_struct = false; - for (const face_t *f = faces; f; f = f->next) { - for (auto &contents : f->contents) - if (!contents.is_valid(options.target_game, false)) + for (auto &f : faces) { + for (auto &contents : f->contents) { + if (!contents.is_valid(options.target_game, false)) { FError("Bad contents in face: {}", contents.to_string(options.target_game)); + } + } lmshift = min(f->lmshift.front, f->lmshift.back); diff --git a/include/qbsp/solidbsp.hh b/include/qbsp/solidbsp.hh index aea7cfaa..7bb90e29 100644 --- a/include/qbsp/solidbsp.hh +++ b/include/qbsp/solidbsp.hh @@ -26,4 +26,4 @@ extern std::atomic splitnodes; void DetailToSolid(node_t *node); -void SubdivideFace(face_t *f, face_t **prevptr); +std::list::iterator SubdivideFace(std::list::iterator it, std::list &surfaces); diff --git a/include/qbsp/surfaces.hh b/include/qbsp/surfaces.hh index 6be00ac2..40af5f57 100644 --- a/include/qbsp/surfaces.hh +++ b/include/qbsp/surfaces.hh @@ -23,5 +23,5 @@ #include -std::list GatherNodeFaces(node_t *headnode); +std::vector GatherNodeFaces(node_t *headnode); void FreeNodes(node_t* node); diff --git a/qbsp/brush.cc b/qbsp/brush.cc index e091c0b2..0fa39012 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -332,7 +332,7 @@ static std::vector CreateBrushFaces(const mapentity_t *src, hullbrush_t } // this face is a keeper - face_t &f = facelist.emplace_front(); + face_t &f = facelist.emplace_back(); f.planenum = PLANENUM_LEAF; f.w.resize(w->size()); diff --git a/qbsp/csg4.cc b/qbsp/csg4.cc index 8d751f12..d42ace43 100644 --- a/qbsp/csg4.cc +++ b/qbsp/csg4.cc @@ -303,7 +303,7 @@ This plane map is later used to build up the surfaces for creating the BSP. Not parallel. ================== */ -void SaveFacesToPlaneList(face_t *facelist, bool mirror, std::map &planefaces) +static void SaveFacesToPlaneList(face_t *facelist, bool mirror, std::map> &planefaces) { face_t *face, *next; @@ -317,8 +317,8 @@ void SaveFacesToPlaneList(face_t *facelist, bool mirror, std::map continue; #endif - face_t *plane_current_facelist = - planefaces[plane]; // returns `null` (and inserts it) if plane is not in the map yet + // returns empty (and inserts it) if plane is not in the map yet + std::list &plane_current_facelist = planefaces[plane]; if (mirror) { face_t *newface = NewFaceFromFace(face); @@ -347,13 +347,9 @@ void SaveFacesToPlaneList(face_t *facelist, bool mirror, std::map } } - plane_current_facelist = MergeFaceToList(newface, plane_current_facelist); + MergeFaceToList(newface, plane_current_facelist); } - plane_current_facelist = MergeFaceToList(face, plane_current_facelist); - plane_current_facelist = FreeMergeListScraps(plane_current_facelist); - - // save the new list back in the map - planefaces[plane] = plane_current_facelist; + MergeFaceToList(face, plane_current_facelist); csgfaces++; } @@ -456,9 +452,9 @@ visible face. Not parallel. ================== */ -std::list BuildSurfaces(const std::map &planefaces) +std::vector BuildSurfaces(std::map> &planefaces) { - std::list surfaces; + std::vector surfaces; for (int i = 0; i < map.numplanes(); i++) { const auto entry = planefaces.find(i); @@ -466,14 +462,13 @@ std::list BuildSurfaces(const std::map &planefaces) if (entry == planefaces.end()) continue; - Q_assert(entry->second != nullptr); + Q_assert(!entry->second.empty()); /* create a new surface to hold the faces on this plane */ - surface_t &surf = surfaces.emplace_front(); + surface_t &surf = surfaces.emplace_back(); surf.planenum = entry->first; - surf.faces = entry->second; - for (const face_t *face = surf.faces; face; face = face->next) - csgmergefaces++; + surf.faces = std::move(entry->second); + csgmergefaces += surf.faces.size(); /* Calculate bounding box and flags */ surf.calculateInfo(); @@ -513,7 +508,7 @@ CSGFaces Returns a list of surfaces containing all of the faces ================== */ -std::list CSGFaces(const mapentity_t *entity) +std::vector CSGFaces(const mapentity_t *entity) { LogPrint(LOG_PROGRESS, "---- {} ----\n", __func__); @@ -634,7 +629,7 @@ std::list CSGFaces(const mapentity_t *entity) }); // Non parallel part: - std::map planefaces; + 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]; @@ -647,7 +642,7 @@ std::list CSGFaces(const mapentity_t *entity) SaveFacesToPlaneList(outside, mirror, planefaces); } - std::list surfaces = BuildSurfaces(planefaces); + std::vector surfaces = BuildSurfaces(planefaces); LogPrint(LOG_STAT, " {:8} brushfaces\n", brushfaces.load()); LogPrint(LOG_STAT, " {:8} csgfaces\n", csgfaces); diff --git a/qbsp/exportobj.cc b/qbsp/exportobj.cc index 9a4f9342..14535ebc 100644 --- a/qbsp/exportobj.cc +++ b/qbsp/exportobj.cc @@ -128,14 +128,12 @@ void ExportObj_Brushes(const std::string &filesuffix, const std::vector &surfaces) +void ExportObj_Surfaces(const std::string &filesuffix, const std::vector &surfaces) { std::vector faces; for (auto &surf : surfaces) { - for (const face_t *face = surf.faces; face; face = face->next) { - faces.push_back(face); - } + std::copy(surf.faces.begin(), surf.faces.end(), std::back_inserter(faces)); } ExportObj_Faces(filesuffix, faces); diff --git a/qbsp/merge.cc b/qbsp/merge.cc index aa020a18..e10663ac 100644 --- a/qbsp/merge.cc +++ b/qbsp/merge.cc @@ -157,51 +157,25 @@ static face_t *TryMerge(face_t *f1, face_t *f2) MergeFaceToList =============== */ -face_t *MergeFaceToList(face_t *face, face_t *list) +void MergeFaceToList(face_t *face, std::list &list) { - face_t *newf, *f; - - f = list; - while (f) { + for (auto it = list.begin(); it != list.end(); ) { #ifdef PARANOID CheckColinear(f); #endif - newf = TryMerge(face, f); + face_t *newf = TryMerge(face, *it); + if (newf) { delete face; - f->w.clear(); // merged out, remove later + list.erase(it); face = newf; - f = list; - } else - f = f->next; - } - - // didn't merge, so add at start - face->next = list; - return face; -} - -/* -=============== -FreeMergeListScraps -=============== -*/ -face_t *FreeMergeListScraps(face_t *merged) -{ - face_t *head, *next; - - head = NULL; - for (; merged; merged = next) { - next = merged->next; - if (!merged->w.size()) { - delete merged; + it = list.begin(); } else { - merged->next = head; - head = merged; + it++; } } - return head; + list.emplace_back(face); } /* @@ -211,16 +185,13 @@ MergePlaneFaces */ inline void MergePlaneFaces(surface_t &plane) { - face_t *merged = NULL, *next; + std::list merged; - for (face_t *f = plane.faces; f; f = next) { - next = f->next; - merged = MergeFaceToList(f, merged); + for (auto &f : plane.faces) { + MergeFaceToList(f, merged); } - // Remove all empty faces (numpoints == -1) and add the remaining - // faces to the plane - plane.faces = FreeMergeListScraps(merged); + plane.faces = std::move(merged); } #include @@ -230,20 +201,16 @@ inline void MergePlaneFaces(surface_t &plane) MergeAll ============ */ -void MergeAll(std::list &surfhead) +void MergeAll(std::vector &surfhead) { std::atomic mergefaces = 0, premergefaces = 0; LogPrint(LOG_PROGRESS, "---- {} ----\n", __func__); tbb::parallel_for_each(surfhead, [&](surface_t &surf) { - for (face_t *f = surf.faces; f; f = f->next) { - premergefaces++; - } + premergefaces += surf.faces.size(); MergePlaneFaces(surf); - for (face_t *f = surf.faces; f; f = f->next) { - mergefaces++; - } + mergefaces += surf.faces.size(); }); LogPrint(LOG_STAT, " {:8} mergefaces (from {}; {:.0}% merged)\n", mergefaces, premergefaces, (static_cast(mergefaces) / premergefaces) * 100.); diff --git a/qbsp/qbsp.cc b/qbsp/qbsp.cc index 9262bdf1..b1f4f34c 100644 --- a/qbsp/qbsp.cc +++ b/qbsp/qbsp.cc @@ -563,7 +563,7 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum) * Take the brush_t's and clip off all overlapping and contained faces, * leaving a perfect skin of the model with no hidden faces */ - std::list surfs = CSGFaces(entity); + std::vector surfs = CSGFaces(entity); if (options.fObjExport && entity == pWorldEnt() && hullnum <= 0) { ExportObj_Surfaces("post_csg", surfs); diff --git a/qbsp/solidbsp.cc b/qbsp/solidbsp.cc index 7527984d..9153561b 100644 --- a/qbsp/solidbsp.cc +++ b/qbsp/solidbsp.cc @@ -266,13 +266,13 @@ ChooseMidPlaneFromList The clipping hull BSP doesn't worry about avoiding splits ================== */ -static std::list::iterator ChooseMidPlaneFromList(std::list &surfaces, const aabb3d &bounds) +static std::vector::iterator ChooseMidPlaneFromList(std::vector &surfaces, const aabb3d &bounds) { /* pick the plane that splits the least */ vec_t bestaxialmetric = VECT_MAX; - std::list::iterator bestaxialsurface = surfaces.end(); + std::vector::iterator bestaxialsurface = surfaces.end(); vec_t bestanymetric = VECT_MAX; - std::list::iterator bestanysurface = surfaces.end(); + std::vector::iterator bestanysurface = surfaces.end(); for (int pass = 0; pass < 2; pass++) { for (auto surf = surfaces.begin(); surf != surfaces.end(); surf++) { @@ -340,12 +340,12 @@ ChoosePlaneFromList The real BSP heuristic ================== */ -static std::list::iterator ChoosePlaneFromList(std::list &surfaces, const aabb3d &bounds) +static std::vector::iterator ChoosePlaneFromList(std::vector &surfaces, const aabb3d &bounds) { /* pick the plane that splits the least */ int minsplits = INT_MAX - 1; vec_t bestdistribution = VECT_MAX; - std::list::iterator bestsurface = surfaces.end(); + std::vector::iterator bestsurface = surfaces.end(); /* Two passes - exhaust all non-detail faces before details */ for (int pass = 0; pass < 2; pass++) { @@ -358,7 +358,7 @@ static std::list::iterator ChoosePlaneFromList(std::list & * and check whether this is a hint split. */ bool hintsplit = false; - for (const face_t *face = surf->faces; face; face = face->next) { + for (auto &face : surf->faces) { if (map.mtexinfos.at(face->texinfo).flags.is_hint) hintsplit = true; } @@ -377,7 +377,7 @@ static std::list::iterator ChoosePlaneFromList(std::list & const qbsp_plane_t &plane2 = map.planes[surf2->planenum]; if (plane.type < 3 && plane.type == plane2.type) continue; - for (const face_t *face = surf2->faces; face; face = face->next) { + for (auto &face : surf2->faces) { const surfflags_t &flags = map.mtexinfos.at(face->texinfo).flags; /* Don't penalize for splitting skip faces */ if (flags.is_skip) @@ -436,11 +436,11 @@ returns NULL if the surface list can not be divided any more (a leaf) Called in parallel. ================== */ -static std::list::iterator SelectPartition(std::list &surfaces) +static std::vector::iterator SelectPartition(std::vector &surfaces) { // count onnode surfaces int surfcount = 0; - std::list::iterator bestsurface = surfaces.end(); + std::vector::iterator bestsurface = surfaces.end(); for (auto surf = surfaces.begin(); surf != surfaces.end(); surf++) { if (!surf->onnode) { @@ -505,88 +505,80 @@ static twosided> DividePlane(surface_t &in, const qplan if (qv::epsilonEqual(inplane->normal, split.normal, EQUAL_EPSILON)) { // check for exactly on node if (inplane->dist == split.dist) { - face_t *facet = in.faces; - in.faces = NULL; in.onnode = true; // divide the facets to the front and back sides - surface_t newsurf(in); + surface_t newsurf = in.shallowCopy(); // Prepend each face in facet list to either in or newsurf lists - face_t *next; - for (; facet; facet = next) { - next = facet->next; - if (facet->planeside == 1) { - facet->next = newsurf.faces; - newsurf.faces = facet; + for (auto it = in.faces.begin(); it != in.faces.end(); ) { + if ((*it)->planeside == 1) { + auto next = std::next(it); + newsurf.faces.splice(newsurf.faces.begin(), in.faces, it); + it = next; } else { - facet->next = in.faces; - in.faces = facet; + it++; } } - // ericw -- added these CalcSurfaceInfo to recalculate the surf bbox. - // pretty sure their omission here was a bug. - newsurf.calculateInfo(); - in.calculateInfo(); - - if (in.faces) + if (!in.faces.empty()) { + in.calculateInfo(); front = std::move(in); + } - if (newsurf.faces) + if (!newsurf.faces.empty()) { + newsurf.calculateInfo(); back = std::move(newsurf); + } return { front, back }; } - if (inplane->dist > split.dist) + if (inplane->dist > split.dist) { front = std::move(in); - else + } else { back = std::move(in); + } return { front, back }; } // do a real split. may still end up entirely on one side // OPTIMIZE: use bounding box for fast test - face_t *frontlist = NULL; - face_t *backlist = NULL; + std::list frontlist, backlist; - face_t *next; - for (face_t *facet = in.faces; facet; facet = next) { - next = facet->next; + for (auto face : in.faces) { + face_t *frontfrag = nullptr; + face_t *backfrag = nullptr; + + SplitFace(face, split, &frontfrag, &backfrag); - face_t *frontfrag = NULL; - face_t *backfrag = NULL; - SplitFace(facet, split, &frontfrag, &backfrag); if (frontfrag) { - frontfrag->next = frontlist; - frontlist = frontfrag; + frontlist.emplace_back(frontfrag); } if (backfrag) { - backfrag->next = backlist; - backlist = backfrag; + backlist.emplace_back(backfrag); } } // if nothing actually got split, just move the in plane - if (frontlist == NULL) { - in.faces = backlist; + if (frontlist.empty()) { + in.faces = std::move(backlist); return { std::nullopt, std::move(in) }; } - if (backlist == NULL) { - in.faces = frontlist; + if (backlist.empty()) { + in.faces = std::move(frontlist); return { std::move(in), std::nullopt }; } // stuff got split, so allocate one new plane and reuse in - surface_t newsurf(in); - newsurf.faces = backlist; - in.faces = frontlist; + surface_t newsurf = in.shallowCopy(); - // recalc bboxes and flags + newsurf.faces = std::move(backlist); newsurf.calculateInfo(); + + in.faces = std::move(frontlist); in.calculateInfo(); return { std::move(in), std::move(newsurf) }; @@ -612,7 +604,7 @@ original faces that have some fragment inside this leaf. Called in parallel. ================== */ -static void LinkConvexFaces(std::list &planelist, node_t *leafnode) +static void LinkConvexFaces(std::vector &planelist, node_t *leafnode) { leafnode->faces = NULL; leafnode->planenum = PLANENUM_LEAF; @@ -621,11 +613,12 @@ static void LinkConvexFaces(std::list &planelist, node_t *leafnode) std::optional contents; for (auto &surf : planelist) { - for (face_t *f = surf.faces; f; f = f->next) { - count++; + count += surf.faces.size(); + for (auto &f : surf.faces) { const int currentpri = contents.has_value() ? contents->priority(options.target_game) : -1; const int fpri = f->contents[0].priority(options.target_game); + if (fpri > currentpri) { contents = f->contents[0]; } @@ -675,11 +668,9 @@ static void LinkConvexFaces(std::list &planelist, node_t *leafnode) leafnode->markfaces.reserve(count); for (auto &surf : planelist) { - for (face_t *f = surf.faces; f; ) { - face_t *next = f->next; + for (auto &f : surf.faces) { leafnode->markfaces.push_back(f->original); delete f; - f = next; } } } @@ -699,20 +690,19 @@ Called in parallel. */ static face_t *LinkNodeFaces(surface_t &surface) { - face_t *list = NULL; - // subdivide large faces - face_t **prevptr = &surface.faces; - face_t *f = *prevptr; - while (f) { - SubdivideFace(f, prevptr); - prevptr = &(*prevptr)->next; - f = *prevptr; + for (auto it = surface.faces.begin(); it != surface.faces.end(); it++) { + it = SubdivideFace(it, surface.faces); } + surface.faces.reverse(); + + nodefaces += surface.faces.size(); + + face_t *list = NULL; + // copy - for (face_t *f = surface.faces; f; f = f->next) { - nodefaces++; + for (auto &f : surface.faces) { face_t *newf = new face_t(*f); f->original = newf; newf->next = list; @@ -729,9 +719,9 @@ PartitionSurfaces Called in parallel. ================== */ -static void PartitionSurfaces(std::list &surfaces, node_t *node) +static void PartitionSurfaces(std::vector &surfaces, node_t *node) { - std::list::iterator split = SelectPartition(surfaces); + std::vector::iterator split = SelectPartition(surfaces); if (split == surfaces.end()) { // this is a leaf node node->planenum = PLANENUM_LEAF; @@ -756,7 +746,7 @@ static void PartitionSurfaces(std::list &surfaces, node_t *node) DivideNodeBounds(node, splitplane); // multiple surfaces, so split all the polysurfaces into front and back lists - std::list frontlist, backlist; + std::vector frontlist, backlist; for (auto &surf : surfaces) { auto frags = DividePlane(surf, splitplane); @@ -769,14 +759,16 @@ static void PartitionSurfaces(std::list &surfaces, node_t *node) } if (frags.front) { - if (!frags.front->faces) + if (frags.front->faces.empty()) { FError("Surface with no faces"); - frontlist.emplace_front(std::move(*frags.front)); + } + frontlist.emplace_back(std::move(*frags.front)); } if (frags.back) { - if (!frags.back->faces) + if (frags.back->faces.empty()) { FError("Surface with no faces"); - backlist.emplace_front(std::move(*frags.back)); + } + backlist.emplace_back(std::move(*frags.back)); } } @@ -791,7 +783,7 @@ static void PartitionSurfaces(std::list &surfaces, node_t *node) SolidBSP ================== */ -node_t *SolidBSP(const mapentity_t *entity, std::list &surfhead, bool midsplit) +node_t *SolidBSP(const mapentity_t *entity, std::vector &surfhead, bool midsplit) { if (surfhead.empty()) { /* diff --git a/qbsp/surfaces.cc b/qbsp/surfaces.cc index 59c81689..e06f6325 100644 --- a/qbsp/surfaces.cc +++ b/qbsp/surfaces.cc @@ -31,13 +31,13 @@ If the face is >256 in either texture direction, carve a valid sized piece off and insert the remainder in the next link =============== */ -void SubdivideFace(face_t *f, face_t **prevptr) +std::list::iterator SubdivideFace(std::list::iterator it, std::list &surfaces) { vec_t mins, maxs; vec_t v; int axis; qbsp_plane_t plane; - face_t *front, *back, *next; + face_t *front, *back; const mtexinfo_t *tex; vec_t subdiv; vec_t extent; @@ -45,15 +45,18 @@ void SubdivideFace(face_t *f, face_t **prevptr) // subdivision disabled if (!options.dxSubdivide) { - return; + return it; } + face_t *f = *it; + /* special (non-surface cached) faces don't need subdivision */ tex = &map.mtexinfos.at(f->texinfo); if (tex->flags.is_skip || tex->flags.is_hint || - !options.target_game->surf_is_subdivided(tex->flags)) - return; + !options.target_game->surf_is_subdivided(tex->flags)) { + return it; + } // subdivision is pretty much pointless other than because of lightmap block limits // one lightmap block will always be added at the end, for smooth interpolation @@ -91,8 +94,9 @@ void SubdivideFace(face_t *f, face_t **prevptr) extent = ceil(maxs) - floor(mins); // extent = maxs - mins; - if (extent <= subdiv) + if (extent <= subdiv) { break; + } // split it plane.normal = tmp; @@ -106,19 +110,20 @@ void SubdivideFace(face_t *f, face_t **prevptr) // plane.dist = (mins + subdiv) / v; plane.dist = (mins + subdiv - 16) / v; - next = f->next; SplitFace(f, plane, &front, &back); if (!front || !back) { LogPrintLocked("didn't split\n"); break; // FError("Didn't split the polygon"); } - *prevptr = back; - back->next = front; - front->next = next; + it = surfaces.erase(it); + it = surfaces.insert(it, front); + it = surfaces.insert(it, back); f = back; } } + + return it; } static void FreeNode(node_t* node) @@ -152,7 +157,7 @@ have inside faces. ============================================================================= */ -static void GatherNodeFaces_r(node_t *node, std::map &planefaces) +static void GatherNodeFaces_r(node_t *node, std::map> &planefaces) { face_t *f, *next; @@ -163,8 +168,7 @@ static void GatherNodeFaces_r(node_t *node, std::map &planefaces) if (!f->w.size()) { // face was removed outside delete f; } else { - f->next = planefaces[f->planenum]; - planefaces[f->planenum] = f; + planefaces[f->planenum].emplace_back(f); } } // don't attempt to free node->faces again as ownership has moved to the planefaces map @@ -180,9 +184,9 @@ static void GatherNodeFaces_r(node_t *node, std::map &planefaces) GatherNodeFaces ================ */ -std::list GatherNodeFaces(node_t *headnode) +std::vector GatherNodeFaces(node_t *headnode) { - std::map planefaces; + std::map> planefaces; GatherNodeFaces_r(headnode, planefaces); return BuildSurfaces(planefaces); }