surface faces now use list/vector

This commit is contained in:
Jonathan 2022-01-28 10:47:52 -05:00 committed by Eric Wasylishen
parent 10b592f64d
commit ed325eedea
13 changed files with 144 additions and 174 deletions

View File

@ -26,7 +26,7 @@
extern int csgmergefaces;
// build surfaces is also used by GatherNodeFaces
std::list<surface_t> BuildSurfaces(const std::map<int, face_t *> &planefaces);
std::vector<surface_t> BuildSurfaces(std::map<int, std::list<face_t *>> &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);

View File

@ -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<surface_t> CSGFaces(const mapentity_t *entity);
std::vector<surface_t> 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<surface_t> &surfhead, bool midsplit);
node_t *SolidBSP(const mapentity_t *entity, std::vector<surface_t> &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<const face_t *> &faces);
void ExportObj_Brushes(const std::string &filesuffix, const std::vector<const brush_t *> &brushes);
void ExportObj_Surfaces(const std::string &filesuffix, const std::list<surface_t> &surfaces);
void ExportObj_Surfaces(const std::string &filesuffix, const std::vector<surface_t> &surfaces);
void ExportObj_Nodes(const std::string &filesuffix, const node_t *nodes);
void ExportObj_Marksurfaces(const std::string &filesuffix, const node_t *nodes);

View File

@ -23,6 +23,5 @@
#include <list>
face_t *MergeFaceToList(face_t *face, face_t *list);
face_t *FreeMergeListScraps(face_t *merged);
void MergeAll(std::list<surface_t> &surfhead);
void MergeFaceToList(face_t *face, std::list<face_t *> &list);
void MergeAll(std::vector<surface_t> &surfhead);

View File

@ -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<face_t *> 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<size_t> 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<short>::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);

View File

@ -26,4 +26,4 @@
extern std::atomic<int> splitnodes;
void DetailToSolid(node_t *node);
void SubdivideFace(face_t *f, face_t **prevptr);
std::list<face_t *>::iterator SubdivideFace(std::list<face_t *>::iterator it, std::list<face_t *> &surfaces);

View File

@ -23,5 +23,5 @@
#include <list>
std::list<surface_t> GatherNodeFaces(node_t *headnode);
std::vector<surface_t> GatherNodeFaces(node_t *headnode);
void FreeNodes(node_t* node);

View File

@ -332,7 +332,7 @@ static std::vector<face_t> 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());

View File

@ -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<int, face_t *> &planefaces)
static void SaveFacesToPlaneList(face_t *facelist, bool mirror, std::map<int, std::list<face_t *>> &planefaces)
{
face_t *face, *next;
@ -317,8 +317,8 @@ void SaveFacesToPlaneList(face_t *facelist, bool mirror, std::map<int, face_t *>
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<face_t *> &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<int, face_t *>
}
}
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<surface_t> BuildSurfaces(const std::map<int, face_t *> &planefaces)
std::vector<surface_t> BuildSurfaces(std::map<int, std::list<face_t *>> &planefaces)
{
std::list<surface_t> surfaces;
std::vector<surface_t> surfaces;
for (int i = 0; i < map.numplanes(); i++) {
const auto entry = planefaces.find(i);
@ -466,14 +462,13 @@ std::list<surface_t> BuildSurfaces(const std::map<int, face_t *> &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<surface_t> CSGFaces(const mapentity_t *entity)
std::vector<surface_t> CSGFaces(const mapentity_t *entity)
{
LogPrint(LOG_PROGRESS, "---- {} ----\n", __func__);
@ -634,7 +629,7 @@ std::list<surface_t> CSGFaces(const mapentity_t *entity)
});
// Non parallel part:
std::map<int, face_t *> planefaces;
std::map<int, std::list<face_t *>> 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<surface_t> CSGFaces(const mapentity_t *entity)
SaveFacesToPlaneList(outside, mirror, planefaces);
}
std::list<surface_t> surfaces = BuildSurfaces(planefaces);
std::vector<surface_t> surfaces = BuildSurfaces(planefaces);
LogPrint(LOG_STAT, " {:8} brushfaces\n", brushfaces.load());
LogPrint(LOG_STAT, " {:8} csgfaces\n", csgfaces);

View File

@ -128,14 +128,12 @@ void ExportObj_Brushes(const std::string &filesuffix, const std::vector<const br
ExportObj_Faces(filesuffix, faces);
}
void ExportObj_Surfaces(const std::string &filesuffix, const std::list<surface_t> &surfaces)
void ExportObj_Surfaces(const std::string &filesuffix, const std::vector<surface_t> &surfaces)
{
std::vector<const face_t *> 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);

View File

@ -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<face_t *> &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<face_t *> 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 <tbb/parallel_for_each.h>
@ -230,20 +201,16 @@ inline void MergePlaneFaces(surface_t &plane)
MergeAll
============
*/
void MergeAll(std::list<surface_t> &surfhead)
void MergeAll(std::vector<surface_t> &surfhead)
{
std::atomic<int> 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<double>(mergefaces) / premergefaces) * 100.);

