From cb464031da63dca3550602befb5517770b2f1e62 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 20 Feb 2022 16:10:44 -0700 Subject: [PATCH] qbsp: track original brushes, populate q2 leafbrushes accurately --- include/qbsp/brush.hh | 8 +++++++- include/qbsp/qbsp.hh | 2 +- qbsp/qbsp.cc | 45 +++++++++++++------------------------------ qbsp/solidbsp.cc | 22 +++++++++++++++------ 4 files changed, 37 insertions(+), 40 deletions(-) diff --git a/include/qbsp/brush.hh b/include/qbsp/brush.hh index b08186e3..b9458af8 100644 --- a/include/qbsp/brush.hh +++ b/include/qbsp/brush.hh @@ -23,14 +23,20 @@ #include #include +#include struct brush_t { - //brush_t *original; // fixme-brushbsp: implement this + /** + * The brushes in the mapentity_t::brushes vector are considered originals. Brush fragments created during + * the BrushBSP will have this pointing back to the original brush in mapentity_t::brushes. + */ + brush_t *original; aabb3d bounds; std::vector faces; contentflags_t contents; /* BSP contents */ short lmshift; /* lightmap scaling (qu/lightmap pixel), passed to the light util */ + std::optional outputnumber; /* only set for original brushes */ void update_bounds(); }; diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index 98cf0e16..f9df1dbc 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -307,7 +307,7 @@ struct node_t // information for leafs contentflags_t contents; // leaf nodes (0 for decision nodes) - // std::vector original_brushes; // fixme-brushbsp: implement this + std::vector original_brushes; std::vector markfaces; // leaf nodes only, point to node faces portal_t *portals; int visleafnum; // -1 = solid diff --git a/qbsp/qbsp.cc b/qbsp/qbsp.cc index a86ee18c..d8cb3e7d 100644 --- a/qbsp/qbsp.cc +++ b/qbsp/qbsp.cc @@ -43,14 +43,6 @@ bool node_t::opaque() const return contents.is_sky(options.target_game) || contents.is_solid(options.target_game); } -// a simple tree structure used for leaf brush -// compression. -struct leafbrush_entry_t -{ - uint32_t offset; - std::map entries; -}; - // per-entity static struct { @@ -58,36 +50,25 @@ static struct uint32_t total_leaf_brushes; } brush_state; -// running total -static uint32_t brush_offset; - -static void ExportBrushList_r(const mapentity_t *entity, node_t *node, const uint32_t &brush_offset) +static void ExportBrushList_r(const mapentity_t *entity, node_t *node) { if (node->planenum == PLANENUM_LEAF) { if (node->contents.native) { - uint32_t b_id = brush_offset; - std::vector brushes; - - for (auto &b : entity->brushes) { - if (node->bounds.intersectWith(b.bounds)) { - brushes.push_back(b_id); - } - b_id++; - } - - if (brushes.size()) { - node->numleafbrushes = brushes.size(); + if (node->original_brushes.size()) { + node->numleafbrushes = node->original_brushes.size(); brush_state.total_leaf_brushes += node->numleafbrushes; node->firstleafbrush = map.bsp.dleafbrushes.size(); - map.bsp.dleafbrushes.insert(map.bsp.dleafbrushes.end(), brushes.begin(), brushes.end()); + for (auto &b : node->original_brushes) { + map.bsp.dleafbrushes.push_back(b->outputnumber.value()); + } } } return; } - ExportBrushList_r(entity, node->children[0], brush_offset); - ExportBrushList_r(entity, node->children[1], brush_offset); + ExportBrushList_r(entity, node->children[0]); + ExportBrushList_r(entity, node->children[1]); } /* @@ -227,7 +208,7 @@ static std::vector> AddBrushBevels(const brus return planes; } -static void ExportBrushList(const mapentity_t *entity, node_t *node, uint32_t &brush_offset) +static void ExportBrushList(mapentity_t *entity, node_t *node) { LogPrint(LOG_PROGRESS, "---- {} ----\n", __func__); @@ -237,6 +218,8 @@ static void ExportBrushList(const mapentity_t *entity, node_t *node, uint32_t &b dbrush_t &brush = map.bsp.dbrushes.emplace_back( dbrush_t{static_cast(map.bsp.dbrushsides.size()), 0, b.contents.native}); + b.outputnumber = { static_cast(map.bsp.dbrushes.size()) }; + auto bevels = AddBrushBevels(b); for (auto &plane : bevels) { @@ -249,9 +232,7 @@ static void ExportBrushList(const mapentity_t *entity, node_t *node, uint32_t &b brush_state.total_brushes++; } - ExportBrushList_r(entity, node, brush_offset); - - brush_offset += brush_state.total_brushes; + ExportBrushList_r(entity, node); LogPrint(LOG_STAT, " {:8} total brushes\n", brush_state.total_brushes); LogPrint(LOG_STAT, " {:8} total brush sides\n", brush_state.total_brush_sides); @@ -645,7 +626,7 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum) firstface = MakeFaceEdges(entity, nodes); if (options.target_game->id == GAME_QUAKE_II) { - ExportBrushList(entity, nodes, brush_offset); + ExportBrushList(entity, nodes); } ExportDrawNodes(entity, nodes, firstface); diff --git a/qbsp/solidbsp.cc b/qbsp/solidbsp.cc index 750375b2..0936d61a 100644 --- a/qbsp/solidbsp.cc +++ b/qbsp/solidbsp.cc @@ -631,8 +631,7 @@ static twosided> SplitBrush(const brush_t &brush, const q for (int i = 0; i < 2; i++) { result[i] = { brush_t{} }; - // fixme-brushbsp: set original pointer - //b[i]->original = brush->original; + result[i]->original = brush.original; // fixme-brushbsp: add a brush_t copy constructor to make sure we get all fields result[i]->contents = brush.contents; result[i]->lmshift = brush.lmshift; @@ -785,6 +784,10 @@ static void CreateLeaf(const std::vector &brushes, node_t *leafnode) for (auto &brush : brushes) { leafnode->contents = MergeContents(leafnode->contents, brush.contents); } + for (auto &brush : brushes) { + Q_assert(brush.original != nullptr); + leafnode->original_brushes.push_back(brush.original); + } if (leafnode->contents.extended & CFLAGS_ILLUSIONARY_VISBLOCKER) { c_illusionary_visblocker++; @@ -828,7 +831,7 @@ PartitionBrushes Called in parallel. ================== */ -static void PartitionBrushes(std::vector &brushes, node_t *node) +static void PartitionBrushes(std::vector brushes, node_t *node) { face_t *split = SelectPartition(brushes); @@ -890,8 +893,8 @@ static void PartitionBrushes(std::vector &brushes, node_t *node) g.run([&]() { PartitionBrushes(backlist, node->children[1]); }); g.wait(); #else - PartitionBrushes(frontlist, node->children[0]); - PartitionBrushes(backlist, node->children[1]); + PartitionBrushes(std::move(frontlist), node->children[0]); + PartitionBrushes(std::move(backlist), node->children[1]); #endif } @@ -943,7 +946,14 @@ node_t *SolidBSP(mapentity_t *entity, bool midsplit) // count map surfaces; this is used when deciding to switch between midsplit and the expensive partitioning mapbrushes = entity->brushes.size(); - PartitionBrushes(entity->brushes, headnode); + // set the original pointers + std::vector brushcopies; + for (brush_t &original : entity->brushes) { + brush_t copy = original; + copy.original = &original; + brushcopies.push_back(std::move(copy)); + } + PartitionBrushes(std::move(brushcopies), headnode); LogPrint(LOG_STAT, " {:8} split nodes\n", splitnodes.load()); LogPrint(LOG_STAT, " {:8} solid leafs\n", c_solid.load());