use std::set instead of vector for original_brushes since we need them implicitly sorted and no dupes
parallelize PruneNodes_R and CalcTreeBounds_r
This commit is contained in:
parent
26a18d5cc3
commit
755a9e65ca
|
|
@ -24,34 +24,6 @@
|
|||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
template<class T>
|
||||
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<class E>
|
||||
std::vector<E> concat(const std::vector<E> &a, const std::vector<E> &b)
|
||||
{
|
||||
std::vector<E> 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<class E>
|
||||
std::vector<E> make_vector(E e)
|
||||
{
|
||||
std::vector<E> result;
|
||||
result.push_back(std::move(e));
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class E>
|
||||
std::list<E> make_list(E e)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -605,9 +605,16 @@ namespace qv
|
|||
|
||||
// there is a node_t structure for every node and leaf in the bsp tree
|
||||
|
||||
#include <set>
|
||||
|
||||
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<bspbrush_t *> original_brushes;
|
||||
std::set<bspbrush_t *, bspbrush_t_less> original_brushes;
|
||||
std::vector<face_t *> markfaces; // leaf nodes only, point to node faces
|
||||
portal_t *portals;
|
||||
int visleafnum; // -1 = solid
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@
|
|||
#include <qbsp/map.hh>
|
||||
#include <qbsp/qbsp.hh>
|
||||
|
||||
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];
|
||||
|
|
|
|||
|
|
@ -408,7 +408,7 @@ static void LeafNode(node_t *leafnode, std::vector<std::unique_ptr<bspbrush_t>>
|
|||
}
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
21
qbsp/tree.cc
21
qbsp/tree.cc
|
|
@ -25,6 +25,7 @@
|
|||
#include <qbsp/qbsp.hh>
|
||||
#include <qbsp/brush.hh>
|
||||
#include <qbsp/portals.hh>
|
||||
#include <tbb/task_group.h>
|
||||
|
||||
//============================================================================
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue