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

Ensure Areas and Bodies only interact with Areas with layers in their mask #42268

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
4 changes: 0 additions & 4 deletions modules/bullet/collision_object_bullet.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,6 @@ class CollisionObjectBullet : public RIDBullet {

virtual void on_collision_filters_change() = 0;

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

virtual void reload_body() = 0;
virtual void set_space(SpaceBullet *p_space) = 0;
_FORCE_INLINE_ SpaceBullet *get_space() const { return space; }
Expand Down
4 changes: 4 additions & 0 deletions modules/bullet/space_bullet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,10 @@ void SpaceBullet::check_ghost_overlaps() {
goto collision_found;
}

if (!(area->get_collision_layer() & otherObject->get_collision_mask())) {
continue;
}

if (overlapped_bt_co->getUserIndex() == CollisionObjectBullet::TYPE_AREA) {
if (!static_cast<AreaBullet *>(overlapped_bt_co->getUserPointer())->is_monitorable()) {
continue;
Expand Down
78 changes: 39 additions & 39 deletions servers/physics_2d/area_pair_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,23 @@
/*************************************************************************/

#include "area_pair_2d_sw.h"

#include "collision_solver_2d_sw.h"

bool AreaPair2DSW::setup(real_t p_step) {
bool result = false;
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;
bool overlap = false;
if (body->mask_has_layer(area) && 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)) {
overlap = true;
}

process_collision = false;
if (result != colliding) {
if (overlap != colliding) {
colliding = overlap;
if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) {
process_collision = true;
} else if (area->has_monitor_callback()) {
process_collision = true;
}

colliding = result;
}

return process_collision;
Expand Down Expand Up @@ -109,46 +109,48 @@ AreaPair2DSW::~AreaPair2DSW() {
//////////////////////////////////

bool Area2Pair2DSW::setup(real_t p_step) {
bool result = false;
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;
bool overlap = false;
if (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)) {
overlap = true;
}

process_collision = false;
if (result != colliding) {
if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
process_collision = true;
} else if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
process_collision = true;
bool b_collides_with_a = overlap && area_b->mask_has_layer(area_a);
bool a_collides_with_b = overlap && area_a->mask_has_layer(area_b);
process_collision_with_a = false;
process_collision_with_b = false;

if (b_collides_with_a != b_colliding_with_a) {
b_colliding_with_a = b_collides_with_a;
if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
process_collision_with_a = true;
}
}

colliding = result;
if (a_collides_with_b != a_colliding_with_b) {
a_colliding_with_b = a_collides_with_b;
if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
process_collision_with_b = true;
}
}

return process_collision;
return process_collision_with_a || process_collision_with_b;
}

bool Area2Pair2DSW::pre_solve(real_t p_step) {
if (!process_collision) {
return false;
if (process_collision_with_a) {
if (b_colliding_with_a) {
area_a->add_area_to_query(area_b, shape_b, shape_a);
} else { // b no longer colliding with a
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
}

if (colliding) {
if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
if (process_collision_with_b) {
if (a_colliding_with_b) {
area_b->add_area_to_query(area_a, shape_a, shape_b);
}

if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
area_a->add_area_to_query(area_b, shape_b, shape_a);
}
} else {
if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
} else { // a no longer colliding with b
area_b->remove_area_from_query(area_a, shape_a, shape_b);
}

if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
}

return false; // Never do any post solving.
Expand All @@ -168,14 +170,12 @@ Area2Pair2DSW::Area2Pair2DSW(Area2DSW *p_area_a, int p_shape_a, Area2DSW *p_area
}

Area2Pair2DSW::~Area2Pair2DSW() {
if (colliding) {
if (area_b->has_area_monitor_callback()) {
area_b->remove_area_from_query(area_a, shape_a, shape_b);
}
if (a_colliding_with_b && area_b->has_area_monitor_callback()) {
area_b->remove_area_from_query(area_a, shape_a, shape_b);
}

if (area_a->has_area_monitor_callback()) {
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
if (b_colliding_with_a && area_a->has_area_monitor_callback()) {
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}

area_a->remove_constraint(this);
Expand Down
6 changes: 4 additions & 2 deletions servers/physics_2d/area_pair_2d_sw.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,10 @@ class Area2Pair2DSW : public Constraint2DSW {
Area2DSW *area_b = nullptr;
int shape_a = 0;
int shape_b = 0;
bool colliding = false;
bool process_collision = false;
bool b_colliding_with_a = false;
bool a_colliding_with_b = false;
bool process_collision_with_a = false;
bool process_collision_with_b = false;

public:
virtual bool setup(real_t p_step) override;
Expand Down
4 changes: 2 additions & 2 deletions servers/physics_2d/collision_object_2d_sw.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,8 @@ class CollisionObject2DSW : public ShapeOwner2DSW {
void set_pickable(bool p_pickable) { pickable = p_pickable; }
_FORCE_INLINE_ bool is_pickable() const { return pickable; }

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

_FORCE_INLINE_ bool interacts_with(CollisionObject2DSW *p_other) const {
Expand Down
2 changes: 1 addition & 1 deletion servers/physics_2d/space_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,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 (!p_body->layer_in_mask(static_cast<Body2DSW *>(intersection_query_results[i]))) {
} 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
78 changes: 39 additions & 39 deletions servers/physics_3d/area_pair_3d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,23 @@
/*************************************************************************/

#include "area_pair_3d_sw.h"

#include "collision_solver_3d_sw.h"

bool AreaPair3DSW::setup(real_t p_step) {
bool result = false;
if (area->interacts_with(body) && CollisionSolver3DSW::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;
bool overlap = false;
if (body->mask_has_layer(area) && CollisionSolver3DSW::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)) {
overlap = true;
}

process_collision = false;
if (result != colliding) {
if (overlap != colliding) {
colliding = overlap;
if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) {
process_collision = true;
} else if (area->has_monitor_callback()) {
process_collision = true;
}

colliding = result;
}

return process_collision;
Expand Down Expand Up @@ -109,46 +109,48 @@ AreaPair3DSW::~AreaPair3DSW() {
////////////////////////////////////////////////////

bool Area2Pair3DSW::setup(real_t p_step) {
bool result = false;
if (area_a->interacts_with(area_b) && CollisionSolver3DSW::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;
bool overlap = false;
if (CollisionSolver3DSW::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)) {
overlap = true;
}

process_collision = false;
if (result != colliding) {
if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
process_collision = true;
} else if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
process_collision = true;
bool b_collides_with_a = overlap && area_b->mask_has_layer(area_a);
bool a_collides_with_b = overlap && area_a->mask_has_layer(area_b);
process_collision_with_a = false;
process_collision_with_b = false;

if (b_collides_with_a != b_colliding_with_a) {
b_colliding_with_a = b_collides_with_a;
if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
process_collision_with_a = true;
}
}

colliding = result;
if (a_collides_with_b != a_colliding_with_b) {
a_colliding_with_b = a_collides_with_b;
if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
process_collision_with_b = true;
}
}

return process_collision;
return process_collision_with_a || process_collision_with_b;
}

bool Area2Pair3DSW::pre_solve(real_t p_step) {
if (!process_collision) {
return false;
if (process_collision_with_a) {
if (b_colliding_with_a) {
area_a->add_area_to_query(area_b, shape_b, shape_a);
} else { // b no longer colliding with a
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
}

if (colliding) {
if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
if (process_collision_with_b) {
if (a_colliding_with_b) {
area_b->add_area_to_query(area_a, shape_a, shape_b);
}

if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
area_a->add_area_to_query(area_b, shape_b, shape_a);
}
} else {
if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) {
} else { // a no longer colliding with b
area_b->remove_area_from_query(area_a, shape_a, shape_b);
}

if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) {
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
}

return false; // Never do any post solving.
Expand All @@ -168,14 +170,12 @@ Area2Pair3DSW::Area2Pair3DSW(Area3DSW *p_area_a, int p_shape_a, Area3DSW *p_area
}

Area2Pair3DSW::~Area2Pair3DSW() {
if (colliding) {
if (area_b->has_area_monitor_callback()) {
area_b->remove_area_from_query(area_a, shape_a, shape_b);
}
if (a_colliding_with_b && area_b->has_area_monitor_callback()) {
area_b->remove_area_from_query(area_a, shape_a, shape_b);
}

if (area_a->has_area_monitor_callback()) {
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}
if (b_colliding_with_a && area_a->has_area_monitor_callback()) {
area_a->remove_area_from_query(area_b, shape_b, shape_a);
}

area_a->remove_constraint(this);
Expand Down
6 changes: 4 additions & 2 deletions servers/physics_3d/area_pair_3d_sw.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,10 @@ class Area2Pair3DSW : public Constraint3DSW {
Area3DSW *area_b;
int shape_a;
int shape_b;
bool colliding = false;
bool process_collision = false;
bool b_colliding_with_a = false;
bool a_colliding_with_b = false;
bool process_collision_with_a = false;
bool process_collision_with_b = false;

public:
virtual bool setup(real_t p_step) override;
Expand Down
4 changes: 2 additions & 2 deletions servers/physics_3d/collision_object_3d_sw.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ class CollisionObject3DSW : public ShapeOwner3DSW {
}
_FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; }

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

_FORCE_INLINE_ bool interacts_with(CollisionObject3DSW *p_other) const {
Expand Down
2 changes: 1 addition & 1 deletion servers/physics_3d/space_3d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) {
keep = false;
} else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_SOFT_BODY) {
keep = false;
} else if (!p_body->layer_in_mask(static_cast<Body3DSW *>(intersection_query_results[i]))) {
} else if (!p_body->mask_has_layer(static_cast<Body3DSW *>(intersection_query_results[i]))) {
keep = false;
} else if (static_cast<Body3DSW *>(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) {
keep = false;
Expand Down