summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2022-12-14 11:25:55 +0100
committerRémi Verschelde <rverschelde@gmail.com>2022-12-14 11:25:55 +0100
commit45edf35f8325d6146762c559f1598c135981394a (patch)
tree1f0774e27e7934ff24e89a999c7d09716a39a978
parentb99bbcc4361d52b31521b99baef35fcd6abc12ff (diff)
parentadeef12b12a9852ec24fa06a145655524816145f (diff)
Merge pull request #69726 from xiongyaohua/tweak_curve
Handle corner cases for curve baking
-rw-r--r--editor/plugins/path_3d_editor_plugin.cpp7
-rw-r--r--scene/resources/curve.cpp38
-rw-r--r--scene/resources/curve.h2
3 files changed, 36 insertions, 11 deletions
diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp
index 63ca78d6c0..7a9e50e482 100644
--- a/editor/plugins/path_3d_editor_plugin.cpp
+++ b/editor/plugins/path_3d_editor_plugin.cpp
@@ -274,13 +274,10 @@ void Path3DGizmo::redraw() {
// Fish Bone.
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 + (-side - forward) * 0.06);
-
- v3p.push_back(p1);
- v3p.push_back(p1 + up * 0.03);
+ v3p.push_back(p1 + (-side - forward + up * 0.3) * 0.06);
}
add_lines(v3p, path_material);
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index 4ab5fae58e..b0a63bb7fa 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -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 {
if (!baked_cache_dirty) {
return;
@@ -835,19 +848,19 @@ void Curve2D::_bake() const {
// Collect positions and sample tilts and tangents for each baked points.
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;
for (int i = 0; i < points.size() - 1; i++) {
for (const KeyValue<real_t, Vector2> &E : midpoints[i]) {
pidx++;
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++;
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.
@@ -1482,6 +1495,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 {
if (!baked_cache_dirty) {
return;
@@ -1541,7 +1567,7 @@ void Curve3D::_bake() const {
// Collect positions and sample tilts and tangents for each baked points.
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;
int pidx = 0;
@@ -1549,13 +1575,13 @@ void Curve3D::_bake() const {
for (const KeyValue<real_t, Vector3> &E : midpoints[i]) {
pidx++;
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);
}
pidx++;
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;
}
diff --git a/scene/resources/curve.h b/scene/resources/curve.h
index ea3ceabb14..26608c47cd 100644
--- a/scene/resources/curve.h
+++ b/scene/resources/curve.h
@@ -178,6 +178,7 @@ class Curve2D : public Resource {
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;
real_t bake_interval = 5.0;
@@ -261,6 +262,7 @@ class Curve3D : public Resource {
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;
struct Interval {