diff options
author | Stanislaw Halik <sthalik@misaki.pl> | 2024-06-07 23:10:49 +0200 |
---|---|---|
committer | Stanislaw Halik <sthalik@misaki.pl> | 2024-06-08 01:11:44 +0200 |
commit | ec524fddfa0d2583d06ee194b06720be0eee8341 (patch) | |
tree | 663497f84b276308c45fda0b4c0c97da34a71254 | |
parent | 089e50cc986730f05c64ae814e21529fcdd44f91 (diff) |
wa
-rw-r--r-- | src/chunk-collision.cpp | 69 | ||||
-rw-r--r-- | src/chunk.cpp | 79 | ||||
-rw-r--r-- | src/chunk.hpp | 36 | ||||
-rw-r--r-- | src/object.cpp | 48 |
4 files changed, 154 insertions, 78 deletions
diff --git a/src/chunk-collision.cpp b/src/chunk-collision.cpp index 18f6d2bb..ff70932b 100644 --- a/src/chunk-collision.cpp +++ b/src/chunk-collision.cpp @@ -194,7 +194,7 @@ void chunk::ensure_passability() noexcept if (!eʹ->is_dynamic()) filter_through_holes(*_rtree, std::bit_cast<object_id>(bb.data), Vector2(bb.start), Vector2(bb.end), has_holes); else - _add_bbox(bb); + _add_bbox_dynamic(bb); } } fm_assert(!_pass_modified); @@ -214,22 +214,53 @@ bool chunk::_bbox_for_scenery(const object& s, bbox& value) noexcept return _bbox_for_scenery(s, s.coord.local(), s.offset, s.bbox_offset, s.bbox_size, value); } -void chunk::_remove_bbox(const bbox& x) +void chunk::_remove_bbox_static_() { mark_passability_modified(); } +void chunk::_add_bbox_static_() { mark_passability_modified(); } + +void chunk::_remove_bbox_(const bbox& x, bool upd, bool is_dynamic) +{ + if (!is_dynamic || upd) + _remove_bbox_static(x); + else + _remove_bbox_dynamic(x); +} + +void chunk::_remove_bbox_dynamic(const bbox& x) { auto start = Vector2(x.start), end = Vector2(x.end); _rtree->Remove(start.data(), end.data(), std::bit_cast<object_id>(x.data)); - //Debug{} << "bbox <<" << x.data.pass << x.data.data << x.start << x.end << _rtree->Count(); + //Debug{} << "bbox <<< dynamic" << x.data.pass << x.data.data << x.start << x.end << _rtree->Count(); } -void chunk::_add_bbox(const bbox& x) +void chunk::_remove_bbox_static([[maybe_unused]] const bbox& x) +{ + _remove_bbox_static_(); + //Debug{} << "bbox <<< static " << x.data.pass << x.data.data << x.start << x.end << _rtree->Count(); +} + +void chunk::_add_bbox_dynamic(const bbox& x) { auto start = Vector2(x.start), end = Vector2(x.end); _rtree->Insert(start.data(), end.data(), std::bit_cast<object_id>(x.data)); + //Debug{} << "bbox >>> dynamic" << x.data.pass << x.data.data << x.start << x.end << _rtree->Count(); +} + +void chunk::_add_bbox_static([[maybe_unused]]const bbox& x) +{ + _add_bbox_static_(); + //Debug{} << "bbox >>> static " << x.data.pass << x.data.data << x.start << x.end << _rtree->Count(); +} - //Debug{} << "bbox >>" << x.data.pass << x.data.data << x.start << x.end << _rtree->Count(); +void chunk::_add_bbox_(const bbox& x, bool upd, bool is_dynamic) +{ + if (!is_dynamic || upd) + _add_bbox_static(x); + else + _add_bbox_dynamic(x); } -void chunk::_replace_bbox(const bbox& x0, const bbox& x1, bool b0, bool b1) +template<bool Dynamic> +void chunk::_replace_bbox_impl(const bbox& x0, const bbox& x1, bool b0, bool b1) { if (_pass_modified) return; @@ -242,13 +273,22 @@ void chunk::_replace_bbox(const bbox& x0, const bbox& x1, bool b0, bool b1) case 1 << 1 | 1 << 0: if (x1 == x0) return; - _remove_bbox(x0); + if constexpr(Dynamic) + _remove_bbox_dynamic(x0); + else + _remove_bbox_static(x0); [[fallthrough]]; case 1 << 1 | 0 << 0: - _add_bbox(x1); + if constexpr(Dynamic) + _add_bbox_dynamic(x1); + else + _add_bbox_static(x1); return; case 0 << 1 | 1 << 0: - _remove_bbox(x0); + if constexpr(Dynamic) + _remove_bbox_dynamic(x0); + else + _remove_bbox_static(x0); return; case 0 << 1 | 0 << 0: return; @@ -258,6 +298,17 @@ void chunk::_replace_bbox(const bbox& x0, const bbox& x1, bool b0, bool b1) std::unreachable(); } +void chunk::_replace_bbox_dynamic(const bbox& x0, const bbox& x, bool b0, bool b) { _replace_bbox_impl<true>(x0, x, b0, b); } +void chunk::_replace_bbox_static(const bbox& x0, const bbox& x, bool b0, bool b) { _replace_bbox_impl<false>(x0, x, b0, b); } + +void chunk::_replace_bbox_(const bbox& x0, const bbox& x, bool b0, bool b, bool upd, bool is_dynamic) +{ + if (!is_dynamic || upd) + _replace_bbox_static(x0, x, b0, b); + else + _replace_bbox_dynamic(x0, x, b0, b); +} + bool chunk::can_place_object(const object_proto& proto, local_coords pos) { (void)ensure_scenery_mesh(); diff --git a/src/chunk.cpp b/src/chunk.cpp index a7848936..d8c660bb 100644 --- a/src/chunk.cpp +++ b/src/chunk.cpp @@ -127,44 +127,51 @@ chunk::~chunk() noexcept chunk::chunk(chunk&&) noexcept = default; chunk& chunk::operator=(chunk&&) noexcept = default; -void chunk::add_object_unsorted(const std::shared_ptr<object>& e) -{ - fm_assert(!e->gone); - _objects_sorted = false; - if (!e->is_dynamic()) - mark_scenery_modified(); - if (bbox bb; _bbox_for_scenery(*e, bb)) - _add_bbox(bb); - arrayReserve(_objects, 8); - arrayAppend(_objects, e); -} - void chunk::sort_objects() { if (_objects_sorted) return; _objects_sorted = true; mark_scenery_modified(); - std::sort(_objects.begin(), _objects.end(), [](const auto& a, const auto& b) { - return a->id < b->id; - }); + std::sort(_objects.begin(), _objects.end(), object_id_lessp); } -void chunk::add_object(const std::shared_ptr<object>& e) +void chunk::add_object_pre(const std::shared_ptr<object>& e) { - fm_assert(_objects_sorted); fm_assert(!e->gone); - if (!e->is_dynamic()) + fm_assert(&*e->c == this); + const auto dyn = e->is_dynamic(), upd = e->updates_passability(); + if (!dyn) mark_scenery_modified(); - if (bbox bb; _bbox_for_scenery(*e, bb)) - _add_bbox(bb); + if (!dyn || upd) + _add_bbox_static_(); + else if (bbox bb; _bbox_for_scenery(*e, bb)) + _add_bbox_dynamic(bb); +} + +void chunk::add_object_unsorted(const std::shared_ptr<object>& e) +{ + add_object_pre(e); + _objects_sorted = false; arrayReserve(_objects, 8); + arrayAppend(_objects, e); +} + +size_t chunk::add_objectʹ(const std::shared_ptr<object>& e) +{ + fm_assert(_objects_sorted); + add_object_pre(e); auto& es = _objects; - auto it = std::lower_bound(es.cbegin(), es.cend(), e, object_id_lessp); - arrayInsert(es, (size_t)std::distance(es.cbegin(), it), e); + arrayReserve(es, 8); + auto* it = std::lower_bound(es.data(), es.data() + es.size(), e, object_id_lessp); + auto i = (size_t)std::distance(es.data(), it); + arrayInsert(es, i, e); + return i; } -void chunk::on_teardown() +void chunk::add_object(const std::shared_ptr<object>& e) { (void)add_objectʹ(e); } + +void chunk::on_teardown() // NOLINT(*-make-member-function-const) { fm_assert(!_teardown); // too late, some chunks were already erased } @@ -174,15 +181,23 @@ bool chunk::is_teardown() const { return _teardown || _world->is_teardown(); } void chunk::remove_object(size_t i) { fm_assert(_objects_sorted); - auto& es = _objects; - fm_debug_assert(i < es.size()); - auto* e = es[i].get(); - fm_assert(!e->gone); - if (!e->is_dynamic()) - mark_scenery_modified(); - if (bbox bb; _bbox_for_scenery(*e, bb)) - _remove_bbox(bb); - arrayRemove(es, i); + fm_debug_assert(i < _objects.size()); + + { + const auto& e = *_objects[i]; + fm_assert(e.c == this); + fm_assert(!e.gone); + + const auto dyn = e.is_dynamic(), upd = e.updates_passability(); + if (!dyn) + mark_scenery_modified(); + if (!dyn || upd) + _remove_bbox_static_(); + else if (bbox bb; _bbox_for_scenery(e, bb)) + _remove_bbox_dynamic(bb); + } + + arrayRemove(_objects, i); } ArrayView<const std::shared_ptr<object>> chunk::objects() const diff --git a/src/chunk.hpp b/src/chunk.hpp index 4b18ada8..94d1e3ca 100644 --- a/src/chunk.hpp +++ b/src/chunk.hpp @@ -100,14 +100,13 @@ public: [[nodiscard]] bool can_place_object(const object_proto& proto, local_coords pos); - void add_object(const std::shared_ptr<object>& e); - void add_object_unsorted(const std::shared_ptr<object>& e); - void sort_objects(); - void remove_object(size_t i); void on_teardown(); bool is_teardown() const; ArrayView<const std::shared_ptr<object>> objects() const; + void remove_object(size_t i); + void sort_objects(); + // for drawing only static constexpr size_t max_wall_quad_count = TILE_COUNT*Wall::Direction_COUNT*(Wall::Group_COUNT+4); @@ -148,6 +147,11 @@ private: void ensure_scenery_buffers(scenery_scratch_buffers bufs); + void add_object(const std::shared_ptr<object>& e); + void add_object_pre(const std::shared_ptr<object>& e); + [[nodiscard]] size_t add_objectʹ(const std::shared_ptr<object>& e); + void add_object_unsorted(const std::shared_ptr<object>& e); + struct bbox final { collision_data data; @@ -156,11 +160,25 @@ private: bool operator==(const bbox& other) const noexcept; }; - static bool _bbox_for_scenery(const object& s, bbox& value) noexcept; - static bool _bbox_for_scenery(const object& s, local_coords local, Vector2b offset, Vector2b bbox_offset, Vector2ub bbox_size, bbox& value) noexcept; - void _remove_bbox(const bbox& x); - void _add_bbox(const bbox& x); - void _replace_bbox(const bbox& x0, const bbox& x, bool b0, bool b); + [[nodiscard]] static bool _bbox_for_scenery(const object& s, bbox& value) noexcept; + [[nodiscard]] static bool _bbox_for_scenery(const object& s, local_coords local, Vector2b offset, + Vector2b bbox_offset, Vector2ub bbox_size, bbox& value) noexcept; + + void _remove_bbox_(const bbox& x, bool upd, bool is_dynamic); + void _remove_bbox_dynamic(const bbox& x); + void _remove_bbox_static(const bbox& x); + void _remove_bbox_static_(); + + void _add_bbox_(const bbox& x, bool upd, bool is_dynamic); + void _add_bbox_dynamic(const bbox& x); + void _add_bbox_static(const bbox& x); + void _add_bbox_static_(); + + template<bool Dynamic> void _replace_bbox_impl(const bbox& x0, const bbox& x, bool b0, bool b); + void _replace_bbox_(const bbox& x0, const bbox& x, bool b0, bool b, bool upd, bool is_dynamic); + void _replace_bbox_dynamic(const bbox& x0, const bbox& x, bool b0, bool b); + void _replace_bbox_static(const bbox& x0, const bbox& x, bool b0, bool b); + GL::Mesh make_wall_mesh(); template<size_t N> static std::array<std::array<UnsignedShort, 6>, N*TILE_COUNT> make_index_array(size_t max); diff --git a/src/object.cpp b/src/object.cpp index 89988747..428db9ab 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -22,8 +22,6 @@ namespace floormat { namespace { -constexpr auto object_id_lessp = [](const auto& a, const auto& b) { return a->id < b->id; }; - // todo rewrite using bitwise ops. try this instead: x = 31; int((x+64+32)/64), (x + 64 + 32)%64 - 1 template<int tile_size> constexpr inline Pair<int, int8_t> normalize_coord(const int8_t cur, const int new_off) @@ -74,7 +72,7 @@ object::~object() noexcept return; #if 0 if (chunk::bbox bb; c->_bbox_for_scenery(*this, bb)) - c->_remove_bbox(bb); + c->_remove_bbox_dynamic(bb); #endif c->_world->erase_object(id); const_cast<object_id&>(id) = 0; @@ -209,7 +207,7 @@ bool object::can_move_to(Vector2i delta) void object::teleport_to(size_t& i, point pt, rotation new_r) { - return teleport_to(i, pt.coord(), pt.offset(), new_r); + teleport_to(i, pt.coord(), pt.offset(), new_r); } void object::teleport_to(size_t& i, global_coords coord_, Vector2b offset_, rotation new_r) @@ -230,8 +228,7 @@ void object::teleport_to(size_t& i, global_coords coord_, Vector2b offset_, rota if (coord_ == coord && offset_ == offset) return; - if (!is_dynamic()) - c->mark_scenery_modified(); + const bool dynamic = is_dynamic(), upd = updates_passability(); chunk::bbox bb0, bb1; const auto bb_offset = rotate_point(bbox_offset, r, new_r); @@ -241,27 +238,21 @@ void object::teleport_to(size_t& i, global_coords coord_, Vector2b offset_, rota if (coord_.chunk() == coord.chunk()) { - c->_replace_bbox(bb0, bb1, b0, b1); - const_cast<global_coords&>(coord) = coord_; + c->_replace_bbox_(bb0, bb1, b0, b1, upd, dynamic); + non_const(coord) = coord_; set_bbox_(offset_, bb_offset, bb_size, pass); - const_cast<rotation&>(r) = new_r; + non_const(r) = new_r; } else { auto& w = *c->_world; - - auto& c2 = w[coord_.chunk3()]; - if (!is_dynamic()) - c2.mark_scenery_modified(); - c2._add_bbox(bb1); c->remove_object(i); - auto& es = c2._objects; - const_cast<global_coords&>(coord) = coord_; + auto& c2 = w[coord_.chunk3()]; + non_const(c) = &c2; + non_const(coord) = coord_; + non_const(r) = new_r; set_bbox_(offset_, bb_offset, bb_size, pass); - const_cast<rotation&>(r) = new_r; - const_cast<class chunk*&>(c) = &c2; - i = (size_t)std::distance(es.cbegin(), std::lower_bound(es.cbegin(), es.cend(), eʹ, object_id_lessp)); - arrayInsert(es, i, move(eʹ)); + i = c2.add_objectʹ(eʹ); } } @@ -314,12 +305,12 @@ uint32_t object::alloc_frame_time(const Ns& dt, T& accum, uint32_t hz, float spe template uint32_t object::alloc_frame_time(const Ns& dt, uint16_t& accum, uint32_t hz, float speed); template uint32_t object::alloc_frame_time(const Ns& dt, uint32_t& accum, uint32_t hz, float speed); -void object::set_bbox_(Vector2b offset_, Vector2b bb_offset_, Vector2ub bb_size_, pass_mode pass_) +void object::set_bbox_(Vector2b offset_, Vector2b bb_offset, Vector2ub bb_size, pass_mode pass_) { - const_cast<Vector2b&>(offset) = offset_; - const_cast<Vector2b&>(bbox_offset) = bb_offset_; - const_cast<Vector2ub&>(bbox_size) = bb_size_; - const_cast<pass_mode&>(pass) = pass_; + non_const(offset) = offset_; + non_const(bbox_offset) = bb_offset; + non_const(bbox_size) = bb_size; + non_const(pass) = pass_; } object::operator object_proto() const @@ -341,15 +332,16 @@ void object::set_bbox(Vector2b offset_, Vector2b bb_offset_, Vector2ub bb_size_, { fm_assert(Vector2ui(bb_size_).product() != 0); - if (offset != offset_) - if (!is_dynamic()) + const auto dyn = is_dynamic(), upd = updates_passability(); + if (!dyn) + if (offset != offset_) c->mark_scenery_modified(); chunk::bbox bb0, bb; const bool b0 = c->_bbox_for_scenery(*this, bb0); set_bbox_(offset_, bb_offset_, bb_size_, pass); const bool b = c->_bbox_for_scenery(*this, bb); - c->_replace_bbox(bb0, bb, b0, b); + c->_replace_bbox_(bb0, bb, b0, b, upd, dyn); } bool object::can_activate(size_t) const { return false; } |