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

Improved Bullet Physics flush algorithm, Lazy collision filter reload, Shape reload regression fix. #40252

Merged
merged 1 commit into from
Jul 27, 2020
Merged
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
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) {
madmiraal marked this conversation as resolved.
Show resolved Hide resolved
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 {}
madmiraal marked this conversation as resolved.
Show resolved Hide resolved
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();
}
madmiraal marked this conversation as resolved.
Show resolved Hide resolved
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;

madmiraal marked this conversation as resolved.
Show resolved Hide resolved
/// 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;

madmiraal marked this conversation as resolved.
Show resolved Hide resolved
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;
}
madmiraal marked this conversation as resolved.
Show resolved Hide resolved
}
_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