From de462de5a01ff4857a78366ee8faf9dc69b6494c Mon Sep 17 00:00:00 2001 From: Sergej Gureev Date: Sat, 22 Feb 2020 16:50:35 +0200 Subject: [PATCH 1/3] Fix one-way collision for moving objects --- servers/physics_2d/body_pair_2d_sw.cpp | 40 ++++++++++++-------------- servers/physics_2d/space_2d_sw.cpp | 16 ++++++----- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index 1523d40d1eac..dacbc773e787 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -295,17 +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) > 0) //greater (normal inverted) + continue; + + valid = true; + break; } if (!valid) { @@ -318,17 +316,15 @@ 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) < 0) //less (normal ok) + continue; + + valid = true; + break; } if (!valid) { collided = false; diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 9cd67256fb27..9407603e6afc 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -793,7 +793,6 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co float owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx); cbk.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work - cbk.invalid_by_dir = 0; if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) { const Body2DSW *b = static_cast(col_obj); @@ -801,16 +800,19 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co //fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction Vector2 lv = b->get_linear_velocity(); //compute displacement from linear velocity - Vector2 motion = lv * Physics2DDirectBodyStateSW::singleton->step; - float motion_len = motion.length(); - motion.normalize(); - cbk.valid_depth += motion_len * MAX(motion.dot(-cbk.valid_dir), 0.0); + Vector2 b_motion = lv * Physics2DDirectBodyStateSW::singleton->step; + float b_depth = b_motion.dot(-cbk.valid_dir); + cbk.valid_depth += MAX(b_depth, 0.0); + + //we need take out own movement into account + Vector2 a_motion = p_motion; + float a_depth = MAX(a_motion.dot(-cbk.valid_dir), 0.0); + cbk.valid_depth += a_depth; } } } else { cbk.valid_dir = Vector2(); cbk.valid_depth = 0; - cbk.invalid_by_dir = 0; } int current_passed = cbk.passed; //save how many points passed collision @@ -848,7 +850,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()) { From c965419d64358125eb358ca000aff3072d0bcea7 Mon Sep 17 00:00:00 2001 From: Sergej Gureev Date: Sat, 22 Feb 2020 18:37:19 +0200 Subject: [PATCH 2/3] Fix fall through one-way TileMap --- servers/physics_2d/physics_2d_server_sw.cpp | 10 +--------- servers/physics_2d/space_2d_sw.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 809c5c40e06d..083d17d6d6ac 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -174,16 +174,8 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 & } 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 + if (rel_dir != Vector2() && cbk->valid_dir.dot(rel_dir) <= 0) { 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; } } diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 9407603e6afc..a42bfe4665a7 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -794,6 +794,11 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co float owc_margin = col_obj->get_shape_one_way_collision_margin(shape_idx); cbk.valid_depth = MAX(owc_margin, p_margin); //user specified, but never less than actual margin or it won't work + //we need take out own movement into account + Vector2 a_motion = p_motion; + float a_depth = a_motion.dot(cbk.valid_dir); + cbk.valid_depth += a_depth; + if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) { const Body2DSW *b = static_cast(col_obj); if (b->get_mode() == Physics2DServer::BODY_MODE_KINEMATIC || b->get_mode() == Physics2DServer::BODY_MODE_RIGID) { @@ -802,12 +807,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co //compute displacement from linear velocity Vector2 b_motion = lv * Physics2DDirectBodyStateSW::singleton->step; float b_depth = b_motion.dot(-cbk.valid_dir); - cbk.valid_depth += MAX(b_depth, 0.0); - - //we need take out own movement into account - Vector2 a_motion = p_motion; - float a_depth = MAX(a_motion.dot(-cbk.valid_dir), 0.0); - cbk.valid_depth += a_depth; + cbk.valid_depth += b_depth; } } } else { From 08824c9b1bd2096782413e1b117f9d2b58d950fe Mon Sep 17 00:00:00 2001 From: Sergej Gureev Date: Mon, 2 Mar 2020 21:31:21 +0200 Subject: [PATCH 3/3] Fix OWC detection at Attempt Motion step --- servers/physics_2d/physics_2d_server_sw.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 083d17d6d6ac..dab51d970aa2 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -167,14 +167,14 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 & if (cbk->max == 0) return; - if (cbk->valid_dir != Vector2()) { + Vector2 rel_dir = (p_point_A - p_point_B).normalized(); + if (cbk->valid_dir != Vector2() && rel_dir != Vector2() && cbk->valid_depth < 10e20) { 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 (rel_dir != Vector2() && cbk->valid_dir.dot(rel_dir) <= 0) { + if (cbk->valid_dir.dot(rel_dir) <= 0) { cbk->invalid_by_dir++; return; }