Skip to content

Commit

Permalink
Merge pull request #39726 from AndreaCatania/add_body_impr_physics
Browse files Browse the repository at this point in the history
Optimized physics object spawn time
  • Loading branch information
akien-mga authored Jul 7, 2020
2 parents 480cb25 + 7709a83 commit bd3a468
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 @@ -178,13 +178,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 bd3a468

Please sign in to comment.