diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2023-02-25 20:11:31 +0100 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2023-02-25 20:11:31 +0100 |
commit | 61def2af0683013866cc4eecd150b8edf76b97da (patch) | |
tree | 166704e99217f8a7db7f24372182190c9b78465d /src/chunk-collision.cpp | |
parent | eb8c57873f6120b8e37fefd170b4adcaf929928e (diff) |
a
Diffstat (limited to 'src/chunk-collision.cpp')
-rw-r--r-- | src/chunk-collision.cpp | 101 |
1 files changed, 101 insertions, 0 deletions
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 |