View File

@ -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<surface_t> surfs = CSGFaces(entity);
std::vector<surface_t> surfs = CSGFaces(entity);
if (options.fObjExport && entity == pWorldEnt() && hullnum <= 0) {
ExportObj_Surfaces("post_csg", surfs);

View File

@ -266,13 +266,13 @@ ChooseMidPlaneFromList
The clipping hull BSP doesn't worry about avoiding splits
==================
*/
static std::list<surface_t>::iterator ChooseMidPlaneFromList(std::list<surface_t> &surfaces, const aabb3d &bounds)
static std::vector<surface_t>::iterator ChooseMidPlaneFromList(std::vector<surface_t> &surfaces, const aabb3d &bounds)
{
/* pick the plane that splits the least */
vec_t bestaxialmetric = VECT_MAX;
std::list<surface_t>::iterator bestaxialsurface = surfaces.end();
std::vector<surface_t>::iterator bestaxialsurface = surfaces.end();
vec_t bestanymetric = VECT_MAX;
std::list<surface_t>::iterator bestanysurface = surfaces.end();
std::vector<surface_t>::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<surface_t>::iterator ChoosePlaneFromList(std::list<surface_t> &surfaces, const aabb3d &bounds)
static std::vector<surface_t>::iterator ChoosePlaneFromList(std::vector<surface_t> &surfaces, const aabb3d &bounds)
{
/* pick the plane that splits the least */
int minsplits = INT_MAX - 1;
vec_t bestdistribution = VECT_MAX;
std::list<surface_t>::iterator bestsurface = surfaces.end();
std::vector<surface_t>::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<surface_t>::iterator ChoosePlaneFromList(std::list<surface_t> &
* 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<surface_t>::iterator ChoosePlaneFromList(std::list<surface_t> &
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<surface_t>::iterator SelectPartition(std::list<surface_t> &surfaces)
static std::vector<surface_t>::iterator SelectPartition(std::vector<surface_t> &surfaces)
{
// count onnode surfaces
int surfcount = 0;
std::list<surface_t>::iterator bestsurface = surfaces.end();
std::vector<surface_t>::iterator bestsurface = surfaces.end();
for (auto surf = surfaces.begin(); surf != surfaces.end(); surf++) {
if (!surf->onnode) {
@ -505,88 +505,80 @@ static twosided<std::optional<surface_t>> 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();
if (!in.faces.empty()) {
in.calculateInfo();
if (in.faces)
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<face_t *> 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<surface_t> &planelist, node_t *leafnode)
static void LinkConvexFaces(std::vector<surface_t> &planelist, node_t *leafnode)
{
leafnode->faces = NULL;
leafnode->planenum = PLANENUM_LEAF;
@ -621,11 +613,12 @@ static void LinkConvexFaces(std::list<surface_t> &planelist, node_t *leafnode)
std::optional<contentflags_t> 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<surface_t> &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<surface_t> &surfaces, node_t *node)
static void PartitionSurfaces(std::vector<surface_t> &surfaces, node_t *node)
{
std::list<surface_t>::iterator split = SelectPartition(surfaces);
std::vector<surface_t>::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<surface_t> &surfaces, node_t *node)
DivideNodeBounds(node, splitplane);
// multiple surfaces, so split all the polysurfaces into front and back lists
std::list<surface_t> frontlist, backlist;
std::vector<surface_t> frontlist, backlist;
for (auto &surf : surfaces) {
auto frags = DividePlane(surf, splitplane);
@ -769,14 +759,16 @@ static void PartitionSurfaces(std::list<surface_t> &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<surface_t> &surfaces, node_t *node)
SolidBSP
==================
*/
node_t *SolidBSP(const mapentity_t *entity, std::list<surface_t> &surfhead, bool midsplit)
node_t *SolidBSP(const mapentity_t *entity, std::vector<surface_t> &surfhead, bool midsplit)
{
if (surfhead.empty()) {
/*

View File

@ -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<face_t *>::iterator SubdivideFace(std::list<face_t *>::iterator it, std::list<face_t *> &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<int, face_t *> &planefaces)
static void GatherNodeFaces_r(node_t *node, std::map<int, std::list<face_t *>> &planefaces)
{
face_t *f, *next;
@ -163,8 +168,7 @@ static void GatherNodeFaces_r(node_t *node, std::map<int, face_t *> &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<int, face_t *> &planefaces)
GatherNodeFaces
================
*/
std::list<surface_t> GatherNodeFaces(node_t *headnode)
std::vector<surface_t> GatherNodeFaces(node_t *headnode)
{
std::map<int, face_t *> planefaces;
std::map<int, std::list<face_t *>> planefaces;
GatherNodeFaces_r(headnode, planefaces);
return BuildSurfaces(planefaces);
}