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

[3.2] Optimized physics object spawn time #40188

Closed
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
26 changes: 13 additions & 13 deletions modules/bullet/area_bullet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ AreaBullet::AreaBullet() :
spOv_gravityMag(10),
spOv_linearDump(0.1),
spOv_angularDump(0.1),
spOv_priority(0),
isScratched(false) {
spOv_priority(0) {

btGhost = bulletnew(btGhostObject);
reload_shapes();
Expand All @@ -64,8 +63,9 @@ AreaBullet::AreaBullet() :
/// In order to use collision objects as trigger, you have to disable the collision response.
set_collision_enabled(false);

for (int i = 0; i < 5; ++i)
for (int i = 0; i < 5; ++i) {
call_event_res_ptr[i] = &call_event_res[i];
}
}

AreaBullet::~AreaBullet() {
Expand All @@ -75,9 +75,7 @@ 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) {
Expand Down Expand Up @@ -122,9 +120,9 @@ void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer:
}

void AreaBullet::scratch() {
if (isScratched)
return;
isScratched = true;
if (space != nullptr) {
space->add_to_pre_flush_queue(this);
}
}

void AreaBullet::clear_overlaps(bool p_notify) {
Expand Down Expand Up @@ -171,7 +169,7 @@ void AreaBullet::main_shape_changed() {
btGhost->setCollisionShape(get_main_shape());
}

void AreaBullet::reload_body() {
void AreaBullet::do_reload_body() {
if (space) {
space->remove_area(this);
space->add_area(this);
Expand All @@ -180,22 +178,24 @@ void AreaBullet::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);
space->remove_area(this);
}

space = p_space;

if (space) {
space->add_area(this);
space->register_collision_object(this);
reload_body();
}
}

void AreaBullet::on_collision_filters_change() {
void AreaBullet::do_reload_collision_filters() {
if (space) {
space->reload_collision_filters(this);
}
Expand Down
20 changes: 9 additions & 11 deletions modules/bullet/area_bullet.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,6 @@ class AreaBullet : public RigidCollisionObjectBullet {
real_t spOv_angularDump;
int spOv_priority;

bool isScratched;

InOutEventCallback eventsCallbacks[2];

public:
Expand Down Expand Up @@ -142,11 +140,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 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, PhysicsServer::AreaBodyStatus p_status);
void set_on_state_change(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant());
void scratch();
Expand All @@ -155,9 +153,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);
Expand All @@ -169,8 +167,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
77 changes: 57 additions & 20 deletions modules/bullet/collision_object_bullet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,19 @@ btTransform CollisionObjectBullet::ShapeWrapper::get_adjusted_transform() const
}

void CollisionObjectBullet::ShapeWrapper::claim_bt_shape(const btVector3 &body_scale) {
if (!bt_shape) {
if (active)
if (bt_shape == nullptr) {
if (active) {
bt_shape = shape->create_bt_shape(scale * body_scale);
else
} else {
bt_shape = ShapeBullet::create_shape_empty();
}
}
}

void CollisionObjectBullet::ShapeWrapper::release_bt_shape() {
if (bt_shape != nullptr) {
shape->destroy_bt_shape(bt_shape);
bt_shape = nullptr;
}
}

Expand Down Expand Up @@ -165,6 +173,22 @@ bool CollisionObjectBullet::has_collision_exception(const CollisionObjectBullet
return !bt_collision_object->checkCollideWith(p_otherCollisionObject->bt_collision_object);
}

void CollisionObjectBullet::reload_body() {
needs_body_reload = true;
}

void CollisionObjectBullet::dispatch_callbacks() {}

void CollisionObjectBullet::pre_process() {
if (needs_body_reload) {
do_reload_body();
} 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) {
collisionsEnabled = p_enabled;
if (collisionsEnabled) {
Expand Down Expand Up @@ -319,8 +343,9 @@ Transform RigidCollisionObjectBullet::get_shape_transform(int p_index) const {
}

void RigidCollisionObjectBullet::set_shape_disabled(int p_index, bool p_disabled) {
if (shapes[p_index].active != p_disabled)
if (shapes[p_index].active != p_disabled) {
return;
}
shapes.write[p_index].active = !p_disabled;
shape_changed(p_index);
}
Expand All @@ -329,59 +354,71 @@ bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) {
return !shapes[p_index].active;
}

void RigidCollisionObjectBullet::pre_process() {
if (need_shape_reload) {
do_reload_shapes();
need_shape_reload = false;
}
CollisionObjectBullet::pre_process();
}

void RigidCollisionObjectBullet::shape_changed(int p_shape_index) {
ShapeWrapper &shp = shapes.write[p_shape_index];
if (shp.bt_shape == mainShape) {
mainShape = NULL;
}
bulletdelete(shp.bt_shape);
shp.release_bt_shape();
reload_shapes();
}

void RigidCollisionObjectBullet::reload_shapes() {
need_shape_reload = true;
if (space) {
space->add_to_flush_queue(this);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

The shape should not be reloaded during the flush but during the pre_process. To fix the issue #40840 you need to insert p_body->pre_process(); at the beginning of the function test_body_motion.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't understand what you mean. I already added p_body->pre_process(); in test_body_motion on the line you mentioned in this comment #40886 (comment) (see 24d50fd#diff-a61d01bcaef4874b6713c0b00e6d4571R1014)

}

void RigidCollisionObjectBullet::do_reload_shapes() {
if (mainShape && mainShape->isCompound()) {
// Destroy compound
bulletdelete(mainShape);
}

mainShape = NULL;

ShapeWrapper *shpWrapper;
const int shape_count = shapes.size();
ShapeWrapper *shapes_ptr = shapes.ptrw();

// Reset shape if required
// Reset all shapes if required
if (force_shape_reset) {
for (int i(0); i < shape_count; ++i) {
shpWrapper = &shapes.write[i];
bulletdelete(shpWrapper->bt_shape);
shapes_ptr[i].release_bt_shape();
}
force_shape_reset = false;
}

const btVector3 body_scale(get_bt_body_scale());

// Try to optimize by not using compound
if (1 == shape_count) {
shpWrapper = &shapes.write[0];
btTransform transform = shpWrapper->get_adjusted_transform();
// Is it possible to optimize by not using compound?
btTransform transform = shapes_ptr[0].get_adjusted_transform();
if (transform.getOrigin().isZero() && transform.getBasis() == transform.getBasis().getIdentity()) {
shpWrapper->claim_bt_shape(body_scale);
mainShape = shpWrapper->bt_shape;
shapes_ptr[0].claim_bt_shape(body_scale);
mainShape = shapes_ptr[0].bt_shape;
main_shape_changed();
// Nothing more to do
return;
}
}

// Optimization not possible use a compound shape
// Optimization not possible use a compound shape.
btCompoundShape *compoundShape = bulletnew(btCompoundShape(enableDynamicAabbTree, shape_count));

for (int i(0); i < shape_count; ++i) {
shpWrapper = &shapes.write[i];
shpWrapper->claim_bt_shape(body_scale);
btTransform scaled_shape_transform(shpWrapper->get_adjusted_transform());
shapes_ptr[i].claim_bt_shape(body_scale);
btTransform scaled_shape_transform(shapes_ptr[i].get_adjusted_transform());
scaled_shape_transform.getOrigin() *= body_scale;
compoundShape->addChildShape(scaled_shape_transform, shpWrapper->bt_shape);
compoundShape->addChildShape(scaled_shape_transform, shapes_ptr[i].bt_shape);
}

compoundShape->recalculateLocalAabb();
Expand All @@ -400,5 +437,5 @@ void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_perm
if (shp.bt_shape == mainShape) {
mainShape = NULL;
}
bulletdelete(shp.bt_shape);
shp.release_bt_shape();
}
Loading