use custom type for two-sided things to simplify brain power (.front/.back is easier to process than [0]/[1])

This commit is contained in:
Jonathan 2022-01-23 00:26:58 -05:00
parent 5a2d522892
commit 5dd2deba8e
5 changed files with 57 additions and 31 deletions

View File

@ -1069,3 +1069,46 @@ std::vector<V> 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<typename T>
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); }
};

View File

@ -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<contentflags_t> contents;
twosided<int16_t> 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<size_t> outputplanenum; // only valid after WriteSurfacePlanes
aabb3d bounds;

View File

@ -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<int, face_t *>
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;
}

View File

@ -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;
}

View File

@ -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];