summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2022-12-06 17:27:44 +0100
committerStanislaw Halik <sthalik@misaki.pl>2022-12-06 17:29:25 +0100
commit646f9d9774d72e9459f50726b200a586d7e07614 (patch)
treeb3f0357c62e252298cbe6c5a8ed314373ac2d5cd
parentd73d869bc195bf8dbb7525ce12acf2c2fde56084 (diff)
src/chunk: stick bboxes into the pointer on 64-bit
-rw-r--r--compat/LooseQuadtree-impl.h10
-rw-r--r--src/chunk-bbox.cpp187
-rw-r--r--src/chunk.cpp91
-rw-r--r--src/chunk.hpp39
-rw-r--r--src/collision.cpp85
-rw-r--r--src/collision.hpp92
-rw-r--r--test/bbox.cpp42
-rw-r--r--test/quadtree.cpp34
8 files changed, 310 insertions, 270 deletions
diff --git a/compat/LooseQuadtree-impl.h b/compat/LooseQuadtree-impl.h
index ff25f682..08591072 100644
--- a/compat/LooseQuadtree-impl.h
+++ b/compat/LooseQuadtree-impl.h
@@ -1265,6 +1265,16 @@ void LooseQuadtree<NumberT, ObjectT, BoundingBoxExtractorT>::Query::Next() {
}
+template <typename NumberT>
+struct TrivialBBExtractor {
+ static void ExtractBoundingBox(const BoundingBox<NumberT> *object, BoundingBox<NumberT> *bbox)
+ {
+ bbox->left = object->left;
+ bbox->top = object->top;
+ bbox->width = object->width;
+ bbox->height = object->height;
+ }
+};
} // namespace loose_quadtree
diff --git a/src/chunk-bbox.cpp b/src/chunk-bbox.cpp
new file mode 100644
index 00000000..78c10a4f
--- /dev/null
+++ b/src/chunk-bbox.cpp
@@ -0,0 +1,187 @@
+#include "chunk.hpp"
+#include "compat/LooseQuadtree-impl.h"
+#include "src/tile-atlas.hpp"
+#include "src/collision.hpp"
+#include <bit>
+#include <Magnum/Math/Vector4.h>
+
+namespace floormat {
+
+template<>
+struct chunk::insert_into_lqt<false>
+{
+ using BB = loose_quadtree::BoundingBox<std::int16_t>;
+ using TBBE = loose_quadtree::TrivialBBExtractor<std::int16_t>;
+ static BB* insert(const BB& bbox, std::vector<BB>& vec)
+ {
+ vec.push_back(bbox);
+ return &vec.back();
+ }
+};
+
+template<>
+struct chunk::insert_into_lqt<true>
+{
+ using BB = loose_quadtree::BoundingBox<std::int16_t>;
+ static compact_bb* insert(const BB& bbox, std::vector<void**>&)
+ {
+ if constexpr(sizeof(void*) >= sizeof(BB))
+ return std::bit_cast<compact_bb*>(bbox);
+ else
+ return {};
+ }
+};
+
+struct collision_bbox final
+{
+ using BB = loose_quadtree::BoundingBox<std::int16_t>;
+ operator BB() const noexcept;
+
+ std::int16_t left = 0, top = 0;
+ std::uint16_t width = 0, height = 0;
+ enum pass_mode pass_mode = pass_mode::pass;
+};
+
+collision_bbox::operator BB() const noexcept
+{
+ return { left, top, (std::int16_t)width, (std::int16_t)height };
+}
+
+static constexpr Vector2s tile_start(std::size_t k)
+{
+ const auto i = std::uint8_t(k);
+ const local_coords coord{i};
+ return sTILE_SIZE2 * Vector2s(coord.x, coord.y) - sTILE_SIZE2/2;
+}
+
+void chunk::ensure_passability() noexcept
+{
+ if (!_pass_modified)
+ return;
+ _pass_modified = false;
+
+ if (!_lqt_move)
+ _lqt_move = make_lqt();
+ if (!_lqt_shoot)
+ _lqt_shoot = make_lqt();
+ if (!_lqt_view)
+ _lqt_view = make_lqt();
+
+ _lqt_move->Clear();
+ _lqt_shoot->Clear();
+ _lqt_view->Clear();
+ _bboxes.clear();
+
+ std::vector<collision_bbox> bboxes; bboxes.reserve(TILE_COUNT*4);
+
+ constexpr auto whole_tile = [](std::size_t k, pass_mode p) constexpr -> collision_bbox {
+ auto start = tile_start(k);
+ return { start[0], start[1], usTILE_SIZE2[0], usTILE_SIZE2[1], p };
+ };
+
+ constexpr auto wall_north = [](std::size_t k, pass_mode p) constexpr -> collision_bbox {
+ auto start = tile_start(k) - Vector2s(0, 1);
+ return { start[0], start[1], usTILE_SIZE2[0], 2, p };
+ };
+
+ constexpr auto wall_west = [](std::size_t k, pass_mode p) constexpr -> collision_bbox {
+ auto start = tile_start(k) - Vector2s(1, 0);
+ return { start[0], start[1], 2, usTILE_SIZE2[1], p };
+ };
+
+ for (std::size_t i = 0; i < TILE_COUNT; i++)
+ {
+ const auto tile = const_cast<chunk&>(*this)[i];
+ if (auto s = tile.scenery())
+ if (auto p = s.frame.passability; p != pass_mode::pass)
+ bboxes.push_back(whole_tile(i, p));
+ if (auto atlas = tile.ground_atlas())
+ if (auto p = atlas->pass_mode(pass_mode::pass); p != pass_mode::pass)
+ bboxes.push_back(whole_tile(i, p));
+ if (auto atlas = tile.wall_north_atlas())
+ if (auto p = atlas->pass_mode(pass_mode::blocked); p != pass_mode::pass)
+ bboxes.push_back(wall_north(i, p));
+ if (auto atlas = tile.wall_west_atlas())
+ if (auto p = atlas->pass_mode(pass_mode::blocked); p != pass_mode::pass)
+ bboxes.push_back(wall_west(i, p));
+ }
+
+ if constexpr (!lqt_compact_bb)
+ _bboxes.reserve(bboxes.size());
+
+ for (const collision_bbox& bbox : bboxes)
+ {
+ auto* ptr = insert_into_lqt<lqt_compact_bb>::insert(bbox, _bboxes);
+
+ switch (bbox.pass_mode)
+ {
+ case pass_mode::blocked:
+ _lqt_view->Insert(ptr);
+ [[fallthrough]];
+ case pass_mode::see_through:
+ _lqt_shoot->Insert(ptr);
+ [[fallthrough]];
+ case pass_mode::shoot_through:
+ _lqt_move->Insert(ptr);
+ break;
+ case pass_mode::pass:
+ break;
+ }
+ }
+}
+
+auto chunk::query_collisions(Vector4s vec, collision type) const -> Query
+{
+ const_cast<chunk&>(*this).ensure_passability();
+ loose_quadtree::BoundingBox<std::int16_t> bbox { vec[0], vec[1], vec[2], vec[3] };
+ return { lqt_from_collision_type(type).QueryIntersectsRegion(bbox) };
+}
+
+auto chunk::query_collisions(Vector2s position, Vector2us size, collision type) const -> Query
+{
+ const_cast<chunk&>(*this).ensure_passability();
+ constexpr auto half = sTILE_SIZE2/2;
+ const auto start = position - half;
+ loose_quadtree::BoundingBox<std::int16_t> bbox {start[0], start[1], (Short)size[0], (Short)size[1] };
+ return { lqt_from_collision_type(type).QueryIntersectsRegion(bbox) };
+}
+
+auto chunk::query_collisions(local_coords p, Vector2us size, Vector2s offset, collision type) const -> Query
+{
+ const_cast<chunk&>(*this).ensure_passability();
+ const auto pos = Vector2s(p.x, p.y) * sTILE_SIZE2 + offset;
+ const auto start = pos - Vector2s(size/2);
+ loose_quadtree::BoundingBox<std::int16_t> bbox { start[0], start[1], (Short)size[0], (Short)size[1] };
+ return { lqt_from_collision_type(type).QueryIntersectsRegion(bbox) };
+}
+
+auto chunk::lqt_from_collision_type(collision type) const noexcept -> lqt&
+{
+ switch (type)
+ {
+ case collision::move:
+ return *_lqt_move;
+ case collision::shoot:
+ return *_lqt_shoot;
+ case collision::view:
+ return *_lqt_view;
+ }
+ fm_abort("wrong collision type '%hhu'", std::uint8_t(type));
+}
+
+auto chunk::make_lqt() -> std::unique_ptr<lqt>
+{
+ return std::make_unique<lqt>();
+}
+
+void chunk::cleanup_lqt()
+{
+ if (_lqt_move)
+ _lqt_move->ForceCleanup();
+ if (_lqt_shoot)
+ _lqt_shoot->ForceCleanup();
+ if (_lqt_view)
+ _lqt_view->ForceCleanup();
+}
+
+} // namespace floormat
diff --git a/src/chunk.cpp b/src/chunk.cpp
index f40480ee..cb9760e1 100644
--- a/src/chunk.cpp
+++ b/src/chunk.cpp
@@ -1,8 +1,6 @@
#include "chunk.hpp"
-#include "compat/LooseQuadtree-impl.h"
-#include "src/collision.hpp"
#include "src/tile-atlas.hpp"
-#include <Magnum/Math/Vector4.h>
+#include "compat/LooseQuadtree-impl.h"
namespace floormat {
@@ -42,94 +40,13 @@ void chunk::mark_modified() noexcept
mark_scenery_modified();
}
-static constexpr auto tile_size2us = Vector2us(iTILE_SIZE2);
-
-static constexpr Vector2s tile_start(std::size_t k)
-{
- const auto i = std::uint8_t(k);
- const local_coords coord{i};
- constexpr auto tile_size2s = Vector2s(tile_size2us), half = tile_size2s/2;
- return tile_size2s * Vector2s(coord.x, coord.y) - half;
-}
-
-auto chunk::ensure_passability() noexcept -> lqt&
-{
- auto& qt = *_static_lqt;
-
- if (!_pass_modified)
- return qt;
- _pass_modified = false;
-
- qt.Clear();
- _lqt_bboxes.clear();
- _lqt_bboxes.reserve(32);
-
- constexpr auto whole_tile = [](std::size_t k, pass_mode p) constexpr -> collision_bbox {
- auto start = tile_start(k);
- return { start[0], start[1], tile_size2us[0], tile_size2us[1], p };
- };
-
- constexpr auto wall_north = [](std::size_t k, pass_mode p) constexpr -> collision_bbox {
- auto start = tile_start(k) - Vector2s(0, 1);
- return { start[0], start[1], tile_size2us[0], 2, p };
- };
-
- constexpr auto wall_west = [](std::size_t k, pass_mode p) constexpr -> collision_bbox {
- auto start = tile_start(k) - Vector2s(1, 0);
- return { start[0], start[1], 2, tile_size2us[1], p };
- };
-
- for (std::size_t i = 0; i < TILE_COUNT; i++)
- {
- const auto tile = const_cast<chunk&>(*this)[i];
- if (auto s = tile.scenery())
- if (auto p = s.frame.passability; p != pass_mode::pass)
- _lqt_bboxes.push_back(whole_tile(i, p));
- if (auto atlas = tile.ground_atlas())
- if (auto p = atlas->pass_mode(pass_mode::pass); p != pass_mode::pass)
- _lqt_bboxes.push_back(whole_tile(i, p));
- if (auto atlas = tile.wall_north_atlas())
- if (auto p = atlas->pass_mode(pass_mode::blocked); p != pass_mode::pass)
- _lqt_bboxes.push_back(wall_north(i, p));
- if (auto atlas = tile.wall_west_atlas())
- if (auto p = atlas->pass_mode(pass_mode::blocked); p != pass_mode::pass)
- _lqt_bboxes.push_back(wall_west(i, p));
- }
-
- for (auto& bbox : _lqt_bboxes)
- qt.Insert(&bbox);
-
- return qt;
-}
-
-using namespace loose_quadtree;
-
-collision_query chunk::query_collisions(Vector4s vec) const
-{
- const_cast<chunk&>(*this).ensure_passability();
- BoundingBox<std::int16_t> bbox { vec[0], vec[1], vec[2], vec[3] };
- return { _static_lqt->QueryIntersectsRegion(bbox) };
-}
-
-collision_query chunk::query_collisions(Vector2s position, Vector2us size) const
-{
- const_cast<chunk&>(*this).ensure_passability();
- constexpr auto half = sTILE_SIZE2/2;
- const auto start = position - half;
- return query_collisions(Vector4s{start[0], start[1], (Short)size[0], (Short)size[1] });
-}
+chunk::chunk() noexcept = default;
-collision_query chunk::query_collisions(local_coords p, Vector2us size, Vector2s offset) const
+chunk::~chunk() noexcept
{
- const_cast<chunk&>(*this).ensure_passability();
- const auto pos = Vector2s(p.x, p.y) * sTILE_SIZE2 + offset;
- const auto start = pos - Vector2s(size/2);
- BoundingBox<std::int16_t> bbox { start[0], start[1], (Short)size[0], (Short)size[1] };
- return { _static_lqt->QueryIntersectsRegion(bbox) };
+ cleanup_lqt();
}
-chunk::chunk() noexcept : _static_lqt { std::make_unique<lqt>() } {}
-chunk::~chunk() noexcept = default;
chunk::chunk(chunk&&) noexcept = default;
chunk& chunk::operator=(chunk&&) noexcept = default;
diff --git a/src/chunk.hpp b/src/chunk.hpp
index a560fa21..2d2a5c75 100644
--- a/src/chunk.hpp
+++ b/src/chunk.hpp
@@ -11,15 +11,22 @@
namespace loose_quadtree {
template<typename Number, typename Object, typename BBExtractor> class LooseQuadtree;
template<typename Number, typename Object, typename BBExtractor> struct Query;
+template<typename Number> struct BoundingBox;
+template<typename Number> struct TrivialBBExtractor;
} // namespace loose_quadtree
namespace floormat {
struct anim_atlas;
-struct collision_iterator;
+template<typename Num, typename BB, typename BBE> struct collision_iterator;
+template<typename Num, typename BB, typename BBE> struct collision_query;
struct collision_bbox;
-struct collision_bb_extractor;
-struct collision_query;
+struct compact_bb;
+struct compact_bb_extractor;
+
+enum class collision : std::uint8_t {
+ view, shoot, move,
+};
struct chunk final
{
@@ -69,12 +76,18 @@ struct chunk final
wall_mesh_tuple ensure_wall_mesh() noexcept;
tile_atlas* wall_atlas_at(std::size_t i) const noexcept;
- using lqt = loose_quadtree::LooseQuadtree<std::int16_t, collision_bbox, collision_bb_extractor>;
- lqt& ensure_passability() noexcept;
+ void ensure_passability() noexcept;
+
+ static constexpr inline bool lqt_compact_bb = sizeof(void*) >= 8;
+ //static constexpr inline bool lqt_compact_bb = false;
+ using BB = std::conditional_t<lqt_compact_bb, compact_bb, loose_quadtree::BoundingBox<std::int16_t>>;
+ using BBE = std::conditional_t<lqt_compact_bb, compact_bb_extractor, loose_quadtree::TrivialBBExtractor<std::int16_t>>;
+ using lqt = loose_quadtree::LooseQuadtree<std::int16_t, BB, BBE>;
+ using Query = collision_query<std::int16_t, BB, BBE>;
- collision_query query_collisions(Vector2s position, Vector2us size) const;
- collision_query query_collisions(local_coords p, Vector2us size, Vector2s offset = {}) const;
- collision_query query_collisions(Vector4s vec) const;
+ Query query_collisions(Vector2s position, Vector2us size, collision type) const;
+ Query query_collisions(local_coords p, Vector2us size, Vector2s offset, collision type) const;
+ Query query_collisions(Vector4s vec, collision type) const;
private:
std::array<std::shared_ptr<tile_atlas>, TILE_COUNT> _ground_atlases;
@@ -86,8 +99,10 @@ private:
std::array<std::shared_ptr<anim_atlas>, TILE_COUNT> _scenery_atlases;
std::array<scenery, TILE_COUNT> _scenery_variants = {};
- std::unique_ptr<lqt> _static_lqt;
- std::vector<collision_bbox> _lqt_bboxes;
+ template<bool> struct insert_into_lqt;
+
+ std::unique_ptr<lqt> _lqt_move, _lqt_shoot, _lqt_view;
+ std::vector<std::conditional_t<lqt_compact_bb, void**, loose_quadtree::BoundingBox<std::int16_t>>> _bboxes;
GL::Mesh ground_mesh{NoCreate}, wall_mesh{NoCreate};
mutable bool _maybe_empty : 1 = true,
@@ -95,6 +110,10 @@ private:
_walls_modified : 1 = true,
_scenery_modified : 1 = true,
_pass_modified : 1 = true;
+
+ lqt& lqt_from_collision_type(collision type) const noexcept;
+ static std::unique_ptr<lqt> make_lqt();
+ void cleanup_lqt();
};
} // namespace floormat
diff --git a/src/collision.cpp b/src/collision.cpp
index 1a9c0b3f..64f33c95 100644
--- a/src/collision.cpp
+++ b/src/collision.cpp
@@ -1,89 +1,12 @@
#include "collision.hpp"
-#include "compat/assert.hpp"
-#include "src/chunk.hpp"
-#include "compat/LooseQuadtree-impl.h"
-#include <utility>
+#include <bit>
namespace floormat {
-void collision_bb_extractor::ExtractBoundingBox(const collision_bbox* x, BB* bbox)
+void compact_bb_extractor::ExtractBoundingBox(compact_bb* object, BB* bbox)
{
- *bbox = { x->left, x->top, std::int16_t(x->width), std::int16_t(x->height) };
-}
-
-collision_iterator::collision_iterator() noexcept : q{nullptr} {}
-collision_iterator::collision_iterator(Query* q) noexcept : q{q} {}
-
-collision_iterator::~collision_iterator() noexcept
-{
- if (q)
- while (!q->EndOfQuery())
- q->Next();
-}
-
-collision_iterator& collision_iterator::operator++() noexcept
-{
- fm_debug_assert(q != nullptr && !q->EndOfQuery());
- q->Next();
- return *this;
-}
-
-auto collision_iterator::operator++(int) noexcept -> const collision_bbox*
-{
- fm_debug_assert(q != nullptr && !q->EndOfQuery());
- auto* bbox = q->GetCurrent();
- fm_debug_assert(bbox != nullptr);
- operator++();
- return bbox;
-}
-
-auto collision_iterator::operator*() const noexcept -> const collision_bbox&
-{
- return *operator->();
-}
-
-auto collision_iterator::operator->() const noexcept -> const collision_bbox*
-{
- fm_debug_assert(q != nullptr && !q->EndOfQuery());
- auto* ptr = q->GetCurrent();
- fm_debug_assert(ptr != nullptr);
- return ptr;
-}
-
-bool collision_iterator::operator==(const collision_iterator& other) const noexcept
-{
- if (q && !other.q) [[likely]]
- return q->EndOfQuery();
- else if (!q && !other.q)
- return true;
- else if (!q)
- return other.q->EndOfQuery();
- else
- return q == other.q;
-}
-
-collision_iterator::operator bool() const noexcept
-{
- return q && !q->EndOfQuery();
-}
-
-collision_query::collision_query(collision_query::Query&& q) noexcept : q{std::move(q)} {}
-collision_iterator collision_query::begin() noexcept { return collision_iterator{&q}; }
-collision_iterator collision_query::end() noexcept { return collision_iterator{nullptr}; }
-
-collision_bbox::operator BB() const noexcept
-{
- return BB{left, top, (Short)width, (Short)height};
-}
-
-bool collision_bbox::intersects(BB bb) const noexcept
-{
- return BB(*this).Intersects(bb);
-}
-
-bool collision_bbox::intersects(collision_bbox bb) const noexcept
-{
- return BB(*this).Intersects(bb);
+ if constexpr(sizeof(void*) >= 8)
+ *bbox = std::bit_cast<loose_quadtree::BoundingBox<std::int16_t>>((void*)object);
}
} // namespace floormat
diff --git a/src/collision.hpp b/src/collision.hpp
index adfec6b0..31be7c1f 100644
--- a/src/collision.hpp
+++ b/src/collision.hpp
@@ -5,59 +5,75 @@
namespace floormat {
-struct collision_bbox final
-{
- using BB = loose_quadtree::BoundingBox<std::int16_t>;
-
- std::int16_t left, top;
- std::uint16_t width, height;
- enum pass_mode pass_mode;
-
- constexpr collision_bbox();
- constexpr collision_bbox(std::int16_t left, std::int16_t top, std::uint16_t width, std::uint16_t height, enum pass_mode p) noexcept;
- operator BB() const noexcept;
- bool intersects(BB bb) const noexcept;
- bool intersects(collision_bbox bb) const noexcept;
-};
-
-constexpr collision_bbox::collision_bbox() :
- left{0}, top{0}, width{0}, height{0}, pass_mode{pass_mode::pass}
-{}
-
-constexpr collision_bbox::collision_bbox(std::int16_t left, std::int16_t top, std::uint16_t width, std::uint16_t height, enum pass_mode p) noexcept :
- left{left}, top{top}, width{width}, height{height}, pass_mode{p}
-{}
+struct compact_bb;
-struct collision_bb_extractor final
+struct compact_bb_extractor final
{
using BB = loose_quadtree::BoundingBox<std::int16_t>;
- static void ExtractBoundingBox(const collision_bbox* object, BB* bbox);
+ [[maybe_unused]] static void ExtractBoundingBox(compact_bb* object, BB* bbox);
};
+template<typename Num, typename BB, typename BBE>
struct collision_iterator final
{
- using Query = typename loose_quadtree::LooseQuadtree<std::int16_t, collision_bbox, collision_bb_extractor>::Query;
+ using Query = typename loose_quadtree::LooseQuadtree<std::int16_t, BB, BBE>::Query;
- explicit collision_iterator() noexcept;
- explicit collision_iterator(Query* q) noexcept;
- ~collision_iterator() noexcept;
- collision_iterator& operator++() noexcept;
- const collision_bbox* operator++(int) noexcept;
- const collision_bbox& operator*() const noexcept;
- const collision_bbox* operator->() const noexcept;
- bool operator==(const collision_iterator& other) const noexcept;
- operator bool() const noexcept;
+ explicit collision_iterator() noexcept : q{nullptr} {}
+ explicit collision_iterator(Query* q) noexcept : q{q} {}
+ ~collision_iterator() noexcept
+ {
+ if (q)
+ while (!q->EndOfQuery())
+ q->Next();
+ }
+ collision_iterator& operator++() noexcept
+ {
+ fm_debug_assert(q != nullptr && !q->EndOfQuery());
+ q->Next();
+ return *this;
+ }
+ const BB* operator++(int) noexcept
+ {
+ fm_debug_assert(q != nullptr && !q->EndOfQuery());
+ auto* bbox = q->GetCurrent();
+ fm_debug_assert(bbox != nullptr);
+ operator++();
+ return bbox;
+ }
+ const BB& operator*() const noexcept { return *operator->(); }
+ const BB* operator->() const noexcept
+ {
+ fm_debug_assert(q != nullptr && !q->EndOfQuery());
+ auto* ptr = q->GetCurrent();
+ fm_debug_assert(ptr != nullptr);
+ return ptr;
+ }
+ bool operator==(const collision_iterator& other) const noexcept
+ {
+ if (q && !other.q) [[likely]]
+ return q->EndOfQuery();
+ else if (!q && !other.q)
+ return true;
+ else if (!q)
+ return other.q->EndOfQuery();
+ else
+ return q == other.q;
+ }
+ operator bool() const noexcept { return q && !q->EndOfQuery(); }
private:
Query* q;
};
+template<typename Num, typename BB, typename BBE>
struct collision_query
{
- using Query = typename loose_quadtree::LooseQuadtree<std::int16_t, collision_bbox, collision_bb_extractor>::Query;
- collision_query(Query&& q) noexcept;
- collision_iterator begin() noexcept;
- static collision_iterator end() noexcept;
+ using Query = typename loose_quadtree::LooseQuadtree<Num, BB, BBE>::Query;
+ collision_query(Query&& q) noexcept : q{std::move(q)} {}
+ ~collision_query() noexcept { while (!q.EndOfQuery()) q.Next(); }
+ collision_iterator<Num, BB, BBE> begin() noexcept { return collision_iterator<Num, BB, BBE>{&q}; }
+ static collision_iterator<Num, BB, BBE> end() noexcept { return collision_iterator<Num, BB, BBE>{nullptr}; }
+ operator bool() const noexcept { return !q.EndOfQuery(); }
private:
Query q;
diff --git a/test/bbox.cpp b/test/bbox.cpp
index 87921271..9ffd6122 100644
--- a/test/bbox.cpp
+++ b/test/bbox.cpp
@@ -2,48 +2,24 @@
#include "src/chunk.hpp"
#include "src/collision.hpp"
#include <Magnum/Math/Vector2.h>
+#include <Magnum/Math/Vector4.h>
namespace floormat {
-static void test_simple(chunk c)
+void test_app::test_bbox()
{
- auto& qt = c.ensure_passability();
- fm_assert(qt.GetSize() >= 2);
+ auto c = make_test_chunk();
- using namespace loose_quadtree;
- using bbox = BoundingBox<std::int16_t>;
constexpr auto pos1 = sTILE_SIZE2 * (TILE_MAX_DIM/2) - Vector2s(0, sTILE_SIZE2[1]/2);
- constexpr auto b1 = bbox{pos1[0], pos1[1], usTILE_SIZE2[0], usTILE_SIZE2[1]};
- auto q1 = qt.QueryIntersectsRegion(b1);
- fm_assert(!q1.EndOfQuery());
- auto x1 = *q1.GetCurrent();
- fm_assert(x1.pass_mode == pass_mode::blocked);
- do q1.Next(); while (!q1.EndOfQuery());
+ constexpr auto b1 = Vector4s{pos1[0], pos1[1], sTILE_SIZE2[0], sTILE_SIZE2[1]};
constexpr auto pos2 = Vector2s(iTILE_SIZE2 * (Vector2i(TILE_MAX_DIM/2) - Vector2i(-1, -1)) - Vector2i(0, iTILE_SIZE[1]/2));
- constexpr auto b2 = bbox{pos2[0], pos2[1], usTILE_SIZE2[0], usTILE_SIZE2[1]};
- auto q2 = qt.QueryIntersectsRegion(b2);
- fm_assert(q2.EndOfQuery());
-}
-
-static void test_wrapper(chunk c)
-{
+ constexpr auto b2 = Vector4s{pos2[0], pos2[1], usTILE_SIZE2[0], usTILE_SIZE2[1]};
{
- int i = 0;
- for (auto b : c.query_collisions(local_coords{TILE_MAX_DIM/2, TILE_MAX_DIM/2},
- usTILE_SIZE2,
- Vector2s(sTILE_SIZE2[0]/2, 0)))
- {
- fm_assert(b.pass_mode == pass_mode::blocked);
- i++;
- }
- fm_assert(i > 0);
+ auto q1 = c.query_collisions(b1, collision::move);
+ fm_assert(q1);
+ auto q2 = c.query_collisions(b2, collision::move);
+ fm_assert(!q2);
}
}
-void test_app::test_bbox()
-{
- test_simple(make_test_chunk());
- test_wrapper(make_test_chunk());
-}
-
} // namespace floormat
diff --git a/test/quadtree.cpp b/test/quadtree.cpp
index 20e270d0..4ad90acc 100644
--- a/test/quadtree.cpp
+++ b/test/quadtree.cpp
@@ -9,6 +9,7 @@
#include "compat/LooseQuadtree.h"
#include "compat/LooseQuadtree-impl.h"
#include "compat/assert.hpp"
+#include "src/collision.hpp"
#include "test/app.hpp"
#include <chrono>
@@ -22,19 +23,6 @@ using namespace loose_quadtree;
namespace {
template <typename NumberT>
-class TrivialBBExtractor {
-public:
- static void ExtractBoundingBox(const BoundingBox<NumberT> *object, BoundingBox<NumberT> *bbox) {
- bbox->left = object->left;
- bbox->top = object->top;
- bbox->width = object->width;
- bbox->height = object->height;
- }
-};
-
-
-
-template <typename NumberT>
void TestBoundingBox() {
BoundingBox<NumberT> big(100, 100, 200, 50);
BoundingBox<NumberT> small_inside(200, 125, 5, 5);
@@ -592,13 +580,11 @@ void TestQueries() {
TestQueryContains<NumberT>(objects, lqt);
}
-
-
template <typename NumberT>
-void StressTest() {
-#ifndef NDEBUG
- const int objects_generated = 10000;
- const int object_fluctuation = 1000;
+[[maybe_unused]] void StressTest() {
+#if 0
+ const int objects_generated = 100;
+ const int object_fluctuation = 10;
#else
const int objects_generated = 200000;
const int object_fluctuation = 20000;
@@ -697,22 +683,28 @@ void StressTest() {
lqt.ForceCleanup();
}
-
+#define FM_NO_QUADTREE_BENCHMARK
template <typename NumberT>
-void RunTests(const char* type_str) {
+void RunTests(const char* type_str)
+{
+ (void)type_str;
+#ifndef FM_NO_QUADTREE_BENCHMARK
printf("quadtree test %13s", type_str);
fflush(stdout);
auto start = std::chrono::high_resolution_clock::now();
+#endif
TestBoundingBox<NumberT>();
TestTraversals<NumberT>();
TestContainer<NumberT>();
TestQueries<NumberT>();
+#ifndef FM_NO_QUADTREE_BENCHMARK
StressTest<NumberT>();
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> time = end - start;
printf(": %.1f ms\n", time.count());
fflush(stdout);
+#endif
}
} // namespace