diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index 935d2c5b..65d0f004 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -630,7 +630,10 @@ struct node_t bool is_leaf = false; // information for decision nodes - qbsp_plane_t plane; // decision node only + size_t planenum; // decision node only + + const qbsp_plane_t &get_plane() const; + int firstface; // decision node only int numfaces; // decision node only twosided> diff --git a/qbsp/brushbsp.cc b/qbsp/brushbsp.cc index e68fe3a6..f52ceee1 100644 --- a/qbsp/brushbsp.cc +++ b/qbsp/brushbsp.cc @@ -621,10 +621,10 @@ static twosided> SplitBrush(std::unique_ptrparent; p; p = p->parent) { - if (qv::epsilonEqual(p->plane, plane)) { + if (p->planenum == planenum) { Error("Tried parent"); } } @@ -875,9 +875,10 @@ static std::optional SelectSplitPlane(const std::vector SelectSplitPlane(const std::vector> b // make sure this was a positive-facing split Q_assert(!(bestplane.value() & 1)); + node->planenum = bestplane.value(); + auto &plane = map.get_plane(bestplane.value()); - node->plane.set_plane(plane); - - auto children = SplitBrushList(std::move(brushes), node->plane, stats); + auto children = SplitBrushList(std::move(brushes), plane, stats); // allocate children before recursing for (int i = 0; i < 2; i++) { @@ -1074,7 +1075,7 @@ static void BuildTree_r(node_t *node, std::vector> b } } - auto children_volumes = SplitBrush(node->volume->copy_unique(), node->plane, stats); + auto children_volumes = SplitBrush(node->volume->copy_unique(), plane, stats); node->children[0]->volume = std::move(children_volumes[0]); node->children[1]->volume = std::move(children_volumes[1]); @@ -1135,9 +1136,9 @@ static std::unique_ptr BrushBSP(mapentity_t *entity, std::vector(); headnode->bounds = entity->bounds; - // The choice of plane is mostly unimportant, but having it at (0, 0, 0) was affecting - // the node bounds calculation. So to be safe, put the plane on the top of the entity bounding box. - headnode->plane = {{0, 0, 1}, headnode->bounds.maxs()[2]}; + // The choice of plane is mostly unimportant, but having it at (0, 0, 0) affects + // the node bounds calculation. + headnode->planenum = 0; headnode->children[0] = std::make_unique(); headnode->children[0]->is_leaf = true; headnode->children[0]->contents = qbsp_options.target_game->create_empty_contents(); diff --git a/qbsp/faces.cc b/qbsp/faces.cc index 7c33f848..a65d1058 100644 --- a/qbsp/faces.cc +++ b/qbsp/faces.cc @@ -295,7 +295,7 @@ static void AddMarksurfaces_r(face_t *face, std::unique_ptr face_copy, n return; } - const qplane3d &splitplane = node->plane; + const qplane3d &splitplane = node->get_plane(); auto [frontFragment, backFragment] = SplitFace(std::move(face_copy), splitplane); if (frontFragment) { @@ -479,7 +479,7 @@ static std::unique_ptr FaceFromPortal(portal_t *p, bool pside) auto f = std::make_unique(); f->texinfo = side->texinfo; - f->planenum = (side->planenum & ~1) | pside; + f->planenum = (side->planenum & ~1) | (pside ? 1 : 0); f->portal = p; f->lmshift = side->lmshift; diff --git a/qbsp/outside.cc b/qbsp/outside.cc index a3289021..51fa5512 100644 --- a/qbsp/outside.cc +++ b/qbsp/outside.cc @@ -59,7 +59,7 @@ static node_t *PointInLeaf(node_t *node, const qvec3d &point) return node; } - vec_t dist = node->plane.distance_to(point); + vec_t dist = node->get_plane().distance_to(point); if (dist > 0) { // point is on the front of the node plane diff --git a/qbsp/portals.cc b/qbsp/portals.cc index f3da675d..82d8dd38 100644 --- a/qbsp/portals.cc +++ b/qbsp/portals.cc @@ -197,13 +197,13 @@ constexpr vec_t SPLIT_WINDING_EPSILON = 0.001; static std::optional BaseWindingForNode(const node_t *node) { - std::optional w = BaseWindingForPlane(node->plane); + std::optional w = BaseWindingForPlane(node->get_plane()); // clip by all the parents for (auto *np = node->parent; np && w;) { const planeside_t keep = (np->children[0].get() == node) ? SIDE_FRONT : SIDE_BACK; - w = w->clip(np->plane, BASE_WINDING_EPSILON, false)[keep]; + w = w->clip(np->get_plane(), BASE_WINDING_EPSILON, false)[keep]; node = np; np = np->parent; @@ -250,7 +250,7 @@ std::unique_ptr MakeNodePortal(node_t *node, const std::list(); - new_portal->plane = node->plane; + new_portal->plane = node->get_plane(); new_portal->onnode = node; new_portal->winding = std::make_unique(*w); new_portal->set_nodes(node->children[0].get(), node->children[1].get()); @@ -268,7 +268,7 @@ children have portals instead of node. */ twosided>> SplitNodePortals(const node_t *node, std::list> boundary_portals, portalstats_t &stats) { - const auto &plane = node->plane; + const auto &plane = node->get_plane(); node_t *f = node->children[0].get(); node_t *b = node->children[1].get(); @@ -791,7 +791,7 @@ static void FindPortalSide(portal_t *p) // bestside[0] is the brushside visible on portal side[0] which is the positive side of the plane, always side_t *bestside[2] = {nullptr, nullptr}; float bestdot = 0; - const qbsp_plane_t &p1 = p->onnode->plane; + const qbsp_plane_t &p1 = p->onnode->get_plane(); // check brushes on both sides of the portal for (int j = 0; j < 2; j++) { @@ -816,7 +816,7 @@ static void FindPortalSide(portal_t *p) // fixme-brushbsp: restore // if (!side.visible) // continue; // non-visible - if (qv::epsilonEqual(side.get_positive_plane(), p1)) { + if ((side.planenum & ~1) == p->onnode->planenum) { // exact match (undirectional) // because the brush is on j of the positive plane, the brushside must be facing away from j diff --git a/qbsp/qbsp.cc b/qbsp/qbsp.cc index 11c2fa87..b134a94b 100644 --- a/qbsp/qbsp.cc +++ b/qbsp/qbsp.cc @@ -56,6 +56,11 @@ const qbsp_plane_t &face_t::get_positive_plane() const return map.get_plane(planenum & ~1); } +const qbsp_plane_t &node_t::get_plane() const +{ + return map.get_plane(planenum); +} + // command line flags namespace settings { diff --git a/qbsp/writebsp.cc b/qbsp/writebsp.cc index c6705d31..f1a3984b 100644 --- a/qbsp/writebsp.cc +++ b/qbsp/writebsp.cc @@ -153,7 +153,7 @@ static size_t ExportClipNodes(node_t *node) // Careful not to modify the vector while using this clipnode pointer bsp2_dclipnode_t &clipnode = map.bsp.dclipnodes[nodenum]; - clipnode.planenum = ExportMapPlane(node->plane); + clipnode.planenum = ExportMapPlane(node->get_plane()); clipnode.children[0] = child0; clipnode.children[1] = child1; @@ -249,7 +249,7 @@ static void ExportDrawNodes(node_t *node) dnode->mins = qv::floor(node->bounds.mins()); dnode->maxs = qv::ceil(node->bounds.maxs()); - dnode->planenum = ExportMapPlane(node->plane); + dnode->planenum = ExportMapPlane(node->get_plane()); dnode->firstface = node->firstface; dnode->numfaces = node->numfaces;