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

[3.x] Ensure KinematicBodies only interact with other Bodies with layers in their mask #42642

Closed
wants to merge 1 commit into from
Closed
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
27 changes: 8 additions & 19 deletions modules/bullet/godot_result_callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,12 @@ bool godotContactAddedCallback(btManifoldPoint &cp, const btCollisionObjectWrapp
return true;
}

bool GodotFilterCallback::test_collision_filters(uint32_t body0_collision_layer, uint32_t body0_collision_mask, uint32_t body1_collision_layer, uint32_t body1_collision_mask) {
return body0_collision_layer & body1_collision_mask || body1_collision_layer & body0_collision_mask;
}

bool GodotFilterCallback::needBroadphaseCollision(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1) const {
return GodotFilterCallback::test_collision_filters(proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask, proxy1->m_collisionFilterGroup, proxy1->m_collisionFilterMask);
return (proxy0->m_collisionFilterGroup & proxy1->m_collisionFilterMask) || (proxy1->m_collisionFilterGroup & proxy0->m_collisionFilterMask);
}

bool GodotClosestRayResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
if (needs) {
if (m_collisionFilterMask & proxy0->m_collisionFilterGroup) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());

Expand Down Expand Up @@ -90,8 +85,7 @@ bool GodotAllConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) con
return false;
}

