Fix tangent baking for curves where the derivative evaluates to 0 due to

collinear control points.
This commit is contained in:
Teschnique 2025-03-16 01:17:33 -07:00
parent 0e2d1526b7
commit a6dc345415
2 changed files with 92 additions and 18 deletions

View file

@ -881,12 +881,22 @@ void Curve2D::_bake_segment2d_even_length(RBMap<real_t, Vector2> &r_bake, real_t
Vector2 Curve2D::_calculate_tangent(const Vector2 &p_begin, const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) {
// Handle corner cases.
if (Math::is_zero_approx(p_t - 0.0f) && p_control_1.is_equal_approx(p_begin)) {
return (p_end - p_begin).normalized();
}
if (Math::is_zero_approx(p_t - 1.0f) && p_control_2.is_equal_approx(p_end)) {
return (p_end - p_begin).normalized();
if (Math::is_zero_approx(p_t - 0.0f)) {
if (p_control_1.is_equal_approx(p_begin)) {
if (p_control_1.is_equal_approx(p_control_2)) {
return (p_end - p_begin).normalized();
} else {
return (p_control_2 - p_begin).normalized();
}
}
} else if (Math::is_zero_approx(p_t - 1.0f)) {
if (p_control_2.is_equal_approx(p_end)) {
if (p_control_2.is_equal_approx(p_control_1)) {
return (p_end - p_begin).normalized();
} else {
return (p_end - p_control_1).normalized();
}
}
}
return p_begin.bezier_derivative(p_control_1, p_control_2, p_end, p_t).normalized();
@ -1620,12 +1630,22 @@ void Curve3D::_bake_segment3d_even_length(RBMap<real_t, Vector3> &r_bake, real_t
Vector3 Curve3D::_calculate_tangent(const Vector3 &p_begin, const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) {
// Handle corner cases.
if (Math::is_zero_approx(p_t - 0.0f) && p_control_1.is_equal_approx(p_begin)) {
return (p_end - p_begin).normalized();
}
if (Math::is_zero_approx(p_t - 1.0f) && p_control_2.is_equal_approx(p_end)) {
return (p_end - p_begin).normalized();
if (Math::is_zero_approx(p_t - 0.0f)) {
if (p_control_1.is_equal_approx(p_begin)) {
if (p_control_1.is_equal_approx(p_control_2)) {
return (p_end - p_begin).normalized();
} else {
return (p_control_2 - p_begin).normalized();
}
}
} else if (Math::is_zero_approx(p_t - 1.0f)) {
if (p_control_2.is_equal_approx(p_end)) {
if (p_control_2.is_equal_approx(p_control_1)) {
return (p_end - p_begin).normalized();
} else {
return (p_end - p_control_1).normalized();
}
}
}
return p_begin.bezier_derivative(p_control_1, p_control_2, p_end, p_t).normalized();