summaryrefslogtreecommitdiffhomepage
path: root/src/chunk-collision.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/chunk-collision.cpp')
-rw-r--r--src/chunk-collision.cpp90
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);
}