Browse Source

Make sure rotated shapes with one way direction collisions work, fixes #12791

Juan Linietsky 6 years ago
parent
commit
3226b44f79
2 changed files with 22 additions and 13 deletions
  1. 3 1
      servers/physics_2d/physics_2d_server_sw.cpp
  2. 19 12
      servers/physics_2d/space_2d_sw.cpp

+ 3 - 1
servers/physics_2d/physics_2d_server_sw.cpp

@@ -169,7 +169,9 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &
 			cbk->invalid_by_dir++;
 			cbk->invalid_by_dir++;
 			return;
 			return;
 		}
 		}
-		if (cbk->valid_dir.dot((p_point_A - p_point_B).normalized()) < 0.7071) { //sqrt(2)/2.0
+		Vector2 rel_dir = (p_point_A - p_point_B).normalized();
+
+		if (cbk->valid_dir.dot(rel_dir) < 0.7071) { //sqrt(2)/2.0 - 45 degrees
 			cbk->invalid_by_dir++;
 			cbk->invalid_by_dir++;
 
 
 			/*
 			/*

+ 19 - 12
servers/physics_2d/space_2d_sw.cpp

@@ -579,9 +579,11 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
 						}
 						}
 					}
 					}
 
 
+					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)) {
 					if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
 
 
-						cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
+						cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
 						cbk.valid_depth = p_margin; //only valid depth is the collision margin
 						cbk.valid_depth = p_margin; //only valid depth is the collision margin
 						cbk.invalid_by_dir = 0;
 						cbk.invalid_by_dir = 0;
 
 
@@ -592,7 +594,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t
 					}
 					}
 
 
 					Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
 					Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
-					if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) {
+					if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, NULL, p_margin)) {
 						if (cbk.amount > 0) {
 						if (cbk.amount > 0) {
 							collided = true;
 							collided = true;
 						}
 						}
@@ -745,9 +747,12 @@ 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)) {
 					if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
 
 
-						cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
+						cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
+
 						cbk.valid_depth = p_margin; //only valid depth is the collision margin
 						cbk.valid_depth = p_margin; //only valid depth is the collision margin
 						cbk.invalid_by_dir = 0;
 						cbk.invalid_by_dir = 0;
 
 
@@ -773,7 +778,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
 					bool did_collide = false;
 					bool did_collide = false;
 
 
 					Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
 					Shape2DSW *against_shape = col_obj->get_shape(shape_idx);
-					if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), cbkres, cbkptr, NULL, p_margin)) {
+					if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), cbkres, cbkptr, NULL, p_margin)) {
 						did_collide = cbk.amount > current_collisions;
 						did_collide = cbk.amount > current_collisions;
 					}
 					}
 
 
@@ -878,14 +883,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
 					continue;
 					continue;
 				}
 				}
 
 
-				Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx);
+				Transform2D col_obj_shape_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx);
 				//test initial overlap, does it collide if going all the way?
 				//test initial overlap, does it collide if going all the way?
-				if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, against_shape, col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) {
+				if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, against_shape, col_obj_shape_xform, Vector2(), NULL, NULL, NULL, 0)) {
 					continue;
 					continue;
 				}
 				}
 
 
 				//test initial overlap
 				//test initial overlap
-				if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) {
+				if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), NULL, NULL, NULL, 0)) {
 
 
 					if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
 					if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) {
 						continue;
 						continue;
@@ -905,7 +910,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
 					real_t ofs = (low + hi) * 0.5;
 					real_t ofs = (low + hi) * 0.5;
 
 
 					Vector2 sep = mnormal; //important optimization for this to work fast enough
 					Vector2 sep = mnormal; //important optimization for this to work fast enough
-					bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * ofs, against_shape, col_obj_xform, Vector2(), NULL, NULL, &sep, 0);
+					bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * ofs, against_shape, col_obj_shape_xform, Vector2(), NULL, NULL, &sep, 0);
 
 
 					if (collided) {
 					if (collided) {
 
 
@@ -923,12 +928,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
 					cbk.max = 1;
 					cbk.max = 1;
 					cbk.amount = 0;
 					cbk.amount = 0;
 					cbk.ptr = cd;
 					cbk.ptr = cd;
-					cbk.valid_dir = body_shape_xform.get_axis(1).normalized();
+					cbk.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
 
 
 					cbk.valid_depth = 10e20;
 					cbk.valid_depth = 10e20;
 
 
 					Vector2 sep = mnormal; //important optimization for this to work fast enough
 					Vector2 sep = mnormal; //important optimization for this to work fast enough
-					bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, 0);
+					bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, 0);
 					if (!collided || cbk.amount == 0) {
 					if (!collided || cbk.amount == 0) {
 						continue;
 						continue;
 					}
 					}
@@ -1013,9 +1018,11 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
 			if (excluded)
 			if (excluded)
 				continue;
 				continue;
 
 
+			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)) {
 			if (col_obj->is_shape_set_as_one_way_collision(shape_idx)) {
 
 
-				rcd.valid_dir = body_shape_xform.get_axis(1).normalized();
+				rcd.valid_dir = col_obj_shape_xform.get_axis(1).normalized();
 				rcd.valid_depth = 10e20;
 				rcd.valid_depth = 10e20;
 			} else {
 			} else {
 				rcd.valid_dir = Vector2();
 				rcd.valid_dir = Vector2();
@@ -1024,7 +1031,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co
 
 
 			rcd.object = col_obj;
 			rcd.object = col_obj;
 			rcd.shape = shape_idx;
 			rcd.shape = shape_idx;
-			bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), Vector2(), _rest_cbk_result, &rcd, NULL, p_margin);
+			bool sc = CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_shape_xform, Vector2(), _rest_cbk_result, &rcd, NULL, p_margin);
 			if (!sc)
 			if (!sc)
 				continue;
 				continue;
 		}
 		}