qbsp: use unique_ptr for portal_t

This commit is contained in:
Eric Wasylishen 2022-07-03 22:45:25 -06:00
parent de68bee886
commit 4ab4cb7dc8
8 changed files with 69 additions and 62 deletions

View File

@ -28,7 +28,6 @@ class mapentity_t;
struct face_t;
std::list<face_t *> 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);

View File

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

View File

@ -27,14 +27,23 @@
#include <common/qvec.hh>
#include <memory>
#include <vector>
struct node_t;
struct portal_t;
struct tree_t
{
std::unique_ptr<node_t> 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<std::unique_ptr<portal_t>> 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);

View File

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

View File

@ -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();
}
/*
=========================================================

View File

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

View File

@ -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())) {

View File

@ -24,6 +24,18 @@
#include <common/vectorutils.hh>
#include <qbsp/qbsp.hh>
#include <qbsp/brush.hh>
#include <qbsp/portals.hh>
//============================================================================
portal_t *tree_t::create_portal()
{
auto *result = new portal_t{};
portals.push_back(std::unique_ptr<portal_t>(result));
return result;
}
//============================================================================