Bladeren bron

Merge pull request #69239 from xiongyaohua/fix_69220

Fix `Curve3D::get_closest_point()` broken
Rémi Verschelde 2 jaren geleden
bovenliggende
commit
33dd934111
2 gewijzigde bestanden met toevoegingen van 13 en 11 verwijderingen
  1. 1 1
      doc/classes/Curve3D.xml
  2. 12 10
      scene/resources/curve.cpp

+ 1 - 1
doc/classes/Curve3D.xml

@@ -64,7 +64,7 @@
 			<return type="Vector3" />
 			<param index="0" name="to_point" type="Vector3" />
 			<description>
-				Returns the closest baked point (in curve's local space) to [param to_point].
+				Returns the closest point on baked segments (in curve's local space) to [param to_point].
 				[param to_point] must be in this curve's local space.
 			</description>
 		</method>

+ 12 - 10
scene/resources/curve.cpp

@@ -1407,15 +1407,15 @@ void Curve3D::_bake_segment3d_even_length(RBMap<real_t, Vector3> &r_bake, real_t
 	Vector3 beg = p_a.bezier_interpolate(p_a + p_out, p_b + p_in, p_b, p_begin);
 	Vector3 end = p_a.bezier_interpolate(p_a + p_out, p_b + p_in, p_b, p_end);
 
-	size_t length = beg.distance_to(end);
+	real_t length = beg.distance_to(end);
 
 	if (length > p_length && p_depth < p_max_depth) {
 		real_t mp = (p_begin + p_end) * 0.5;
 		Vector3 mid = p_a.bezier_interpolate(p_a + p_out, p_b + p_in, p_b, mp);
 		r_bake[mp] = mid;
 
-		_bake_segment3d(r_bake, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_max_depth, p_length);
-		_bake_segment3d(r_bake, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_max_depth, p_length);
+		_bake_segment3d_even_length(r_bake, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_max_depth, p_length);
+		_bake_segment3d_even_length(r_bake, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_max_depth, p_length);
 	}
 }
 
@@ -1839,10 +1839,11 @@ Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const {
 	real_t nearest_dist = -1.0f;
 
 	for (int i = 0; i < pc - 1; i++) {
+		const real_t interval = baked_dist_cache[i + 1] - baked_dist_cache[i];
 		Vector3 origin = r[i];
-		Vector3 direction = (r[i + 1] - origin) / bake_interval;
+		Vector3 direction = (r[i + 1] - origin) / interval;
 
-		real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+		real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, interval);
 		Vector3 proj = origin + direction * d;
 
 		real_t dist = proj.distance_squared_to(p_to_point);
@@ -1875,13 +1876,16 @@ real_t Curve3D::get_closest_offset(const Vector3 &p_to_point) const {
 
 	real_t nearest = 0.0f;
 	real_t nearest_dist = -1.0f;
-	real_t offset = 0.0f;
+	real_t offset;
 
 	for (int i = 0; i < pc - 1; i++) {
+		offset = baked_dist_cache[i];
+
+		const real_t interval = baked_dist_cache[i + 1] - baked_dist_cache[i];
 		Vector3 origin = r[i];
-		Vector3 direction = (r[i + 1] - origin) / bake_interval;
+		Vector3 direction = (r[i + 1] - origin) / interval;
 
-		real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, bake_interval);
+		real_t d = CLAMP((p_to_point - origin).dot(direction), 0.0f, interval);
 		Vector3 proj = origin + direction * d;
 
 		real_t dist = proj.distance_squared_to(p_to_point);
@@ -1890,8 +1894,6 @@ real_t Curve3D::get_closest_offset(const Vector3 &p_to_point) const {
 			nearest = offset + d;
 			nearest_dist = dist;
 		}
-
-		offset += bake_interval;
 	}
 
 	return nearest;