From 8d0d6d6921d5dfb398f4ab04e4d3937ab550c4ff Mon Sep 17 00:00:00 2001 From: Andrea Catania Date: Fri, 10 Jul 2020 09:21:12 +0200 Subject: [PATCH] - Enhanced the flush mechanism by flushing only needed thing. - Flushing Areas before anything else. - Make sure to correctly fetch gravity when the integrate_forces function is used - Lazy reload body when layer and mask changes - Shapes are reloaded just before the physics step starts. - Improved some other parts of the code. - Added override keyword - Using LocalVector --- modules/bullet/area_bullet.cpp | 21 ++--- modules/bullet/area_bullet.h | 24 +++-- modules/bullet/bullet_physics_server.h | 2 +- modules/bullet/collision_object_bullet.cpp | 44 +++++---- modules/bullet/collision_object_bullet.h | 40 ++++---- modules/bullet/rigid_body_bullet.cpp | 105 +++++++++++---------- modules/bullet/rigid_body_bullet.h | 52 +++++----- modules/bullet/soft_body_bullet.cpp | 18 ++-- modules/bullet/soft_body_bullet.h | 20 ++-- modules/bullet/space_bullet.cpp | 43 +++++++-- modules/bullet/space_bullet.h | 18 ++-- 11 files changed, 217 insertions(+), 170 deletions(-) diff --git a/modules/bullet/area_bullet.cpp b/modules/bullet/area_bullet.cpp index edbd9565b8cf..b35019bea3df 100644 --- a/modules/bullet/area_bullet.cpp +++ b/modules/bullet/area_bullet.cpp @@ -65,14 +65,11 @@ AreaBullet::~AreaBullet() { } void AreaBullet::dispatch_callbacks() { - if (!isScratched) { - return; - } - isScratched = false; + RigidCollisionObjectBullet::dispatch_callbacks(); // Reverse order because I've to remove EXIT objects for (int i = overlappingObjects.size() - 1; 0 <= i; --i) { - OverlappingObjectData &otherObj = overlappingObjects.write[i]; + OverlappingObjectData &otherObj = overlappingObjects[i]; switch (otherObj.state) { case OVERLAP_STATE_ENTER: @@ -112,10 +109,9 @@ void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer3 } void AreaBullet::scratch() { - if (isScratched) { - return; + if (space != nullptr) { + space->add_to_pre_flush_queue(this); } - isScratched = true; } void AreaBullet::clear_overlaps(bool p_notify) { @@ -173,9 +169,9 @@ void AreaBullet::do_reload_body() { void AreaBullet::set_space(SpaceBullet *p_space) { // Clear the old space if there is one + if (space) { clear_overlaps(false); - isScratched = false; // Remove this object form the physics world space->unregister_collision_object(this); @@ -187,10 +183,11 @@ void AreaBullet::set_space(SpaceBullet *p_space) { if (space) { space->register_collision_object(this); reload_body(); + scratch(); } } -void AreaBullet::on_collision_filters_change() { +void AreaBullet::do_reload_collision_filters() { if (space) { space->reload_collision_filters(this); } @@ -204,13 +201,13 @@ void AreaBullet::add_overlap(CollisionObjectBullet *p_otherObject) { void AreaBullet::put_overlap_as_exit(int p_index) { scratch(); - overlappingObjects.write[p_index].state = OVERLAP_STATE_EXIT; + overlappingObjects[p_index].state = OVERLAP_STATE_EXIT; } void AreaBullet::put_overlap_as_inside(int p_index) { // This check is required to be sure this body was inside if (OVERLAP_STATE_DIRTY == overlappingObjects[p_index].state) { - overlappingObjects.write[p_index].state = OVERLAP_STATE_INSIDE; + overlappingObjects[p_index].state = OVERLAP_STATE_INSIDE; } } diff --git a/modules/bullet/area_bullet.h b/modules/bullet/area_bullet.h index 12272092f727..51fbc1f71d13 100644 --- a/modules/bullet/area_bullet.h +++ b/modules/bullet/area_bullet.h @@ -32,7 +32,7 @@ #define AREABULLET_H #include "collision_object_bullet.h" -#include "core/vector.h" +#include "core/local_vector.h" #include "servers/physics_server_3d.h" #include "space_bullet.h" @@ -83,7 +83,7 @@ class AreaBullet : public RigidCollisionObjectBullet { Variant *call_event_res_ptr[5]; btGhostObject *btGhost; - Vector overlappingObjects; + LocalVector overlappingObjects; bool monitorable = true; PhysicsServer3D::AreaSpaceOverrideMode spOv_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; @@ -96,8 +96,6 @@ class AreaBullet : public RigidCollisionObjectBullet { real_t spOv_angularDump = 0.1; int spOv_priority = 0; - bool isScratched = false; - InOutEventCallback eventsCallbacks[2]; public: @@ -139,11 +137,11 @@ class AreaBullet : public RigidCollisionObjectBullet { _FORCE_INLINE_ void set_spOv_priority(int p_priority) { spOv_priority = p_priority; } _FORCE_INLINE_ int get_spOv_priority() { return spOv_priority; } - virtual void main_shape_changed(); - virtual void do_reload_body(); - virtual void set_space(SpaceBullet *p_space); + virtual void main_shape_changed() override; + virtual void do_reload_body() override; + virtual void set_space(SpaceBullet *p_space) override; - virtual void dispatch_callbacks(); + virtual void dispatch_callbacks() override; void call_event(CollisionObjectBullet *p_otherObject, PhysicsServer3D::AreaBodyStatus p_status); void set_on_state_change(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant()); void scratch(); @@ -152,9 +150,9 @@ class AreaBullet : public RigidCollisionObjectBullet { // Dispatch the callbacks and removes from overlapping list void remove_overlap(CollisionObjectBullet *p_object, bool p_notify); - virtual void on_collision_filters_change(); - virtual void on_collision_checker_start() {} - virtual void on_collision_checker_end() { isTransformChanged = false; } + virtual void do_reload_collision_filters() override; + virtual void on_collision_checker_start() override {} + virtual void on_collision_checker_end() override { isTransformChanged = false; } void add_overlap(CollisionObjectBullet *p_otherObject); void put_overlap_as_exit(int p_index); @@ -166,8 +164,8 @@ class AreaBullet : public RigidCollisionObjectBullet { void set_event_callback(Type p_callbackObjectType, ObjectID p_id, const StringName &p_method); bool has_event_callback(Type p_callbackObjectType); - virtual void on_enter_area(AreaBullet *p_area); - virtual void on_exit_area(AreaBullet *p_area); + virtual void on_enter_area(AreaBullet *p_area) override; + virtual void on_exit_area(AreaBullet *p_area) override; }; #endif diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 6078babaf8d4..eb95120f74c3 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -52,7 +52,7 @@ class BulletPhysicsServer3D : public PhysicsServer3D { bool active = true; char active_spaces_count = 0; - Vector active_spaces; + LocalVector active_spaces; mutable RID_PtrOwner space_owner; mutable RID_PtrOwner shape_owner; diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index dd208965bdd1..660e9afc5edf 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -165,11 +165,20 @@ bool CollisionObjectBullet::has_collision_exception(const CollisionObjectBullet return !bt_collision_object->checkCollideWith(p_otherCollisionObject->bt_collision_object); } -void CollisionObjectBullet::prepare_object_for_dispatch() { - if (need_body_reload) { +void CollisionObjectBullet::reload_body() { + needs_body_reload = true; +} + +void CollisionObjectBullet::dispatch_callbacks() {} + +void CollisionObjectBullet::pre_process() { + if (needs_body_reload) { do_reload_body(); - need_body_reload = false; + } else if (needs_collision_filters_reload) { + do_reload_collision_filters(); } + needs_body_reload = false; + needs_collision_filters_reload = false; } void CollisionObjectBullet::set_collision_enabled(bool p_enabled) { @@ -245,7 +254,7 @@ void RigidCollisionObjectBullet::add_shape(ShapeBullet *p_shape, const Transform } void RigidCollisionObjectBullet::set_shape(int p_index, ShapeBullet *p_shape) { - ShapeWrapper &shp = shapes.write[p_index]; + ShapeWrapper &shp = shapes[p_index]; shp.shape->remove_owner(this); p_shape->add_owner(this); shp.shape = p_shape; @@ -307,7 +316,7 @@ void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBod void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) { ERR_FAIL_INDEX(p_index, get_shape_count()); - shapes.write[p_index].set_transform(p_transform); + shapes[p_index].set_transform(p_transform); shape_changed(p_index); } @@ -325,7 +334,7 @@ void RigidCollisionObjectBullet::set_shape_disabled(int p_index, bool p_disabled if (shapes[p_index].active != p_disabled) { return; } - shapes.write[p_index].active = !p_disabled; + shapes[p_index].active = !p_disabled; shape_changed(p_index); } @@ -333,16 +342,16 @@ bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) { return !shapes[p_index].active; } -void RigidCollisionObjectBullet::prepare_object_for_dispatch() { +void RigidCollisionObjectBullet::pre_process() { if (need_shape_reload) { do_reload_shapes(); need_shape_reload = false; } - CollisionObjectBullet::prepare_object_for_dispatch(); + CollisionObjectBullet::pre_process(); } void RigidCollisionObjectBullet::shape_changed(int p_shape_index) { - ShapeWrapper &shp = shapes.write[p_shape_index]; + ShapeWrapper &shp = shapes[p_shape_index]; if (shp.bt_shape == mainShape) { mainShape = nullptr; } @@ -363,12 +372,11 @@ void RigidCollisionObjectBullet::do_reload_shapes() { mainShape = nullptr; const int shape_count = shapes.size(); - ShapeWrapper *shapes_ptr = shapes.ptrw(); // Reset all shapes if required if (force_shape_reset) { for (int i(0); i < shape_count; ++i) { - shapes_ptr[i].release_bt_shape(); + shapes[i].release_bt_shape(); } force_shape_reset = false; } @@ -377,10 +385,10 @@ void RigidCollisionObjectBullet::do_reload_shapes() { if (1 == shape_count) { // Is it possible to optimize by not using compound? - btTransform transform = shapes_ptr[0].get_adjusted_transform(); + btTransform transform = shapes[0].get_adjusted_transform(); if (transform.getOrigin().isZero() && transform.getBasis() == transform.getBasis().getIdentity()) { - shapes_ptr[0].claim_bt_shape(body_scale); - mainShape = shapes_ptr[0].bt_shape; + shapes[0].claim_bt_shape(body_scale); + mainShape = shapes[0].bt_shape; main_shape_changed(); // Nothing more to do return; @@ -391,10 +399,10 @@ void RigidCollisionObjectBullet::do_reload_shapes() { btCompoundShape *compoundShape = bulletnew(btCompoundShape(enableDynamicAabbTree, shape_count)); for (int i(0); i < shape_count; ++i) { - shapes_ptr[i].claim_bt_shape(body_scale); - btTransform scaled_shape_transform(shapes_ptr[i].get_adjusted_transform()); + shapes[i].claim_bt_shape(body_scale); + btTransform scaled_shape_transform(shapes[i].get_adjusted_transform()); scaled_shape_transform.getOrigin() *= body_scale; - compoundShape->addChildShape(scaled_shape_transform, shapes_ptr[i].bt_shape); + compoundShape->addChildShape(scaled_shape_transform, shapes[i].bt_shape); } compoundShape->recalculateLocalAabb(); @@ -408,7 +416,7 @@ void RigidCollisionObjectBullet::body_scale_changed() { } void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody) { - ShapeWrapper &shp = shapes.write[p_index]; + ShapeWrapper &shp = shapes[p_index]; shp.shape->remove_owner(this, p_permanentlyFromThisBody); if (shp.bt_shape == mainShape) { mainShape = nullptr; diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h index ac74661f2429..920d80af23d8 100644 --- a/modules/bullet/collision_object_bullet.h +++ b/modules/bullet/collision_object_bullet.h @@ -31,6 +31,7 @@ #ifndef COLLISION_OBJECT_BULLET_H #define COLLISION_OBJECT_BULLET_H +#include "core/local_vector.h" #include "core/math/transform.h" #include "core/math/vector3.h" #include "core/object.h" @@ -126,16 +127,18 @@ class CollisionObjectBullet : public RIDBullet { VSet exceptions; - bool need_body_reload = true; + bool needs_body_reload = true; + bool needs_collision_filters_reload = true; /// This array is used to know all areas where this Object is overlapped in /// New area is added when overlap with new area (AreaBullet::addOverlap), then is removed when it exit (CollisionObjectBullet::onExitArea) /// This array is used mainly to know which area hold the pointer of this object - Vector areasOverlapped; + LocalVector areasOverlapped; bool isTransformChanged = false; public: bool is_in_world = false; + bool is_in_flush_queue = false; public: CollisionObjectBullet(Type p_type); @@ -171,7 +174,7 @@ class CollisionObjectBullet : public RIDBullet { _FORCE_INLINE_ void set_collision_layer(uint32_t p_layer) { if (collisionLayer != p_layer) { collisionLayer = p_layer; - on_collision_filters_change(); + needs_collision_filters_reload = true; } } _FORCE_INLINE_ uint32_t get_collision_layer() const { return collisionLayer; } @@ -179,24 +182,23 @@ class CollisionObjectBullet : public RIDBullet { _FORCE_INLINE_ void set_collision_mask(uint32_t p_mask) { if (collisionMask != p_mask) { collisionMask = p_mask; - on_collision_filters_change(); + needs_collision_filters_reload = true; } } _FORCE_INLINE_ uint32_t get_collision_mask() const { return collisionMask; } - virtual void on_collision_filters_change() = 0; + virtual void do_reload_collision_filters() = 0; _FORCE_INLINE_ bool test_collision_mask(CollisionObjectBullet *p_other) const { return collisionLayer & p_other->collisionMask || p_other->collisionLayer & collisionMask; } bool need_reload_body() const { - return need_body_reload; + return needs_body_reload; } - void reload_body() { - need_body_reload = true; - } + void reload_body(); + virtual void do_reload_body() = 0; virtual void set_space(SpaceBullet *p_space) = 0; _FORCE_INLINE_ SpaceBullet *get_space() const { return space; } @@ -204,8 +206,8 @@ class CollisionObjectBullet : public RIDBullet { virtual void on_collision_checker_start() = 0; virtual void on_collision_checker_end() = 0; - virtual void prepare_object_for_dispatch(); - virtual void dispatch_callbacks() = 0; + virtual void dispatch_callbacks(); + virtual void pre_process(); void set_collision_enabled(bool p_enabled); bool is_collisions_response_enabled(); @@ -229,7 +231,7 @@ class CollisionObjectBullet : public RIDBullet { class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwnerBullet { protected: btCollisionShape *mainShape = nullptr; - Vector shapes; + LocalVector shapes; bool need_shape_reload = true; public: @@ -237,7 +239,7 @@ class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwn CollisionObjectBullet(p_type) {} ~RigidCollisionObjectBullet(); - _FORCE_INLINE_ const Vector &get_shapes_wrappers() const { return shapes; } + _FORCE_INLINE_ const LocalVector &get_shapes_wrappers() const { return shapes; } _FORCE_INLINE_ btCollisionShape *get_main_shape() const { return mainShape; } @@ -248,9 +250,9 @@ class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwn ShapeBullet *get_shape(int p_index) const; btCollisionShape *get_bt_shape(int p_index) const; - int find_shape(ShapeBullet *p_shape) const; + virtual int find_shape(ShapeBullet *p_shape) const override; - virtual void remove_shape_full(ShapeBullet *p_shape); + virtual void remove_shape_full(ShapeBullet *p_shape) override; void remove_shape_full(int p_index); void remove_all_shapes(bool p_permanentlyFromThisBody = false, bool p_force_not_reload = false); @@ -262,15 +264,15 @@ class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwn void set_shape_disabled(int p_index, bool p_disabled); bool is_shape_disabled(int p_index); - virtual void prepare_object_for_dispatch(); + virtual void pre_process() override; - virtual void shape_changed(int p_shape_index); - void reload_shapes(); + virtual void shape_changed(int p_shape_index) override; + virtual void reload_shapes() override; bool need_reload_shapes() const { return need_shape_reload; } virtual void do_reload_shapes(); virtual void main_shape_changed() = 0; - virtual void body_scale_changed(); + virtual void body_scale_changed() override; private: void internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody = false); diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 717c99c7381d..5c1144b8759c 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -51,9 +51,7 @@ BulletPhysicsDirectBodyState3D *BulletPhysicsDirectBodyState3D::singleton = nullptr; Vector3 BulletPhysicsDirectBodyState3D::get_total_gravity() const { - Vector3 gVec; - B_TO_G(body->btBody->getGravity(), gVec); - return gVec; + return body->total_gravity; } float BulletPhysicsDirectBodyState3D::get_total_angular_damp() const { @@ -183,7 +181,7 @@ int BulletPhysicsDirectBodyState3D::get_contact_collider_shape(int p_contact_idx } Vector3 BulletPhysicsDirectBodyState3D::get_contact_collider_velocity_at_position(int p_contact_idx) const { - RigidBodyBullet::CollisionData &colDat = body->collisions.write[p_contact_idx]; + RigidBodyBullet::CollisionData &colDat = body->collisions[p_contact_idx]; btVector3 hitLocation; G_TO_B(colDat.hitLocalLocation, hitLocation); @@ -213,7 +211,7 @@ void RigidBodyBullet::KinematicUtilities::setSafeMargin(btScalar p_margin) { } void RigidBodyBullet::KinematicUtilities::copyAllOwnerShapes() { - const Vector &shapes_wrappers(owner->get_shapes_wrappers()); + const LocalVector &shapes_wrappers(owner->get_shapes_wrappers()); const int shapes_count = shapes_wrappers.size(); just_delete_shapes(shapes_count); @@ -228,8 +226,8 @@ void RigidBodyBullet::KinematicUtilities::copyAllOwnerShapes() { continue; } - shapes.write[i].transform = shape_wrapper->transform; - shapes.write[i].transform.getOrigin() *= owner_scale; + shapes[i].transform = shape_wrapper->transform; + shapes[i].transform.getOrigin() *= owner_scale; switch (shape_wrapper->shape->get_type()) { case PhysicsServer3D::SHAPE_SPHERE: case PhysicsServer3D::SHAPE_BOX: @@ -237,11 +235,11 @@ void RigidBodyBullet::KinematicUtilities::copyAllOwnerShapes() { case PhysicsServer3D::SHAPE_CYLINDER: case PhysicsServer3D::SHAPE_CONVEX_POLYGON: case PhysicsServer3D::SHAPE_RAY: { - shapes.write[i].shape = static_cast(shape_wrapper->shape->internal_create_bt_shape(owner_scale * shape_wrapper->scale, safe_margin)); + shapes[i].shape = static_cast(shape_wrapper->shape->internal_create_bt_shape(owner_scale * shape_wrapper->scale, safe_margin)); } break; default: WARN_PRINT("This shape is not supported for kinematic collision."); - shapes.write[i].shape = nullptr; + shapes[i].shape = nullptr; } } } @@ -249,7 +247,7 @@ void RigidBodyBullet::KinematicUtilities::copyAllOwnerShapes() { void RigidBodyBullet::KinematicUtilities::just_delete_shapes(int new_size) { for (int i = shapes.size() - 1; 0 <= i; --i) { if (shapes[i].shape) { - bulletdelete(shapes.write[i].shape); + bulletdelete(shapes[i].shape); } } shapes.resize(new_size); @@ -271,8 +269,8 @@ RigidBodyBullet::RigidBodyBullet() : reload_axis_lock(); areasWhereIam.resize(maxAreasWhereIam); - for (int i = areasWhereIam.size() - 1; 0 <= i; --i) { - areasWhereIam.write[i] = nullptr; + for (uint32_t i = 0; i < areasWhereIam.size(); i += 1) { + areasWhereIam[i] = nullptr; } btBody->setSleepingThresholds(0.2, 0.2); @@ -335,16 +333,15 @@ void RigidBodyBullet::set_space(SpaceBullet *p_space) { if (space) { space->register_collision_object(this); reload_body(); + space->add_to_flush_queue(this); } } void RigidBodyBullet::dispatch_callbacks() { + RigidCollisionObjectBullet::dispatch_callbacks(); + /// The check isFirstTransformChanged is necessary in order to call integrated forces only when the first transform is sent if ((btBody->isKinematicObject() || btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && can_integrate_forces) { - if (omit_forces_integration) { - btBody->clearForces(); - } - BulletPhysicsDirectBodyState3D *bodyDirect = BulletPhysicsDirectBodyState3D::get_singleton(this); Variant variantBodyDirect = bodyDirect; @@ -362,16 +359,22 @@ void RigidBodyBullet::dispatch_callbacks() { } } + previousActiveState = btBody->isActive(); +} + +void RigidBodyBullet::pre_process() { + RigidCollisionObjectBullet::pre_process(); + if (isScratchedSpaceOverrideModificator || 0 < countGravityPointSpaces) { isScratchedSpaceOverrideModificator = false; reload_space_override_modificator(); } - /// Lock axis - btBody->setLinearVelocity(btBody->getLinearVelocity() * btBody->getLinearFactor()); - btBody->setAngularVelocity(btBody->getAngularVelocity() * btBody->getAngularFactor()); - - previousActiveState = btBody->isActive(); + if (is_active()) { + /// Lock axis + btBody->setLinearVelocity(btBody->getLinearVelocity() * btBody->getLinearFactor()); + btBody->setAngularVelocity(btBody->getAngularVelocity() * btBody->getAngularFactor()); + } } void RigidBodyBullet::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) { @@ -392,7 +395,7 @@ void RigidBodyBullet::scratch_space_override_modificator() { isScratchedSpaceOverrideModificator = true; } -void RigidBodyBullet::on_collision_filters_change() { +void RigidBodyBullet::do_reload_collision_filters() { if (space) { space->reload_collision_filters(this); } @@ -405,14 +408,15 @@ void RigidBodyBullet::on_collision_checker_start() { collisionsCount = 0; // Swap array - Vector *s = prev_collision_traces; - prev_collision_traces = curr_collision_traces; - curr_collision_traces = s; + SWAP(prev_collision_traces, curr_collision_traces); } void RigidBodyBullet::on_collision_checker_end() { // Always true if active and not a static or kinematic body isTransformChanged = btBody->isActive() && !btBody->isStaticOrKinematicObject(); + if (isTransformChanged && space != nullptr) { + space->add_to_flush_queue(this); + } } bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index) { @@ -420,7 +424,7 @@ bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const return false; } - CollisionData &cd = collisions.write[collisionsCount]; + CollisionData &cd = collisions[collisionsCount]; cd.hitLocalLocation = p_hitLocalLocation; cd.otherObject = p_otherObject; cd.hitWorldLocation = p_hitWorldLocation; @@ -429,7 +433,7 @@ bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const cd.other_object_shape = p_other_shape_index; cd.local_shape = p_local_shape_index; - curr_collision_traces->write[collisionsCount] = p_otherObject; + (*curr_collision_traces)[collisionsCount] = p_otherObject; ++collisionsCount; return true; @@ -464,6 +468,7 @@ bool RigidBodyBullet::is_active() const { void RigidBodyBullet::set_omit_forces_integration(bool p_omit) { omit_forces_integration = p_omit; + scratch_space_override_modificator(); } void RigidBodyBullet::set_param(PhysicsServer3D::BodyParameter p_param, real_t p_value) { @@ -839,15 +844,15 @@ void RigidBodyBullet::on_enter_area(AreaBullet *p_area) { for (int i = 0; i < areaWhereIamCount; ++i) { if (nullptr == areasWhereIam[i]) { // This area has the highest priority - areasWhereIam.write[i] = p_area; + areasWhereIam[i] = p_area; break; } else { if (areasWhereIam[i]->get_spOv_priority() > p_area->get_spOv_priority()) { // The position was found, just shift all elements for (int j = i; j < areaWhereIamCount; ++j) { - areasWhereIam.write[j + 1] = areasWhereIam[j]; + areasWhereIam[j + 1] = areasWhereIam[j]; } - areasWhereIam.write[i] = p_area; + areasWhereIam[i] = p_area; break; } } @@ -871,7 +876,7 @@ void RigidBodyBullet::on_exit_area(AreaBullet *p_area) { if (p_area == areasWhereIam[i]) { // The area was found, just shift down all elements for (int j = i; j < areaWhereIamCount; ++j) { - areasWhereIam.write[j] = areasWhereIam[j + 1]; + areasWhereIam[j] = areasWhereIam[j + 1]; } wasTheAreaFound = true; break; @@ -884,7 +889,7 @@ void RigidBodyBullet::on_exit_area(AreaBullet *p_area) { } --areaWhereIamCount; - areasWhereIam.write[areaWhereIamCount] = nullptr; // Even if this is not required, I clear the last element to be safe + areasWhereIam[areaWhereIamCount] = nullptr; // Even if this is not required, I clear the last element to be safe if (PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED != p_area->get_spOv_mode()) { scratch_space_override_modificator(); } @@ -897,36 +902,31 @@ void RigidBodyBullet::reload_space_override_modificator() { return; } - Vector3 newGravity(0.0, 0.0, 0.0); + Vector3 newGravity; real_t newLinearDamp = MAX(0.0, linearDamp); real_t newAngularDamp = MAX(0.0, angularDamp); - AreaBullet *currentArea; - // Variable used to calculate new gravity for gravity point areas, it is pointed by currentGravity pointer - Vector3 support_gravity(0, 0, 0); - bool stopped = false; - for (int i = areaWhereIamCount - 1; (0 <= i) && !stopped; --i) { - currentArea = areasWhereIam[i]; + for (int i = 0; i < areaWhereIamCount && !stopped; i += 1) { + AreaBullet *currentArea = areasWhereIam[i]; if (!currentArea || PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED == currentArea->get_spOv_mode()) { continue; } + Vector3 support_gravity; + /// Here is calculated the gravity if (currentArea->is_spOv_gravityPoint()) { /// It calculates the direction of new gravity support_gravity = currentArea->get_transform().xform(currentArea->get_spOv_gravityVec()) - get_transform().get_origin(); - real_t distanceMag = support_gravity.length(); + + const real_t distanceMag = support_gravity.length(); // Normalized in this way to avoid the double call of function "length()" if (distanceMag == 0) { - support_gravity.x = 0; - support_gravity.y = 0; - support_gravity.z = 0; + support_gravity = Vector3(); } else { - support_gravity.x /= distanceMag; - support_gravity.y /= distanceMag; - support_gravity.z /= distanceMag; + support_gravity /= distanceMag; } /// Here is calculated the final gravity @@ -988,10 +988,17 @@ void RigidBodyBullet::reload_space_override_modificator() { newAngularDamp += space->get_angular_damp(); } - btVector3 newBtGravity; - G_TO_B(newGravity * gravity_scale, newBtGravity); + total_gravity = newGravity; + + if (omit_forces_integration) { + // Custom behaviour. + btBody->setGravity(btVector3(0, 0, 0)); + } else { + btVector3 newBtGravity; + G_TO_B(newGravity * gravity_scale, newBtGravity); + btBody->setGravity(newBtGravity); + } - btBody->setGravity(newBtGravity); btBody->setDamping(newLinearDamp, newAngularDamp); } diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h index eb62d0d39e0a..047645677bef 100644 --- a/modules/bullet/rigid_body_bullet.h +++ b/modules/bullet/rigid_body_bullet.h @@ -171,7 +171,7 @@ class RigidBodyBullet : public RigidCollisionObjectBullet { struct KinematicUtilities { RigidBodyBullet *owner; btScalar safe_margin; - Vector shapes; + LocalVector shapes; KinematicUtilities(RigidBodyBullet *p_owner); ~KinematicUtilities(); @@ -193,6 +193,7 @@ class RigidBodyBullet : public RigidCollisionObjectBullet { PhysicsServer3D::BodyMode mode; GodotMotionState *godotMotionState; btRigidBody *btBody; + Vector3 total_gravity; uint16_t locked_axis = 0; real_t mass = 1; real_t gravity_scale = 1; @@ -202,18 +203,18 @@ class RigidBodyBullet : public RigidCollisionObjectBullet { bool omit_forces_integration = false; bool can_integrate_forces = false; - Vector collisions; - Vector collision_traces_1; - Vector collision_traces_2; - Vector *prev_collision_traces; - Vector *curr_collision_traces; + LocalVector collisions; + LocalVector collision_traces_1; + LocalVector collision_traces_2; + LocalVector *prev_collision_traces; + LocalVector *curr_collision_traces; // these parameters are used to avoid vector resize - int maxCollisionsDetection = 0; - int collisionsCount = 0; - int prev_collision_count = 0; + uint32_t maxCollisionsDetection = 0; + uint32_t collisionsCount = 0; + uint32_t prev_collision_count = 0; - Vector areasWhereIam; + LocalVector areasWhereIam; // these parameters are used to avoid vector resize int maxAreasWhereIam = 10; int areaWhereIamCount = 0; @@ -235,21 +236,20 @@ class RigidBodyBullet : public RigidCollisionObjectBullet { _FORCE_INLINE_ btRigidBody *get_bt_rigid_body() { return btBody; } - virtual void main_shape_changed(); - virtual void do_reload_body(); - virtual void set_space(SpaceBullet *p_space); + virtual void main_shape_changed() override; + virtual void do_reload_body() override; + virtual void set_space(SpaceBullet *p_space) override; - virtual void dispatch_callbacks(); + virtual void dispatch_callbacks() override; + virtual void pre_process() override; void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant()); void scratch_space_override_modificator(); - virtual void on_collision_filters_change(); - virtual void on_collision_checker_start(); - virtual void on_collision_checker_end(); - - void set_max_collisions_detection(int p_maxCollisionsDetection) { - ERR_FAIL_COND(0 > p_maxCollisionsDetection); + virtual void do_reload_collision_filters() override; + virtual void on_collision_checker_start() override; + virtual void on_collision_checker_end() override; + void set_max_collisions_detection(uint32_t p_maxCollisionsDetection) { maxCollisionsDetection = p_maxCollisionsDetection; collisions.resize(p_maxCollisionsDetection); @@ -312,19 +312,19 @@ class RigidBodyBullet : public RigidCollisionObjectBullet { void set_angular_velocity(const Vector3 &p_velocity); Vector3 get_angular_velocity() const; - virtual void set_transform__bullet(const btTransform &p_global_transform); - virtual const btTransform &get_transform__bullet() const; + virtual void set_transform__bullet(const btTransform &p_global_transform) override; + virtual const btTransform &get_transform__bullet() const override; - virtual void do_reload_shapes(); + virtual void do_reload_shapes() override; - virtual void on_enter_area(AreaBullet *p_area); - virtual void on_exit_area(AreaBullet *p_area); + virtual void on_enter_area(AreaBullet *p_area) override; + virtual void on_exit_area(AreaBullet *p_area) override; void reload_space_override_modificator(); /// Kinematic void reload_kinematic_shapes(); - virtual void notify_transform_changed(); + virtual void notify_transform_changed() override; private: void _internal_set_mass(real_t p_mass); diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp index 3fccd3d8a2bd..ee48b3c5f0e4 100644 --- a/modules/bullet/soft_body_bullet.cpp +++ b/modules/bullet/soft_body_bullet.cpp @@ -346,14 +346,14 @@ void SoftBodyBullet::set_trimesh_body_shape(Vector p_indices, Vector()); } - indices_table.write[vertex_id].push_back(vs_vertex_index); + indices_table[vertex_id].push_back(vs_vertex_index); vs_indices_to_physics_table.push_back(vertex_id); } } const int indices_map_size(indices_table.size()); - Vector bt_vertices; + LocalVector bt_vertices; { // Parse vertices to bullet @@ -361,13 +361,13 @@ void SoftBodyBullet::set_trimesh_body_shape(Vector p_indices, Vector bt_triangles; + LocalVector bt_triangles; const int triangles_size(p_indices.size() / 3); { // Parse indices @@ -377,9 +377,9 @@ void SoftBodyBullet::set_trimesh_body_shape(Vector p_indices, Vector> indices_table; + LocalVector> indices_table; btSoftBody::Material *mat0; // This is just a copy of pointer managed by btSoftBody bool isScratched = false; @@ -73,7 +72,7 @@ class SoftBodyBullet : public CollisionObjectBullet { real_t pose_matching_coefficient = 0.; // [0,1] real_t damping_coefficient = 0.01; // [0,1] real_t drag_coefficient = 0.; // [0,1] - Vector pinned_nodes; + LocalVector pinned_nodes; // Other property to add //btScalar kVC; // Volume conversation coefficient [0,+inf] @@ -87,15 +86,14 @@ class SoftBodyBullet : public CollisionObjectBullet { SoftBodyBullet(); ~SoftBodyBullet(); - virtual void do_reload_body(); - virtual void set_space(SpaceBullet *p_space); + virtual void do_reload_body() override; + virtual void set_space(SpaceBullet *p_space) override; - virtual void dispatch_callbacks() {} - virtual void on_collision_filters_change() {} - virtual void on_collision_checker_start() {} - virtual void on_collision_checker_end() {} - virtual void on_enter_area(AreaBullet *p_area); - virtual void on_exit_area(AreaBullet *p_area); + virtual void do_reload_collision_filters() override {} + virtual void on_collision_checker_start() override {} + virtual void on_collision_checker_end() override {} + virtual void on_enter_area(AreaBullet *p_area) override; + virtual void on_exit_area(AreaBullet *p_area) override; _FORCE_INLINE_ btSoftBody *get_bt_soft_body() const { return bt_soft_body; } diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 70e137b16db7..a26d2866c419 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -348,16 +348,46 @@ SpaceBullet::~SpaceBullet() { destroy_world(); } +void SpaceBullet::add_to_pre_flush_queue(CollisionObjectBullet *p_co) { + if (p_co->is_in_flush_queue == false) { + p_co->is_in_flush_queue = true; + queue_pre_flush.push_back(p_co); + } +} + +void SpaceBullet::add_to_flush_queue(CollisionObjectBullet *p_co) { + if (p_co->is_in_flush_queue == false) { + p_co->is_in_flush_queue = true; + queue_flush.push_back(p_co); + } +} + +void SpaceBullet::remove_from_any_queue(CollisionObjectBullet *p_co) { + if (p_co->is_in_flush_queue) { + p_co->is_in_flush_queue = false; + queue_pre_flush.erase(p_co); + queue_flush.erase(p_co); + } +} + void SpaceBullet::flush_queries() { - const int size = collision_objects.size(); - CollisionObjectBullet **objects = collision_objects.ptrw(); - for (int i = 0; i < size; i += 1) { - objects[i]->prepare_object_for_dispatch(); - objects[i]->dispatch_callbacks(); + for (uint32_t i = 0; i < queue_pre_flush.size(); i += 1) { + queue_pre_flush[i]->dispatch_callbacks(); + queue_pre_flush[i]->is_in_flush_queue = false; } + for (uint32_t i = 0; i < queue_flush.size(); i += 1) { + queue_flush[i]->dispatch_callbacks(); + queue_flush[i]->is_in_flush_queue = false; + } + queue_pre_flush.clear(); + queue_flush.clear(); } void SpaceBullet::step(real_t p_delta_time) { + for (uint32_t i = 0; i < collision_objects.size(); i += 1) { + collision_objects[i]->pre_process(); + } + delta_time = p_delta_time; dynamicsWorld->stepSimulation(p_delta_time, 0, 0); } @@ -488,6 +518,7 @@ void SpaceBullet::register_collision_object(CollisionObjectBullet *p_object) { } void SpaceBullet::unregister_collision_object(CollisionObjectBullet *p_object) { + remove_from_any_queue(p_object); collision_objects.erase(p_object); } @@ -702,7 +733,7 @@ void SpaceBullet::check_ghost_overlaps() { /// 1. Reset all states for (i = area->overlappingObjects.size() - 1; 0 <= i; --i) { - AreaBullet::OverlappingObjectData &otherObj = area->overlappingObjects.write[i]; + AreaBullet::OverlappingObjectData &otherObj = area->overlappingObjects[i]; // This check prevent the overwrite of ENTER state // if this function is called more times before dispatchCallbacks if (otherObj.state != AreaBullet::OVERLAP_STATE_ENTER) { diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index aa9a70594e54..897f902fe183 100644 --- a/modules/bullet/space_bullet.h +++ b/modules/bullet/space_bullet.h @@ -31,8 +31,8 @@ #ifndef SPACE_BULLET_H #define SPACE_BULLET_H +#include "core/local_vector.h" #include "core/variant.h" -#include "core/vector.h" #include "godot_result_callbacks.h" #include "rid_bullet.h" #include "servers/physics_server_3d.h" @@ -110,17 +110,23 @@ class SpaceBullet : public RIDBullet { real_t linear_damp = 0.0; real_t angular_damp = 0.0; - Vector collision_objects; - Vector areas; + LocalVector queue_pre_flush; + LocalVector queue_flush; + LocalVector collision_objects; + LocalVector areas; - Vector contactDebug; - int contactDebugCount = 0; + LocalVector contactDebug; + uint32_t contactDebugCount = 0; real_t delta_time = 0.; public: SpaceBullet(); virtual ~SpaceBullet(); + void add_to_flush_queue(CollisionObjectBullet *p_co); + void add_to_pre_flush_queue(CollisionObjectBullet *p_co); + void remove_from_any_queue(CollisionObjectBullet *p_co); + void flush_queries(); real_t get_delta_time() { return delta_time; } void step(real_t p_delta_time); @@ -177,7 +183,7 @@ class SpaceBullet : public RIDBullet { } _FORCE_INLINE_ void add_debug_contact(const Vector3 &p_contact) { if (contactDebugCount < contactDebug.size()) { - contactDebug.write[contactDebugCount++] = p_contact; + contactDebug[contactDebugCount++] = p_contact; } } _FORCE_INLINE_ Vector get_debug_contacts() { return contactDebug; }