Browse Source

Fix Camera3D::project_position() when depth=zfar

Florent Guiocheau 10 months ago
parent
commit
771e561cdd
2 changed files with 11 additions and 2 deletions
  1. 5 2
      scene/3d/camera_3d.cpp
  2. 6 0
      tests/scene/test_camera_3d.h

+ 5 - 2
scene/3d/camera_3d.cpp

@@ -528,9 +528,12 @@ Vector3 Camera3D::project_position(const Point2 &p_point, real_t p_z_depth) cons
 	}
 	}
 	Size2 viewport_size = get_viewport()->get_visible_rect().size;
 	Size2 viewport_size = get_viewport()->get_visible_rect().size;
 
 
-	Projection cm = _get_camera_projection(p_z_depth);
+	Projection cm = _get_camera_projection(_near);
 
 
-	Vector2 vp_he = cm.get_viewport_half_extents();
+	Plane z_slice(Vector3(0, 0, 1), -p_z_depth);
+	Vector3 res;
+	z_slice.intersect_3(cm.get_projection_plane(Projection::Planes::PLANE_RIGHT), cm.get_projection_plane(Projection::Planes::PLANE_TOP), &res);
+	Vector2 vp_he(res.x, res.y);
 
 
 	Vector2 point;
 	Vector2 point;
 	point.x = (p_point.x / viewport_size.x) * 2.0 - 1.0;
 	point.x = (p_point.x / viewport_size.x) * 2.0 - 1.0;

+ 6 - 0
tests/scene/test_camera_3d.h

@@ -231,10 +231,13 @@ TEST_CASE("[SceneTree][Camera3D] Project/Unproject position") {
 			test_camera->set_orthogonal(5.0f, 0.5f, 1000.0f);
 			test_camera->set_orthogonal(5.0f, 0.5f, 1000.0f);
 			// Center.
 			// Center.
 			CHECK(test_camera->project_position(Vector2(200, 100), 0.5f).is_equal_approx(Vector3(0, 0, -0.5f)));
 			CHECK(test_camera->project_position(Vector2(200, 100), 0.5f).is_equal_approx(Vector3(0, 0, -0.5f)));
+			CHECK(test_camera->project_position(Vector2(200, 100), test_camera->get_far()).is_equal_approx(Vector3(0, 0, -test_camera->get_far())));
 			// Top left.
 			// Top left.
 			CHECK(test_camera->project_position(Vector2(0, 0), 1.5f).is_equal_approx(Vector3(-5.0f, 2.5f, -1.5f)));
 			CHECK(test_camera->project_position(Vector2(0, 0), 1.5f).is_equal_approx(Vector3(-5.0f, 2.5f, -1.5f)));
+			CHECK(test_camera->project_position(Vector2(0, 0), test_camera->get_near()).is_equal_approx(Vector3(-5.0f, 2.5f, -test_camera->get_near())));
 			// Bottom right.
 			// Bottom right.
 			CHECK(test_camera->project_position(Vector2(400, 200), 5.0f).is_equal_approx(Vector3(5.0f, -2.5f, -5.0f)));
 			CHECK(test_camera->project_position(Vector2(400, 200), 5.0f).is_equal_approx(Vector3(5.0f, -2.5f, -5.0f)));
+			CHECK(test_camera->project_position(Vector2(400, 200), test_camera->get_far()).is_equal_approx(Vector3(5.0f, -2.5f, -test_camera->get_far())));
 		}
 		}
 
 
 		SUBCASE("Perspective projection") {
 		SUBCASE("Perspective projection") {
@@ -242,12 +245,15 @@ TEST_CASE("[SceneTree][Camera3D] Project/Unproject position") {
 			// Center.
 			// Center.
 			CHECK(test_camera->project_position(Vector2(200, 100), 0.5f).is_equal_approx(Vector3(0, 0, -0.5f)));
 			CHECK(test_camera->project_position(Vector2(200, 100), 0.5f).is_equal_approx(Vector3(0, 0, -0.5f)));
 			CHECK(test_camera->project_position(Vector2(200, 100), 100.0f).is_equal_approx(Vector3(0, 0, -100.0f)));
 			CHECK(test_camera->project_position(Vector2(200, 100), 100.0f).is_equal_approx(Vector3(0, 0, -100.0f)));
+			CHECK(test_camera->project_position(Vector2(200, 100), test_camera->get_far()).is_equal_approx(Vector3(0, 0, -1.0f) * test_camera->get_far()));
 			// 3/4th way to Top left.
 			// 3/4th way to Top left.
 			CHECK(test_camera->project_position(Vector2(100, 50), 0.5f).is_equal_approx(Vector3(-SQRT3 * 0.5f, SQRT3 * 0.25f, -0.5f)));
 			CHECK(test_camera->project_position(Vector2(100, 50), 0.5f).is_equal_approx(Vector3(-SQRT3 * 0.5f, SQRT3 * 0.25f, -0.5f)));
 			CHECK(test_camera->project_position(Vector2(100, 50), 1.0f).is_equal_approx(Vector3(-SQRT3, SQRT3 * 0.5f, -1.0f)));
 			CHECK(test_camera->project_position(Vector2(100, 50), 1.0f).is_equal_approx(Vector3(-SQRT3, SQRT3 * 0.5f, -1.0f)));
+			CHECK(test_camera->project_position(Vector2(100, 50), test_camera->get_near()).is_equal_approx(Vector3(-SQRT3, SQRT3 * 0.5f, -1.0f) * test_camera->get_near()));
 			// 3/4th way to Bottom right.
 			// 3/4th way to Bottom right.
 			CHECK(test_camera->project_position(Vector2(300, 150), 0.5f).is_equal_approx(Vector3(SQRT3 * 0.5f, -SQRT3 * 0.25f, -0.5f)));
 			CHECK(test_camera->project_position(Vector2(300, 150), 0.5f).is_equal_approx(Vector3(SQRT3 * 0.5f, -SQRT3 * 0.25f, -0.5f)));
 			CHECK(test_camera->project_position(Vector2(300, 150), 1.0f).is_equal_approx(Vector3(SQRT3, -SQRT3 * 0.5f, -1.0f)));
 			CHECK(test_camera->project_position(Vector2(300, 150), 1.0f).is_equal_approx(Vector3(SQRT3, -SQRT3 * 0.5f, -1.0f)));
+			CHECK(test_camera->project_position(Vector2(300, 150), test_camera->get_far()).is_equal_approx(Vector3(SQRT3, -SQRT3 * 0.5f, -1.0f) * test_camera->get_far()));
 		}
 		}
 	}
 	}