From 674be0c81251df810130cc4ec28f3dbf83f43f41 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 25 Jan 2022 03:23:39 -0500 Subject: [PATCH] Fix a few messages (missing newlines, period in wrong place) Use fragments to store TJunction bits instead of having them in separate-but-chained faces --- include/qbsp/qbsp.hh | 16 +++++++---- qbsp/map.cc | 6 ++-- qbsp/surfaces.cc | 65 ++++++++++++++++++++++++++++++-------------- qbsp/tjunc.cc | 59 ++++++++++++++++------------------------ qbsp/writebsp.cc | 10 ++++--- 5 files changed, 89 insertions(+), 67 deletions(-) diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index 2234fd5b..7bf2f511 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -204,7 +204,15 @@ struct mtexinfo_t class mapentity_t; -struct face_t +struct face_fragment_t +{ + winding_t w; + std::vector edges; // only filled in MakeFaceEdges + std::optional outputnumber; // only valid for original faces after + // write surfaces +}; + +struct face_t : face_fragment_t { face_t *next; @@ -216,14 +224,12 @@ struct face_t mapentity_t *src_entity; // source entity face_t *original; // face on node - std::optional outputnumber; // only valid for original faces after - // write surfaces bool touchesOccupiedLeaf; // internal use in outside.cc qvec3d origin; vec_t radius; - std::vector edges; // only filled in MakeFaceEdges - winding_t w; + // filled by TJunc + std::list fragments; }; struct surface_t diff --git a/qbsp/map.cc b/qbsp/map.cc index 5104bae9..05b96984 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -1543,13 +1543,13 @@ mapbrush_t ParseBrush(parser_t &parser, const mapentity_t *entity) for (int i = 0; i < brush.numfaces; i++) { const mapface_t &check = brush.face(i); if (qv::epsilonEqual(check.plane, face->plane)) { - LogPrint("line {}: Brush with duplicate plane", parser.linenum); + LogPrint("line {}: Brush with duplicate plane\n", parser.linenum); discardFace = true; continue; } if (qv::epsilonEqual(-check.plane, face->plane)) { /* FIXME - this is actually an invalid brush */ - LogPrint("line {}: Brush with duplicate plane", parser.linenum); + LogPrint("line {}: Brush with duplicate plane\n", parser.linenum); continue; } } @@ -1874,7 +1874,7 @@ void LoadMapFile(void) auto file = fs::load(options.szMapName); if (!file) { - FError("Couldn't load map file \"{}.\"\n", options.szMapName); + FError("Couldn't load map file \"{}\".\n", options.szMapName); return; } diff --git a/qbsp/surfaces.cc b/qbsp/surfaces.cc index 772797b9..59c81689 100644 --- a/qbsp/surfaces.cc +++ b/qbsp/surfaces.cc @@ -317,6 +317,23 @@ inline size_t GetEdge(mapentity_t *entity, const qvec3d &p1, const qvec3d &p2, c return i; } +static void FindFaceFragmentEdges(mapentity_t *entity, face_t *face, face_fragment_t *fragment) +{ + fragment->outputnumber = std::nullopt; + + if (fragment->w.size() > MAXEDGES) { + FError("Internal error: face->numpoints > MAXEDGES"); + } + + fragment->edges.resize(fragment->w.size()); + + for (size_t i = 0; i < fragment->w.size(); i++) { + const qvec3d &p1 = fragment->w[i]; + const qvec3d &p2 = fragment->w[(i + 1) % fragment->w.size()]; + fragment->edges[i] = GetEdge(entity, p1, p2, face); + } +} + /* ================== FindFaceEdges @@ -329,16 +346,10 @@ static void FindFaceEdges(mapentity_t *entity, face_t *face) if (map.mtexinfos.at(face->texinfo).flags.is_hint) return; - face->outputnumber = std::nullopt; - if (face->w.size() > MAXEDGES) - FError("Internal error: face->numpoints > MAXEDGES"); + FindFaceFragmentEdges(entity, face, face); - face->edges.resize(face->w.size()); - - for (size_t i = 0; i < face->w.size(); i++) { - const qvec3d &p1 = face->w[i]; - const qvec3d &p2 = face->w[(i + 1) % face->w.size()]; - face->edges[i] = GetEdge(entity, p1, p2, face); + for (auto &fragment : face->fragments) { + FindFaceFragmentEdges(entity, face, &fragment); } } @@ -365,21 +376,16 @@ static int MakeFaceEdges_r(mapentity_t *entity, node_t *node, int progress) /* ============== -EmitFace +EmitFaceFragment ============== */ -static void EmitFace(mapentity_t *entity, face_t *face) +static void EmitFaceFragment(mapentity_t *entity, face_t *face, face_fragment_t *fragment) { int i; - if (!options.includeSkip && map.mtexinfos.at(face->texinfo).flags.is_skip) - return; - if (map.mtexinfos.at(face->texinfo).flags.is_hint) - return; - // emit a region - Q_assert(!face->outputnumber.has_value()); - face->outputnumber = map.bsp.dfaces.size(); + Q_assert(!fragment->outputnumber.has_value()); + fragment->outputnumber = map.bsp.dfaces.size(); mface_t &out = map.bsp.dfaces.emplace_back(); @@ -396,12 +402,31 @@ static void EmitFace(mapentity_t *entity, face_t *face) // emit surfedges out.firstedge = static_cast(map.bsp.dsurfedges.size()); - std::copy(face->edges.cbegin(), face->edges.cbegin() + face->w.size(), std::back_inserter(map.bsp.dsurfedges)); - face->edges.clear(); + std::copy(fragment->edges.cbegin(), fragment->edges.cbegin() + fragment->w.size(), std::back_inserter(map.bsp.dsurfedges)); + fragment->edges.clear(); out.numedges = static_cast(map.bsp.dsurfedges.size()) - out.firstedge; } +/* +============== +EmitFace +============== +*/ +static void EmitFace(mapentity_t *entity, face_t *face) +{ + if (!options.includeSkip && map.mtexinfos.at(face->texinfo).flags.is_skip) + return; + if (map.mtexinfos.at(face->texinfo).flags.is_hint) + return; + + EmitFaceFragment(entity, face, face); + + for (auto &fragment : face->fragments) { + EmitFaceFragment(entity, face, &fragment); + } +} + /* ============== GrowNodeRegion diff --git a/qbsp/tjunc.cc b/qbsp/tjunc.cc index 4cb6d7cc..c3954476 100644 --- a/qbsp/tjunc.cc +++ b/qbsp/tjunc.cc @@ -238,25 +238,20 @@ static void AddFaceEdges(face_t *f) */ #define MAX_SUPERFACE_POINTS 8192 -static void SplitFaceForTjunc(face_t *face, face_t *original, face_t **facelist) +static void SplitFaceForTjunc(face_t *face, face_t *original) { winding_t &w = face->w; - face_t *newf, *chain; qvec3d edgevec[2]; vec_t angle; int i, firstcorner, lastcorner; - chain = NULL; do { if (w.size() <= MAXPOINTS) { /* * the face is now small enough without more cutting so * copy it back to the original */ - *original = *face; - original->original = chain; - original->next = *facelist; - *facelist = original; + *original = std::move(*face); return; } @@ -298,27 +293,23 @@ restart: * cut off as big a piece as possible, less than MAXPOINTS, and not * past lastcorner */ - newf = NewFaceFromFace(face); - if (face->original) - FError("original face still exists"); + winding_t neww(face->w); - newf->original = chain; - chain = newf; - newf->next = *facelist; - *facelist = newf; if (w.size() - firstcorner <= MAXPOINTS) - newf->w.resize(firstcorner + 2); + neww.resize(firstcorner + 2); else if (lastcorner + 2 < MAXPOINTS && w.size() - lastcorner <= MAXPOINTS) - newf->w.resize(lastcorner + 2); + neww.resize(lastcorner + 2); else - newf->w.resize(MAXPOINTS); + neww.resize(MAXPOINTS); - for (i = 0; i < newf->w.size(); i++) - newf->w[i] = w[i]; - for (i = newf->w.size() - 1; i < w.size(); i++) - w[i - (newf->w.size() - 2)] = w[i]; + for (i = 0; i < neww.size(); i++) + Q_assert(qv::equalExact(neww[i], w[i])); + for (i = neww.size() - 1; i < w.size(); i++) + w[i - (neww.size() - 2)] = w[i]; - w.resize(w.size() - (newf->w.size() - 2)); + w.resize(w.size() - (neww.size() - 2)); + + face->fragments.emplace_front(face_fragment_t { std::move(neww) }); } while (1); } @@ -328,14 +319,14 @@ FixFaceEdges =============== */ -static void FixFaceEdges(face_t *face, face_t *superface, face_t **facelist) +static void FixFaceEdges(face_t *face, face_t *superface) { int i, j; wedge_t *edge; wvert_t *v; vec_t t1, t2; - *superface = *face; + *superface = std::move(*face); restart: for (i = 0; i < superface->w.size(); i++) { @@ -366,14 +357,12 @@ restart: } if (superface->w.size() <= MAXPOINTS) { - *face = *superface; - face->next = *facelist; - *facelist = face; + *face = std::move(*superface); return; } /* Too many edges - needs to be split into multiple faces */ - SplitFaceForTjunc(superface, face, facelist); + SplitFaceForTjunc(superface, face); } //============================================================================ @@ -408,19 +397,19 @@ static void tjunc_find_r(node_t *node) static void tjunc_fix_r(node_t *node, face_t *superface) { - face_t *face, *next, *facelist; - if (node->planenum == PLANENUM_LEAF) return; - facelist = NULL; - - for (face = node->faces; face; face = next) { + face_t *root = nullptr, *next; + + for (face_t *face = node->faces; face; face = next) { next = face->next; - FixFaceEdges(face, superface, &facelist); + FixFaceEdges(face, superface); + face->next = root; + root = face; } - node->faces = facelist; + node->faces = root; tjunc_fix_r(node->children[0], superface); tjunc_fix_r(node->children[1], superface); diff --git a/qbsp/writebsp.cc b/qbsp/writebsp.cc index 7232f309..dd61d83c 100644 --- a/qbsp/writebsp.cc +++ b/qbsp/writebsp.cc @@ -193,10 +193,12 @@ static void ExportLeaf(mapentity_t *entity, node_t *node) continue; /* emit a marksurface */ - do { - map.bsp.dleaffaces.push_back(face->outputnumber.value()); - face = face->original; /* grab tjunction split faces */ - } while (face); + map.bsp.dleaffaces.push_back(face->outputnumber.value()); + + /* grab tjunction split faces */ + for (auto &fragment : face->fragments) { + map.bsp.dleaffaces.push_back(fragment.outputnumber.value()); + } } dleaf.nummarksurfaces = static_cast(map.bsp.dleaffaces.size()) - dleaf.firstmarksurface;