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

Optimized physics object spawn time, improved bullet physics server code. #42643

Closed
wants to merge 2 commits 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
27 changes: 13 additions & 14 deletions modules/bullet/area_bullet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -164,7 +160,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 @@ -173,22 +169,25 @@ 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();
scratch();
}
}

void AreaBullet::on_collision_filters_change() {
void AreaBullet::do_reload_collision_filters() {
if (space) {
space->reload_collision_filters(this);
}
Expand All @@ -202,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;
}
}

Expand Down
22 changes: 10 additions & 12 deletions modules/bullet/area_bullet.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class AreaBullet : public RigidCollisionObjectBullet {
Variant *call_event_res_ptr[5];

btGhostObject *btGhost;
Vector<OverlappingObjectData> overlappingObjects;
LocalVector<OverlappingObjectData> overlappingObjects;
bool monitorable = true;

PhysicsServer3D::AreaSpaceOverrideMode spOv_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED;
Expand All @@ -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:
Expand Down Expand Up @@ -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 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();
Expand All @@ -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);
Expand All @@ -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
2 changes: 1 addition & 1 deletion modules/bullet/bullet_physics_server.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class BulletPhysicsServer3D : public PhysicsServer3D {

bool active = true;
char active_spaces_count = 0;
Vector<SpaceBullet *> active_spaces;
LocalVector<SpaceBullet *> active_spaces;

mutable RID_PtrOwner<SpaceBullet> space_owner;
mutable RID_PtrOwner<ShapeBullet> shape_owner;
Expand Down
104 changes: 82 additions & 22 deletions modules/bullet/collision_object_bullet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ btTransform CollisionObjectBullet::ShapeWrapper::get_adjusted_transform() const
}

void CollisionObjectBullet::ShapeWrapper::claim_bt_shape(const btVector3 &body_scale) {
if (!bt_shape) {
if (bt_shape == nullptr) {
if (active) {
bt_shape = shape->create_bt_shape(scale * body_scale);
} else {
Expand All @@ -88,6 +88,13 @@ void CollisionObjectBullet::ShapeWrapper::claim_bt_shape(const btVector3 &body_s
}
}

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

CollisionObjectBullet::CollisionObjectBullet(Type p_type) :
RIDBullet(),
type(p_type) {}
Expand Down Expand Up @@ -158,6 +165,47 @@ bool CollisionObjectBullet::has_collision_exception(const CollisionObjectBullet
return !bt_collision_object->checkCollideWith(p_otherCollisionObject->bt_collision_object);
}

void CollisionObjectBullet::set_collision_layer(uint32_t p_layer) {
if (collisionLayer != p_layer) {
collisionLayer = p_layer;
needs_collision_filters_reload = true;
if (likely(space)) {
space->add_to_dirty_queue(this);
}
}
}

void CollisionObjectBullet::set_collision_mask(uint32_t p_mask) {
if (collisionMask != p_mask) {
collisionMask = p_mask;
needs_collision_filters_reload = true;
if (likely(space)) {
space->add_to_dirty_queue(this);
}
}
}

void CollisionObjectBullet::reload_body() {
needs_body_reload = true;
if (likely(space)) {
space->add_to_dirty_queue(this);
}
}

void CollisionObjectBullet::dispatch_callbacks() {}

void CollisionObjectBullet::flush_dirty() {
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::pre_process() {}

void CollisionObjectBullet::set_collision_enabled(bool p_enabled) {
collisionsEnabled = p_enabled;
if (collisionsEnabled) {
Expand Down Expand Up @@ -231,7 +279,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;
Expand Down Expand Up @@ -293,7 +341,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);
}

Expand All @@ -311,66 +359,78 @@ 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);
}

bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) {
return !shapes[p_index].active;
}

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

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;
}
bulletdelete(shp.bt_shape);
shp.release_bt_shape();
reload_shapes();
}

void RigidCollisionObjectBullet::reload_shapes() {
need_shape_reload = true;
if (likely(space)) {
space->add_to_dirty_queue(this);
}
}

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

mainShape = nullptr;

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

// 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[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[0].get_adjusted_transform();
if (transform.getOrigin().isZero() && transform.getBasis() == transform.getBasis().getIdentity()) {
shpWrapper->claim_bt_shape(body_scale);
mainShape = shpWrapper->bt_shape;
shapes[0].claim_bt_shape(body_scale);
mainShape = shapes[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[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, shpWrapper->bt_shape);
compoundShape->addChildShape(scaled_shape_transform, shapes[i].bt_shape);
}

compoundShape->recalculateLocalAabb();
Expand All @@ -384,10 +444,10 @@ 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;
}
bulletdelete(shp.bt_shape);
shp.release_bt_shape();
}
Loading