diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2022-12-06 17:27:44 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2022-12-06 17:29:25 +0100 |
commit | 646f9d9774d72e9459f50726b200a586d7e07614 (patch) | |
tree | b3f0357c62e252298cbe6c5a8ed314373ac2d5cd | |
parent | d73d869bc195bf8dbb7525ce12acf2c2fde56084 (diff) |
src/chunk: stick bboxes into the pointer on 64-bit
-rw-r--r-- | compat/LooseQuadtree-impl.h | 10 | ||||
-rw-r--r-- | src/chunk-bbox.cpp | 187 | ||||
-rw-r--r-- | src/chunk.cpp | 91 | ||||
-rw-r--r-- | src/chunk.hpp | 39 | ||||
-rw-r--r-- | src/collision.cpp | 85 | ||||
-rw-r--r-- | src/collision.hpp | 92 | ||||
-rw-r--r-- | test/bbox.cpp | 42 | ||||
-rw-r--r-- | test/quadtree.cpp | 34 |
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 |