You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-08 12:40:44 +00:00
Handle corner cases for curve baking
When control point and point have equal position, the derivative is 0 vector, which cause error message in Basis::look_at(). This commit handles this case.
This commit is contained in:
@@ -274,13 +274,10 @@ void Path3DGizmo::redraw() {
|
|||||||
|
|
||||||
// Fish Bone.
|
// Fish Bone.
|
||||||
v3p.push_back(p1);
|
v3p.push_back(p1);
|
||||||
v3p.push_back(p1 + (side - forward) * 0.06);
|
v3p.push_back(p1 + (side - forward + up * 0.3) * 0.06);
|
||||||
|
|
||||||
v3p.push_back(p1);
|
v3p.push_back(p1);
|
||||||
v3p.push_back(p1 + (-side - forward) * 0.06);
|
v3p.push_back(p1 + (-side - forward + up * 0.3) * 0.06);
|
||||||
|
|
||||||
v3p.push_back(p1);
|
|
||||||
v3p.push_back(p1 + up * 0.03);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add_lines(v3p, path_material);
|
add_lines(v3p, path_material);
|
||||||
|
|||||||
@@ -790,6 +790,19 @@ 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
return p_begin.bezier_derivative(p_control_1, p_control_2, p_end, p_t).normalized();
|
||||||
|
}
|
||||||
|
|
||||||
void Curve2D::_bake() const {
|
void Curve2D::_bake() const {
|
||||||
if (!baked_cache_dirty) {
|
if (!baked_cache_dirty) {
|
||||||
return;
|
return;
|
||||||
@@ -835,19 +848,19 @@ void Curve2D::_bake() const {
|
|||||||
|
|
||||||
// Collect positions and sample tilts and tangents for each baked points.
|
// Collect positions and sample tilts and tangents for each baked points.
|
||||||
bpw[0] = points[0].position;
|
bpw[0] = points[0].position;
|
||||||
bfw[0] = points[0].position.bezier_derivative(points[0].position + points[0].out, points[1].position + points[1].in, points[1].position, 0.0).normalized();
|
bfw[0] = _calculate_tangent(points[0].position, points[0].position + points[0].out, points[1].position + points[1].in, points[1].position, 0.0);
|
||||||
int pidx = 0;
|
int pidx = 0;
|
||||||
|
|
||||||
for (int i = 0; i < points.size() - 1; i++) {
|
for (int i = 0; i < points.size() - 1; i++) {
|
||||||
for (const KeyValue<real_t, Vector2> &E : midpoints[i]) {
|
for (const KeyValue<real_t, Vector2> &E : midpoints[i]) {
|
||||||
pidx++;
|
pidx++;
|
||||||
bpw[pidx] = E.value;
|
bpw[pidx] = E.value;
|
||||||
bfw[pidx] = points[i].position.bezier_derivative(points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, E.key).normalized();
|
bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, E.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
pidx++;
|
pidx++;
|
||||||
bpw[pidx] = points[i + 1].position;
|
bpw[pidx] = points[i + 1].position;
|
||||||
bfw[pidx] = points[i].position.bezier_derivative(points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, 1.0).normalized();
|
bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recalculate the baked distances.
|
// Recalculate the baked distances.
|
||||||
@@ -1480,6 +1493,19 @@ 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
return p_begin.bezier_derivative(p_control_1, p_control_2, p_end, p_t).normalized();
|
||||||
|
}
|
||||||
|
|
||||||
void Curve3D::_bake() const {
|
void Curve3D::_bake() const {
|
||||||
if (!baked_cache_dirty) {
|
if (!baked_cache_dirty) {
|
||||||
return;
|
return;
|
||||||
@@ -1539,7 +1565,7 @@ void Curve3D::_bake() const {
|
|||||||
|
|
||||||
// Collect positions and sample tilts and tangents for each baked points.
|
// Collect positions and sample tilts and tangents for each baked points.
|
||||||
bpw[0] = points[0].position;
|
bpw[0] = points[0].position;
|
||||||
bfw[0] = points[0].position.bezier_derivative(points[0].position + points[0].out, points[1].position + points[1].in, points[1].position, 0.0).normalized();
|
bfw[0] = _calculate_tangent(points[0].position, points[0].position + points[0].out, points[1].position + points[1].in, points[1].position, 0.0);
|
||||||
btw[0] = points[0].tilt;
|
btw[0] = points[0].tilt;
|
||||||
int pidx = 0;
|
int pidx = 0;
|
||||||
|
|
||||||
@@ -1547,13 +1573,13 @@ void Curve3D::_bake() const {
|
|||||||
for (const KeyValue<real_t, Vector3> &E : midpoints[i]) {
|
for (const KeyValue<real_t, Vector3> &E : midpoints[i]) {
|
||||||
pidx++;
|
pidx++;
|
||||||
bpw[pidx] = E.value;
|
bpw[pidx] = E.value;
|
||||||
bfw[pidx] = points[i].position.bezier_derivative(points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, E.key).normalized();
|
bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, E.key);
|
||||||
btw[pidx] = Math::lerp(points[i].tilt, points[i + 1].tilt, E.key);
|
btw[pidx] = Math::lerp(points[i].tilt, points[i + 1].tilt, E.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
pidx++;
|
pidx++;
|
||||||
bpw[pidx] = points[i + 1].position;
|
bpw[pidx] = points[i + 1].position;
|
||||||
bfw[pidx] = points[i].position.bezier_derivative(points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, 1.0).normalized();
|
bfw[pidx] = _calculate_tangent(points[i].position, points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, 1.0);
|
||||||
btw[pidx] = points[i + 1].tilt;
|
btw[pidx] = points[i + 1].tilt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ class Curve2D : public Resource {
|
|||||||
|
|
||||||
void mark_dirty();
|
void mark_dirty();
|
||||||
|
|
||||||
|
static Vector2 _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);
|
||||||
void _bake() const;
|
void _bake() const;
|
||||||
|
|
||||||
real_t bake_interval = 5.0;
|
real_t bake_interval = 5.0;
|
||||||
@@ -261,6 +262,7 @@ class Curve3D : public Resource {
|
|||||||
|
|
||||||
void mark_dirty();
|
void mark_dirty();
|
||||||
|
|
||||||
|
static Vector3 _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);
|
||||||
void _bake() const;
|
void _bake() const;
|
||||||
|
|
||||||
struct Interval {
|
struct Interval {
|
||||||
|
|||||||
Reference in New Issue
Block a user