Skip to content

Commit

Permalink
Merge pull request #40252 from AndreaCatania/flush
Browse files Browse the repository at this point in the history
Improved Bullet Physics flush algorithm, Lazy collision filter reload, Shape reload regression fix.
  • Loading branch information
akien-mga authored Jul 27, 2020
2 parents bd9fc75 + 8d0d6d6 commit 3e87022
Show file tree
Hide file tree
Showing 11 changed files with 217 additions and 170 deletions.
21 changes: 9 additions & 12 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 @@ -173,9 +169,9 @@ void AreaBullet::do_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);
Expand All @@ -187,10 +183,11 @@ void AreaBullet::set_space(SpaceBullet *p_space) {
if (space) {
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 @@ -204,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
24 changes: 11 additions & 13 deletions modules/bullet/area_bullet.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
#define AREABULLET_H

#include "collision_object_bullet.h"
#include "core/vector.h"
#include "core/local_vector.h"
#include "servers/physics_server_3d.h"
#include "space_bullet.h"

Expand Down 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 do_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
44 changes: 26 additions & 18 deletions modules/bullet/collision_object_bullet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,20 @@ 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) {
void CollisionObjectBullet::reload_body() {
needs_body_reload = true;
}

void CollisionObjectBullet::dispatch_callbacks() {}

void CollisionObjectBullet::pre_process() {
if (needs_body_reload) {
do_reload_body();
need_body_reload = false;
} 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) {
Expand Down Expand Up @@ -245,7 +254,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 @@ -307,7 +316,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 @@ -325,24 +334,24 @@ 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::prepare_object_for_dispatch() {
void RigidCollisionObjectBullet::pre_process() {
if (need_shape_reload) {
do_reload_shapes();
need_shape_reload = false;
}
CollisionObjectBullet::prepare_object_for_dispatch();
CollisionObjectBullet::pre_process();
}

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;
}
Expand All @@ -363,12 +372,11 @@ void RigidCollisionObjectBullet::do_reload_shapes() {
mainShape = nullptr;

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

// Reset all shapes if required
if (force_shape_reset) {
for (int i(0); i < shape_count; ++i) {
shapes_ptr[i].release_bt_shape();
shapes[i].release_bt_shape();
}
force_shape_reset = false;
}
Expand All @@ -377,10 +385,10 @@ void RigidCollisionObjectBullet::do_reload_shapes() {

if (1 == shape_count) {
// Is it possible to optimize by not using compound?
btTransform transform = shapes_ptr[0].get_adjusted_transform();
btTransform transform = shapes[0].get_adjusted_transform();
if (transform.getOrigin().isZero() && transform.getBasis() == transform.getBasis().getIdentity()) {
shapes_ptr[0].claim_bt_shape(body_scale);
mainShape = shapes_ptr[0].bt_shape;
shapes[0].claim_bt_shape(body_scale);
mainShape = shapes[0].bt_shape;
main_shape_changed();
// Nothing more to do
return;
Expand All @@ -391,10 +399,10 @@ void RigidCollisionObjectBullet::do_reload_shapes() {
btCompoundShape *compoundShape = bulletnew(btCompoundShape(enableDynamicAabbTree, shape_count));

for (int i(0); i < shape_count; ++i) {
shapes_ptr[i].claim_bt_shape(body_scale);
btTransform scaled_shape_transform(shapes_ptr[i].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, shapes_ptr[i].bt_shape);
compoundShape->addChildShape(scaled_shape_transform, shapes[i].bt_shape);
}

compoundShape->recalculateLocalAabb();
Expand All @@ -408,7 +416,7 @@ 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;
Expand Down
40 changes: 21 additions & 19 deletions modules/bullet/collision_object_bullet.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#ifndef COLLISION_OBJECT_BULLET_H
#define COLLISION_OBJECT_BULLET_H

#include "core/local_vector.h"
#include "core/math/transform.h"
#include "core/math/vector3.h"
#include "core/object.h"
Expand Down Expand Up @@ -126,16 +127,18 @@ class CollisionObjectBullet : public RIDBullet {

VSet<RID> exceptions;

bool need_body_reload = true;
bool needs_body_reload = true;
bool needs_collision_filters_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;
LocalVector<AreaBullet *> areasOverlapped;
bool isTransformChanged = false;

public:
bool is_in_world = false;
bool is_in_flush_queue = false;

public:
CollisionObjectBullet(Type p_type);
Expand Down Expand Up @@ -171,41 +174,40 @@ class CollisionObjectBullet : public RIDBullet {
_FORCE_INLINE_ void set_collision_layer(uint32_t p_layer) {
if (collisionLayer != p_layer) {
collisionLayer = p_layer;
on_collision_filters_change();
needs_collision_filters_reload = true;
}
}
_FORCE_INLINE_ uint32_t get_collision_layer() const { return collisionLayer; }

_FORCE_INLINE_ void set_collision_mask(uint32_t p_mask) {
if (collisionMask != p_mask) {
collisionMask = p_mask;
on_collision_filters_change();
needs_collision_filters_reload = true;
}
}
_FORCE_INLINE_ uint32_t get_collision_mask() const { return collisionMask; }

virtual void on_collision_filters_change() = 0;
virtual void do_reload_collision_filters() = 0;

_FORCE_INLINE_ bool test_collision_mask(CollisionObjectBullet *p_other) const {
return collisionLayer & p_other->collisionMask || p_other->collisionLayer & collisionMask;
}

bool need_reload_body() const {
return need_body_reload;
return needs_body_reload;
}

void reload_body() {
need_body_reload = true;
}
void reload_body();

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;
virtual void dispatch_callbacks();
virtual void pre_process();

void set_collision_enabled(bool p_enabled);
bool is_collisions_response_enabled();
Expand All @@ -229,15 +231,15 @@ class CollisionObjectBullet : public RIDBullet {
class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwnerBullet {
protected:
btCollisionShape *mainShape = nullptr;
Vector<ShapeWrapper> shapes;
LocalVector<ShapeWrapper> shapes;
bool need_shape_reload = true;

public:
RigidCollisionObjectBullet(Type p_type) :
CollisionObjectBullet(p_type) {}
~RigidCollisionObjectBullet();

_FORCE_INLINE_ const Vector<ShapeWrapper> &get_shapes_wrappers() const { return shapes; }
_FORCE_INLINE_ const LocalVector<ShapeWrapper> &get_shapes_wrappers() const { return shapes; }

_FORCE_INLINE_ btCollisionShape *get_main_shape() const { return mainShape; }

Expand All @@ -248,9 +250,9 @@ class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwn
ShapeBullet *get_shape(int p_index) const;
btCollisionShape *get_bt_shape(int p_index) const;

int find_shape(ShapeBullet *p_shape) const;
virtual int find_shape(ShapeBullet *p_shape) const override;

virtual void remove_shape_full(ShapeBullet *p_shape);
virtual void remove_shape_full(ShapeBullet *p_shape) override;
void remove_shape_full(int p_index);
void remove_all_shapes(bool p_permanentlyFromThisBody = false, bool p_force_not_reload = false);

Expand All @@ -262,15 +264,15 @@ 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 pre_process() override;

virtual void shape_changed(int p_shape_index);
void reload_shapes();
virtual void shape_changed(int p_shape_index) override;
virtual void reload_shapes() override;
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();
virtual void body_scale_changed() override;

private:
void internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody = false);
Expand Down
Loading

0 comments on commit 3e87022

Please sign in to comment.