Browse Source

Merge pull request #39590 from madmiraal/fix-35744-3.2

[3.2] Normalise p_up_direction vector in move_and_slide()
Rémi Verschelde 5 years ago
parent
commit
893cf84278
2 changed files with 22 additions and 18 deletions
  1. 11 9
      scene/2d/physics_body_2d.cpp
  2. 11 9
      scene/3d/physics_body.cpp

+ 11 - 9
scene/2d/physics_body_2d.cpp

@@ -1216,6 +1216,7 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
 
 
 	Vector2 body_velocity = p_linear_velocity;
 	Vector2 body_velocity = p_linear_velocity;
 	Vector2 body_velocity_normal = body_velocity.normalized();
 	Vector2 body_velocity_normal = body_velocity.normalized();
+	Vector2 up_direction = p_up_direction.normalized();
 
 
 	Vector2 current_floor_velocity = floor_velocity;
 	Vector2 current_floor_velocity = floor_velocity;
 	if (on_floor && on_floor_body.is_valid()) {
 	if (on_floor && on_floor_body.is_valid()) {
@@ -1263,11 +1264,11 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
 				colliders.push_back(collision);
 				colliders.push_back(collision);
 				motion = collision.remainder;
 				motion = collision.remainder;
 
 
-				if (p_up_direction == Vector2()) {
+				if (up_direction == Vector2()) {
 					//all is a wall
 					//all is a wall
 					on_wall = true;
 					on_wall = true;
 				} else {
 				} else {
-					if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
+					if (Math::acos(collision.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
 
 
 						on_floor = true;
 						on_floor = true;
 						floor_normal = collision.normal;
 						floor_normal = collision.normal;
@@ -1275,14 +1276,14 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
 						floor_velocity = collision.collider_vel;
 						floor_velocity = collision.collider_vel;
 
 
 						if (p_stop_on_slope) {
 						if (p_stop_on_slope) {
-							if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) {
+							if ((body_velocity_normal + up_direction).length() < 0.01 && collision.travel.length() < 1) {
 								Transform2D gt = get_global_transform();
 								Transform2D gt = get_global_transform();
-								gt.elements[2] -= collision.travel.slide(p_up_direction);
+								gt.elements[2] -= collision.travel.slide(up_direction);
 								set_global_transform(gt);
 								set_global_transform(gt);
 								return Vector2();
 								return Vector2();
 							}
 							}
 						}
 						}
-					} else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
+					} else if (Math::acos(collision.normal.dot(-up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
 						on_ceiling = true;
 						on_ceiling = true;
 					} else {
 					} else {
 						on_wall = true;
 						on_wall = true;
@@ -1305,9 +1306,10 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const
 
 
 Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
 Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
 
 
+	Vector2 up_direction = p_up_direction.normalized();
 	bool was_on_floor = on_floor;
 	bool was_on_floor = on_floor;
 
 
-	Vector2 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
+	Vector2 ret = move_and_slide(p_linear_velocity, up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
 	if (!was_on_floor || p_snap == Vector2()) {
 	if (!was_on_floor || p_snap == Vector2()) {
 		return ret;
 		return ret;
 	}
 	}
@@ -1317,8 +1319,8 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci
 
 
 	if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
 	if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
 		bool apply = true;
 		bool apply = true;
-		if (p_up_direction != Vector2()) {
-			if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) {
+		if (up_direction != Vector2()) {
+			if (Math::acos(col.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
 				on_floor = true;
 				on_floor = true;
 				floor_normal = col.normal;
 				floor_normal = col.normal;
 				on_floor_body = col.collider_rid;
 				on_floor_body = col.collider_rid;
@@ -1326,7 +1328,7 @@ Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_veloci
 				if (p_stop_on_slope) {
 				if (p_stop_on_slope) {
 					// move and collide may stray the object a bit because of pre un-stucking,
 					// move and collide may stray the object a bit because of pre un-stucking,
 					// so only ensure that motion happens on floor direction in this case.
 					// so only ensure that motion happens on floor direction in this case.
-					col.travel = p_up_direction * p_up_direction.dot(col.travel);
+					col.travel = up_direction * up_direction.dot(col.travel);
 				}
 				}
 
 
 			} else {
 			} else {

+ 11 - 9
scene/3d/physics_body.cpp

@@ -1145,6 +1145,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
 
 
 	Vector3 body_velocity = p_linear_velocity;
 	Vector3 body_velocity = p_linear_velocity;
 	Vector3 body_velocity_normal = body_velocity.normalized();
 	Vector3 body_velocity_normal = body_velocity.normalized();
+	Vector3 up_direction = p_up_direction.normalized();
 
 
 	for (int i = 0; i < 3; i++) {
 	for (int i = 0; i < 3; i++) {
 		if (locked_axis & (1 << i)) {
 		if (locked_axis & (1 << i)) {
@@ -1189,11 +1190,11 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
 				colliders.push_back(collision);
 				colliders.push_back(collision);
 				motion = collision.remainder;
 				motion = collision.remainder;
 
 
-				if (p_up_direction == Vector3()) {
+				if (up_direction == Vector3()) {
 					//all is a wall
 					//all is a wall
 					on_wall = true;
 					on_wall = true;
 				} else {
 				} else {
-					if (Math::acos(collision.normal.dot(p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
+					if (Math::acos(collision.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //floor
 
 
 						on_floor = true;
 						on_floor = true;
 						floor_normal = collision.normal;
 						floor_normal = collision.normal;
@@ -1201,14 +1202,14 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
 						floor_velocity = collision.collider_vel;
 						floor_velocity = collision.collider_vel;
 
 
 						if (p_stop_on_slope) {
 						if (p_stop_on_slope) {
-							if ((body_velocity_normal + p_up_direction).length() < 0.01 && collision.travel.length() < 1) {
+							if ((body_velocity_normal + up_direction).length() < 0.01 && collision.travel.length() < 1) {
 								Transform gt = get_global_transform();
 								Transform gt = get_global_transform();
-								gt.origin -= collision.travel.slide(p_up_direction);
+								gt.origin -= collision.travel.slide(up_direction);
 								set_global_transform(gt);
 								set_global_transform(gt);
 								return Vector3();
 								return Vector3();
 							}
 							}
 						}
 						}
-					} else if (Math::acos(collision.normal.dot(-p_up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
+					} else if (Math::acos(collision.normal.dot(-up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) { //ceiling
 						on_ceiling = true;
 						on_ceiling = true;
 					} else {
 					} else {
 						on_wall = true;
 						on_wall = true;
@@ -1237,9 +1238,10 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve
 
 
 Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
 Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_up_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) {
 
 
+	Vector3 up_direction = p_up_direction.normalized();
 	bool was_on_floor = on_floor;
 	bool was_on_floor = on_floor;
 
 
-	Vector3 ret = move_and_slide(p_linear_velocity, p_up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
+	Vector3 ret = move_and_slide(p_linear_velocity, up_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia);
 	if (!was_on_floor || p_snap == Vector3()) {
 	if (!was_on_floor || p_snap == Vector3()) {
 		return ret;
 		return ret;
 	}
 	}
@@ -1250,8 +1252,8 @@ Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity
 	if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
 	if (move_and_collide(p_snap, p_infinite_inertia, col, false, true)) {
 
 
 		bool apply = true;
 		bool apply = true;
-		if (p_up_direction != Vector3()) {
-			if (Math::acos(p_up_direction.normalized().dot(col.normal)) < p_floor_max_angle) {
+		if (up_direction != Vector3()) {
+			if (Math::acos(col.normal.dot(up_direction)) <= p_floor_max_angle + FLOOR_ANGLE_THRESHOLD) {
 				on_floor = true;
 				on_floor = true;
 				floor_normal = col.normal;
 				floor_normal = col.normal;
 				on_floor_body = col.collider_rid;
 				on_floor_body = col.collider_rid;
@@ -1259,7 +1261,7 @@ Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity
 				if (p_stop_on_slope) {
 				if (p_stop_on_slope) {
 					// move and collide may stray the object a bit because of pre un-stucking,
 					// move and collide may stray the object a bit because of pre un-stucking,
 					// so only ensure that motion happens on floor direction in this case.
 					// so only ensure that motion happens on floor direction in this case.
-					col.travel = col.travel.project(p_up_direction);
+					col.travel = col.travel.project(up_direction);
 				}
 				}
 			} else {
 			} else {
 				apply = false; //snapped with floor direction, but did not snap to a floor, do not snap.
 				apply = false; //snapped with floor direction, but did not snap to a floor, do not snap.