summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/RTree.cpp2
-rw-r--r--src/RTree.h13
-rw-r--r--src/RTree.hpp36
-rw-r--r--src/chunk-collision.cpp101
-rw-r--r--src/chunk.hpp16
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,