node_t planenum

This commit is contained in:
Jonathan 2022-08-02 16:04:48 -04:00
parent 46a643c3f0
commit a75f4239e3
7 changed files with 32 additions and 23 deletions

View File

@ -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<std::unique_ptr<node_t>>

View File

@ -621,10 +621,10 @@ static twosided<std::unique_ptr<bspbrush_t>> SplitBrush(std::unique_ptr<bspbrush
return result;
}
static void CheckPlaneAgainstParents(const qbsp_plane_t &plane, node_t *node)
inline void CheckPlaneAgainstParents(size_t planenum, node_t *node)
{
for (node_t *p = node->parent; p; p = p->parent) {
if (qv::epsilonEqual(p->plane, plane)) {
if (p->planenum == planenum) {
Error("Tried parent");
}
}
@ -875,9 +875,10 @@ static std::optional<size_t> SelectSplitPlane(const std::vector<std::unique_ptr<
if (side.visible ^ (pass < 2))
continue; // only check visible faces on first pass
size_t positive_planenum = side.planenum & ~1;
const qbsp_plane_t &plane = side.get_positive_plane(); // always use positive facing plane
CheckPlaneAgainstParents(plane, node);
CheckPlaneAgainstParents(positive_planenum, node);
if (!CheckPlaneAgainstVolume(plane, node, stats))
continue; // would produce a tiny volume
@ -892,7 +893,7 @@ static std::optional<size_t> SelectSplitPlane(const std::vector<std::unique_ptr<
for (auto &test : brushes) {
int bsplits;
int s = TestBrushToPlanenum(*test, side.planenum & ~1, &bsplits, &hintsplit, &epsilonbrush);
int s = TestBrushToPlanenum(*test, positive_planenum, &bsplits, &hintsplit, &epsilonbrush);
splits += bsplits;
if (bsplits && (s & PSIDE_FACING))
@ -1054,10 +1055,10 @@ static void BuildTree_r(node_t *node, std::vector<std::unique_ptr<bspbrush_t>> 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<std::unique_ptr<bspbrush_t>> 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<tree_t> BrushBSP(mapentity_t *entity, std::vector<std::un
*/
auto headnode = std::make_unique<node_t>();
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<node_t>();
headnode->children[0]->is_leaf = true;
headnode->children[0]->contents = qbsp_options.target_game->create_empty_contents();

View File

@ -295,7 +295,7 @@ static void AddMarksurfaces_r(face_t *face, std::unique_ptr<face_t> 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<face_t> FaceFromPortal(portal_t *p, bool pside)
auto f = std::make_unique<face_t>();
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;

View File

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

View File

@ -197,13 +197,13 @@ constexpr vec_t SPLIT_WINDING_EPSILON = 0.001;
static std::optional<winding_t> BaseWindingForNode(const node_t *node)
{
std::optional<winding_t> w = BaseWindingForPlane(node->plane);
std::optional<winding_t> 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<buildportal_t> MakeNodePortal(node_t *node, const std::list<std:
}
auto new_portal = std::make_unique<buildportal_t>();
new_portal->plane = node->plane;
new_portal->plane = node->get_plane();
new_portal->onnode = node;
new_portal->winding = std::make_unique<winding_t>(*w);
new_portal->set_nodes(node->children[0].get(), node->children[1].get());
@ -268,7 +268,7 @@ children have portals instead of node.
*/
twosided<std::list<std::unique_ptr<buildportal_t>>> SplitNodePortals(const node_t *node, std::list<std::unique_ptr<buildportal_t>> 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

View File

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

View File

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