Skip to content

Commit

Permalink
Ensure Areas and Bodies only interact with Areas with layers in their…
Browse files Browse the repository at this point in the history
… mask.
  • Loading branch information
madmiraal committed Jul 21, 2021
1 parent 8cc599d commit dae6a57
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 92 deletions.
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

0 comments on commit dae6a57

Please sign in to comment.