summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-06-07 23:10:49 +0200
committerStanislaw Halik <sthalik@misaki.pl>2024-06-08 01:11:44 +0200
commitec524fddfa0d2583d06ee194b06720be0eee8341 (patch)
tree663497f84b276308c45fda0b4c0c97da34a71254
parent089e50cc986730f05c64ae814e21529fcdd44f91 (diff)
wa
-rw-r--r--src/chunk-collision.cpp69
-rw-r--r--src/chunk.cpp79
-rw-r--r--src/chunk.hpp36
-rw-r--r--src/object.cpp48
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; }