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.2] Fix multiple issues with one-way collisions #42575

Merged
merged 1 commit into from
Jan 7, 2021
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
4 changes: 2 additions & 2 deletions servers/physics/space_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transfo
Vector3 a = sr[k * 2 + 0];
Vector3 b = sr[k * 2 + 1];

recover_motion += (b - a) * 0.4;
recover_motion += (b - a) / cbk.amount;

float depth = a.distance_to(b);
if (depth > result.collision_depth) {
Expand Down Expand Up @@ -791,7 +791,7 @@ bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Ve

Vector3 a = sr[i * 2 + 0];
Vector3 b = sr[i * 2 + 1];
recover_motion += (b - a) * 0.4;
recover_motion += (b - a) / cbk.amount;
}

if (recover_motion == Vector3()) {
Expand Down
39 changes: 16 additions & 23 deletions servers/physics_2d/body_pair_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -295,19 +295,15 @@ bool BodyPair2DSW::setup(real_t p_step) {
if (A->is_shape_set_as_one_way_collision(shape_A)) {
Vector2 direction = xform_A.get_axis(1).normalized();
bool valid = false;
if (B->get_linear_velocity().dot(direction) >= 0) {
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
if (!c.reused)
continue;
if (c.normal.dot(direction) > 0) //greater (normal inverted)
continue;

valid = true;
break;
}
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
if (!c.reused)
continue;
if (c.normal.dot(direction) > -CMP_EPSILON) //greater (normal inverted)
continue;
valid = true;
break;
}

if (!valid) {
collided = false;
oneway_disabled = true;
Expand All @@ -318,17 +314,14 @@ bool BodyPair2DSW::setup(real_t p_step) {
if (B->is_shape_set_as_one_way_collision(shape_B)) {
Vector2 direction = xform_B.get_axis(1).normalized();
bool valid = false;
if (A->get_linear_velocity().dot(direction) >= 0) {
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
if (!c.reused)
continue;
if (c.normal.dot(direction) < 0) //less (normal ok)
continue;

valid = true;
break;
}
for (int i = 0; i < contact_count; i++) {
Contact &c = contacts[i];
if (!c.reused)
continue;
if (c.normal.dot(direction) < CMP_EPSILON) //less (normal ok)
continue;
valid = true;
break;
}
if (!valid) {
collided = false;
Expand Down
32 changes: 13 additions & 19 deletions servers/physics_2d/physics_2d_server_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,24 +167,19 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &
if (cbk->max == 0)
return;

Vector2 rel_dir = (p_point_A - p_point_B);
real_t rel_length2 = rel_dir.length_squared();
if (cbk->valid_dir != Vector2()) {
if (p_point_A.distance_squared_to(p_point_B) > cbk->valid_depth * cbk->valid_depth) {
cbk->invalid_by_dir++;
return;
}
Vector2 rel_dir = (p_point_A - p_point_B).normalized();

if (cbk->valid_dir.dot(rel_dir) < Math_SQRT12) { //sqrt(2)/2.0 - 45 degrees
cbk->invalid_by_dir++;

/*
print_line("A: "+p_point_A);
print_line("B: "+p_point_B);
print_line("discard too angled "+rtos(cbk->valid_dir.dot((p_point_A-p_point_B))));
print_line("resnorm: "+(p_point_A-p_point_B).normalized());
print_line("distance: "+rtos(p_point_A.distance_to(p_point_B)));
*/
return;
if (cbk->valid_depth < 10e20) {
if (rel_length2 > cbk->valid_depth * cbk->valid_depth ||
(rel_length2 > CMP_EPSILON && cbk->valid_dir.dot(rel_dir.normalized()) < CMP_EPSILON)) {
cbk->invalid_by_dir++;
return;
}
} else {
if (rel_length2 > 0 && cbk->valid_dir.dot(rel_dir.normalized()) < CMP_EPSILON) {
return;
}
}
}

Expand All @@ -201,8 +196,7 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &
}
}

real_t d = p_point_A.distance_squared_to(p_point_B);
if (d < min_depth)
if (rel_length2 < min_depth)
return;
cbk->ptr[min_depth_idx * 2 + 0] = p_point_A;
cbk->ptr[min_depth_idx * 2 + 1] = p_point_B;
Expand Down
28 changes: 12 additions & 16 deletions servers/physics_2d/space_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,24 +370,24 @@ struct _RestCallbackData2D {
Vector2 best_normal;
real_t best_len;
Vector2 valid_dir;
real_t valid_depth;
real_t min_allowed_depth;
};

static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) {

_RestCallbackData2D *rd = (_RestCallbackData2D *)p_userdata;

if (rd->valid_dir != Vector2()) {
if (p_point_A.distance_squared_to(p_point_B) > rd->valid_depth * rd->valid_depth)
return;
if (rd->valid_dir.dot((p_point_A - p_point_B).normalized()) < Math_PI * 0.25)
return;
}

Vector2 contact_rel = p_point_B - p_point_A;
real_t len = contact_rel.length();

if (len == 0)
return;

Vector2 normal = contact_rel / len;

if (rd->valid_dir != Vector2() && rd->valid_dir.dot(normal) > -CMP_EPSILON)
return;

if (len < rd->min_allowed_depth)
return;

Expand All @@ -396,7 +396,7 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B,

rd->best_len = len;
rd->best_contact = p_point_B;
rd->best_normal = contact_rel / len;
rd->best_normal = normal;
rd->best_object = rd->object;
rd->best_shape = rd->shape;
rd->best_local_shape = rd->local_shape;
Expand Down Expand Up @@ -431,7 +431,6 @@ bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_sh
continue;

rcd.valid_dir = Vector2();
rcd.valid_depth = 0;
rcd.object = col_obj;
rcd.shape = shape_idx;
rcd.local_shape = 0;
Expand Down Expand Up @@ -638,7 +637,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
Vector2 a = sr[k * 2 + 0];
Vector2 b = sr[k * 2 + 1];

recover_motion += (b - a) * 0.4;
recover_motion += (b - a) / cbk.amount;

float depth = a.distance_to(b);
if (depth > result.collision_depth) {
Expand Down Expand Up @@ -849,7 +848,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co

Vector2 a = sr[i * 2 + 0];
Vector2 b = sr[i * 2 + 1];
recover_motion += (b - a) * 0.4;
recover_motion += (b - a) / cbk.amount;
}

if (recover_motion == Vector2()) {
Expand Down Expand Up @@ -1010,7 +1009,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
best_shape = -1; //no best shape with cast, reset to -1
}

{
if (safe < 1) {

//it collided, let's get the rest info in unsafe advance
Transform2D ugt = body_transform;
Expand Down Expand Up @@ -1070,12 +1069,9 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);

if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {

rcd.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
rcd.valid_depth = 10e20;
} else {
rcd.valid_dir = Vector2();
rcd.valid_depth = 0;
}

rcd.object = col_obj;
Expand Down