Browse Source

Fix Curve3D baking up vectors for nontrivial curves.

The code was modified in 42aa539 to have a different basis vector, but
this line was missed and caused up vectors to invert sometimes.

Fixes #81879
Ryan Hitchman 1 year ago
parent
commit
734b9d2379
2 changed files with 10 additions and 2 deletions
  1. 2 2
      scene/resources/curve.cpp
  2. 8 0
      tests/scene/test_curve_3d.h

+ 2 - 2
scene/resources/curve.cpp

@@ -1662,7 +1662,7 @@ void Curve3D::_bake() const {
 		const Vector3 *forward_ptr = baked_forward_vector_cache.ptr();
 		const Vector3 *forward_ptr = baked_forward_vector_cache.ptr();
 		const Vector3 *points_ptr = baked_point_cache.ptr();
 		const Vector3 *points_ptr = baked_point_cache.ptr();
 
 
-		Basis frame; // X-right, Y-up, Z-forward.
+		Basis frame; // X-right, Y-up, -Z-forward.
 		Basis frame_prev;
 		Basis frame_prev;
 
 
 		// Set the initial frame based on Y-up rule.
 		// Set the initial frame based on Y-up rule.
@@ -1683,7 +1683,7 @@ void Curve3D::_bake() const {
 			Vector3 forward = forward_ptr[idx];
 			Vector3 forward = forward_ptr[idx];
 
 
 			Basis rotate;
 			Basis rotate;
-			rotate.rotate_to_align(frame_prev.get_column(2), forward);
+			rotate.rotate_to_align(-frame_prev.get_column(2), forward);
 			frame = rotate * frame_prev;
 			frame = rotate * frame_prev;
 			frame.orthonormalize(); // guard against float error accumulation
 			frame.orthonormalize(); // guard against float error accumulation
 
 

+ 8 - 0
tests/scene/test_curve_3d.h

@@ -209,6 +209,14 @@ TEST_CASE("[Curve3D] Sampling") {
 		CHECK(curve->get_closest_point(Vector3(50, 50, 0)) == Vector3(0, 50, 0));
 		CHECK(curve->get_closest_point(Vector3(50, 50, 0)) == Vector3(0, 50, 0));
 		CHECK(curve->get_closest_point(Vector3(0, 100, 0)) == Vector3(0, 50, 0));
 		CHECK(curve->get_closest_point(Vector3(0, 100, 0)) == Vector3(0, 50, 0));
 	}
 	}
+
+	SUBCASE("sample_baked_up_vector, off-axis") {
+		// Regression test for issue #81879
+		Ref<Curve3D> c = memnew(Curve3D);
+		c->add_point(Vector3());
+		c->add_point(Vector3(0, .1, 1));
+		CHECK_LT((c->sample_baked_up_vector(c->get_closest_offset(Vector3(0, 0, .9))) - Vector3(0, 0.995037, -0.099504)).length(), 0.01);
+	}
 }
 }
 
 
 TEST_CASE("[Curve3D] Tessellation") {
 TEST_CASE("[Curve3D] Tessellation") {