diff options
Diffstat (limited to 'src/chunk-collision.cpp')
| -rw-r--r-- | src/chunk-collision.cpp | 90 |
1 files changed, 44 insertions, 46 deletions
diff --git a/src/chunk-collision.cpp b/src/chunk-collision.cpp index ec6f4ff2..b0170755 100644 --- a/src/chunk-collision.cpp +++ b/src/chunk-collision.cpp @@ -10,6 +10,7 @@ #include "src/hole.hpp" #include "src/wall-atlas.hpp" #include <bit> +#include <utility> #include <Corrade/Containers/StructuredBindings.h> #include <Corrade/Containers/Pair.h> @@ -17,7 +18,7 @@ namespace floormat { bool collision_data::operator==(const collision_data&) const noexcept = default; bool chunk::bbox::operator==(const floormat::chunk::bbox& other) const noexcept = default; -chunk::RTree* chunk::rtree() noexcept { ensure_passability(); return &*_rtree; } +Chunk_RTree* chunk::rtree() noexcept { ensure_passability(); return &*_rtree; } world& chunk::world() noexcept { return *_world; } namespace { @@ -34,7 +35,7 @@ constexpr object_id make_id(collision_type type, pass_mode p, object_id id) } template<bool IsNeighbor> -bool add_holes_from_chunk(chunk::RTree& rtree, chunk& c, Vector2b chunk_offset) +bool add_holes_from_chunk(Chunk_RTree& rtree, chunk& c, Vector2b chunk_offset) { bool has_holes = false; constexpr auto chunk_size = iTILE_SIZE2 * TILE_MAX_DIM; @@ -65,47 +66,22 @@ bool add_holes_from_chunk(chunk::RTree& rtree, chunk& c, Vector2b chunk_offset) return has_holes; } -#if 1 -CORRADE_NEVER_INLINE -bool find_hole_in_bbox(CutResult<float>::rect& hole, chunk::RTree& rtree, Vector2 min, Vector2 max) -{ - bool ret = true; - rtree.Search(min.data(), max.data(), [&](uint64_t data, const chunk::RTree::Rect& r) { - auto x = std::bit_cast<collision_data>(data); - if (x.pass == (uint64_t)pass_mode::pass && x.tag == (uint64_t)collision_type::none) - { - CutResult<float>::rect holeʹ { - .min = { r.m_min[0], r.m_min[1] }, - .max = { r.m_max[0], r.m_max[1] }, - }; - if (rect_intersects(holeʹ.min, holeʹ.max, min, max)) - { - hole = holeʹ; - return ret = false; - } - } - return true; - }); - return ret; -} - -CORRADE_NEVER_INLINE -void filter_through_holes(chunk::RTree& rtree, object_id id, Vector2 min, Vector2 max, bool has_holes) +void filter_through_holes(Chunk_RTree& rtree, object_id id, Vector2 min, Vector2 max, bool has_holes) { if (!has_holes) return rtree.Insert(min.data(), max.data(), id); start: - fm_assert(min != max); // todo! + fm_assert(min != max); CutResult<float>::rect hole; - bool ret = find_hole_in_bbox(hole, rtree, min, max); + bool ret = chunk::find_hole_in_bbox(hole, rtree, min, max); if (ret) [[likely]] rtree.Insert(min.data(), max.data(), id); else { auto res = CutResult<float>::cut(min, max, hole.min, hole.max); - if (!res.found) + if (!res.found()) { rtree.Insert(min.data(), max.data(), id); } @@ -117,19 +93,40 @@ start: } else { - for (auto i = 0uz; i < res.size; i++) + for (auto i = 0u; i < res.size; i++) filter_through_holes(rtree, id, res.array[i].min, res.array[i].max, has_holes); } } } -#else -void filter_through_holes(chunk::RTree& rtree, object_id id, Vector2 min, Vector2 max, bool) + +} // namespace + +#if 1 +bool chunk::find_hole_in_bbox(CutResult<float>::rect& hole, const Chunk_RTree& rtree, Vector2 min, Vector2 max) { - rtree.Insert(min.data(), max.data(), id); + bool ret = true; + rtree.Search(min.data(), max.data(), [&](uint64_t data, const Chunk_RTree::Rect& r) { + auto x = std::bit_cast<collision_data>(data); + if (x.pass == (uint64_t)pass_mode::pass && x.type == (uint64_t)collision_type::none) + { + CutResult<float>::rect holeʹ { + .min = { r.m_min[0], r.m_min[1] }, + .max = { r.m_max[0], r.m_max[1] }, + }; + if (rect_intersects(holeʹ.min, holeʹ.max, min, max)) + { + hole = holeʹ; + return ret = false; + } + } + return true; + }); + return ret; } +#else +bool chunk::find_hole_in_bbox(CutResult<float>::rect&, Chunk_RTree&, Vector2, Vector2) { return true; } #endif - -} // namespace +bool chunk::find_hole_in_bbox(CutResult<float>::rect& hole, Vector2 min, Vector2 max) { return find_hole_in_bbox(hole, *rtree(), min, max); } void chunk::ensure_passability() noexcept { @@ -143,15 +140,16 @@ void chunk::ensure_passability() noexcept //Debug{} << ".. reset passability" << _coord; bool has_holes = false; + auto& rtree = *_rtree; { - has_holes |= add_holes_from_chunk<false>(*_rtree, *this, {}); + has_holes |= add_holes_from_chunk<false>(rtree, *this, {}); const auto nbs = _world->neighbors(_coord); for (auto i = 0u; i < 8; i++) if (nbs[i]) - has_holes |= add_holes_from_chunk<true>(*_rtree, *nbs[i], world::neighbor_offsets[i]); + has_holes |= add_holes_from_chunk<true>(rtree, *nbs[i], world::neighbor_offsets[i]); } - for (auto i = 0uz; i < TILE_COUNT; i++) + for (auto i = 0u; i < TILE_COUNT; i++) { if (const auto* atlas = ground_atlas_at(i)) { @@ -160,29 +158,29 @@ void chunk::ensure_passability() noexcept if (pass == pass_mode::pass) [[likely]] continue; auto id = make_id(collision_type::geometry, pass, i+1); - filter_through_holes(*_rtree, id, min, max, has_holes); + filter_through_holes(rtree, id, min, max, has_holes); } } - for (auto i = 0uz; i < TILE_COUNT; i++) + for (auto i = 0u; i < TILE_COUNT; i++) { auto tile = operator[](i); if (const auto* atlas = tile.wall_north_atlas().get()) { auto [min, max] = wall_north(i, (float)atlas->info().depth); auto id = make_id(collision_type::geometry, atlas->info().passability, TILE_COUNT+i+1); - filter_through_holes(*_rtree, id, min, max, has_holes); + filter_through_holes(rtree, id, min, max, has_holes); if (tile.wall_west_atlas()) { auto [min, max] = wall_pillar(i, (float)atlas->info().depth); - filter_through_holes(*_rtree, id, min, max, has_holes); + filter_through_holes(rtree, id, min, max, has_holes); } } if (const auto* atlas = tile.wall_west_atlas().get()) { auto [min, max] = wall_west(i, (float)atlas->info().depth); auto id = make_id(collision_type::geometry, atlas->info().passability, TILE_COUNT*2+i+1); - filter_through_holes(*_rtree, id, min, max, has_holes); + filter_through_holes(rtree, id, min, max, has_holes); } } for (const bptr<object>& eʹ : objects()) @@ -193,7 +191,7 @@ void chunk::ensure_passability() noexcept if (_bbox_for_scenery(*eʹ, bb)) { if (!eʹ->is_dynamic()) - filter_through_holes(*_rtree, std::bit_cast<object_id>(bb.data), Vector2(bb.start), Vector2(bb.end), has_holes); + filter_through_holes(rtree, std::bit_cast<object_id>(bb.data), Vector2(bb.start), Vector2(bb.end), has_holes); else _add_bbox_dynamic(bb); } |
