Skip to content

Commit

Permalink
Optimized physics object spawn time and some other parts of the bulle…
Browse files Browse the repository at this point in the history
…t server.

- Optimized physics object spawn time, by integrating lazy body reload.
- Optimized shape usage when the shape is not scaled.
- Make sure to correctly fetch gravity when the integrate_forces function is used
- Added override keyword
- Using LocalVector
  • Loading branch information
AndreaCatania committed Dec 11, 2020
1 parent 146316c commit 9cc2a73
Show file tree
Hide file tree
Showing 13 changed files with 470 additions and 219 deletions.
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

0 comments on commit 9cc2a73

Please sign in to comment.