surface faces now use list/vector
This commit is contained in:
parent
10b592f64d
commit
ed325eedea
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
33
qbsp/csg4.cc
33
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<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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
136
qbsp/solidbsp.cc
136
qbsp/solidbsp.cc
|
|
@ -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()) {
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue