Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Give each RigidBody its own DirectBodyState wrapper. #42928

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions modules/bullet/bullet_physics_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -850,8 +850,8 @@ bool BulletPhysicsServer3D::body_is_ray_pickable(RID p_body) const {

PhysicsDirectBodyState3D *BulletPhysicsServer3D::body_get_direct_state(RID p_body) {
RigidBodyBullet *body = rigid_body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, nullptr);
return BulletPhysicsDirectBodyState3D::get_singleton(body);
ERR_FAIL_COND_V_MSG(!body, nullptr, "Body with RID " + itos(p_body.get_id()) + " not owned by this server.");
return body->get_direct_state();
}

bool BulletPhysicsServer3D::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) {
Expand Down Expand Up @@ -1522,16 +1522,13 @@ void BulletPhysicsServer3D::free(RID p_rid) {
}

void BulletPhysicsServer3D::init() {
BulletPhysicsDirectBodyState3D::initSingleton();
}

void BulletPhysicsServer3D::step(real_t p_deltaTime) {
if (!active) {
return;
}

BulletPhysicsDirectBodyState3D::singleton_setDeltaTime(p_deltaTime);

for (int i = 0; i < active_spaces_count; ++i) {
active_spaces[i]->step(p_deltaTime);
}
Expand All @@ -1548,7 +1545,6 @@ void BulletPhysicsServer3D::flush_queries() {
}

void BulletPhysicsServer3D::finish() {
BulletPhysicsDirectBodyState3D::destroySingleton();
}

int BulletPhysicsServer3D::get_process_info(ProcessInfo p_info) {
Expand Down
15 changes: 9 additions & 6 deletions modules/bullet/rigid_body_bullet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@
@author AndreaCatania
*/

BulletPhysicsDirectBodyState3D *BulletPhysicsDirectBodyState3D::singleton = nullptr;

Vector3 BulletPhysicsDirectBodyState3D::get_total_gravity() const {
Vector3 gVec;
B_TO_G(body->btBody->getGravity(), gVec);
Expand Down Expand Up @@ -194,6 +192,10 @@ Vector3 BulletPhysicsDirectBodyState3D::get_contact_collider_velocity_at_positio
return velocityAtPoint;
}

real_t BulletPhysicsDirectBodyState3D::get_step() const {
return body->get_space()->get_delta_time();
}

PhysicsDirectSpaceState3D *BulletPhysicsDirectBodyState3D::get_space_state() {
return body->get_space()->get_direct_state();
}
Expand Down Expand Up @@ -279,11 +281,14 @@ RigidBodyBullet::RigidBodyBullet() :

prev_collision_traces = &collision_traces_1;
curr_collision_traces = &collision_traces_2;

direct_access = memnew(BulletPhysicsDirectBodyState3D);
direct_access->body = this;
}

RigidBodyBullet::~RigidBodyBullet() {
bulletdelete(godotMotionState);

memdelete(direct_access);
if (force_integration_callback) {
memdelete(force_integration_callback);
}
Expand Down Expand Up @@ -342,9 +347,7 @@ void RigidBodyBullet::dispatch_callbacks() {
btBody->clearForces();
}

BulletPhysicsDirectBodyState3D *bodyDirect = BulletPhysicsDirectBodyState3D::get_singleton(this);

Variant variantBodyDirect = bodyDirect;
Variant variantBodyDirect = direct_access;

Object *obj = ObjectDB::get_instance(force_integration_callback->id);
if (!obj) {
Expand Down
41 changes: 5 additions & 36 deletions modules/bullet/rigid_body_bullet.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,49 +45,15 @@ class AreaBullet;
class SpaceBullet;
class btRigidBody;
class GodotMotionState;
class BulletPhysicsDirectBodyState3D;

/// This class could be used in multi thread with few changes but currently
/// is set to be only in one single thread.
///
/// In the system there is only one object at a time that manage all bodies and is
/// created by BulletPhysicsServer3D and is held by the "singleton" variable of this class
/// Each time something require it, the body must be set again.

class BulletPhysicsDirectBodyState3D : public PhysicsDirectBodyState3D {
GDCLASS(BulletPhysicsDirectBodyState3D, PhysicsDirectBodyState3D);

static BulletPhysicsDirectBodyState3D *singleton;

public:
/// This class avoid the creation of more object of this class
static void initSingleton() {
if (!singleton) {
singleton = memnew(BulletPhysicsDirectBodyState3D);
}
}

static void destroySingleton() {
memdelete(singleton);
singleton = nullptr;
}

static void singleton_setDeltaTime(real_t p_deltaTime) {
singleton->deltaTime = p_deltaTime;
}

static BulletPhysicsDirectBodyState3D *get_singleton(RigidBodyBullet *p_body) {
singleton->body = p_body;
return singleton;
}

public:
RigidBodyBullet *body = nullptr;
real_t deltaTime = 0.0;

private:
BulletPhysicsDirectBodyState3D() {}

public:
virtual Vector3 get_total_gravity() const override;
virtual real_t get_total_angular_damp() const override;
virtual real_t get_total_linear_damp() const override;
Expand Down Expand Up @@ -133,7 +99,7 @@ class BulletPhysicsDirectBodyState3D : public PhysicsDirectBodyState3D {
virtual int get_contact_collider_shape(int p_contact_idx) const override;
virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const override;

virtual real_t get_step() const override { return deltaTime; }
virtual real_t get_step() const override;
virtual void integrate_forces() override {
// Skip the execution of this function
}
Expand Down Expand Up @@ -185,6 +151,7 @@ class RigidBodyBullet : public RigidCollisionObjectBullet {
};

private:
BulletPhysicsDirectBodyState3D *direct_access = nullptr;
friend class BulletPhysicsDirectBodyState3D;

// This is required only for Kinematic movement
Expand Down Expand Up @@ -229,6 +196,8 @@ class RigidBodyBullet : public RigidCollisionObjectBullet {
RigidBodyBullet();
~RigidBodyBullet();

BulletPhysicsDirectBodyState3D *get_direct_state() const { return direct_access; }

void init_kinematic_utilities();
void destroy_kinematic_utilities();
_FORCE_INLINE_ KinematicUtilities *get_kinematic_utilities() const { return kinematic_utilities; }
Expand Down
15 changes: 9 additions & 6 deletions servers/physics_2d/body_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,10 +585,7 @@ void Body2DSW::wakeup_neighbours() {

void Body2DSW::call_queries() {
if (fi_callback) {
PhysicsDirectBodyState2DSW *dbs = PhysicsDirectBodyState2DSW::singleton;
dbs->body = this;

Variant v = dbs;
Variant v = direct_access;
const Variant *vp[2] = { &v, &fi_callback->callback_udata };

Object *obj = ObjectDB::get_instance(fi_callback->id);
Expand Down Expand Up @@ -674,20 +671,26 @@ Body2DSW::Body2DSW() :
continuous_cd_mode = PhysicsServer2D::CCD_MODE_DISABLED;
can_sleep = true;
fi_callback = nullptr;

direct_access = memnew(PhysicsDirectBodyState2DSW);
direct_access->body = this;
}

Body2DSW::~Body2DSW() {
memdelete(direct_access);
if (fi_callback) {
memdelete(fi_callback);
}
}

PhysicsDirectBodyState2DSW *PhysicsDirectBodyState2DSW::singleton = nullptr;

PhysicsDirectSpaceState2D *PhysicsDirectBodyState2DSW::get_space_state() {
return body->get_space()->get_direct_state();
}

real_t PhysicsDirectBodyState2DSW::get_step() const {
return body->get_space()->get_step();
}

Variant PhysicsDirectBodyState2DSW::get_contact_collider_shape_metadata(int p_contact_idx) const {
ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Variant());

Expand Down
16 changes: 8 additions & 8 deletions servers/physics_2d/body_2d_sw.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "core/templates/vset.h"

class Constraint2DSW;
class PhysicsDirectBodyState2DSW;

class Body2DSW : public CollisionObject2DSW {
PhysicsServer2D::BodyMode mode;
Expand Down Expand Up @@ -130,6 +131,7 @@ class Body2DSW : public CollisionObject2DSW {

_FORCE_INLINE_ void _compute_area_gravity_and_dampenings(const Area2DSW *p_area);

PhysicsDirectBodyState2DSW *direct_access = nullptr;
friend class PhysicsDirectBodyState2DSW; // i give up, too many functions to expose

public:
Expand Down Expand Up @@ -289,6 +291,8 @@ class Body2DSW : public CollisionObject2DSW {

bool sleep_test(real_t p_step);

PhysicsDirectBodyState2DSW *get_direct_state() const { return direct_access; }

Body2DSW();
~Body2DSW();
};
Expand Down Expand Up @@ -341,9 +345,7 @@ class PhysicsDirectBodyState2DSW : public PhysicsDirectBodyState2D {
GDCLASS(PhysicsDirectBodyState2DSW, PhysicsDirectBodyState2D);

public:
static PhysicsDirectBodyState2DSW *singleton;
Body2DSW *body;
real_t step;
Body2DSW *body = nullptr;

virtual Vector2 get_total_gravity() const override { return body->gravity; } // get gravity vector working on this body space/area
virtual real_t get_total_angular_damp() const override { return body->area_angular_damp; } // get density of this body space/area
Expand Down Expand Up @@ -411,11 +413,9 @@ class PhysicsDirectBodyState2DSW : public PhysicsDirectBodyState2D {

virtual PhysicsDirectSpaceState2D *get_space_state() override;

virtual real_t get_step() const override { return step; }
PhysicsDirectBodyState2DSW() {
singleton = this;
body = nullptr;
}
virtual real_t get_step() const override;

PhysicsDirectBodyState2DSW() {}
};

#endif // BODY_2D_SW_H
20 changes: 3 additions & 17 deletions servers/physics_2d/physics_server_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -968,19 +968,10 @@ int PhysicsServer2DSW::body_test_ray_separation(RID p_body, const Transform2D &p
}

PhysicsDirectBodyState2D *PhysicsServer2DSW::body_get_direct_state(RID p_body) {
ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");

if (!body_owner.owns(p_body)) {
return nullptr;
}

Body2DSW *body = body_owner.getornull(p_body);
ERR_FAIL_COND_V(!body, nullptr);
ERR_FAIL_COND_V(!body->get_space(), nullptr);
ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");

direct_state->body = body;
return direct_state;
ERR_FAIL_COND_V_MSG(!body, nullptr, "Body with RID " + itos(p_body.get_id()) + " not owned by this server.");
ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || (body->get_space() && body->get_space()->is_locked()), nullptr, "Body state is inaccessible right now, wait for iteration or physics process notification.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also think this handles multi-threaded nicely. i.e. if someone uses this incorrectly they will know.

return body->get_direct_state();
}

/* JOINT API */
Expand Down Expand Up @@ -1240,10 +1231,8 @@ void PhysicsServer2DSW::set_active(bool p_active) {

void PhysicsServer2DSW::init() {
doing_sync = false;
last_step = 0.001;
iterations = 8; // 8?
stepper = memnew(Step2DSW);
direct_state = memnew(PhysicsDirectBodyState2DSW);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel it may be a better idea to create this on demand (when requested, if null, create and return)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used to sync the server state with the Godot scene every iteration; so I think there is little point in delaying its creation:

void Body2DSW::call_queries() {
if (fi_callback) {
PhysicsDirectBodyState2DSW *dbs = PhysicsDirectBodyState2DSW::singleton;
dbs->body = this;
Variant v = dbs;
const Variant *vp[2] = { &v, &fi_callback->callback_udata };

BTW This PR simplifies this to simply use it's own copy:
DirectAccess

Note: fi_callback is defined during the RigidBody creation:

PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed");

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

};

void PhysicsServer2DSW::step(real_t p_step) {
Expand All @@ -1253,8 +1242,6 @@ void PhysicsServer2DSW::step(real_t p_step) {

_update_shapes();

last_step = p_step;
PhysicsDirectBodyState2DSW::singleton->step = p_step;
island_count = 0;
active_objects = 0;
collision_pairs = 0;
Expand Down Expand Up @@ -1326,7 +1313,6 @@ void PhysicsServer2DSW::end_sync() {

void PhysicsServer2DSW::finish() {
memdelete(stepper);
memdelete(direct_state);
};

void PhysicsServer2DSW::_update_shapes() {
Expand Down
3 changes: 0 additions & 3 deletions servers/physics_2d/physics_server_2d_sw.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ class PhysicsServer2DSW : public PhysicsServer2D {
bool active;
int iterations;
bool doing_sync;
real_t last_step;

int island_count;
int active_objects;
Expand All @@ -59,8 +58,6 @@ class PhysicsServer2DSW : public PhysicsServer2D {
Step2DSW *stepper;
Set<const Space2DSW *> active_spaces;

PhysicsDirectBodyState2DSW *direct_state;

mutable RID_PtrOwner<Shape2DSW, true> shape_owner;
mutable RID_PtrOwner<Space2DSW, true> space_owner;
mutable RID_PtrOwner<Area2DSW, true> area_owner;
Expand Down
2 changes: 1 addition & 1 deletion servers/physics_2d/space_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
//fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction
Vector2 lv = b->get_linear_velocity();
//compute displacement from linear velocity
Vector2 motion = lv * PhysicsDirectBodyState2DSW::singleton->step;
Vector2 motion = lv * step;
real_t motion_len = motion.length();
motion.normalize();
cbk.valid_depth += motion_len * MAX(motion.dot(-cbk.valid_dir), 0.0);
Expand Down
4 changes: 4 additions & 0 deletions servers/physics_2d/space_2d_sw.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class Space2DSW {

bool locked;

real_t step;
int island_count;
int active_objects;
int collision_pairs;
Expand All @@ -132,6 +133,9 @@ class Space2DSW {
_FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; }
_FORCE_INLINE_ RID get_self() const { return self; }

_FORCE_INLINE_ void set_step(const real_t &p_step) { step = p_step; }
_FORCE_INLINE_ real_t get_step() const { return step; }

void set_default_area(Area2DSW *p_area) { area = p_area; }
Area2DSW *get_default_area() const { return area; }

Expand Down
2 changes: 1 addition & 1 deletion servers/physics_2d/step_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ void Step2DSW::_check_suspend(Body2DSW *p_island, real_t p_delta) {

void Step2DSW::step(Space2DSW *p_space, real_t p_delta, int p_iterations) {
p_space->lock(); // can't access space during this

p_space->set_step(p_delta);
p_space->setup(); //update inertias, etc

const SelfList<Body2DSW>::List *body_list = &p_space->get_active_body_list();
Expand Down
15 changes: 9 additions & 6 deletions servers/physics_3d/body_3d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -682,10 +682,7 @@ void Body3DSW::wakeup_neighbours() {

void Body3DSW::call_queries() {
if (fi_callback) {
PhysicsDirectBodyState3DSW *dbs = PhysicsDirectBodyState3DSW::singleton;
dbs->body = this;

Variant v = dbs;
Variant v = direct_access;

Object *obj = ObjectDB::get_instance(fi_callback->id);
if (!obj) {
Expand Down Expand Up @@ -772,16 +769,22 @@ Body3DSW::Body3DSW() :
continuous_cd = false;
can_sleep = true;
fi_callback = nullptr;

direct_access = memnew(PhysicsDirectBodyState3DSW);
direct_access->body = this;
}

Body3DSW::~Body3DSW() {
memdelete(direct_access);
if (fi_callback) {
memdelete(fi_callback);
}
}

PhysicsDirectBodyState3DSW *PhysicsDirectBodyState3DSW::singleton = nullptr;

PhysicsDirectSpaceState3D *PhysicsDirectBodyState3DSW::get_space_state() {
return body->get_space()->get_direct_state();
}

real_t PhysicsDirectBodyState3DSW::get_step() const {
return body->get_space()->get_step();
}
Loading