diff options
Diffstat (limited to 'src/chunk-collision.cpp')
-rw-r--r-- | src/chunk-collision.cpp | 92 |
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 |