diff --git a/include/common/qvec.hh b/include/common/qvec.hh index 7066b02c..393f1de7 100644 --- a/include/common/qvec.hh +++ b/include/common/qvec.hh @@ -1069,3 +1069,46 @@ std::vector PointsAlongLine(const V &start, const V &end, const float step) bool LinesOverlap(const qvec3f &p0, const qvec3f &p1, const qvec3f &q0, const qvec3f &q1, const vec_t &on_epsilon = DEFAULT_ON_EPSILON); + +template +struct twosided +{ + T front, back; + + // 0 is front, 1 is back + constexpr T &operator[](const int32_t &i) + { + switch (i) + { + case 0: return front; + case 1: return back; + } + + throw std::exception(); + } + // 0 is front, 1 is back + constexpr const T &operator[](const int32_t &i) const + { + switch (i) + { + case 0: return front; + case 1: return back; + } + + throw std::exception(); + } + + // iterator support + T *begin() { return &front; } + T *end() { return (&back) + 1; } + + const T *begin() const { return &front; } + const T *end() const { return (&back) + 1; } + + // swap the front and back values + constexpr void swap() { std::swap(front, back); } + + // equality checks + constexpr bool operator==(const twosided &other) const { return front == other.front && back == other.back; } + constexpr bool operator!=(const twosided &other) const { return !(*this == other); } +}; \ No newline at end of file diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index eab83fdd..f3034332 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -129,8 +129,8 @@ struct face_t int planenum; int planeside; // which side is the front of the face int texinfo; - contentflags_t contents[2]; // 0 = front side - short lmshift[2]; // lightmap scale. + twosided contents; + twosided lmshift; mapentity_t *src_entity; // source entity face_t *original; // face on node @@ -147,7 +147,6 @@ struct face_t struct surface_t { surface_t *next; - surface_t *original; // before BSP cuts it up int planenum; std::optional outputplanenum; // only valid after WriteSurfacePlanes aabb3d bounds; diff --git a/qbsp/csg4.cc b/qbsp/csg4.cc index f4a3ae83..b9957594 100644 --- a/qbsp/csg4.cc +++ b/qbsp/csg4.cc @@ -77,10 +77,8 @@ face_t *NewFaceFromFace(face_t *in) newf->texinfo = in->texinfo; newf->planeside = in->planeside; newf->original = in->original; - newf->contents[0] = in->contents[0]; - newf->contents[1] = in->contents[1]; - newf->lmshift[0] = in->lmshift[0]; - newf->lmshift[1] = in->lmshift[1]; + newf->contents = in->contents; + newf->lmshift = in->lmshift; newf->src_entity = in->src_entity; newf->origin = in->origin; @@ -328,10 +326,8 @@ void SaveFacesToPlaneList(face_t *facelist, bool mirror, std::map face_t *newface = NewFaceFromFace(face); newface->w = face->w.flip(); newface->planeside = face->planeside ^ 1; - newface->contents[0] = face->contents[1]; - newface->contents[1] = face->contents[0]; - newface->lmshift[0] = face->lmshift[1]; - newface->lmshift[1] = face->lmshift[0]; + newface->contents.swap(); + newface->lmshift.swap(); // e.g. for a water volume: // the face facing the air: @@ -503,10 +499,8 @@ static face_t *CopyBrushFaces(const brush_t &brush) for (auto &face : brush.faces) { brushfaces++; newface = new face_t(face); - newface->contents[0] = options.target_game->create_empty_contents(); - newface->contents[1] = brush.contents; - newface->lmshift[0] = brush.lmshift; - newface->lmshift[1] = brush.lmshift; + newface->contents = { options.target_game->create_empty_contents(), brush.contents }; + newface->lmshift = { brush.lmshift, brush.lmshift }; newface->next = facelist; facelist = newface; } diff --git a/qbsp/merge.cc b/qbsp/merge.cc index 388003a7..58eb1aaf 100644 --- a/qbsp/merge.cc +++ b/qbsp/merge.cc @@ -65,8 +65,7 @@ static face_t *TryMerge(face_t *f1, face_t *f2) bool keep1, keep2; if (!f1->w.size() || !f2->w.size() || f1->planeside != f2->planeside || f1->texinfo != f2->texinfo || - f1->contents[0] != f2->contents[0] || f1->contents[1] != f2->contents[1] || f1->lmshift[0] != f2->lmshift[0] || - f1->lmshift[1] != f2->lmshift[1]) + f1->contents != f2->contents || f1->lmshift != f2->lmshift) return NULL; // find a common edge @@ -194,9 +193,9 @@ face_t *FreeMergeListScraps(face_t *merged) head = NULL; for (; merged; merged = next) { next = merged->next; - if (!merged->w.size()) + if (!merged->w.size()) { delete merged; - else { + } else { merged->next = head; head = merged; } diff --git a/qbsp/solidbsp.cc b/qbsp/solidbsp.cc index 5719071d..194cffe5 100644 --- a/qbsp/solidbsp.cc +++ b/qbsp/solidbsp.cc @@ -503,7 +503,6 @@ void CalcSurfaceInfo(surface_t *surf) // calculate a bounding box surf->bounds = {}; - surf->has_detail = false; surf->has_struct = false; for (const face_t *f = surf->faces; f; f = f->next) { @@ -511,18 +510,10 @@ void CalcSurfaceInfo(surface_t *surf) if (!contents.is_valid(options.target_game, false)) FError("Bad contents in face: {}", contents.to_string(options.target_game)); - surf->lmshift = (f->lmshift[0] < f->lmshift[1]) ? f->lmshift[0] : f->lmshift[1]; + surf->lmshift = min(f->lmshift.front, f->lmshift.back); - bool faceIsDetail = false; - - if ((f->contents[0].extended | f->contents[1].extended) & - (CFLAGS_DETAIL | CFLAGS_DETAIL_ILLUSIONARY | CFLAGS_DETAIL_FENCE | CFLAGS_WAS_ILLUSIONARY)) - faceIsDetail = true; - - if (faceIsDetail) - surf->has_detail = true; - else - surf->has_struct = true; + surf->has_struct = !((f->contents[0].extended | f->contents[1].extended) & + (CFLAGS_DETAIL | CFLAGS_DETAIL_ILLUSIONARY | CFLAGS_DETAIL_FENCE | CFLAGS_WAS_ILLUSIONARY)); for (int i = 0; i < f->w.size(); i++) { surf->bounds += f->w[i];