From 4ab4cb7dc81e6c698c19c392772fee80b91f5146 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 3 Jul 2022 22:45:25 -0600 Subject: [PATCH] qbsp: use unique_ptr for portal_t --- include/qbsp/faces.hh | 1 - include/qbsp/portals.hh | 8 ++--- include/qbsp/tree.hh | 9 ++++++ qbsp/faces.cc | 18 ------------ qbsp/portals.cc | 65 ++++++++++++++++++++++------------------- qbsp/prtfile.cc | 16 +++++----- qbsp/qbsp.cc | 2 +- qbsp/tree.cc | 12 ++++++++ 8 files changed, 69 insertions(+), 62 deletions(-) diff --git a/include/qbsp/faces.hh b/include/qbsp/faces.hh index 0b0444ca..cc893256 100644 --- a/include/qbsp/faces.hh +++ b/include/qbsp/faces.hh @@ -28,7 +28,6 @@ class mapentity_t; struct face_t; std::list SubdivideFace(face_t *f); -void FreeNodes(node_t *node); void MakeVisibleFaces(mapentity_t *entity, node_t *headnode); void MakeMarkFaces(mapentity_t* entity, node_t* headnode); void MakeFaces(node_t *node); diff --git a/include/qbsp/portals.hh b/include/qbsp/portals.hh index 7de46844..f7eee628 100644 --- a/include/qbsp/portals.hh +++ b/include/qbsp/portals.hh @@ -51,11 +51,11 @@ struct portalstats_t { contentflags_t ClusterContents(const node_t *node); bool Portal_VisFlood(const portal_t *p); bool Portal_EntityFlood(const portal_t *p, int32_t s); -void MakeNodePortal(node_t *node, portalstats_t &stats); -void SplitNodePortals(node_t *node, portalstats_t &stats); +void MakeNodePortal(tree_t *tree, node_t *node, portalstats_t &stats); +void SplitNodePortals(tree_t *tree, node_t *node, portalstats_t &stats); void MakeTreePortals(tree_t *tree); -void FreeTreePortals_r(node_t *node); -void AssertNoPortals(node_t *node); +void FreeTreePortals(tree_t *tree); +void AssertNoPortals(tree_t *tree); void MakeHeadnodePortals(tree_t *tree); void EmitAreaPortals(node_t *headnode); void FloodAreas(mapentity_t *entity, node_t *headnode); diff --git a/include/qbsp/tree.hh b/include/qbsp/tree.hh index fb4fc093..e97a9f82 100644 --- a/include/qbsp/tree.hh +++ b/include/qbsp/tree.hh @@ -27,14 +27,23 @@ #include #include +#include struct node_t; +struct portal_t; struct tree_t { std::unique_ptr headnode; node_t outside_node = {}; // portals outside the world face this aabb3d bounds; + + // here for ownership/memory management - not intended to be iterated directly + std::vector> portals; + + // creates a new portal owned by `this` (stored in the `portals` vector) and + // returns a raw pointer to it + portal_t *create_portal(); }; void DetailToSolid(node_t *node); diff --git a/qbsp/faces.cc b/qbsp/faces.cc index 90728dc0..68b7baec 100644 --- a/qbsp/faces.cc +++ b/qbsp/faces.cc @@ -173,24 +173,6 @@ static void SubdivideNodeFaces(node_t *node) node->facelist = result; } -static void FreeNode(node_t *node) -{ - FreeTreePortals_r(node); - for (face_t *f : node->facelist) { - delete f; - } - delete node; -} - -void FreeNodes(node_t *node) -{ - if (node->planenum != PLANENUM_LEAF) { - FreeNodes(node->children[0].get()); - FreeNodes(node->children[1].get()); - } - FreeNode(node); -} - //=========================================================================== // This is a kludge. Should be pEdgeFaces[2]. diff --git a/qbsp/portals.cc b/qbsp/portals.cc index be2f4a7d..7b70daee 100644 --- a/qbsp/portals.cc +++ b/qbsp/portals.cc @@ -178,7 +178,7 @@ void MakeHeadnodePortals(tree_t *tree) for (j = 0; j < 2; j++) { n = j * 3 + i; - p = new portal_t{}; + p = tree->create_portal(); portals[n] = p; qplane3d &pl = bplanes[n] = {}; @@ -254,7 +254,7 @@ and clipping it by all of parents of this node, as well as all the other portals in the node. ================== */ -void MakeNodePortal(node_t *node, portalstats_t &stats) +void MakeNodePortal(tree_t *tree, node_t *node, portalstats_t &stats) { const auto lock = std::lock_guard(map_planes_lock); @@ -291,7 +291,7 @@ void MakeNodePortal(node_t *node, portalstats_t &stats) return; } - auto *new_portal = new portal_t{}; + portal_t *new_portal = tree->create_portal(); new_portal->planenum = node->planenum; new_portal->onnode = node; new_portal->winding = w; @@ -306,7 +306,7 @@ Move or split the portals that bound node so that the node's children have portals instead of node. ============== */ -void SplitNodePortals(node_t *node, portalstats_t &stats) +void SplitNodePortals(tree_t *tree, node_t *node, portalstats_t &stats) { const auto lock = std::lock_guard(map_planes_lock); @@ -370,7 +370,8 @@ void SplitNodePortals(node_t *node, portalstats_t &stats) } // the winding is split - auto *new_portal = new portal_t{*p}; + portal_t *new_portal = tree->create_portal(); + *new_portal = *p; new_portal->winding = backwinding; p->winding = frontwinding; @@ -413,7 +414,7 @@ void CalcNodeBounds(node_t *node) MakeTreePortals_r ================== */ -void MakeTreePortals_r(node_t *node, portalstats_t &stats) +void MakeTreePortals_r(tree_t *tree, node_t *node, portalstats_t &stats) { CalcNodeBounds(node); if (node->bounds.mins()[0] >= node->bounds.maxs()[0]) @@ -436,11 +437,11 @@ void MakeTreePortals_r(node_t *node, portalstats_t &stats) if (node->planenum == PLANENUM_LEAF) return; - MakeNodePortal(node, stats); - SplitNodePortals(node, stats); + MakeNodePortal(tree, node, stats); + SplitNodePortals(tree, node, stats); - MakeTreePortals_r(node->children[0].get(), stats); - MakeTreePortals_r(node->children[1].get(), stats); + MakeTreePortals_r(tree, node->children[0].get(), stats); + MakeTreePortals_r(tree, node->children[1].get(), stats); } /* @@ -450,53 +451,57 @@ MakeTreePortals */ void MakeTreePortals(tree_t *tree) { - FreeTreePortals_r(tree->headnode.get()); + FreeTreePortals(tree); - AssertNoPortals(tree->headnode.get()); + AssertNoPortals(tree); portalstats_t stats{}; MakeHeadnodePortals(tree); - MakeTreePortals_r(tree->headnode.get(), stats); + MakeTreePortals_r(tree, tree->headnode.get(), stats); } -void AssertNoPortals(node_t *node) +static void AssertNoPortals_r(node_t *node) { Q_assert(!node->portals); if (node->planenum != PLANENUM_LEAF) { - AssertNoPortals(node->children[0].get()); - AssertNoPortals(node->children[1].get()); + AssertNoPortals_r(node->children[0].get()); + AssertNoPortals_r(node->children[1].get()); } } +void AssertNoPortals(tree_t *tree) +{ + AssertNoPortals_r(tree->headnode.get()); + Q_assert(!tree->outside_node.portals); + Q_assert(tree->portals.empty()); +} + /* ================== FreeTreePortals_r ================== */ -void FreeTreePortals_r(node_t *node) +static void ClearNodePortals_r(node_t *node) { - portal_t *p, *nextp; - if (node->planenum != PLANENUM_LEAF) { - FreeTreePortals_r(node->children[0].get()); - FreeTreePortals_r(node->children[1].get()); + ClearNodePortals_r(node->children[0].get()); + ClearNodePortals_r(node->children[1].get()); } - for (p = node->portals; p; p = nextp) { - if (p->nodes[0] == node) - nextp = p->next[0]; - else - nextp = p->next[1]; - RemovePortalFromNode(p, p->nodes[0]); - RemovePortalFromNode(p, p->nodes[1]); - delete p; - } node->portals = nullptr; } +void FreeTreePortals(tree_t *tree) +{ + ClearNodePortals_r(tree->headnode.get()); + tree->outside_node.portals = nullptr; + + tree->portals.clear(); +} + /* ========================================================= diff --git a/qbsp/prtfile.cc b/qbsp/prtfile.cc index 70b018a2..80dbdb44 100644 --- a/qbsp/prtfile.cc +++ b/qbsp/prtfile.cc @@ -257,18 +257,18 @@ static void WritePortalfile(node_t *headnode, portal_state_t *state) CreateVisPortals_r ================ */ -void CreateVisPortals_r(node_t *node, portalstats_t &stats) +void CreateVisPortals_r(tree_t *tree, node_t *node, portalstats_t &stats) { // stop as soon as we get to a detail_seperator, which // means that everything below is in a single cluster if (node->planenum == PLANENUM_LEAF || node->detail_separator ) return; - MakeNodePortal(node, stats); - SplitNodePortals(node, stats); + MakeNodePortal(tree, node, stats); + SplitNodePortals(tree, node, stats); - CreateVisPortals_r(node->children[0].get(), stats); - CreateVisPortals_r(node->children[1].get(), stats); + CreateVisPortals_r(tree, node->children[0].get(), stats); + CreateVisPortals_r(tree, node->children[1].get(), stats); } /* @@ -282,13 +282,13 @@ void WritePortalFile(tree_t *tree) portal_state_t state{}; - FreeTreePortals_r(tree->headnode.get()); + FreeTreePortals(tree); - AssertNoPortals(tree->headnode.get()); + AssertNoPortals(tree); MakeHeadnodePortals(tree); portalstats_t stats{}; - CreateVisPortals_r(tree->headnode.get(), stats); + CreateVisPortals_r(tree, tree->headnode.get(), stats); /* save portal file for vis tracing */ WritePortalfile(tree->headnode.get(), &state); diff --git a/qbsp/qbsp.cc b/qbsp/qbsp.cc index 5fd6d50d..67138105 100644 --- a/qbsp/qbsp.cc +++ b/qbsp/qbsp.cc @@ -646,7 +646,7 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum) MarkVisibleSides(tree, entity); MakeFaces(tree->headnode.get()); - FreeTreePortals_r(tree->headnode.get()); + FreeTreePortals(tree); PruneNodes(tree->headnode.get()); if (hullnum <= 0 && entity == map.world_entity() && (!map.leakfile || options.keepprt.value())) { diff --git a/qbsp/tree.cc b/qbsp/tree.cc index ffa27eb5..4b07933e 100644 --- a/qbsp/tree.cc +++ b/qbsp/tree.cc @@ -24,6 +24,18 @@ #include #include #include +#include + +//============================================================================ + +portal_t *tree_t::create_portal() +{ + auto *result = new portal_t{}; + + portals.push_back(std::unique_ptr(result)); + + return result; +} //============================================================================