Optimitzed area overlap checks

This commit is contained in:
Andrea Catania 2018-10-07 07:14:38 +02:00
parent 7d681274f8
commit 15305ec91f
10 changed files with 62 additions and 43 deletions

View file

@ -157,6 +157,7 @@ public:
virtual void on_collision_filters_change(); virtual void on_collision_filters_change();
virtual void on_collision_checker_start() {} virtual void on_collision_checker_start() {}
virtual void on_collision_checker_end() { isTransformChanged = false; }
void add_overlap(CollisionObjectBullet *p_otherObject); void add_overlap(CollisionObjectBullet *p_otherObject);
void put_overlap_as_exit(int p_index); void put_overlap_as_exit(int p_index);

View file

@ -1489,7 +1489,7 @@ void BulletPhysicsServer::free(RID p_rid) {
body->set_space(NULL); body->set_space(NULL);
body->remove_all_shapes(true); body->remove_all_shapes(true, true);
rigid_body_owner.free(p_rid); rigid_body_owner.free(p_rid);
bulletdelete(body); bulletdelete(body);
@ -1509,7 +1509,7 @@ void BulletPhysicsServer::free(RID p_rid) {
area->set_space(NULL); area->set_space(NULL);
area->remove_all_shapes(true); area->remove_all_shapes(true, true);
area_owner.free(p_rid); area_owner.free(p_rid);
bulletdelete(area); bulletdelete(area);

View file

@ -74,7 +74,8 @@ CollisionObjectBullet::CollisionObjectBullet(Type p_type) :
bt_collision_object(NULL), bt_collision_object(NULL),
body_scale(1., 1., 1.), body_scale(1., 1., 1.),
force_shape_reset(false), force_shape_reset(false),
space(NULL) {} space(NULL),
isTransformChanged(false) {}
CollisionObjectBullet::~CollisionObjectBullet() { CollisionObjectBullet::~CollisionObjectBullet() {
// Remove all overlapping, notify is not required since godot take care of it // Remove all overlapping, notify is not required since godot take care of it
@ -188,19 +189,24 @@ Transform CollisionObjectBullet::get_transform() const {
void CollisionObjectBullet::set_transform__bullet(const btTransform &p_global_transform) { void CollisionObjectBullet::set_transform__bullet(const btTransform &p_global_transform) {
bt_collision_object->setWorldTransform(p_global_transform); bt_collision_object->setWorldTransform(p_global_transform);
notify_transform_changed();
} }
const btTransform &CollisionObjectBullet::get_transform__bullet() const { const btTransform &CollisionObjectBullet::get_transform__bullet() const {
return bt_collision_object->getWorldTransform(); return bt_collision_object->getWorldTransform();
} }
void CollisionObjectBullet::notify_transform_changed() {
isTransformChanged = true;
}
RigidCollisionObjectBullet::RigidCollisionObjectBullet(Type p_type) : RigidCollisionObjectBullet::RigidCollisionObjectBullet(Type p_type) :
CollisionObjectBullet(p_type), CollisionObjectBullet(p_type),
mainShape(NULL) { mainShape(NULL) {
} }
RigidCollisionObjectBullet::~RigidCollisionObjectBullet() { RigidCollisionObjectBullet::~RigidCollisionObjectBullet() {
remove_all_shapes(true); remove_all_shapes(true, true);
if (mainShape && mainShape->isCompound()) { if (mainShape && mainShape->isCompound()) {
bulletdelete(mainShape); bulletdelete(mainShape);
} }
@ -260,13 +266,14 @@ void RigidCollisionObjectBullet::remove_shape_full(int p_index) {
reload_shapes(); reload_shapes();
} }
void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBody) { void RigidCollisionObjectBullet::remove_all_shapes(bool p_permanentlyFromThisBody, bool p_force_not_reload) {
// Reverse order required for delete. // Reverse order required for delete.
for (int i = shapes.size() - 1; 0 <= i; --i) { for (int i = shapes.size() - 1; 0 <= i; --i) {
internal_shape_destroy(i, p_permanentlyFromThisBody); internal_shape_destroy(i, p_permanentlyFromThisBody);
} }
shapes.clear(); shapes.clear();
reload_shapes(); if (!p_force_not_reload)
reload_shapes();
} }
void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) { void RigidCollisionObjectBullet::set_shape_transform(int p_index, const Transform &p_transform) {
@ -323,9 +330,6 @@ void RigidCollisionObjectBullet::reload_shapes() {
const btVector3 body_scale(get_bt_body_scale()); const btVector3 body_scale(get_bt_body_scale());
if (!shape_count)
return;
// Try to optimize by not using compound // Try to optimize by not using compound
if (1 == shape_count) { if (1 == shape_count) {
shpWrapper = &shapes.write[0]; shpWrapper = &shapes.write[0];

View file

@ -132,6 +132,7 @@ protected:
/// New area is added when overlap with new area (AreaBullet::addOverlap), then is removed when it exit (CollisionObjectBullet::onExitArea) /// 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 /// This array is used mainly to know which area hold the pointer of this object
Vector<AreaBullet *> areasOverlapped; Vector<AreaBullet *> areasOverlapped;
bool isTransformChanged;
public: public:
CollisionObjectBullet(Type p_type); CollisionObjectBullet(Type p_type);
@ -187,6 +188,7 @@ public:
_FORCE_INLINE_ SpaceBullet *get_space() const { return space; } _FORCE_INLINE_ SpaceBullet *get_space() const { return space; }
virtual void on_collision_checker_start() = 0; virtual void on_collision_checker_start() = 0;
virtual void on_collision_checker_end() = 0;
virtual void dispatch_callbacks() = 0; virtual void dispatch_callbacks() = 0;
@ -204,6 +206,9 @@ public:
Transform get_transform() const; Transform get_transform() const;
virtual void set_transform__bullet(const btTransform &p_global_transform); virtual void set_transform__bullet(const btTransform &p_global_transform);
virtual const btTransform &get_transform__bullet() const; virtual const btTransform &get_transform__bullet() const;
bool is_transform_changed() const { return isTransformChanged; }
virtual void notify_transform_changed();
}; };
class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwnerBullet { class RigidCollisionObjectBullet : public CollisionObjectBullet, public ShapeOwnerBullet {
@ -230,7 +235,7 @@ public:
virtual void remove_shape_full(ShapeBullet *p_shape); virtual void remove_shape_full(ShapeBullet *p_shape);
void remove_shape_full(int p_index); void remove_shape_full(int p_index);
void remove_all_shapes(bool p_permanentlyFromThisBody = false); void remove_all_shapes(bool p_permanentlyFromThisBody = false, bool p_force_not_reload = false);
void set_shape_transform(int p_index, const Transform &p_transform); void set_shape_transform(int p_index, const Transform &p_transform);

View file

@ -82,7 +82,7 @@ public:
virtual void setWorldTransform(const btTransform &worldTrans) { virtual void setWorldTransform(const btTransform &worldTrans) {
bodyCurrentWorldTransform = worldTrans; bodyCurrentWorldTransform = worldTrans;
owner->scratch(); owner->notify_transform_changed();
} }
public: public:

View file

@ -265,13 +265,13 @@ RigidBodyBullet::RigidBodyBullet() :
angularDamp(0), angularDamp(0),
can_sleep(true), can_sleep(true),
omit_forces_integration(false), omit_forces_integration(false),
can_integrate_forces(false),
maxCollisionsDetection(0), maxCollisionsDetection(0),
collisionsCount(0), collisionsCount(0),
maxAreasWhereIam(10), maxAreasWhereIam(10),
areaWhereIamCount(0), areaWhereIamCount(0),
countGravityPointSpaces(0), countGravityPointSpaces(0),
isScratchedSpaceOverrideModificator(false), isScratchedSpaceOverrideModificator(false),
isTransformChanged(false),
previousActiveState(true), previousActiveState(true),
force_integration_callback(NULL) { force_integration_callback(NULL) {
@ -332,7 +332,7 @@ void RigidBodyBullet::reload_body() {
void RigidBodyBullet::set_space(SpaceBullet *p_space) { void RigidBodyBullet::set_space(SpaceBullet *p_space) {
// Clear the old space if there is one // Clear the old space if there is one
if (space) { if (space) {
isTransformChanged = false; can_integrate_forces = false;
// Remove all eventual constraints // Remove all eventual constraints
assert_no_constraints(); assert_no_constraints();
@ -349,8 +349,8 @@ void RigidBodyBullet::set_space(SpaceBullet *p_space) {
} }
void RigidBodyBullet::dispatch_callbacks() { void RigidBodyBullet::dispatch_callbacks() {
/// The check isTransformChanged is necessary in order to call integrated forces only when the first transform is sent /// The check isFirstTransformChanged is necessary in order to call integrated forces only when the first transform is sent
if ((btBody->isKinematicObject() || btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && isTransformChanged) { if ((btBody->isKinematicObject() || btBody->isActive() || previousActiveState != btBody->isActive()) && force_integration_callback && can_integrate_forces) {
if (omit_forces_integration) if (omit_forces_integration)
btBody->clearForces(); btBody->clearForces();
@ -399,10 +399,6 @@ void RigidBodyBullet::set_force_integration_callback(ObjectID p_id, const String
} }
} }
void RigidBodyBullet::scratch() {
isTransformChanged = true;
}
void RigidBodyBullet::scratch_space_override_modificator() { void RigidBodyBullet::scratch_space_override_modificator() {
isScratchedSpaceOverrideModificator = true; isScratchedSpaceOverrideModificator = true;
} }
@ -417,6 +413,11 @@ void RigidBodyBullet::on_collision_checker_start() {
collisionsCount = 0; collisionsCount = 0;
} }
void RigidBodyBullet::on_collision_checker_end() {
// Always true if active and not a static or kinematic body
isTransformChanged = btBody->isActive() && !btBody->isStaticOrKinematicObject();
}
bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index) { bool RigidBodyBullet::add_collision_object(RigidBodyBullet *p_otherObject, const Vector3 &p_hitWorldLocation, const Vector3 &p_hitLocalLocation, const Vector3 &p_hitNormal, const float &p_appliedImpulse, int p_other_shape_index, int p_local_shape_index) {
if (collisionsCount >= maxCollisionsDetection) { if (collisionsCount >= maxCollisionsDetection) {
@ -519,7 +520,7 @@ real_t RigidBodyBullet::get_param(PhysicsServer::BodyParameter p_param) const {
void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) { void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) {
// This is necessary to block force_integration untile next move // This is necessary to block force_integration untile next move
isTransformChanged = false; can_integrate_forces = false;
destroy_kinematic_utilities(); destroy_kinematic_utilities();
// The mode change is relevant to its mass // The mode change is relevant to its mass
switch (p_mode) { switch (p_mode) {
@ -776,8 +777,7 @@ void RigidBodyBullet::set_transform__bullet(const btTransform &p_global_transfor
// The kinematic use MotionState class // The kinematic use MotionState class
godotMotionState->moveBody(p_global_transform); godotMotionState->moveBody(p_global_transform);
} }
btBody->setWorldTransform(p_global_transform); CollisionObjectBullet::set_transform__bullet(p_global_transform);
scratch();
} }
const btTransform &RigidBodyBullet::get_transform__bullet() const { const btTransform &RigidBodyBullet::get_transform__bullet() const {
@ -986,6 +986,11 @@ void RigidBodyBullet::reload_kinematic_shapes() {
kinematic_utilities->copyAllOwnerShapes(); kinematic_utilities->copyAllOwnerShapes();
} }
void RigidBodyBullet::notify_transform_changed() {
RigidCollisionObjectBullet::notify_transform_changed();
can_integrate_forces = true;
}
void RigidBodyBullet::_internal_set_mass(real_t p_mass) { void RigidBodyBullet::_internal_set_mass(real_t p_mass) {
btVector3 localInertia(0, 0, 0); btVector3 localInertia(0, 0, 0);

View file

@ -202,6 +202,7 @@ private:
real_t angularDamp; real_t angularDamp;
bool can_sleep; bool can_sleep;
bool omit_forces_integration; bool omit_forces_integration;
bool can_integrate_forces;
Vector<CollisionData> collisions; Vector<CollisionData> collisions;
// these parameters are used to avoid vector resize // these parameters are used to avoid vector resize
@ -216,7 +217,6 @@ private:
int countGravityPointSpaces; int countGravityPointSpaces;
bool isScratchedSpaceOverrideModificator; bool isScratchedSpaceOverrideModificator;
bool isTransformChanged;
bool previousActiveState; // Last check state bool previousActiveState; // Last check state
ForceIntegrationCallback *force_integration_callback; ForceIntegrationCallback *force_integration_callback;
@ -237,11 +237,12 @@ public:
virtual void dispatch_callbacks(); virtual void dispatch_callbacks();
void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant()); void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant());
void scratch();
void scratch_space_override_modificator(); void scratch_space_override_modificator();
virtual void on_collision_filters_change(); virtual void on_collision_filters_change();
virtual void on_collision_checker_start(); virtual void on_collision_checker_start();
virtual void on_collision_checker_end();
void set_max_collisions_detection(int p_maxCollisionsDetection) { void set_max_collisions_detection(int p_maxCollisionsDetection) {
maxCollisionsDetection = p_maxCollisionsDetection; maxCollisionsDetection = p_maxCollisionsDetection;
collisions.resize(p_maxCollisionsDetection); collisions.resize(p_maxCollisionsDetection);
@ -311,6 +312,8 @@ public:
/// Kinematic /// Kinematic
void reload_kinematic_shapes(); void reload_kinematic_shapes();
virtual void notify_transform_changed();
private: private:
void _internal_set_mass(real_t p_mass); void _internal_set_mass(real_t p_mass);
}; };

View file

@ -72,12 +72,6 @@ void SoftBodyBullet::set_space(SpaceBullet *p_space) {
} }
} }
void SoftBodyBullet::dispatch_callbacks() {}
void SoftBodyBullet::on_collision_filters_change() {}
void SoftBodyBullet::on_collision_checker_start() {}
void SoftBodyBullet::on_enter_area(AreaBullet *p_area) {} void SoftBodyBullet::on_enter_area(AreaBullet *p_area) {}
void SoftBodyBullet::on_exit_area(AreaBullet *p_area) {} void SoftBodyBullet::on_exit_area(AreaBullet *p_area) {}

View file

@ -91,9 +91,10 @@ public:
virtual void reload_body(); virtual void reload_body();
virtual void set_space(SpaceBullet *p_space); virtual void set_space(SpaceBullet *p_space);
virtual void dispatch_callbacks(); virtual void dispatch_callbacks() {}
virtual void on_collision_filters_change(); virtual void on_collision_filters_change() {}
virtual void on_collision_checker_start(); virtual void on_collision_checker_start() {}
virtual void on_collision_checker_end() {}
virtual void on_enter_area(AreaBullet *p_area); virtual void on_enter_area(AreaBullet *p_area);
virtual void on_exit_area(AreaBullet *p_area); virtual void on_exit_area(AreaBullet *p_area);

View file

@ -540,17 +540,20 @@ void onBulletPreTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep
void onBulletTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep) { void onBulletTickCallback(btDynamicsWorld *p_dynamicsWorld, btScalar timeStep) {
// Notify all Collision objects the collision checker is started
const btCollisionObjectArray &colObjArray = p_dynamicsWorld->getCollisionObjectArray(); const btCollisionObjectArray &colObjArray = p_dynamicsWorld->getCollisionObjectArray();
// Notify all Collision objects the collision checker is started
for (int i = colObjArray.size() - 1; 0 <= i; --i) { for (int i = colObjArray.size() - 1; 0 <= i; --i) {
CollisionObjectBullet *colObj = static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer()); static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer())->on_collision_checker_start();
assert(NULL != colObj);
colObj->on_collision_checker_start();
} }
SpaceBullet *sb = static_cast<SpaceBullet *>(p_dynamicsWorld->getWorldUserInfo()); SpaceBullet *sb = static_cast<SpaceBullet *>(p_dynamicsWorld->getWorldUserInfo());
sb->check_ghost_overlaps(); sb->check_ghost_overlaps();
sb->check_body_collision(); sb->check_body_collision();
for (int i = colObjArray.size() - 1; 0 <= i; --i) {
static_cast<CollisionObjectBullet *>(colObjArray[i]->getUserPointer())->on_collision_checker_end();
}
} }
BulletPhysicsDirectSpaceState *SpaceBullet::get_direct_state() { BulletPhysicsDirectSpaceState *SpaceBullet::get_direct_state() {
@ -649,7 +652,6 @@ void SpaceBullet::check_ghost_overlaps() {
btConvexShape *area_shape; btConvexShape *area_shape;
btGjkPairDetector::ClosestPointInput gjk_input; btGjkPairDetector::ClosestPointInput gjk_input;
AreaBullet *area; AreaBullet *area;
RigidCollisionObjectBullet *otherObject;
int x(-1), i(-1), y(-1), z(-1), indexOverlap(-1); int x(-1), i(-1), y(-1), z(-1), indexOverlap(-1);
/// For each areas /// For each areas
@ -676,13 +678,17 @@ void SpaceBullet::check_ghost_overlaps() {
// For each overlapping // For each overlapping
for (i = ghostOverlaps.size() - 1; 0 <= i; --i) { for (i = ghostOverlaps.size() - 1; 0 <= i; --i) {
if (ghostOverlaps[i]->getUserIndex() == CollisionObjectBullet::TYPE_AREA) { btCollisionObject *overlapped_bt_co = ghostOverlaps[i];
if (!static_cast<AreaBullet *>(ghostOverlaps[i]->getUserPointer())->is_monitorable()) RigidCollisionObjectBullet *otherObject = static_cast<RigidCollisionObjectBullet *>(overlapped_bt_co->getUserPointer());
continue;
} else if (ghostOverlaps[i]->getUserIndex() != CollisionObjectBullet::TYPE_RIGID_BODY) if (!area->is_transform_changed() && !otherObject->is_transform_changed())
continue; continue;
otherObject = static_cast<RigidCollisionObjectBullet *>(ghostOverlaps[i]->getUserPointer()); if (overlapped_bt_co->getUserIndex() == CollisionObjectBullet::TYPE_AREA) {
if (!static_cast<AreaBullet *>(overlapped_bt_co->getUserPointer())->is_monitorable())
continue;
} else if (overlapped_bt_co->getUserIndex() != CollisionObjectBullet::TYPE_RIGID_BODY)
continue;
bool hasOverlap = false; bool hasOverlap = false;