Skip to content

Commit

Permalink
Optimized physics object spawn time and optimized shape usage when th…
Browse files Browse the repository at this point in the history
…e shape is not scaled
  • Loading branch information
AndreaCatania committed Jun 24, 2020
1 parent d360e6f commit 7709a83
Show file tree
Hide file tree
Showing 12 changed files with 204 additions and 71 deletions.
6 changes: 4 additions & 2 deletions modules/bullet/area_bullet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,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 @@ -177,13 +177,15 @@ void AreaBullet::set_space(SpaceBullet *p_space) {
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();
}
}

Expand Down
2 changes: 1 addition & 1 deletion modules/bullet/area_bullet.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class AreaBullet : public RigidCollisionObjectBullet {
_FORCE_INLINE_ int get_spOv_priority() { return spOv_priority; }

virtual void main_shape_changed();
virtual void reload_body();
virtual void do_reload_body();
virtual void set_space(SpaceBullet *p_space);

virtual void dispatch_callbacks();
Expand Down
58 changes: 41 additions & 17 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,13 @@ 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) {
do_reload_body();
need_body_reload = false;
}
}

void CollisionObjectBullet::set_collision_enabled(bool p_enabled) {
collisionsEnabled = p_enabled;
if (collisionsEnabled) {
Expand Down Expand Up @@ -319,58 +333,68 @@ bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) {
return !shapes[p_index].active;
}

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

void RigidCollisionObjectBullet::shape_changed(int p_shape_index) {
ShapeWrapper &shp = shapes.write[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;
}

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

mainShape = nullptr;

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 @@ -389,5 +413,5 @@ void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_perm
if (shp.bt_shape == mainShape) {
mainShape = nullptr;
}
bulletdelete(shp.bt_shape);
shp.release_bt_shape();
}
26 changes: 23 additions & 3 deletions modules/bullet/collision_object_bullet.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,12 @@ class CollisionObjectBullet : public RIDBullet {

struct ShapeWrapper {
ShapeBullet *shape = nullptr;
btCollisionShape *bt_shape = nullptr;
btTransform transform;
btVector3 scale;
bool active = true;
btCollisionShape *bt_shape = nullptr;

public:
ShapeWrapper() {}

ShapeWrapper(ShapeBullet *p_shape, const btTransform &p_transform, bool p_active) :
Expand Down Expand Up @@ -107,6 +108,7 @@ class CollisionObjectBullet : public RIDBullet {
btTransform get_adjusted_transform() const;

void claim_bt_shape(const btVector3 &body_scale);
void release_bt_shape();
};

protected:
Expand All @@ -124,12 +126,17 @@ class CollisionObjectBullet : public RIDBullet {

VSet<RID> exceptions;

bool need_body_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<AreaBullet *> areasOverlapped;
bool isTransformChanged = false;

public:
bool is_in_world = false;

public:
CollisionObjectBullet(Type p_type);
virtual ~CollisionObjectBullet();
Expand Down Expand Up @@ -183,13 +190,21 @@ class CollisionObjectBullet : public RIDBullet {
return collisionLayer & p_other->collisionMask || p_other->collisionLayer & collisionMask;
}

virtual void reload_body() = 0;
bool need_reload_body() const {
return need_body_reload;
}

void reload_body() {
need_body_reload = true;
}
virtual void do_reload_body() = 0;
virtual void set_space(SpaceBullet *p_space) = 0;
_FORCE_INLINE_ SpaceBullet *get_space() const { return space; }

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;

void set_collision_enabled(bool p_enabled);
Expand All @@ -215,6 +230,7 @@ class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwn
protected:
btCollisionShape *mainShape = nullptr;
Vector<ShapeWrapper> shapes;
bool need_shape_reload = true;

public:
RigidCollisionObjectBullet(Type p_type) :
Expand Down Expand Up @@ -246,8 +262,12 @@ 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 shape_changed(int p_shape_index);
virtual void reload_shapes();
void reload_shapes();
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();
Expand Down
12 changes: 7 additions & 5 deletions modules/bullet/rigid_body_bullet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ void RigidBodyBullet::KinematicUtilities::copyAllOwnerShapes() {
case PhysicsServer3D::SHAPE_CYLINDER:
case PhysicsServer3D::SHAPE_CONVEX_POLYGON:
case PhysicsServer3D::SHAPE_RAY: {
shapes.write[i].shape = static_cast<btConvexShape *>(shape_wrapper->shape->create_bt_shape(owner_scale * shape_wrapper->scale, safe_margin));
shapes.write[i].shape = static_cast<btConvexShape *>(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.");
Expand Down Expand Up @@ -307,7 +307,7 @@ void RigidBodyBullet::main_shape_changed() {
set_continuous_collision_detection(is_continuous_collision_detection_enabled()); // Reset
}

void RigidBodyBullet::reload_body() {
void RigidBodyBullet::do_reload_body() {
if (space) {
space->remove_rigid_body(this);
if (get_main_shape()) {
Expand All @@ -325,13 +325,15 @@ void RigidBodyBullet::set_space(SpaceBullet *p_space) {
assert_no_constraints();

// Remove this object form the physics world
space->unregister_collision_object(this);
space->remove_rigid_body(this);
}

space = p_space;

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

Expand Down Expand Up @@ -803,8 +805,8 @@ const btTransform &RigidBodyBullet::get_transform__bullet() const {
}
}

void RigidBodyBullet::reload_shapes() {
RigidCollisionObjectBullet::reload_shapes();
void RigidBodyBullet::do_reload_shapes() {
RigidCollisionObjectBullet::do_reload_shapes();

const btScalar invMass = btBody->getInvMass();
const btScalar mass = invMass == 0 ? 0 : 1 / invMass;
Expand Down
4 changes: 2 additions & 2 deletions modules/bullet/rigid_body_bullet.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ class RigidBodyBullet : public RigidCollisionObjectBullet {
_FORCE_INLINE_ btRigidBody *get_bt_rigid_body() { return btBody; }

virtual void main_shape_changed();
virtual void reload_body();
virtual void do_reload_body();
virtual void set_space(SpaceBullet *p_space);

virtual void dispatch_callbacks();
Expand Down Expand Up @@ -315,7 +315,7 @@ class RigidBodyBullet : public RigidCollisionObjectBullet {
virtual void set_transform__bullet(const btTransform &p_global_transform);
virtual const btTransform &get_transform__bullet() const;

virtual void reload_shapes();
virtual void do_reload_shapes();

virtual void on_enter_area(AreaBullet *p_area);
virtual void on_exit_area(AreaBullet *p_area);
Expand Down
Loading

0 comments on commit 7709a83

Please sign in to comment.