diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/RTree.cpp | 2 | ||||
| -rw-r--r-- | src/RTree.h | 13 | ||||
| -rw-r--r-- | src/RTree.hpp | 36 | ||||
| -rw-r--r-- | src/chunk-collision.cpp | 101 | ||||
| -rw-r--r-- | src/chunk.hpp | 16 |
5 files changed, 150 insertions, 18 deletions
diff --git a/src/RTree.cpp b/src/RTree.cpp index c6f79c77..32323e69 100644 --- a/src/RTree.cpp +++ b/src/RTree.cpp @@ -1,3 +1,3 @@ #include "RTree.hpp" -template class RTree<void*, unsigned, 2, float>; +template class RTree<std::uint64_t, float, 2, float>; diff --git a/src/RTree.h b/src/RTree.h index 50fd0384..f4139450 100644 --- a/src/RTree.h +++ b/src/RTree.h @@ -7,7 +7,6 @@ //#define RTREE_STDIO -#include "compat/assert.hpp" #ifdef RTREE_STDIO #include <stdio.h> #endif @@ -18,9 +17,6 @@ // RTree.h // -#define RTREE_TEMPLATE template<class DATATYPE, class ELEMTYPE, int NUMDIMS, class ELEMTYPEREAL, int TMAXNODES, int TMINNODES> -#define RTREE_QUAL RTree<DATATYPE, ELEMTYPE, NUMDIMS, ELEMTYPEREAL, TMAXNODES, TMINNODES> - #define RTREE_DONT_USE_MEMPOOLS // This version does not contain a fixed memory allocator, fill in lines with EXAMPLE to implement one. #define RTREE_USE_SPHERICAL_VOLUME // Better split classification, may be slower on some systems @@ -69,7 +65,8 @@ public: RTree(); RTree(const RTree& other); - virtual ~RTree(); + virtual ~RTree() noexcept; + RTree& operator=(const RTree&); /// Insert entry /// \param a_min Min of bounding rect @@ -180,8 +177,6 @@ public: /// Get object at iterator position DATATYPE& GetAt(Iterator& a_it) { return *a_it; } -protected: - /// Minimal bounding rectangle (n-dimensional) struct Rect { @@ -189,6 +184,8 @@ protected: ELEMTYPE m_max[NUMDIMS]; ///< Max dimensions of bounding box }; +protected: + /// May be data or may be another subtree /// The parents level determines this. /// If the parents level is 0, then this is data @@ -281,7 +278,7 @@ public: void ListTree(std::vector<Rect>& vec, std::vector<Node*>& temp) const; }; -extern template class RTree<void*, unsigned, 2, float>; +extern template class RTree<std::uint64_t, float, 2, float>; //#undef RTREE_TEMPLATE //#undef RTREE_QUAL diff --git a/src/RTree.hpp b/src/RTree.hpp index e421db5a..a8f9e031 100644 --- a/src/RTree.hpp +++ b/src/RTree.hpp @@ -1,7 +1,6 @@ #pragma once #include "RTree.h" - #include <math.h> #include <stdlib.h> #include <cassert> @@ -14,6 +13,14 @@ #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" #endif +#define RTREE_TEMPLATE template<class DATATYPE, class ELEMTYPE, int NUMDIMS, class ELEMTYPEREAL, int TMAXNODES, int TMINNODES> +#define RTREE_QUAL RTree<DATATYPE, ELEMTYPE, NUMDIMS, ELEMTYPEREAL, TMAXNODES, TMINNODES> +#undef _DEBUG +#ifndef FM_NO_DEBUG +#define _DEBUG +#endif + +#include "compat/assert.hpp" //#define ASSERT assert // RTree uses ASSERT( condition ) #undef ASSERT #define ASSERT fm_assert @@ -134,9 +141,19 @@ RTREE_QUAL::RTree(const RTree& other) : RTree() CopyRec(m_root, other.m_root); } +RTREE_TEMPLATE +RTREE_QUAL& RTREE_QUAL::operator=(const RTree& other) +{ + if (&other != this) + { + RemoveAll(); + CopyRec(m_root, other.m_root); + } + return *this; +} RTREE_TEMPLATE -RTREE_QUAL::~RTree() +RTREE_QUAL::~RTree() noexcept { Reset(); // Free, or reset node memory } @@ -1293,13 +1310,10 @@ bool RTREE_QUAL::Search(Node* a_node, Rect* a_rect, int& a_foundCount, F&& callb { if(Overlap(a_rect, &a_node->m_branch[index].m_rect)) { - DATATYPE& id = a_node->m_branch[index].m_data; ++a_foundCount; - - if(callback && !callback(id)) - { - return false; // Don't continue searching - } + const Rect& r = a_node->m_branch[index].m_rect; + if(!callback(a_node->m_branch[index].m_data, r)) + return false; // Don't continue searching } } } @@ -1460,6 +1474,12 @@ bool RTREE_QUAL::Iterator::FindNextData() } } +#undef _DEBUG +#undef ASSERT + +#undef RTREE_QUAL +#undef RTREE_TEMPLATE + #ifdef __GNUG__ #pragma GCC diagnostic pop #endif diff --git a/src/chunk-collision.cpp b/src/chunk-collision.cpp new file mode 100644 index 00000000..bec90f32 --- /dev/null +++ b/src/chunk-collision.cpp @@ -0,0 +1,101 @@ +#include "chunk.hpp" +#include "RTree.hpp" +#include "tile-atlas.hpp" +#include <bit> +#include <Corrade/Containers/PairStl.h> + +namespace floormat { + +namespace { + +constexpr Vector2 tile_start(std::size_t k) +{ + const auto i = std::uint8_t(k); + const local_coords coord{i}; + return TILE_SIZE2 * Vector2(coord.x, coord.y) - TILE_SIZE2*.5f; +} + +constexpr Pair<Vector2, Vector2> scenery_tile(std::size_t k, const scenery& sc) +{ + constexpr auto half = Vector2(TILE_SIZE2)/2; + auto center = tile_start(k) + Vector2(sc.bbox_offset) + half; + auto start = center - Vector2(sc.bbox_size); + auto size = Vector2(sc.bbox_size)*2; + return { start, start + size, }; +}; + +constexpr Pair<Vector2, Vector2> whole_tile(std::size_t k) +{ + auto start = tile_start(k); + return { start, start + TILE_SIZE2, }; +}; + +constexpr Pair<Vector2, Vector2> wall_north(std::size_t k) +{ + auto start = tile_start(k) - Vector2(0, 1); + return { start, start + Vector2(TILE_SIZE2[0], 2), }; +}; + +constexpr Pair<Vector2, Vector2> wall_west(std::size_t k) +{ + auto start = tile_start(k) - Vector2(1, 0); + return { start, start + Vector2(2, TILE_SIZE2[1]), }; +}; + +constexpr std::uint64_t make_id(collision_type type, std::uint64_t id) +{ + return std::bit_cast<std::uint64_t>(collision_data { (std::uint64_t)type, id }); +} + +} // namespace + +void chunk::ensure_passability() noexcept +{ + if (!_pass_modified) + return; + _pass_modified = false; + + _rtree.RemoveAll(); + + for (std::size_t i = 0; i < TILE_COUNT; i++) + { + auto tile = operator[](i); + if (auto s = tile.scenery()) + if (s.frame.passability != pass_mode::pass && Vector2ui(s.frame.bbox_size).product() > 0) + { + auto [start, end] = scenery_tile(i, s.frame); + auto id = make_id(collision_type::scenery, i); + _rtree.Insert(start.data(), end.data(), id); + } + } + for (std::size_t i = 0; i < TILE_COUNT; i++) + { + if (const auto* atlas = ground_atlas_at(i)) + if (atlas->pass_mode(pass_mode::pass) != pass_mode::pass) + { + auto [start, end] = whole_tile(i); + auto id = make_id(collision_type::geometry, i); + _rtree.Insert(start.data(), end.data(), id); + } + } + for (std::size_t i = 0; i < TILE_COUNT; i++) + { + auto tile = operator[](i); + if (const auto* atlas = tile.wall_north_atlas().get()) + if (atlas->pass_mode(pass_mode::blocked) != pass_mode::pass) + { + auto [start, end] = wall_north(i); + auto id = make_id(collision_type::geometry, i); + _rtree.Insert(start.data(), end.data(), id); + } + if (const auto* atlas = tile.wall_west_atlas().get()) + if (atlas->pass_mode(pass_mode::blocked) != pass_mode::pass) + { + auto [start, end] = wall_west(i); + auto id = make_id(collision_type::geometry, i); + _rtree.Insert(start.data(), end.data(), id); + } + } +} + +} // namespace floormat diff --git a/src/chunk.hpp b/src/chunk.hpp index 9dd0f117..f117237c 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -4,9 +4,9 @@ #include "scenery.hpp" #include <type_traits> #include <array> -#include <vector> #include <memory> #include <Magnum/GL/Mesh.h> +#include "RTree.h" namespace floormat { @@ -16,6 +16,15 @@ enum class collision : std::uint8_t { view, shoot, move, }; +enum class collision_type : std::uint8_t { + none, entity, scenery, geometry, +}; + +struct collision_data final { + std::uint64_t tag : 2; + std::uint64_t data : 62; +}; + struct chunk final { friend struct tile_ref; @@ -77,6 +86,8 @@ struct chunk final void ensure_passability() noexcept; + RTree<std::uint64_t, float, 2, float>* rtree() const noexcept { return &const_cast<chunk*>(this)->_rtree; } + private: std::array<std::shared_ptr<tile_atlas>, TILE_COUNT> _ground_atlases; std::array<std::uint8_t, TILE_COUNT> ground_indexes = {}; @@ -89,6 +100,9 @@ private: std::array<scenery, TILE_COUNT> _scenery_variants = {}; GL::Mesh ground_mesh{NoCreate}, wall_mesh{NoCreate}, scenery_mesh{NoCreate}; + + RTree<std::uint64_t, float, 2, float> _rtree; + mutable bool _maybe_empty : 1 = true, _ground_modified : 1 = true, _walls_modified : 1 = true, |
