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

Fix one-way collision for moving objects #36280

Closed
wants to merge 3 commits 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
44 changes: 20 additions & 24 deletions servers/physics_2d/body_pair_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,19 +288,17 @@ 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) {
Expand All @@ -313,19 +311,17 @@ 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;
Expand Down
14 changes: 3 additions & 11 deletions servers/physics_2d/physics_server_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,23 +149,15 @@ void PhysicsServer2DSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &
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 (cbk->valid_dir.dot(rel_dir) < Math_SQRT12) { //sqrt(2)/2.0 - 45 degrees
if (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;
}
}
Expand Down
16 changes: 9 additions & 7 deletions servers/physics_2d/space_2d_sw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -798,24 +798,26 @@ 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;

//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<const Body2DSW *>(col_obj);
if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) {
//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 * PhysicsDirectBodyState2DSW::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 * PhysicsDirectBodyState2DSW::singleton->step;
float b_depth = b_motion.dot(-cbk.valid_dir);
cbk.valid_depth += b_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
Expand Down Expand Up @@ -852,7 +854,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
for (int i = 0; i < cbk.amount; i++) {
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