const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
if (needs) {
if (m_collisionFilterMask & proxy0->m_collisionFilterGroup) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
if (m_exclude->has(gObj->get_self())) {
Expand Down Expand Up @@ -123,8 +117,7 @@ btScalar GodotAllConvexResultCallback::addSingleResult(btCollisionWorld::LocalCo
}

bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
if (needs) {
if (m_collisionFilterMask & proxy0->m_collisionFilterGroup) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());
if (gObj == m_self_object) {
Expand All @@ -150,8 +143,7 @@ bool GodotKinClosestConvexResultCallback::needsCollision(btBroadphaseProxy *prox
}

bool GodotClosestConvexResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
if (needs) {
if (m_collisionFilterMask & proxy0->m_collisionFilterGroup) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());

Expand Down Expand Up @@ -188,8 +180,7 @@ bool GodotAllContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) co
return false;
}

const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
if (needs) {
if (m_collisionFilterMask & proxy0->m_collisionFilterGroup) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());

Expand Down Expand Up @@ -244,8 +235,7 @@ bool GodotContactPairContactResultCallback::needsCollision(btBroadphaseProxy *pr
return false;
}

const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
if (needs) {
if (m_collisionFilterMask & proxy0->m_collisionFilterGroup) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());

Expand Down Expand Up @@ -287,8 +277,7 @@ btScalar GodotContactPairContactResultCallback::addSingleResult(btManifoldPoint
}

bool GodotRestInfoContactResultCallback::needsCollision(btBroadphaseProxy *proxy0) const {
const bool needs = GodotFilterCallback::test_collision_filters(m_collisionFilterGroup, m_collisionFilterMask, proxy0->m_collisionFilterGroup, proxy0->m_collisionFilterMask);
if (needs) {
if (m_collisionFilterMask & proxy0->m_collisionFilterGroup) {
btCollisionObject *btObj = static_cast<btCollisionObject *>(proxy0->m_clientObject);
CollisionObjectBullet *gObj = static_cast<CollisionObjectBullet *>(btObj->getUserPointer());

Expand Down
2 changes: 0 additions & 2 deletions modules/bullet/godot_result_callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ bool godotContactAddedCallback(btManifoldPoint &cp, const btCollisionObjectWrapp

/// This class is required to implement custom collision behaviour in the broadphase
struct GodotFilterCallback : public btOverlapFilterCallback {
static bool test_collision_filters(uint32_t body0_collision_layer, uint32_t body0_collision_mask, uint32_t body1_collision_layer, uint32_t body1_collision_mask);

// return true when pairs need collision
virtual bool needBroadphaseCollision(btBroadphaseProxy *proxy0, btBroadphaseProxy *proxy1) const;
};
Expand Down
10 changes: 4 additions & 6 deletions modules/bullet/space_bullet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,6 @@ struct RecoverPenetrationBroadPhaseCallback : public btBroadphaseAabbCallback {
btDbvtVolume bounds;

const btCollisionObject *self_collision_object;
uint32_t collision_layer;
uint32_t collision_mask;

struct CompoundLeafCallback : btDbvt::ICollide {
Expand Down Expand Up @@ -1143,9 +1142,8 @@ struct RecoverPenetrationBroadPhaseCallback : public btBroadphaseAabbCallback {
Vector<BroadphaseResult> results;

public:
RecoverPenetrationBroadPhaseCallback(const btCollisionObject *p_self_collision_object, uint32_t p_collision_layer, uint32_t p_collision_mask, btVector3 p_aabb_min, btVector3 p_aabb_max) :
RecoverPenetrationBroadPhaseCallback(const btCollisionObject *p_self_collision_object, uint32_t p_collision_mask, btVector3 p_aabb_min, btVector3 p_aabb_max) :
self_collision_object(p_self_collision_object),
collision_layer(p_collision_layer),
collision_mask(p_collision_mask) {
bounds = btDbvtVolume::FromMM(p_aabb_min, p_aabb_max);
}
Expand All @@ -1155,7 +1153,7 @@ struct RecoverPenetrationBroadPhaseCallback : public btBroadphaseAabbCallback {
virtual bool process(const btBroadphaseProxy *proxy) {
btCollisionObject *co = static_cast<btCollisionObject *>(proxy->m_clientObject);
if (co->getInternalType() <= btCollisionObject::CO_RIGID_BODY) {
if (self_collision_object != proxy->m_clientObject && GodotFilterCallback::test_collision_filters(collision_layer, collision_mask, proxy->m_collisionFilterGroup, proxy->m_collisionFilterMask)) {
if (self_collision_object != proxy->m_clientObject && (collision_mask & proxy->m_collisionFilterGroup)) {
if (co->getCollisionShape()->isCompound()) {
const btCompoundShape *cs = static_cast<btCompoundShape *>(co->getCollisionShape());

Expand Down Expand Up @@ -1238,7 +1236,7 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran
}

// Perform broadphase test
RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask(), aabb_min, aabb_max);
RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_mask(), aabb_min, aabb_max);
dynamicsWorld->getBroadphase()->aabbTest(aabb_min, aabb_max, recover_broad_result);

bool penetration = false;
Expand Down Expand Up @@ -1429,7 +1427,7 @@ int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btT
}

// Perform broadphase test
RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask(), aabb_min, aabb_max);
RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_mask(), aabb_min, aabb_max);
dynamicsWorld->getBroadphase()->aabbTest(aabb_min, aabb_max, recover_broad_result);

int ray_count = 0;
Expand Down
4 changes: 2 additions & 2 deletions servers/physics/area_pair_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

bool AreaPairSW::setup(real_t p_step) {
bool result = false;
if (area->test_collision_mask(body) && CollisionSolverSW::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) {
if (area->interacts_with(body) && CollisionSolverSW::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), nullptr, this)) {
result = true;
}

Expand Down Expand Up @@ -94,7 +94,7 @@ AreaPairSW::~AreaPairSW() {

bool Area2PairSW::setup(real_t p_step) {
bool result = false;
if (area_a->test_collision_mask(area_b) && CollisionSolverSW::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) {
if (area_a->interacts_with(area_b) && CollisionSolverSW::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), nullptr, this)) {
result = true;
}

Expand Down
2 changes: 1 addition & 1 deletion servers/physics/body_pair_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ real_t combine_friction(BodySW *A, BodySW *B) {

bool BodyPairSW::setup(real_t p_step) {
//cannot collide
if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) {
if (!A->interacts_with(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) {
collided = false;
return false;
}
Expand Down
6 changes: 5 additions & 1 deletion servers/physics/collision_object_sw.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,11 @@ class CollisionObjectSW : public ShapeOwnerSW {
}
_FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; }

_FORCE_INLINE_ bool test_collision_mask(CollisionObjectSW *p_other) const {
_FORCE_INLINE_ bool mask_has_layer(CollisionObjectSW *p_other) const {
return collision_layer & p_other->collision_mask;
}

_FORCE_INLINE_ bool interacts_with(CollisionObjectSW *p_other) const {
return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask;
}

Expand Down
4 changes: 2 additions & 2 deletions servers/physics/space_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ int SpaceSW::_cull_aabb_for_body(BodySW *p_body, const AABB &p_aabb) {
keep = false;
} else if (intersection_query_results[i]->get_type() == CollisionObjectSW::TYPE_AREA) {
keep = false;
} else if ((static_cast<BodySW *>(intersection_query_results[i])->test_collision_mask(p_body)) == 0) {
} else if (!p_body->mask_has_layer(static_cast<BodySW *>(intersection_query_results[i]))) {
keep = false;
} else if (static_cast<BodySW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) {
keep = false;
Expand Down Expand Up @@ -1064,7 +1064,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve
}

void *SpaceSW::_broadphase_pair(CollisionObjectSW *A, int p_subindex_A, CollisionObjectSW *B, int p_subindex_B, void *p_self) {
if (!A->test_collision_mask(B)) {
if (!A->interacts_with(B)) {
return nullptr;
}

Expand Down
4 changes: 2 additions & 2 deletions servers/physics_2d/area_pair_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

bool AreaPair2DSW::setup(real_t p_step) {
bool result = false;
if (area->test_collision_mask(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), nullptr, this)) {
if (area->interacts_with(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), Vector2(), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), Vector2(), nullptr, this)) {
result = true;
}

Expand Down Expand Up @@ -94,7 +94,7 @@ AreaPair2DSW::~AreaPair2DSW() {

bool Area2Pair2DSW::setup(real_t p_step) {
bool result = false;
if (area_a->test_collision_mask(area_b) && CollisionSolver2DSW::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), nullptr, this)) {
if (area_a->interacts_with(area_b) && CollisionSolver2DSW::solve(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), Vector2(), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), Vector2(), nullptr, this)) {
result = true;
}

Expand Down
2 changes: 1 addition & 1 deletion servers/physics_2d/body_pair_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ real_t combine_friction(Body2DSW *A, Body2DSW *B) {

bool BodyPair2DSW::setup(real_t p_step) {
//cannot collide
if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) {
if (!A->interacts_with(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) {
collided = false;
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion servers/physics_2d/broad_phase_2d_hash_grid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ void BroadPhase2DHashGrid::_unpair_attempt(Element *p_elem, Element *p_with) {
void BroadPhase2DHashGrid::_check_motion(Element *p_elem) {
for (Map<Element *, PairData *>::Element *E = p_elem->paired.front(); E; E = E->next()) {
bool physical_collision = p_elem->aabb.intersects(E->key()->aabb);
bool logical_collision = p_elem->owner->test_collision_mask(E->key()->owner);
bool logical_collision = p_elem->owner->interacts_with(E->key()->owner);

if (physical_collision && logical_collision) {
if (!E->get()->colliding && pair_callback) {
Expand Down
6 changes: 5 additions & 1 deletion servers/physics_2d/collision_object_2d_sw.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,11 @@ class CollisionObject2DSW : public ShapeOwner2DSW {
void set_pickable(bool p_pickable) { pickable = p_pickable; }
_FORCE_INLINE_ bool is_pickable() const { return pickable; }

_FORCE_INLINE_ bool test_collision_mask(CollisionObject2DSW *p_other) const {
_FORCE_INLINE_ bool mask_has_layer(CollisionObject2DSW *p_other) const {
return collision_layer & p_other->collision_mask;
}

_FORCE_INLINE_ bool interacts_with(CollisionObject2DSW *p_other) const {
return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask;
}

Expand Down
4 changes: 2 additions & 2 deletions servers/physics_2d/space_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) {
keep = false;
} else if (intersection_query_results[i]->get_type() == CollisionObject2DSW::TYPE_AREA) {
keep = false;
} else if ((static_cast<Body2DSW *>(intersection_query_results[i])->test_collision_mask(p_body)) == 0) {
} else if (!p_body->mask_has_layer(static_cast<Body2DSW *>(intersection_query_results[i]))) {
keep = false;
} else if (static_cast<Body2DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) {
keep = false;
Expand Down Expand Up @@ -1187,7 +1187,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
}

void *Space2DSW::_broadphase_pair(CollisionObject2DSW *A, int p_subindex_A, CollisionObject2DSW *B, int p_subindex_B, void *p_self) {
if (!A->test_collision_mask(B)) {
if (!A->interacts_with(B)) {
return nullptr;
}

Expand Down