From 097b564cc6c250864bb26e4f786b006a00e5853e Mon Sep 17 00:00:00 2001 From: Jonathan Date: Wed, 10 Aug 2022 16:02:16 -0400 Subject: [PATCH] remove bspbrush_t::original; it is no longer required since mapbrush_t is what the output is being written to use some explicit types (bspbrush_t::ptr for pointer, bspbrush_t::container for container of pointers, and bspbrush_t::make_ptr to create one) so that we can swap it out with different pointers easier later swap out bspbrush_t::ptr from unique_ptr to shared_ptr; it's not important yet, but it does not increase compilation time and will allow us to pass things to functions like SplitBrush without destroying the original as long as we still have a reference to it somewhere (important for ChopBrushes) add get_positive_plane to mapface_t instead of creating a whole copy of the bspbrush_t list, BrushBSP now just creates copies of the shared_ptrs which are then filtered down the tree; the originals are never modified by SplitBrushList and friends, only split into new brushes, so this is safe from what I can tell portals now directly reference the mapface_ts original_brushes now directly reference the mapbrush_ts early exit in `BrushBSP` if brush list is empty (moved to top) --- include/qbsp/brush.hh | 16 ++++-- include/qbsp/brushbsp.hh | 4 +- include/qbsp/csg.hh | 1 - include/qbsp/map.hh | 7 ++- include/qbsp/outside.hh | 4 +- include/qbsp/portals.hh | 6 +- include/qbsp/qbsp.hh | 5 +- qbsp/brush.cc | 12 ++-- qbsp/brushbsp.cc | 119 ++++++++++++++++++--------------------- qbsp/csg.cc | 13 ----- qbsp/faces.cc | 4 +- qbsp/map.cc | 9 ++- qbsp/outside.cc | 10 ++-- qbsp/portals.cc | 14 ++--- qbsp/qbsp.cc | 11 ++-- qbsp/tree.cc | 5 +- 16 files changed, 114 insertions(+), 126 deletions(-) diff --git a/include/qbsp/brush.hh b/include/qbsp/brush.hh index 30b4938e..fa74a423 100644 --- a/include/qbsp/brush.hh +++ b/include/qbsp/brush.hh @@ -22,13 +22,13 @@ #pragma once #include -#include #include #include class mapentity_t; struct maptexinfo_t; struct mapface_t; +struct qbsp_plane_t; struct side_t { @@ -51,11 +51,19 @@ class mapbrush_t; struct bspbrush_t { + using ptr = std::shared_ptr; + using container = std::vector; + + template + static inline ptr make_ptr(Args&& ...args) + { + return std::make_shared(std::forward(args)...); + } + /** * The brushes in main brush vectors are considered originals. Brush fragments created during * the BrushBSP will have this pointing back to the original brush in the list. */ - bspbrush_t *original; mapbrush_t *mapbrush; aabb3d bounds; int side, testside; // side of node during construction @@ -67,10 +75,8 @@ struct bspbrush_t bool update_bounds(bool warn_on_failures); - std::unique_ptr copy_unique() const; + ptr copy_unique() const; }; -using bspbrush_vector_t = std::vector>; - std::optional LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush, const contentflags_t &contents, const int hullnum); bool CreateBrushWindings(bspbrush_t *brush); \ No newline at end of file diff --git a/include/qbsp/brushbsp.hh b/include/qbsp/brushbsp.hh index 0d1049d2..26fe7f46 100644 --- a/include/qbsp/brushbsp.hh +++ b/include/qbsp/brushbsp.hh @@ -39,5 +39,5 @@ struct tree_t; constexpr vec_t EDGE_LENGTH_EPSILON = 0.2; bool WindingIsTiny(const winding_t &w, double size = EDGE_LENGTH_EPSILON); -std::unique_ptr BrushFromBounds(const aabb3d &bounds); -std::unique_ptr BrushBSP(mapentity_t *entity, const bspbrush_vector_t &brushes, std::optional forced_quick_tree); +bspbrush_t::ptr BrushFromBounds(const aabb3d &bounds); +std::unique_ptr BrushBSP(mapentity_t *entity, const bspbrush_t::container &brushes, std::optional forced_quick_tree); diff --git a/include/qbsp/csg.hh b/include/qbsp/csg.hh index 999ad6f7..ca592cd6 100644 --- a/include/qbsp/csg.hh +++ b/include/qbsp/csg.hh @@ -37,4 +37,3 @@ std::unique_ptr CopyFace(const face_t *in); std::tuple, std::unique_ptr> SplitFace( std::unique_ptr in, const qplane3d &split); void UpdateFaceSphere(face_t *in); -bspbrush_vector_t MakeBspBrushList(const bspbrush_vector_t &brushes); diff --git a/include/qbsp/map.hh b/include/qbsp/map.hh index 62433f07..c4494f00 100644 --- a/include/qbsp/map.hh +++ b/include/qbsp/map.hh @@ -67,8 +67,9 @@ struct mapface_t const texvecf &get_texvecs() const; void set_texvecs(const texvecf &vecs); - + const qbsp_plane_t &get_plane() const; + const qbsp_plane_t &get_positive_plane() const; }; enum class brushformat_t @@ -344,7 +345,7 @@ qvec3d FixRotateOrigin(mapentity_t *entity); constexpr int HULL_COLLISION = -1; /* Create BSP brushes from map brushes */ -void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_vector_t &brushes); +void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_t::container &brushes); std::list CSGFace( face_t *srcface, const mapentity_t *srcentity, const bspbrush_t *srcbrush, const node_t *srcnode); @@ -366,6 +367,6 @@ void ExportObj_Brushes(const std::string &filesuffix, const std::vector> &list); +void WriteBspBrushMap(const fs::path &name, const bspbrush_t::container &list); bool IsValidTextureProjection(const qvec3f &faceNormal, const qvec3f &s_vec, const qvec3f &t_vec); diff --git a/include/qbsp/outside.hh b/include/qbsp/outside.hh index 52dac84b..e49b67e9 100644 --- a/include/qbsp/outside.hh +++ b/include/qbsp/outside.hh @@ -28,7 +28,7 @@ class mapentity_t; struct node_t; struct tree_t; -bool FillOutside(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_vector_t &brushes); +bool FillOutside(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_t::container &brushes); std::vector FindOccupiedClusters(node_t *headnode); -void FillBrushEntity(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_vector_t &brushes); +void FillBrushEntity(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_t::container &brushes); diff --git a/include/qbsp/portals.hh b/include/qbsp/portals.hh index a755bafd..93cf54c0 100644 --- a/include/qbsp/portals.hh +++ b/include/qbsp/portals.hh @@ -40,8 +40,8 @@ struct portal_t std::unique_ptr winding; bool sidefound; // false if ->side hasn't been checked - side_t *sides[2]; // [0] = the brush side visible on nodes[0] - it could come from a brush in nodes[1]. NULL = - // non-visible + mapface_t *sides[2]; // [0] = the brush side visible on nodes[0] - it could come from a brush in nodes[1]. NULL = + // non-visible face_t *face[2]; // output face in bsp file }; @@ -78,4 +78,4 @@ std::list> MakeHeadnodePortals(tree_t *tree); void MakePortalsFromBuildportals(tree_t *tree, std::list> buildportals); void EmitAreaPortals(node_t *headnode); void FloodAreas(mapentity_t *entity, node_t *headnode); -void MarkVisibleSides(tree_t *tree, mapentity_t *entity, bspbrush_vector_t &brushes); +void MarkVisibleSides(tree_t *tree, mapentity_t *entity, bspbrush_t::container &brushes); diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index f1939601..50ef77b3 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -48,6 +48,7 @@ #include #include #include +#include enum texcoord_style_t { @@ -633,7 +634,7 @@ struct node_t aabb3d bounds; // bounding volume, not just points inside node_t *parent; // this is also a bounding volume like `bounds` - std::unique_ptr volume; // one for each leaf/node + bspbrush_t::ptr volume; // one for each leaf/node bool is_leaf = false; // information for decision nodes @@ -662,7 +663,7 @@ struct node_t uint32_t firstleafbrush; // Q2 uint32_t numleafbrushes; int32_t area; - std::vector original_brushes; + std::vector original_brushes; }; void InitQBSP(int argc, const char **argv); diff --git a/qbsp/brush.cc b/qbsp/brush.cc index 41d862ab..d4640282 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -40,14 +40,12 @@ const qbsp_plane_t &side_t::get_plane() const const qbsp_plane_t &side_t::get_positive_plane() const { - auto &p = map.get_plane(planenum & ~1); - Q_assert(p.get_normal()[(int) p.get_type() % 3] > 0); - return p; + return map.get_plane(planenum & ~1); } -std::unique_ptr bspbrush_t::copy_unique() const +bspbrush_t::ptr bspbrush_t::copy_unique() const { - return std::make_unique(*this); + return bspbrush_t::make_ptr(*this); } /* @@ -347,7 +345,7 @@ std::optional LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush //============================================================================= -static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, const int hullnum, content_stats_base_t &stats, bspbrush_vector_t &brushes) +static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, const int hullnum, content_stats_base_t &stats, bspbrush_t::container &brushes) { // _omitbrushes 1 just discards all brushes in the entity. // could be useful for geometry guides, selective compilation, etc. @@ -515,7 +513,7 @@ hullnum HULL_COLLISION should contain ALL brushes. (used by BSPX_CreateBrushList hullnum 0 does not contain clip brushes. ============ */ -void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_vector_t &brushes) +void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_t::container &brushes) { logging::funcheader(); diff --git a/qbsp/brushbsp.cc b/qbsp/brushbsp.cc index 1b8f86a5..a805859f 100644 --- a/qbsp/brushbsp.cc +++ b/qbsp/brushbsp.cc @@ -79,9 +79,9 @@ BrushFromBounds Creates a new axial brush ================== */ -std::unique_ptr BrushFromBounds(const aabb3d &bounds) +bspbrush_t::ptr BrushFromBounds(const aabb3d &bounds) { - auto b = std::make_unique(); + auto b = bspbrush_t::make_ptr(); b->sides.resize(6); for (int i = 0; i < 3; i++) { @@ -377,7 +377,7 @@ Creates a leaf node. Called in parallel. ================== */ -static void LeafNode(node_t *leafnode, std::vector> brushes, bspstats_t &stats) +static void LeafNode(node_t *leafnode, bspbrush_t::container brushes, bspstats_t &stats) { leafnode->facelist.clear(); leafnode->is_leaf = true; @@ -387,8 +387,8 @@ static void LeafNode(node_t *leafnode, std::vector> leafnode->contents = qbsp_options.target_game->combine_contents(leafnode->contents, brush->contents); } for (auto &brush : brushes) { - Q_assert(brush->original != nullptr); - leafnode->original_brushes.push_back(brush->original); + Q_assert(brush->mapbrush != nullptr); + leafnode->original_brushes.push_back(brush->mapbrush); } qbsp_options.target_game->count_contents_in_stats(leafnode->contents, *stats.leafstats); @@ -434,10 +434,10 @@ input. https://github.com/id-Software/Quake-2-Tools/blob/master/bsp/qbsp3/brushbsp.c#L935 ================ */ -static twosided> SplitBrush(std::unique_ptr brush, size_t planenum, bspstats_t &stats) +static twosided SplitBrush(bspbrush_t::ptr brush, size_t planenum, bspstats_t &stats) { const qplane3d &split = map.planes[planenum]; - twosided> result; + twosided result; // check all points vec_t d_front = 0; @@ -493,7 +493,7 @@ static twosided> SplitBrush(std::unique_ptr(); - result[i]->original = brush->original; + result[i]->mapbrush = brush->mapbrush; // fixme-brushbsp: add a bspbrush_t copy constructor to make sure we get all fields result[i]->contents = brush->contents; result[i]->sides.reserve(brush->sides.size() + 1); @@ -695,7 +695,7 @@ ChooseMidPlaneFromList The clipping hull BSP doesn't worry about avoiding splits ================== */ -static std::optional ChooseMidPlaneFromList(const std::vector> &brushes, const node_t *node, bspstats_t &stats) +static std::optional ChooseMidPlaneFromList(const bspbrush_t::container &brushes, const node_t *node, bspstats_t &stats) { vec_t bestaxialmetric = VECT_MAX; std::optional bestaxialplane; @@ -750,7 +750,7 @@ Using heuristics, chooses a plane to partition the brushes with. Returns nullopt if there are no valid planes to split with. ================ */ -static std::optional SelectSplitPlane(const std::vector> &brushes, node_t *node, std::optional forced_quick_tree, bspstats_t &stats) +static std::optional SelectSplitPlane(const bspbrush_t::container &brushes, node_t *node, std::optional forced_quick_tree, bspstats_t &stats) { // no brushes left to split, so we can't use any plane. if (!brushes.size()) { @@ -803,9 +803,9 @@ static std::optional SelectSplitPlane(const std::vectororiginal->contents.is_any_detail(qbsp_options.target_game)) + if ((pass & 1) && !brush->mapbrush->contents.is_any_detail(qbsp_options.target_game)) continue; - if (!(pass & 1) && brush->original->contents.is_any_detail(qbsp_options.target_game)) + if (!(pass & 1) && brush->mapbrush->contents.is_any_detail(qbsp_options.target_game)) continue; for (auto &side : brush->sides) { if (side.bevel) @@ -926,10 +926,10 @@ static std::optional SelectSplitPlane(const std::vector>, 2> SplitBrushList( - std::vector> brushes, size_t planenum, bspstats_t &stats) +static std::array SplitBrushList( + bspbrush_t::container brushes, size_t planenum, bspstats_t &stats) { - std::array>, 2> result; + std::array result; for (auto &brush : brushes) { int sides = brush->side; @@ -979,7 +979,7 @@ BuildTree_r Called in parallel. ================== */ -static void BuildTree_r(tree_t *tree, node_t *node, std::vector> brushes, std::optional forced_quick_tree, bspstats_t &stats) +static void BuildTree_r(tree_t *tree, node_t *node, bspbrush_t::container brushes, std::optional forced_quick_tree, bspstats_t &stats) { // find the best plane to use as a splitter auto bestplane = SelectSplitPlane(brushes, node, forced_quick_tree, stats); @@ -1021,10 +1021,10 @@ static void BuildTree_r(tree_t *tree, node_t *node, std::vectorvolume), bestplane.value(), stats); - node->volume = nullptr; - node->children[0]->volume = std::move(children_volumes[0]); - node->children[1]->volume = std::move(children_volumes[1]); + auto children_volumes = SplitBrush(std::move(node->volume), bestplane.value(), stats); + node->volume = nullptr; + node->children[0]->volume = std::move(children_volumes[0]); + node->children[1]->volume = std::move(children_volumes[1]); // recursively process children tbb::task_group g; @@ -1038,43 +1038,10 @@ static void BuildTree_r(tree_t *tree, node_t *node, std::vector BrushBSP_internal(mapentity_t *entity, std::vector> brushlist, std::optional forced_quick_tree) +std::unique_ptr BrushBSP(mapentity_t *entity, const bspbrush_t::container &brushlist, std::optional forced_quick_tree) { auto tree = std::make_unique(); - size_t c_faces = 0; - size_t c_nonvisfaces = 0; - size_t c_brushes = 0; - - for (const auto &b : brushlist) { - c_brushes++; - -#if 0 - // fixme-brushbsp: why does this just print and do nothing? should - // the brush be removed? - double volume = BrushVolume(*b); - if (volume < qbsp_options.microvolume.value()) { - logging::print("WARNING: {}: microbrush\n", - b->original->mapbrush->line); - } -#endif - - for (side_t &side : b->sides) { - if (side.bevel) - continue; - if (!side.w) - continue; - if (side.onnode) - continue; - if (side.source->visible) - c_faces++; - else - c_nonvisfaces++; - } - - tree->bounds += b->bounds; - } - if (brushlist.empty()) { /* * We allow an entity to be constructed with no visible brushes @@ -1102,20 +1069,52 @@ static std::unique_ptr BrushBSP_internal(mapentity_t *entity, std::vecto return tree; } + size_t c_faces = 0; + size_t c_nonvisfaces = 0; + size_t c_brushes = 0; + + for (const auto &b : brushlist) { + c_brushes++; + +#if 0 + // fixme-brushbsp: why does this just print and do nothing? should + // the brush be removed? + double volume = BrushVolume(*b); + if (volume < qbsp_options.microvolume.value()) { + logging::print("WARNING: {}: microbrush\n", + b->mapbrush->line); + } +#endif + + for (side_t &side : b->sides) { + if (side.bevel) + continue; + if (!side.w) + continue; + if (side.onnode) + continue; + if (side.source->visible) + c_faces++; + else + c_nonvisfaces++; + } + + tree->bounds += b->bounds; + } + logging::print(logging::flag::STAT, " {:8} brushes\n", c_brushes); logging::print(logging::flag::STAT, " {:8} visible faces\n", c_faces); logging::print(logging::flag::STAT, " {:8} nonvisible faces\n", c_nonvisfaces); auto node = tree->create_node(); - - node->volume = BrushFromBounds(tree->bounds.grow(SIDESPACE)); + node->volume = BrushFromBounds(tree->bounds.grow(SIDESPACE)); node->bounds = tree->bounds.grow(SIDESPACE); tree->headnode = node; bspstats_t stats{}; stats.leafstats = qbsp_options.target_game->create_content_stats(); - BuildTree_r(tree.get(), tree->headnode, std::move(brushlist), forced_quick_tree, stats); + BuildTree_r(tree.get(), tree->headnode, brushlist, forced_quick_tree, stats); logging::print(logging::flag::STAT, " {:8} visible nodes\n", stats.c_nodes - stats.c_nonvis); if (stats.c_nonvis) { @@ -1149,9 +1148,3 @@ static std::unique_ptr BrushBSP_internal(mapentity_t *entity, std::vecto return tree; } - -std::unique_ptr BrushBSP(mapentity_t *entity, const std::vector> &brushlist, std::optional forced_quick_tree) -{ - logging::funcheader(); - return BrushBSP_internal(entity, MakeBspBrushList(brushlist), forced_quick_tree); -} \ No newline at end of file diff --git a/qbsp/csg.cc b/qbsp/csg.cc index 93122056..ff71ca30 100644 --- a/qbsp/csg.cc +++ b/qbsp/csg.cc @@ -120,16 +120,3 @@ std::tuple, std::unique_ptr> SplitFace( return {std::move(new_front), std::move(new_back)}; } - -std::vector> MakeBspBrushList(const bspbrush_vector_t &brushes) -{ - // set the original pointers - std::vector> brushcopies; - for (const auto &original : brushes) { - auto copy = original->copy_unique(); - copy->original = original.get(); - brushcopies.push_back(std::move(copy)); - } - - return brushcopies; -} diff --git a/qbsp/faces.cc b/qbsp/faces.cc index 21bee8e9..af2fe533 100644 --- a/qbsp/faces.cc +++ b/qbsp/faces.cc @@ -472,7 +472,7 @@ see also FindPortalSide which populates p->side */ static std::unique_ptr FaceFromPortal(portal_t *p, bool pside) { - side_t *side = p->sides[pside]; + mapface_t *side = p->sides[pside]; if (!side) return nullptr; // portal does not bridge different visible contents @@ -481,7 +481,7 @@ static std::unique_ptr FaceFromPortal(portal_t *p, bool pside) f->texinfo = side->texinfo; f->planenum = (side->planenum & ~1) | (pside ? 1 : 0); f->portal = p; - f->original_side = side->source; + f->original_side = side; #if 0 bool make_face = diff --git a/qbsp/map.cc b/qbsp/map.cc index 4000bff3..bec70f15 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -1554,6 +1554,11 @@ const qbsp_plane_t &mapface_t::get_plane() const return map.get_plane(planenum); } +const qbsp_plane_t &mapface_t::get_positive_plane() const +{ + return map.get_plane(planenum & ~1); +} + bool IsValidTextureProjection(const qvec3f &faceNormal, const qvec3f &s_vec, const qvec3f &t_vec) { // TODO: This doesn't match how light does it (TexSpaceToWorld) @@ -2798,7 +2803,7 @@ WriteBspBrushMap from q3map ================== */ -void WriteBspBrushMap(const fs::path &name, const std::vector> &list) +void WriteBspBrushMap(const fs::path &name, const bspbrush_t::container &list) { std::shared_lock lock(map_planes_lock); @@ -2845,7 +2850,7 @@ from q3map */ static void TestExpandBrushes(mapentity_t *src) { - std::vector> hull1brushes; + bspbrush_t::container hull1brushes; for (auto &mapbrush : src->mapbrushes) { auto hull1brush = LoadBrush(src, &mapbrush, {CONTENTS_SOLID}, diff --git a/qbsp/outside.cc b/qbsp/outside.cc index d4cd4008..25fdc9d1 100644 --- a/qbsp/outside.cc +++ b/qbsp/outside.cc @@ -349,7 +349,7 @@ std::vector FindOccupiedClusters(node_t *headnode) //============================================================================= -static void MarkBrushSidesInvisible(mapentity_t *entity, bspbrush_vector_t &brushes) +static void MarkBrushSidesInvisible(mapentity_t *entity, bspbrush_t::container &brushes) { for (auto &brush : brushes) { for (auto &face : brush->sides) { @@ -412,13 +412,13 @@ static void MarkVisibleBrushSides_R(node_t *node) // optimized case: just mark the brush sides in the neighbouring // leaf that are coplanar for (auto *brush : neighbour_leaf->original_brushes) { - for (auto &side : brush->sides) { + for (auto &side : brush->faces) { // fixme-brushbsp: should this be get_plane() ? // fixme-brushbsp: planenum if (qv::epsilonEqual(side.get_positive_plane(), portal->plane)) { // we've found a brush side in an original brush in the neighbouring // leaf, on a portal to this (non-opaque) leaf, so mark it as visible. - side.source->visible = true; + side.visible = true; } } } @@ -600,7 +600,7 @@ get incorrectly marked as "invisible"). Special cases: structural fully covered by detail still needs to be marked "visible". =========== */ -bool FillOutside(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_vector_t &brushes) +bool FillOutside(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_t::container &brushes) { node_t *node = tree->headnode; @@ -720,7 +720,7 @@ bool FillOutside(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_ return true; } -void FillBrushEntity(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_vector_t &brushes) +void FillBrushEntity(mapentity_t *entity, tree_t *tree, const int hullnum, bspbrush_t::container &brushes) { logging::funcheader(); diff --git a/qbsp/portals.cc b/qbsp/portals.cc index 5696fe09..08e0a2e9 100644 --- a/qbsp/portals.cc +++ b/qbsp/portals.cc @@ -573,8 +573,8 @@ static mapentity_t *AreanodeEntityForLeaf(node_t *node) } for (auto &brush : node->original_brushes) { - if (brush->mapbrush->func_areaportal) { - return brush->mapbrush->func_areaportal; + if (brush->func_areaportal) { + return brush->func_areaportal; } } return nullptr; @@ -791,8 +791,8 @@ static void FindPortalSide(portal_t *p) return; // 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}; - side_t *exactside[2] = {nullptr, nullptr}; + mapface_t *bestside[2] = {nullptr, nullptr}; + mapface_t *exactside[2] = {nullptr, nullptr}; float bestdot = 0; const qbsp_plane_t &p1 = p->onnode->get_plane(); @@ -813,7 +813,7 @@ static void FindPortalSide(portal_t *p) continue; } - for (auto &side : brush->sides) { + for (auto &side : brush->faces) { if (side.bevel) continue; if ((side.planenum & ~1) == p->onnode->planenum) { @@ -899,7 +899,7 @@ static void MarkVisibleSides_r(node_t *node) FindPortalSide(p); for (int i = 0; i < 2; ++i) { if (p->sides[i]) { - p->sides[i]->source->visible = true; + p->sides[i]->visible = true; } } } @@ -911,7 +911,7 @@ MarkVisibleSides ============= */ -void MarkVisibleSides(tree_t *tree, mapentity_t *entity, bspbrush_vector_t &brushes) +void MarkVisibleSides(tree_t *tree, mapentity_t *entity, bspbrush_t::container &brushes) { logging::funcheader(); diff --git a/qbsp/qbsp.cc b/qbsp/qbsp.cc index f393a2df..dd1c2d5a 100644 --- a/qbsp/qbsp.cc +++ b/qbsp/qbsp.cc @@ -306,14 +306,13 @@ static void ExportBrushList_r(const mapentity_t *entity, node_t *node) node->firstleafbrush = map.bsp.dleafbrushes.size(); for (auto &b : node->original_brushes) { - if (!b->mapbrush->outputnumber.has_value()) { - // FIXME - b->mapbrush->outputnumber = {static_cast(map.bsp.dbrushes.size())}; + if (!b->outputnumber.has_value()) { + b->outputnumber = {static_cast(map.bsp.dbrushes.size())}; dbrush_t &brush = map.bsp.dbrushes.emplace_back( dbrush_t{static_cast(map.bsp.dbrushsides.size()), 0, b->contents.native}); - for (auto &side : b->mapbrush->faces) { + for (auto &side : b->faces) { map.bsp.dbrushsides.push_back( {(uint32_t) ExportMapPlane(side.planenum), (int32_t)ExportMapTexinfo(side.texinfo)}); brush.numsides++; @@ -323,7 +322,7 @@ static void ExportBrushList_r(const mapentity_t *entity, node_t *node) brush_state.total_brushes++; } - map.bsp.dleafbrushes.push_back(b->mapbrush->outputnumber.value()); + map.bsp.dleafbrushes.push_back(b->outputnumber.value()); } } } @@ -442,7 +441,7 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum) // reserve enough brushes; we would only make less, // never more - bspbrush_vector_t brushes; + bspbrush_t::container brushes; brushes.reserve(entity->mapbrushes.size()); /* diff --git a/qbsp/tree.cc b/qbsp/tree.cc index 7bec5456..e3bba442 100644 --- a/qbsp/tree.cc +++ b/qbsp/tree.cc @@ -82,9 +82,8 @@ static void ConvertNodeToLeaf(node_t *node, const contentflags_t &contents) node->original_brushes = std::move(node->children[base]->original_brushes); node->original_brushes.insert(node->original_brushes.end(), node->children[base ^ 1]->original_brushes.begin(), node->children[base ^ 1]->original_brushes.end()); - std::sort(node->original_brushes.begin(), node->original_brushes.end(), [](const bspbrush_t *a, const bspbrush_t *b) { - return a->mapbrush < b->mapbrush; - }); + // sort by pointer (since mapbrush_t is in a flat vector) + std::sort(node->original_brushes.begin(), node->original_brushes.end()); auto unique = std::unique(node->original_brushes.begin(), node->original_brushes.end()); node->original_brushes.erase(unique, node->original_brushes.end());