summaryrefslogtreecommitdiffhomepage
path: root/src/chunk-collision.cpp
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2023-03-01 17:23:27 +0100
committerStanislaw Halik <sthalik@misaki.pl>2023-03-01 17:23:27 +0100
commit257c2420545eb632a53c0fe3cd317be613dcb272 (patch)
tree95dfb97898f84ea60b293e60453bef1c57088fa4 /src/chunk-collision.cpp
parentf6aed5a3ae2e6b2b2eb822deee0a579ca66cd13f (diff)
editor: update bboxes from a central place
Diffstat (limited to 'src/chunk-collision.cpp')
-rw-r--r--src/chunk-collision.cpp92
1 files changed, 68 insertions, 24 deletions
diff --git a/src/chunk-collision.cpp b/src/chunk-collision.cpp
index 5b85de1e..bd761b03 100644
--- a/src/chunk-collision.cpp
+++ b/src/chunk-collision.cpp
@@ -18,36 +18,36 @@ constexpr Vector2 tile_start(std::size_t k)
return TILE_SIZE2 * Vector2(coord) - half_tile;
}
-constexpr Pair<Vector2, Vector2> scenery_tile(std::size_t k, const scenery& sc)
+constexpr Pair<Vector2i, Vector2i> scenery_tile(std::size_t k, const scenery& sc)
{
const local_coords coord{k};
- auto center = TILE_SIZE2 * Vector2(coord) + Vector2(sc.offset) + Vector2(sc.bbox_offset);
- auto start = center - Vector2(sc.bbox_size);
- auto size = Vector2(sc.bbox_size)*2;
+ auto center = iTILE_SIZE2 * Vector2i(coord) + Vector2i(sc.offset) + Vector2i(sc.bbox_offset);
+ auto start = center - Vector2i(sc.bbox_size);
+ auto size = Vector2i(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)
+constexpr std::uint64_t make_id(collision_type type, pass_mode p, std::uint64_t id)
{
- return std::bit_cast<std::uint64_t>(collision_data { (std::uint64_t)type, id });
+ return std::bit_cast<std::uint64_t>(collision_data { (std::uint64_t)type, (std::uint64_t)p, id });
}
} // namespace
@@ -62,22 +62,20 @@ void chunk::ensure_passability() noexcept
for (auto i = 0_uz; 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);
- }
+ if (auto s = operator[](i).scenery())
+ {
+ bbox box;
+ if (_bbox_for_scenery(i, box))
+ _add_bbox(box);
+ }
}
for (auto i = 0_uz; i < TILE_COUNT; i++)
{
if (const auto* atlas = ground_atlas_at(i))
- if (atlas->pass_mode(pass_mode::pass) != pass_mode::pass)
+ if (auto p = atlas->pass_mode(pass_mode::pass); p != pass_mode::pass)
{
auto [start, end] = whole_tile(i);
- auto id = make_id(collision_type::geometry, i);
+ auto id = make_id(collision_type::geometry, p, i);
_rtree.Insert(start.data(), end.data(), id);
}
}
@@ -85,20 +83,66 @@ void chunk::ensure_passability() noexcept
{
auto tile = operator[](i);
if (const auto* atlas = tile.wall_north_atlas().get())
- if (atlas->pass_mode(pass_mode::blocked) != pass_mode::pass)
+ if (auto p = atlas->pass_mode(pass_mode::blocked); p != pass_mode::pass)
{
auto [start, end] = wall_north(i);
- auto id = make_id(collision_type::geometry, i);
+ auto id = make_id(collision_type::geometry, p, 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)
+ if (auto p = atlas->pass_mode(pass_mode::blocked); p != pass_mode::pass)
{
auto [start, end] = wall_west(i);
- auto id = make_id(collision_type::geometry, i);
+ auto id = make_id(collision_type::geometry, p, i);
_rtree.Insert(start.data(), end.data(), id);
}
}
}
+bool chunk::_bbox_for_scenery(std::size_t i, bbox& value) noexcept
+{
+ fm_debug_assert(i < TILE_COUNT);
+ auto [atlas, s] = operator[](i).scenery();
+ auto [start, end] = scenery_tile(i, s);
+ auto id = make_id(collision_type::scenery, s.passability, i);
+ value = { .id = id, .start = start, .end = end };
+ return atlas && s.passability != pass_mode::pass && Vector2i(s.bbox_size).product() > 0;
+}
+
+void chunk::_remove_bbox(const bbox& x)
+{
+ auto start = Vector2(x.start), end = Vector2(x.end);
+ fm_assert(_rtree.Remove(start.data(), end.data(), x.id));
+}
+
+void chunk::_add_bbox(const bbox& x)
+{
+ auto start = Vector2(x.start), end = Vector2(x.end);
+ _rtree.Insert(start.data(), end.data(), x.id);
+}
+
+void chunk::_replace_bbox(const bbox& x0, const bbox& x1, bool b0, bool b1)
+{
+ unsigned i = (unsigned)b1 << 1 | (unsigned)(b0 ? 1 : 0) << 0;
+ CORRADE_ASSUME(i < 4u);
+
+ switch (i) // NOLINT(hicpp-multiway-paths-covered)
+ {
+ case 1 << 1 | 1 << 0:
+ if (x1 == x0)
+ return;
+ _remove_bbox(x0);
+ [[fallthrough]];
+ case 1 << 1 | 0 << 0:
+ _add_bbox(x1);
+ return;
+ case 0 << 1 | 1 << 0:
+ _remove_bbox(x0);
+ return;
+ case 0 << 1 | 0 << 0:
+ return;
+ }
+ CORRADE_ASSUME(false);
+}
+
} // namespace floormat