diff --git a/modules/jolt_physics/objects/jolt_area_3d.cpp b/modules/jolt_physics/objects/jolt_area_3d.cpp index eeaeca0faa1..7b8b4b59ca0 100644 --- a/modules/jolt_physics/objects/jolt_area_3d.cpp +++ b/modules/jolt_physics/objects/jolt_area_3d.cpp @@ -59,26 +59,6 @@ JPH::ObjectLayer JoltArea3D::_get_object_layer() const { return space->map_to_object_layer(_get_broad_phase_layer(), collision_layer, collision_mask); } -bool JoltArea3D::_has_pending_events() const { - if (body_monitor_callback.is_valid()) { - for (const KeyValue &E : bodies_by_id) { - if (!E.value.pending_added.is_empty() || !E.value.pending_removed.is_empty()) { - return true; - } - } - } - - if (area_monitor_callback.is_valid()) { - for (const KeyValue &E : areas_by_id) { - if (!E.value.pending_added.is_empty() || !E.value.pending_removed.is_empty()) { - return true; - } - } - } - - return false; -} - void JoltArea3D::_add_to_space() { jolt_shape = build_shapes(true); @@ -136,6 +116,8 @@ void JoltArea3D::_add_shape_pair(Overlap &p_overlap, const JPH::BodyID &p_body_i shape_indices.self = find_shape_index(p_self_shape_id); p_overlap.pending_added.push_back(shape_indices); + + _events_changed(); } bool JoltArea3D::_remove_shape_pair(Overlap &p_overlap, const JPH::SubShapeID &p_other_shape_id, const JPH::SubShapeID &p_self_shape_id) { @@ -148,6 +130,8 @@ bool JoltArea3D::_remove_shape_pair(Overlap &p_overlap, const JPH::SubShapeID &p p_overlap.pending_removed.push_back(shape_pair->value); p_overlap.shape_pairs.remove(shape_pair); + _events_changed(); + return true; } @@ -224,10 +208,16 @@ void JoltArea3D::_force_bodies_entered() { for (KeyValue &E : bodies_by_id) { Overlap &body = E.value; + if (unlikely(body.shape_pairs.is_empty())) { + continue; + } + for (const KeyValue &P : body.shape_pairs) { body.pending_removed.erase(P.value); body.pending_added.push_back(P.value); } + + _events_changed(); } } @@ -236,11 +226,17 @@ void JoltArea3D::_force_bodies_exited(bool p_remove) { const JPH::BodyID &id = E.key; Overlap &body = E.value; + if (unlikely(body.shape_pairs.is_empty())) { + continue; + } + for (const KeyValue &P : body.shape_pairs) { body.pending_added.erase(P.value); body.pending_removed.push_back(P.value); } + _events_changed(); + if (p_remove) { body.shape_pairs.clear(); _notify_body_exited(id); @@ -252,10 +248,16 @@ void JoltArea3D::_force_areas_entered() { for (KeyValue &E : areas_by_id) { Overlap &area = E.value; + if (unlikely(area.shape_pairs.is_empty())) { + continue; + } + for (const KeyValue &P : area.shape_pairs) { area.pending_removed.erase(P.value); area.pending_added.push_back(P.value); } + + _events_changed(); } } @@ -263,11 +265,17 @@ void JoltArea3D::_force_areas_exited(bool p_remove) { for (KeyValue &E : areas_by_id) { Overlap &area = E.value; + if (unlikely(area.shape_pairs.is_empty())) { + continue; + } + for (const KeyValue &P : area.shape_pairs) { area.pending_added.erase(P.value); area.pending_removed.push_back(P.value); } + _events_changed(); + if (p_remove) { area.shape_pairs.clear(); } @@ -313,6 +321,10 @@ void JoltArea3D::_space_changed() { _update_default_gravity(); } +void JoltArea3D::_events_changed() { + _enqueue_call_queries(); +} + void JoltArea3D::_body_monitoring_changed() { if (has_body_monitor_callback()) { _force_bodies_entered(); @@ -664,11 +676,13 @@ void JoltArea3D::body_exited(const JPH::BodyID &p_body_id, bool p_notify) { return; } - for (KeyValue &E : overlap->shape_pairs) { + for (const KeyValue &E : overlap->shape_pairs) { overlap->pending_added.erase(E.value); overlap->pending_removed.push_back(E.value); } + _events_changed(); + overlap->shape_pairs.clear(); if (p_notify) { @@ -691,6 +705,8 @@ void JoltArea3D::area_exited(const JPH::BodyID &p_body_id) { overlap->pending_removed.push_back(E.value); } + _events_changed(); + overlap->shape_pairs.clear(); } @@ -698,9 +714,3 @@ void JoltArea3D::call_queries() { _flush_events(bodies_by_id, body_monitor_callback); _flush_events(areas_by_id, area_monitor_callback); } - -void JoltArea3D::post_step(float p_step, JPH::Body &p_jolt_body) { - if (_has_pending_events()) { - _enqueue_call_queries(); - } -} diff --git a/modules/jolt_physics/objects/jolt_area_3d.h b/modules/jolt_physics/objects/jolt_area_3d.h index 18410c34cfc..30e79efe48d 100644 --- a/modules/jolt_physics/objects/jolt_area_3d.h +++ b/modules/jolt_physics/objects/jolt_area_3d.h @@ -117,8 +117,6 @@ private: virtual JPH::EMotionType _get_motion_type() const override { return JPH::EMotionType::Kinematic; } - bool _has_pending_events() const; - virtual void _add_to_space() override; void _enqueue_call_queries(); @@ -145,6 +143,7 @@ private: virtual void _space_changing() override; virtual void _space_changed() override; + void _events_changed(); void _body_monitoring_changed(); void _area_monitoring_changed(); void _monitorable_changed(); @@ -228,8 +227,6 @@ public: virtual bool has_custom_center_of_mass() const override { return false; } virtual Vector3 get_center_of_mass_custom() const override { return Vector3(); } - - virtual void post_step(float p_step, JPH::Body &p_jolt_body) override; }; #endif // JOLT_AREA_3D_H diff --git a/modules/jolt_physics/objects/jolt_object_3d.cpp b/modules/jolt_physics/objects/jolt_object_3d.cpp index 7ee46acbeff..1c2019d9fa3 100644 --- a/modules/jolt_physics/objects/jolt_object_3d.cpp +++ b/modules/jolt_physics/objects/jolt_object_3d.cpp @@ -136,12 +136,6 @@ bool JoltObject3D::can_interact_with(const JoltObject3D &p_other) const { } } -void JoltObject3D::pre_step(float p_step, JPH::Body &p_jolt_body) { -} - -void JoltObject3D::post_step(float p_step, JPH::Body &p_jolt_body) { -} - String JoltObject3D::to_string() const { Object *instance = get_instance(); return instance != nullptr ? instance->to_string() : ""; diff --git a/modules/jolt_physics/objects/jolt_object_3d.h b/modules/jolt_physics/objects/jolt_object_3d.h index 6fa9cc79050..b040e135e13 100644 --- a/modules/jolt_physics/objects/jolt_object_3d.h +++ b/modules/jolt_physics/objects/jolt_object_3d.h @@ -148,8 +148,7 @@ public: virtual bool reports_contacts() const = 0; - virtual void pre_step(float p_step, JPH::Body &p_jolt_body); - virtual void post_step(float p_step, JPH::Body &p_jolt_body); + virtual void pre_step(float p_step, JPH::Body &p_jolt_body) {} String to_string() const; }; diff --git a/modules/jolt_physics/objects/jolt_shaped_object_3d.cpp b/modules/jolt_physics/objects/jolt_shaped_object_3d.cpp index 6ceb77733b8..bfe77e008d5 100644 --- a/modules/jolt_physics/objects/jolt_shaped_object_3d.cpp +++ b/modules/jolt_physics/objects/jolt_shaped_object_3d.cpp @@ -140,14 +140,26 @@ JPH::ShapeRefC JoltShapedObject3D::_try_build_compound_shape(bool p_optimize) { return shape_result.Get(); } +void JoltShapedObject3D::_enqueue_shapes_changed() { + if (space != nullptr) { + space->enqueue_shapes_changed(&shapes_changed_element); + } +} + +void JoltShapedObject3D::_dequeue_shapes_changed() { + if (space != nullptr) { + space->dequeue_shapes_changed(&shapes_changed_element); + } +} + void JoltShapedObject3D::_enqueue_needs_optimization() { - if (!needs_optimization_element.in_list()) { + if (space != nullptr) { space->enqueue_needs_optimization(&needs_optimization_element); } } void JoltShapedObject3D::_dequeue_needs_optimization() { - if (needs_optimization_element.in_list()) { + if (space != nullptr) { space->dequeue_needs_optimization(&needs_optimization_element); } } @@ -160,8 +172,11 @@ void JoltShapedObject3D::_shapes_changed() { void JoltShapedObject3D::_space_changing() { JoltObject3D::_space_changing(); + _dequeue_shapes_changed(); _dequeue_needs_optimization(); + previous_jolt_shape = nullptr; + if (space != nullptr) { const JoltWritableBody3D body = space->write_body(jolt_id); ERR_FAIL_COND(body.is_invalid()); @@ -172,6 +187,7 @@ void JoltShapedObject3D::_space_changing() { JoltShapedObject3D::JoltShapedObject3D(ObjectType p_object_type) : JoltObject3D(p_object_type), + shapes_changed_element(this), needs_optimization_element(this) { jolt_settings->mAllowSleeping = true; jolt_settings->mFriction = 1.0f; @@ -317,6 +333,8 @@ void JoltShapedObject3D::commit_shapes(bool p_optimize_compound) { space->get_body_iface().SetShape(jolt_id, jolt_shape, false, JPH::EActivation::DontActivate); + _enqueue_shapes_changed(); + if (!p_optimize_compound && jolt_shape->GetType() == JPH::EShapeType::Compound) { _enqueue_needs_optimization(); } else { @@ -369,6 +387,10 @@ void JoltShapedObject3D::clear_shapes() { _shapes_changed(); } +void JoltShapedObject3D::clear_previous_shape() { + previous_jolt_shape = nullptr; +} + int JoltShapedObject3D::find_shape_index(uint32_t p_shape_instance_id) const { for (int i = 0; i < (int)shapes.size(); ++i) { if (shapes[i].get_id() == p_shape_instance_id) { @@ -450,9 +472,3 @@ void JoltShapedObject3D::set_shape_disabled(int p_index, bool p_disabled) { _shapes_changed(); } - -void JoltShapedObject3D::post_step(float p_step, JPH::Body &p_jolt_body) { - JoltObject3D::post_step(p_step, p_jolt_body); - - previous_jolt_shape = nullptr; -} diff --git a/modules/jolt_physics/objects/jolt_shaped_object_3d.h b/modules/jolt_physics/objects/jolt_shaped_object_3d.h index fee9f5f6b0e..dbb054de0f1 100644 --- a/modules/jolt_physics/objects/jolt_shaped_object_3d.h +++ b/modules/jolt_physics/objects/jolt_shaped_object_3d.h @@ -44,6 +44,7 @@ class JoltShapedObject3D : public JoltObject3D { friend class JoltShape3D; protected: + SelfList shapes_changed_element; SelfList needs_optimization_element; Vector3 scale = Vector3(1, 1, 1); @@ -61,6 +62,9 @@ protected: JPH::ShapeRefC _try_build_single_shape(); JPH::ShapeRefC _try_build_compound_shape(bool p_optimize); + void _enqueue_shapes_changed(); + void _dequeue_shapes_changed(); + void _enqueue_needs_optimization(); void _dequeue_needs_optimization(); @@ -106,6 +110,7 @@ public: void set_shape(int p_index, JoltShape3D *p_shape); void clear_shapes(); + void clear_previous_shape(); int get_shape_count() const { return shapes.size(); } @@ -123,8 +128,6 @@ public: bool is_shape_disabled(int p_index) const; void set_shape_disabled(int p_index, bool p_disabled); - - virtual void post_step(float p_step, JPH::Body &p_jolt_body) override; }; #endif // JOLT_SHAPED_OBJECT_3D_H diff --git a/modules/jolt_physics/spaces/jolt_space_3d.cpp b/modules/jolt_physics/spaces/jolt_space_3d.cpp index 06afe72a1d0..1304ee25f22 100644 --- a/modules/jolt_physics/spaces/jolt_space_3d.cpp +++ b/modules/jolt_physics/spaces/jolt_space_3d.cpp @@ -85,16 +85,10 @@ void JoltSpace3D::_pre_step(float p_step) { void JoltSpace3D::_post_step(float p_step) { contact_listener->post_step(); - // WARNING: The list of active bodies may have changed between `pre_step` and `post_step`. - - const JPH::BodyLockInterface &lock_iface = get_lock_iface(); - const JPH::BodyID *active_rigid_bodies = physics_system->GetActiveBodiesUnsafe(JPH::EBodyType::RigidBody); - const JPH::uint32 active_rigid_body_count = physics_system->GetNumActiveBodies(JPH::EBodyType::RigidBody); - - for (JPH::uint32 i = 0; i < active_rigid_body_count; i++) { - JPH::Body *jolt_body = lock_iface.TryGetBody(active_rigid_bodies[i]); - JoltObject3D *object = reinterpret_cast(jolt_body->GetUserData()); - object->post_step(p_step, *jolt_body); + while (shapes_changed_list.first()) { + JoltShapedObject3D *object = shapes_changed_list.first()->self(); + shapes_changed_list.remove(shapes_changed_list.first()); + object->clear_previous_shape(); } } @@ -433,6 +427,18 @@ void JoltSpace3D::dequeue_call_queries(SelfList *p_area) { } } +void JoltSpace3D::enqueue_shapes_changed(SelfList *p_object) { + if (!p_object->in_list()) { + shapes_changed_list.add(p_object); + } +} + +void JoltSpace3D::dequeue_shapes_changed(SelfList *p_object) { + if (p_object->in_list()) { + shapes_changed_list.remove(p_object); + } +} + void JoltSpace3D::enqueue_needs_optimization(SelfList *p_object) { if (!p_object->in_list()) { needs_optimization_list.add(p_object); diff --git a/modules/jolt_physics/spaces/jolt_space_3d.h b/modules/jolt_physics/spaces/jolt_space_3d.h index c12b5c5f0fe..16a8f362c63 100644 --- a/modules/jolt_physics/spaces/jolt_space_3d.h +++ b/modules/jolt_physics/spaces/jolt_space_3d.h @@ -59,6 +59,7 @@ class JoltShapedObject3D; class JoltSpace3D { SelfList::List body_call_queries_list; SelfList::List area_call_queries_list; + SelfList::List shapes_changed_list; SelfList::List needs_optimization_list; RID rid; @@ -142,6 +143,9 @@ public: void dequeue_call_queries(SelfList *p_body); void dequeue_call_queries(SelfList *p_area); + void enqueue_shapes_changed(SelfList *p_object); + void dequeue_shapes_changed(SelfList *p_object); + void enqueue_needs_optimization(SelfList *p_object); void dequeue_needs_optimization(SelfList *p_object);