From 1d729ba573489e7f281e04afa178d50195889116 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 2 Aug 2022 14:55:38 -0400 Subject: [PATCH] side_t using planenums --- include/qbsp/brush.hh | 5 ++-- include/qbsp/map.hh | 13 ++++++++++ qbsp/brush.cc | 27 ++++++++++---------- qbsp/brushbsp.cc | 57 +++++++++++++++++++++++-------------------- qbsp/faces.cc | 4 +-- qbsp/map.cc | 3 ++- qbsp/outside.cc | 3 ++- qbsp/portals.cc | 4 +-- qbsp/qbsp.cc | 19 +++++---------- 9 files changed, 75 insertions(+), 60 deletions(-) diff --git a/include/qbsp/brush.hh b/include/qbsp/brush.hh index d8e680eb..15bd759c 100644 --- a/include/qbsp/brush.hh +++ b/include/qbsp/brush.hh @@ -33,8 +33,7 @@ struct maptexinfo_t; struct side_t { winding_t w; - qbsp_plane_t plane; - bool plane_flipped; // whether `plane` is flipped or not + size_t planenum; int texinfo; int16_t lmshift; @@ -48,6 +47,8 @@ struct side_t bool tested; const maptexinfo_t &get_texinfo() const; + const qbsp_plane_t &get_plane() const; + const qbsp_plane_t &get_positive_plane() const; }; class mapbrush_t; diff --git a/include/qbsp/map.hh b/include/qbsp/map.hh index 4edf2f0f..46b6d674 100644 --- a/include/qbsp/map.hh +++ b/include/qbsp/map.hh @@ -163,6 +163,19 @@ struct mapdata_t return planes.size() - 2; } + + // find the specified plane in the list if it exists. throws + // if not. + inline size_t find_plane(const qplane3d &plane) + { + for (size_t i = 0; i < planes.size(); i++) { + if (qv::epsilonEqual(planes[i], plane)) { + return i; + } + } + + throw std::bad_function_call(); + } // find the specified plane in the list if it exists, or // return a new one diff --git a/qbsp/brush.cc b/qbsp/brush.cc index 75f02b03..34716e7e 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -38,6 +38,16 @@ const maptexinfo_t &side_t::get_texinfo() const return map.mtexinfos[this->texinfo]; } +const qbsp_plane_t &side_t::get_plane() const +{ + return map.get_plane(planenum); +} + +const qbsp_plane_t &side_t::get_positive_plane() const +{ + return map.get_plane(planenum & ~1); +} + std::unique_ptr bspbrush_t::copy_unique() const { return std::make_unique(*this); @@ -80,11 +90,7 @@ qplane3d Face_Plane(const face_t *face) qplane3d Face_Plane(const side_t *face) { - if (face->plane_flipped) { - return -face->plane; - } - - return face->plane; + return face->get_plane(); } /* @@ -96,8 +102,6 @@ Note: this will not catch 0 area polygons */ static void CheckFace(side_t *face, const mapface_t &sourceface) { - const qplane3d &plane = face->plane; - if (face->w.size() < 3) { if (face->w.size() == 2) { logging::print( @@ -112,11 +116,8 @@ static void CheckFace(side_t *face, const mapface_t &sourceface) return; } - qvec3d facenormal = plane.normal; - - if (face->plane_flipped) { - facenormal = -facenormal; - } + const qbsp_plane_t &plane = face->get_plane(); + qvec3d facenormal = plane.get_normal(); for (size_t i = 0; i < face->w.size(); i++) { const qvec3d &p1 = face->w[i]; @@ -326,7 +327,7 @@ static std::vector CreateBrushFaces(const mapentity_t *src, hullbrush_t plane.dist = qv::dot(plane.normal, point); f.texinfo = hullnum > 0 ? 0 : mapface.texinfo; - f.plane_flipped = f.plane.set_plane(plane, true); + f.planenum = map.add_or_find_plane(plane); CheckFace(&f, mapface); } diff --git a/qbsp/brushbsp.cc b/qbsp/brushbsp.cc index 2b6dead5..78b81612 100644 --- a/qbsp/brushbsp.cc +++ b/qbsp/brushbsp.cc @@ -116,7 +116,7 @@ std::unique_ptr BrushFromBounds(const aabb3d &bounds) plane.dist = bounds.maxs()[i]; side_t &side = b->sides[i]; - side.plane_flipped = side.plane.set_plane(plane, true); + side.planenum = map.add_or_find_plane(plane); } { @@ -125,7 +125,7 @@ std::unique_ptr BrushFromBounds(const aabb3d &bounds) plane.dist = -bounds.mins()[i]; side_t &side = b->sides[3 + i]; - side.plane_flipped = side.plane.set_plane(plane, true); + side.planenum = map.add_or_find_plane(plane); } } @@ -274,7 +274,7 @@ TestBrushToPlanenum ============ */ static int TestBrushToPlanenum( - const bspbrush_t &brush, const qbsp_plane_t &plane, int *numsplits, bool *hintsplit, int *epsilonbrush) + const bspbrush_t &brush, size_t planenum, int *numsplits, bool *hintsplit, int *epsilonbrush) { if (numsplits) { *numsplits = 0; @@ -286,17 +286,16 @@ static int TestBrushToPlanenum( // if the brush actually uses the planenum, // we can tell the side for sure for (auto &side : brush.sides) { - if (qv::epsilonEqual(side.plane, plane)) { - if (side.plane_flipped == SIDE_FRONT) { - return PSIDE_BACK | PSIDE_FACING; - } else { - return PSIDE_FRONT | PSIDE_FACING; - } + if (side.planenum == planenum) { + return PSIDE_BACK | PSIDE_FACING; + } else if (side.planenum == (planenum ^ 1)) { + return PSIDE_FRONT|PSIDE_FACING; } } // box on plane side // int s = SphereOnPlaneSide(brush.sphere_origin, brush.sphere_radius, plane); + const qbsp_plane_t &plane = map.get_plane(planenum); int s = BoxOnPlaneSide(brush.bounds, plane); if (s != PSIDE_BOTH) return s; @@ -589,7 +588,7 @@ static twosided> SplitBrush(std::unique_ptr ChooseMidPlaneFromList(const std::vector> &brushes, const node_t *node) +static std::optional ChooseMidPlaneFromList(const std::vector> &brushes, const node_t *node) { vec_t bestaxialmetric = VECT_MAX; - std::optional bestaxialplane; + std::optional bestaxialplane; vec_t bestanymetric = VECT_MAX; - std::optional bestanyplane; + std::optional bestanyplane; for (auto &brush : brushes) { for (auto &side : brush->sides) { @@ -729,7 +728,7 @@ static std::optional ChooseMidPlaneFromList(const std::vector ChooseMidPlaneFromList(const std::vector SelectSplitPlane(const std::vector> &brushes, node_t *node, std::optional forced_quick_tree, bspstats_t &stats) +static std::optional SelectSplitPlane(const std::vector> &brushes, node_t *node, std::optional forced_quick_tree, bspstats_t &stats) { // no brushes left to split, so we can't use any plane. if (!brushes.size()) { @@ -776,6 +775,7 @@ static std::optional SelectSplitPlane(const std::vector SelectSplitPlane(const std::vector SelectSplitPlane(const std::vector SelectSplitPlane(const std::vector SelectSplitPlane(const std::vectorsides) { - if (qv::epsilonEqual(testside.plane, plane)) { + if ((testside.planenum & ~1) == (side.planenum & ~1)) { testside.tested = true; } } @@ -966,7 +967,7 @@ static std::optional SelectSplitPlane(const std::vectorplane; + return bestside->planenum & ~1; } /* @@ -1001,7 +1002,7 @@ static std::array>, 2> SplitBrushList( // as a splitter again if (sides & PSIDE_FACING) { for (auto &side : brush->sides) { - if (qv::epsilonEqual(side.plane, plane)) { + if (qv::epsilonEqual(side.get_positive_plane(), plane)) { side.onnode = true; } } @@ -1045,7 +1046,11 @@ static void BuildTree_r(node_t *node, std::vector> b // this is a splitplane node stats.c_nodes++; - node->plane.set_plane(bestplane.value(), true); // always use front facing + // make sure this was a positive-facing split + Q_assert(!(bestplane.value() & 1)); + + auto &plane = map.get_plane(bestplane.value()); + node->plane.set_plane(plane); auto children = SplitBrushList(std::move(brushes), node->plane); @@ -1057,9 +1062,9 @@ static void BuildTree_r(node_t *node, std::vector> b } for (int i = 0; i < 3; i++) { - if (bestplane->get_normal()[i] == 1.0) { - node->children[0]->bounds[0][i] = bestplane->get_dist(); - node->children[1]->bounds[1][i] = bestplane->get_dist(); + if (plane.get_normal()[i] == 1.0) { + node->children[0]->bounds[0][i] = plane.get_dist(); + node->children[1]->bounds[1][i] = plane.get_dist(); break; } } diff --git a/qbsp/faces.cc b/qbsp/faces.cc index a3a83243..1a0bfe64 100644 --- a/qbsp/faces.cc +++ b/qbsp/faces.cc @@ -479,8 +479,8 @@ static std::unique_ptr FaceFromPortal(portal_t *p, bool pside) auto f = std::make_unique(); f->texinfo = side->texinfo; - f->plane = side->plane; - f->plane_flipped = pside; + f->plane = side->get_positive_plane(); + f->plane_flipped = side->planenum & 1; f->portal = p; f->lmshift = side->lmshift; diff --git a/qbsp/map.cc b/qbsp/map.cc index f1a93d25..4c09de52 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -2095,6 +2095,7 @@ void LoadMapFile(void) logging::print(logging::flag::STAT, " {:8} entities\n", map.entities.size()); logging::print(logging::flag::STAT, " {:8} unique texnames\n", map.miptex.size()); logging::print(logging::flag::STAT, " {:8} texinfo\n", map.mtexinfos.size()); + logging::print(logging::flag::STAT, " {:8} unique planes\n", map.planes.size()); logging::print(logging::flag::STAT, "\n"); if (qbsp_options.expand.value()) { @@ -2443,7 +2444,7 @@ void WriteBspBrushMap(const fs::path &name, const std::vectorsides) { // FIXME: Factor out this mess - winding_t w = BaseWindingForPlane(face.plane_flipped ? -face.plane : face.plane); + winding_t w = BaseWindingForPlane(face.get_plane()); fmt::print(f, "( {} ) ", w[0]); fmt::print(f, "( {} ) ", w[1]); diff --git a/qbsp/outside.cc b/qbsp/outside.cc index 00b73fc4..a3289021 100644 --- a/qbsp/outside.cc +++ b/qbsp/outside.cc @@ -411,7 +411,8 @@ static void MarkVisibleBrushSides_R(node_t *node) // leaf that are coplanar for (auto *brush : neighbour_leaf->original_brushes) { for (auto &side : brush->sides) { - if (qv::epsilonEqual(side.plane, portal->plane)) { + //if (qv::epsilonEqual(side.plane, portal->plane)) { + if (qv::epsilonEqual(side.get_positive_plane(), portal->plane)) { // we've found a brush side in an original brush in the neighbouring // leaf, on a portal to this (non-opaque) leaf, so mark it as visible. side.visible = true; diff --git a/qbsp/portals.cc b/qbsp/portals.cc index 35ceafdb..25ffd280 100644 --- a/qbsp/portals.cc +++ b/qbsp/portals.cc @@ -816,11 +816,11 @@ static void FindPortalSide(portal_t *p) // fixme-brushbsp: restore // if (!side.visible) // continue; // non-visible - if (qv::epsilonEqual(side.plane, p1)) { + if (qv::epsilonEqual(side.get_positive_plane(), p1)) { // exact match (undirectional) // because the brush is on j of the positive plane, the brushside must be facing away from j - Q_assert(side.plane_flipped == !j); + Q_assert((side.planenum & 1) == !j); // see which way(s) we want to generate faces - we could be a brush on either side of // the portal, generating either a outward face (common case) or an inward face (liquids) or both. diff --git a/qbsp/qbsp.cc b/qbsp/qbsp.cc index efbed9f3..f274abd2 100644 --- a/qbsp/qbsp.cc +++ b/qbsp/qbsp.cc @@ -316,7 +316,7 @@ static std::vector> AddBrushBevels(const bspb std::vector> planes; for (auto &f : b.sides) { - qplane3d plane = f.plane_flipped ? -f.plane : f.plane; + const qplane3d &plane = f.get_plane(); int32_t outputplanenum = ExportMapPlane(plane); planes.emplace_back(outputplanenum, &f); } @@ -398,7 +398,7 @@ static std::vector> AddBrushBevels(const bspb // behind this plane, it is a proper edge bevel for (; it != b.sides.end(); it++) { auto &f = *it; - qplane3d plane = f.plane_flipped ? -f.plane : f.plane; + const qplane3d &plane = f.get_plane(); // if this plane has allready been used, skip it if (qv::epsilonEqual(current, plane)) @@ -776,7 +776,7 @@ static void BSPX_Brushes_AddModel( permodel.numbrushes++; for (auto &f : b->sides) { /*skip axial*/ - const auto &plane = f.plane; + const auto &plane = f.get_plane(); if (plane.get_type() < plane_type_t::PLANE_ANYX) continue; permodel.numfaces++; @@ -794,7 +794,7 @@ static void BSPX_Brushes_AddModel( for (auto &f : b->sides) { /*skip axial*/ - const auto &plane = f.plane; + const auto &plane = f.get_plane(); if (plane.get_type() < plane_type_t::PLANE_ANYX) continue; perbrush.numfaces++; @@ -835,18 +835,11 @@ static void BSPX_Brushes_AddModel( for (auto &f : b->sides) { /*skip axial*/ - const auto &plane = f.plane; + const auto &plane = f.get_plane(); if (plane.get_type() < plane_type_t::PLANE_ANYX) continue; - bspxbrushes_perface perface; - - if (f.plane_flipped) { - perface = -plane.get_plane(); - } else { - perface = plane.get_plane(); - } - + bspxbrushes_perface perface = qplane3f(plane.get_normal(), plane.get_dist()); str <= std::tie(perface.normal, perface.dist); } }