diff --git a/include/common/vectorutils.hh b/include/common/vectorutils.hh index c96a7139..8a3302c4 100644 --- a/include/common/vectorutils.hh +++ b/include/common/vectorutils.hh @@ -24,34 +24,6 @@ #include #include -template -void sort_and_remove_duplicates(T &v) -{ - std::sort(v.begin(), v.end()); - - auto last = std::unique(v.begin(), v.end()); - v.erase(last, v.end()); -} - -template -std::vector concat(const std::vector &a, const std::vector &b) -{ - std::vector result; - result.reserve(a.size() + b.size()); - - std::copy(a.begin(), a.end(), std::back_inserter(result)); - std::copy(b.begin(), b.end(), std::back_inserter(result)); - return result; -} - -template -std::vector make_vector(E e) -{ - std::vector result; - result.push_back(std::move(e)); - return result; -} - template std::list make_list(E e) { diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index 158aada4..eac457ef 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -605,9 +605,16 @@ namespace qv // there is a node_t structure for every node and leaf in the bsp tree +#include + struct bspbrush_t; struct side_t; +struct bspbrush_t_less +{ + bool operator()(const bspbrush_t *a, const bspbrush_t *b) const; +}; + struct node_t { // both leafs and nodes @@ -627,7 +634,7 @@ struct node_t // information for leafs contentflags_t contents; // leaf nodes (0 for decision nodes) - std::vector original_brushes; + std::set original_brushes; std::vector markfaces; // leaf nodes only, point to node faces portal_t *portals; int visleafnum; // -1 = solid diff --git a/qbsp/brush.cc b/qbsp/brush.cc index ab0040c2..0f148a48 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -28,6 +28,11 @@ #include #include +bool bspbrush_t_less::operator()(const bspbrush_t *a, const bspbrush_t *b) const +{ + return a->file_order < b->file_order; +} + const maptexinfo_t &side_t::get_texinfo() const { return map.mtexinfos[this->texinfo]; diff --git a/qbsp/brushbsp.cc b/qbsp/brushbsp.cc index 4fd914a8..dc9fe196 100644 --- a/qbsp/brushbsp.cc +++ b/qbsp/brushbsp.cc @@ -408,7 +408,7 @@ static void LeafNode(node_t *leafnode, std::vector> } for (auto &brush : brushes) { Q_assert(brush->original != nullptr); - leafnode->original_brushes.push_back(brush->original); + leafnode->original_brushes.insert(brush->original); } qbsp_options.target_game->count_contents_in_stats(leafnode->contents, *stats.leafstats); diff --git a/qbsp/portals.cc b/qbsp/portals.cc index 561def49..162aef74 100644 --- a/qbsp/portals.cc +++ b/qbsp/portals.cc @@ -392,11 +392,12 @@ static void CalcTreeBounds_r(tree_t *tree, node_t *node) return; } - CalcTreeBounds_r(tree, node->children[0].get()); - CalcTreeBounds_r(tree, node->children[1].get()); + tbb::task_group g; + g.run([&]() { CalcTreeBounds_r(tree, node->children[0].get()); }); + g.run([&]() { CalcTreeBounds_r(tree, node->children[1].get()); }); + g.wait(); - node->bounds = node->children[0]->bounds; - node->bounds += node->children[1]->bounds; + node->bounds = node->children[0]->bounds + node->children[1]->bounds; if (node->bounds.mins()[0] >= node->bounds.maxs()[0]) { logging::print("WARNING: node without a volume\n"); @@ -406,8 +407,8 @@ static void CalcTreeBounds_r(tree_t *tree, node_t *node) node->bounds = {node->parent->bounds.mins(), node->parent->bounds.mins()}; } - for (int i = 0; i < 3; i++) { - if (fabs(node->bounds.mins()[i]) > qbsp_options.worldextent.value()) { + for (auto &v : node->bounds.mins()) { + if (fabs(v) > qbsp_options.worldextent.value()) { logging::print("WARNING: node with unbounded volume\n"); break; } @@ -517,6 +518,8 @@ void MakeTreePortals(tree_t *tree) MakePortalsFromBuildportals(tree, std::move(buildportals)); + logging::header("CalcTreeBounds"); + CalcTreeBounds_r(tree, tree->headnode.get()); logging::print(logging::flag::STAT, " {:8} tiny portals\n", stats.c_tinyportals); diff --git a/qbsp/tree.cc b/qbsp/tree.cc index 46347338..0d6eb00b 100644 --- a/qbsp/tree.cc +++ b/qbsp/tree.cc @@ -25,6 +25,7 @@ #include #include #include +#include //============================================================================ @@ -62,14 +63,15 @@ void FreeTreePortals(tree_t *tree) static void ConvertNodeToLeaf(node_t *node, const contentflags_t &contents) { // merge the children's brush lists - node->original_brushes = concat(node->children[0]->original_brushes, node->children[1]->original_brushes); - sort_and_remove_duplicates(node->original_brushes); + node->original_brushes = node->children[0]->original_brushes; + node->original_brushes.insert(node->children[1]->original_brushes.begin(), node->children[1]->original_brushes.end()); node->is_leaf = true; - for (int i = 0; i < 2; ++i) { - node->children[i] = nullptr; + for (auto &child : node->children) { + child = nullptr; } + node->facelist.clear(); node->contents = contents; @@ -77,14 +79,16 @@ static void ConvertNodeToLeaf(node_t *node, const contentflags_t &contents) Q_assert(node->markfaces.empty()); } -static void PruneNodes_R(node_t *node, int &count_pruned) +static void PruneNodes_R(node_t *node, std::atomic_int32_t &count_pruned) { if (node->is_leaf) { return; } - PruneNodes_R(node->children[0].get(), count_pruned); - PruneNodes_R(node->children[1].get(), count_pruned); + tbb::task_group g; + g.run([&]() { PruneNodes_R(node->children[0].get(), count_pruned); }); + g.run([&]() { PruneNodes_R(node->children[1].get(), count_pruned); }); + g.wait(); if (node->children[0]->is_leaf && node->children[0]->contents.is_any_solid(qbsp_options.target_game) && node->children[1]->is_leaf && node->children[1]->contents.is_any_solid(qbsp_options.target_game)) { @@ -109,7 +113,8 @@ void PruneNodes(node_t *node) { logging::funcheader(); - int count_pruned = 0; + std::atomic_int32_t count_pruned = 0; + PruneNodes_R(node, count_pruned); logging::print(logging::flag::STAT, " {:8} pruned nodes\n", count_pruned);