Skip to content

Commit c96d6d8

Browse files
committed
work on new drawing functions (AlpineMapsOrg#162)
1 parent f8af936 commit c96d6d8

File tree

5 files changed

+133
-68
lines changed

5 files changed

+133
-68
lines changed

nucleus/camera/PositionStorage.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@
2222

2323
namespace nucleus::camera {
2424

25-
PositionStorage* PositionStorage::_instance = nullptr;
25+
PositionStorage* PositionStorage::s_instance = nullptr;
2626

27-
const std::map<std::string, Definition>& PositionStorage::positions() const { return _positions; }
27+
const std::map<std::string, Definition>& PositionStorage::positions() const { return m_positions; }
2828

2929
PositionStorage* PositionStorage::instance()
3030
{
31-
if (_instance == nullptr) {
32-
_instance = new PositionStorage;
31+
if (s_instance == nullptr) {
32+
s_instance = new PositionStorage;
3333
}
34-
return _instance;
34+
return s_instance;
3535
}
3636
}

nucleus/camera/PositionStorage.h

+16-16
Original file line numberDiff line numberDiff line change
@@ -94,27 +94,27 @@ class PositionStorage {
9494

9595
private:
9696
PositionStorage() {
97-
_positions.insert({"hochgrubach_spitze", nucleus::camera::stored_positions::oestl_hochgrubach_spitze()});
98-
_positions.insert({"stephansdom", nucleus::camera::stored_positions::stephansdom()});
99-
_positions.insert({"stephansdom_closeup", nucleus::camera::stored_positions::stephansdom_closeup()});
100-
_positions.insert({"grossglockner", nucleus::camera::stored_positions::grossglockner()});
101-
_positions.insert({"grossglockner_topdown", nucleus::camera::stored_positions::grossglockner_topdown()});
102-
_positions.insert({"schneeberg", nucleus::camera::stored_positions::schneeberg()});
103-
_positions.insert({"karwendel", nucleus::camera::stored_positions::karwendel()});
104-
_positions.insert({"wien", nucleus::camera::stored_positions::wien()});
105-
_positions.insert({"grossglockner_shadow", nucleus::camera::stored_positions::grossglockner_shadow()});
106-
_positions.insert({"weichtalhaus", nucleus::camera::stored_positions::weichtalhaus()});
97+
m_positions.insert({ "hochgrubach_spitze", nucleus::camera::stored_positions::oestl_hochgrubach_spitze() });
98+
m_positions.insert({ "stephansdom", nucleus::camera::stored_positions::stephansdom() });
99+
m_positions.insert({ "stephansdom_closeup", nucleus::camera::stored_positions::stephansdom_closeup() });
100+
m_positions.insert({ "grossglockner", nucleus::camera::stored_positions::grossglockner() });
101+
m_positions.insert({ "grossglockner_topdown", nucleus::camera::stored_positions::grossglockner_topdown() });
102+
m_positions.insert({ "schneeberg", nucleus::camera::stored_positions::schneeberg() });
103+
m_positions.insert({ "karwendel", nucleus::camera::stored_positions::karwendel() });
104+
m_positions.insert({ "wien", nucleus::camera::stored_positions::wien() });
105+
m_positions.insert({ "grossglockner_shadow", nucleus::camera::stored_positions::grossglockner_shadow() });
106+
m_positions.insert({ "weichtalhaus", nucleus::camera::stored_positions::weichtalhaus() });
107107
}
108-
static PositionStorage* _instance;
109-
std::map<std::string, nucleus::camera::Definition> _positions;
108+
static PositionStorage* s_instance;
109+
std::map<std::string, nucleus::camera::Definition> m_positions;
110110

111111
public:
112112
PositionStorage(PositionStorage &other) = delete;
113113
void operator=(const PositionStorage &) = delete;
114114
static PositionStorage *instance();
115115
nucleus::camera::Definition get(const std::string& name) {
116-
auto it = _positions.find(name);
117-
if (it != _positions.end()) {
116+
auto it = m_positions.find(name);
117+
if (it != m_positions.end()) {
118118
return it->second;
119119
} else {
120120
qWarning() << "Position by name" << name << "not existing.";
@@ -124,7 +124,7 @@ class PositionStorage {
124124

125125
nucleus::camera::Definition get_by_index(unsigned id) {
126126
unsigned i = 0;
127-
for (const auto& kv : _positions) {
127+
for (const auto& kv : m_positions) {
128128
if (i == id) return kv.second;
129129
i++;
130130
}
@@ -134,7 +134,7 @@ class PositionStorage {
134134

135135
QList<QString> getPositionList() {
136136
QList<QString> res;
137-
for (const auto& kv : _positions) {
137+
for (const auto& kv : m_positions) {
138138
res.append(kv.first.c_str());
139139
}
140140
return res;

nucleus/tile/drawing.cpp

+58-37
Original file line numberDiff line numberDiff line change
@@ -22,55 +22,76 @@
2222

2323
namespace nucleus::tile::drawing {
2424

25-
std::vector<TileBounds> generate_list(const camera::Definition& camera, utils::AabbDecoratorPtr aabb_decorator, unsigned int max_zoom_level)
25+
std::vector<tile::Id> generate_list(const camera::Definition& camera, utils::AabbDecoratorPtr aabb_decorator, unsigned int max_zoom_level)
2626
{
2727
const auto tile_refine_functor = tile::utils::refineFunctor(camera, aabb_decorator, 1, 256, max_zoom_level);
28+
return radix::quad_tree::onTheFlyTraverse(tile::Id { 0, { 0, 0 } }, tile_refine_functor, [](const tile::Id& v) { return v.children(); });
29+
}
30+
31+
std::vector<TileBounds> compute_bounds(const std::vector<Id>& tiles, utils::AabbDecoratorPtr aabb_decorator)
32+
{
33+
std::vector<TileBounds> bounded_tiles;
34+
bounded_tiles.reserve(tiles.size());
35+
for (const auto& t : tiles) {
36+
bounded_tiles.emplace_back(t, aabb_decorator->aabb(t));
37+
}
38+
return bounded_tiles;
39+
}
2840

29-
auto tiles = radix::quad_tree::onTheFlyTraverse(tile::Id { 0, { 0, 0 } }, tile_refine_functor, [](const tile::Id& v) { return v.children(); });
41+
std::vector<tile::Id> limit(std::vector<tile::Id> tiles, uint max_n_tiles)
42+
{
43+
if (tiles.size() < max_n_tiles)
44+
return tiles;
3045

31-
if (tiles.size() > max_n_tiles) {
32-
std::sort(tiles.begin(), tiles.end(), [&](const tile::Id& a, const tile::Id& b) { return a.zoom_level > b.zoom_level; });
33-
std::unordered_set<tile::Id, tile::Id::Hasher> id_set;
34-
id_set.reserve(tiles.size());
35-
for (const auto t : tiles) {
36-
id_set.insert(t);
46+
std::sort(tiles.begin(), tiles.end(), [&](const tile::Id& a, const tile::Id& b) { return a.zoom_level > b.zoom_level; });
47+
std::unordered_set<tile::Id, tile::Id::Hasher> id_set;
48+
id_set.reserve(tiles.size());
49+
for (const auto t : tiles) {
50+
id_set.insert(t);
51+
}
52+
const auto all_in_set = [&](const std::array<Id, 4>& siblings) {
53+
for (const auto& s : siblings) {
54+
if (!id_set.contains(s))
55+
return false;
3756
}
38-
const auto all_in_set = [&](const std::array<Id, 4>& siblings) {
39-
for (const auto& s : siblings) {
40-
if (!id_set.contains(s))
41-
return false;
42-
}
43-
return true;
44-
};
45-
const auto remove = [&](const std::array<Id, 4>& siblings) {
46-
for (const auto& s : siblings) {
47-
const auto pos = std::find(tiles.crbegin(), tiles.crend(), s);
48-
tiles.erase(std::next(pos).base());
49-
id_set.erase(s);
50-
}
51-
return true;
52-
};
57+
return true;
58+
};
59+
const auto remove = [&](const std::array<Id, 4>& siblings) {
60+
for (const auto& s : siblings) {
61+
const auto pos = std::find(tiles.crbegin(), tiles.crend(), s);
62+
tiles.erase(std::next(pos).base());
63+
id_set.erase(s);
64+
}
65+
return true;
66+
};
5367

54-
while (tiles.size() > max_n_tiles) {
55-
for (auto it = tiles.crbegin(); it != tiles.crend(); ++it) {
56-
const auto parent = (*it).parent();
57-
const auto siblings = parent.children();
58-
if (all_in_set(siblings)) {
59-
remove(siblings);
60-
tiles.push_back(parent);
61-
id_set.insert(parent);
62-
break;
63-
}
68+
while (tiles.size() > max_n_tiles) {
69+
for (auto it = tiles.crbegin(); it != tiles.crend(); ++it) {
70+
const auto parent = (*it).parent();
71+
const auto siblings = parent.children();
72+
if (all_in_set(siblings)) {
73+
remove(siblings);
74+
tiles.push_back(parent);
75+
id_set.insert(parent);
76+
break;
6477
}
6578
}
6679
}
80+
return tiles;
81+
}
82+
83+
std::vector<TileBounds> cull(std::vector<TileBounds> tiles, const camera::Definition& camera)
84+
{
85+
std::vector<TileBounds> culled_tiles;
86+
culled_tiles.reserve(tiles.size());
87+
const auto frustum = camera.frustum();
6788

68-
std::vector<TileBounds> bounded_tiles;
69-
bounded_tiles.reserve(tiles.size());
7089
for (const auto& t : tiles) {
71-
bounded_tiles.emplace_back(t, aabb_decorator->aabb(t));
90+
if (tile::utils::camera_frustum_contains_tile(frustum, t.bounds))
91+
culled_tiles.push_back(t);
7292
}
73-
return bounded_tiles;
93+
94+
return culled_tiles;
7495
}
7596

7697
std::vector<TileBounds> sort(std::vector<TileBounds> list, const glm::dvec3& camera_position)

nucleus/tile/drawing.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
namespace nucleus::tile::drawing {
2626
constexpr uint max_n_tiles = 1024;
2727

28-
std::vector<TileBounds> generate_list(const camera::Definition& camera, utils::AabbDecoratorPtr aabb_decorator, unsigned max_zoom_level);
28+
std::vector<tile::Id> generate_list(const camera::Definition& camera, utils::AabbDecoratorPtr aabb_decorator, unsigned max_zoom_level);
29+
std::vector<TileBounds> compute_bounds(const std::vector<tile::Id>& tiles, utils::AabbDecoratorPtr aabb_decorator);
30+
std::vector<tile::Id> limit(std::vector<tile::Id> tiles, uint max_n_tiles);
31+
std::vector<TileBounds> cull(std::vector<TileBounds> list, const camera::Definition& camera);
2932
std::vector<TileBounds> sort(std::vector<TileBounds> list, const glm::dvec3& camera_position);
3033
}

unittests/nucleus/tile_drawing.cpp

+50-9
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,24 @@ TEST_CASE("tile/drawing")
3232
TileHeights h;
3333
h.emplace({ 0, { 0, 0 } }, { 100, 4000 });
3434
const auto aabb_decorator = AabbDecorator::make(std::move(h));
35-
std::vector<std::pair<nucleus::camera::Definition, std::vector<TileBounds>>> lists;
35+
std::vector<std::pair<nucleus::camera::Definition, std::vector<tile::Id>>> lists;
36+
std::vector<std::pair<nucleus::camera::Definition, std::vector<TileBounds>>> tile_bound_lists;
3637
SECTION("should not generate more than 1024 tiles for all test cameras + sorting")
3738
{
3839
for (auto [name, camera] : nucleus::camera::PositionStorage::instance()->positions()) {
3940
CAPTURE(name);
4041
camera.set_viewport_size({ 1920, 1080 });
41-
auto list = drawing::generate_list(camera, aabb_decorator, 20);
42+
const auto list = drawing::generate_list(camera, aabb_decorator, 20);
4243
lists.emplace_back(camera, list);
43-
CHECK(list.size() <= 1024u);
44+
const auto limited = drawing::limit(list, 1024u);
45+
CHECK(limited.size() <= 1024u);
46+
47+
const auto tiles_with_bounds = drawing::compute_bounds(limited, aabb_decorator);
48+
tile_bound_lists.emplace_back(camera, tiles_with_bounds);
4449
// qDebug() << "list.size(): " << list.size();
45-
list = drawing::sort(list, camera.position());
50+
const auto sorted = drawing::sort(tiles_with_bounds, camera.position());
4651
auto dist = 0.0;
47-
for (const auto t : list) {
52+
for (const auto t : sorted) {
4853
const auto d = glm::distance(t.bounds.centre(), camera.position());
4954
CHECK(d > dist);
5055
}
@@ -53,15 +58,51 @@ TEST_CASE("tile/drawing")
5358

5459
BENCHMARK("generate list")
5560
{
56-
for (auto [camera, list] : lists) {
57-
list = drawing::generate_list(camera, aabb_decorator, 20);
61+
std::vector<std::vector<tile::Id>> tmp;
62+
tmp.reserve(lists.size());
63+
for (const auto& [camera, list] : lists) {
64+
tmp.push_back(drawing::generate_list(camera, aabb_decorator, 20));
5865
}
66+
return tmp;
67+
};
68+
69+
BENCHMARK("limit")
70+
{
71+
std::vector<std::vector<tile::Id>> tmp;
72+
tmp.reserve(lists.size());
73+
for (const auto& [camera, list] : lists) {
74+
tmp.push_back(drawing::limit(list, 1024u));
75+
}
76+
return tmp;
77+
};
78+
79+
BENCHMARK("compute_aabbs")
80+
{
81+
std::vector<std::vector<TileBounds>> tmp;
82+
tmp.reserve(lists.size());
83+
for (const auto& [camera, list] : lists) {
84+
tmp.push_back(drawing::compute_bounds(list, aabb_decorator));
85+
}
86+
return tmp;
5987
};
6088

6189
BENCHMARK("sort")
6290
{
63-
for (auto [camera, list] : lists) {
64-
list = drawing::sort(list, camera.position());
91+
std::vector<std::vector<TileBounds>> tmp;
92+
tmp.reserve(lists.size());
93+
for (const auto& [camera, list] : tile_bound_lists) {
94+
tmp.push_back(drawing::sort(list, camera.position()));
95+
}
96+
return tmp;
97+
};
98+
99+
BENCHMARK("cull")
100+
{
101+
std::vector<std::vector<TileBounds>> tmp;
102+
tmp.reserve(lists.size());
103+
for (const auto& [camera, list] : tile_bound_lists) {
104+
tmp.push_back(drawing::cull(list, camera));
65105
}
106+
return tmp;
66107
};
67108
}

0 commit comments

Comments
 (0)