Refactor Curve3D::_bake() method
The main change is to caculate tangent directly from bezier curve, without going through discretized polyline, avoiding pitfalls of discretization. Other changes are: 1. Add an bezier_derivative() method for Vector3, Vector2, and Math; 2. Add an tesselate_even_length() method to Curve3D, which tesselate bezier curve to even length segments adaptively; 3. Cache the tangent vectors in baked_tangent_vector_cache;
This commit is contained in:
parent
fa270c2456
commit
f9fa182abc
11 changed files with 223 additions and 130 deletions
|
|
@ -364,6 +364,26 @@ public:
|
|||
return p_start * omt3 + p_control_1 * omt2 * p_t * 3.0f + p_control_2 * omt * t2 * 3.0f + p_end * t3;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double bezier_derivative(double p_start, double p_control_1, double p_control_2, double p_end, double p_t) {
|
||||
/* Formula from Wikipedia article on Bezier curves. */
|
||||
double omt = (1.0 - p_t);
|
||||
double omt2 = omt * omt;
|
||||
double t2 = p_t * p_t;
|
||||
|
||||
double d = (p_control_1 - p_start) * 3.0 * omt2 + (p_control_2 - p_control_1) * 6.0 * omt * p_t + (p_end - p_control_2) * 3.0 * t2;
|
||||
return d;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ float bezier_derivative(float p_start, float p_control_1, float p_control_2, float p_end, float p_t) {
|
||||
/* Formula from Wikipedia article on Bezier curves. */
|
||||
float omt = (1.0f - p_t);
|
||||
float omt2 = omt * omt;
|
||||
float t2 = p_t * p_t;
|
||||
|
||||
float d = (p_control_1 - p_start) * 3.0f * omt2 + (p_control_2 - p_control_1) * 6.0f * omt * p_t + (p_end - p_control_2) * 3.0f * t2;
|
||||
return d;
|
||||
}
|
||||
|
||||
static _ALWAYS_INLINE_ double lerp_angle(double p_from, double p_to, double p_weight) {
|
||||
double difference = fmod(p_to - p_from, Math_TAU);
|
||||
double distance = fmod(2.0 * difference, Math_TAU) - difference;
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ struct _NO_DISCARD_ Vector2 {
|
|||
_FORCE_INLINE_ Vector2 cubic_interpolate(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight) const;
|
||||
_FORCE_INLINE_ Vector2 cubic_interpolate_in_time(const Vector2 &p_b, const Vector2 &p_pre_a, const Vector2 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const;
|
||||
_FORCE_INLINE_ Vector2 bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const;
|
||||
_FORCE_INLINE_ Vector2 bezier_derivative(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const;
|
||||
|
||||
Vector2 move_toward(const Vector2 &p_to, const real_t p_delta) const;
|
||||
|
||||
|
|
@ -289,6 +290,18 @@ Vector2 Vector2::bezier_interpolate(const Vector2 &p_control_1, const Vector2 &p
|
|||
return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3;
|
||||
}
|
||||
|
||||
Vector2 Vector2::bezier_derivative(const Vector2 &p_control_1, const Vector2 &p_control_2, const Vector2 &p_end, const real_t p_t) const {
|
||||
Vector2 res = *this;
|
||||
|
||||
/* Formula from Wikipedia article on Bezier curves. */
|
||||
real_t omt = (1.0 - p_t);
|
||||
real_t omt2 = omt * omt;
|
||||
real_t t2 = p_t * p_t;
|
||||
|
||||
Vector2 d = (p_control_1 - res) * 3.0 * omt2 + (p_control_2 - p_control_1) * 6.0 * omt * p_t + (p_end - p_control_2) * 3.0 * t2;
|
||||
return d;
|
||||
}
|
||||
|
||||
Vector2 Vector2::direction_to(const Vector2 &p_to) const {
|
||||
Vector2 ret(p_to.x - x, p_to.y - y);
|
||||
ret.normalize();
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ struct _NO_DISCARD_ Vector3 {
|
|||
_FORCE_INLINE_ Vector3 cubic_interpolate(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight) const;
|
||||
_FORCE_INLINE_ Vector3 cubic_interpolate_in_time(const Vector3 &p_b, const Vector3 &p_pre_a, const Vector3 &p_post_b, const real_t p_weight, const real_t &p_b_t, const real_t &p_pre_a_t, const real_t &p_post_b_t) const;
|
||||
_FORCE_INLINE_ Vector3 bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const;
|
||||
_FORCE_INLINE_ Vector3 bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const;
|
||||
|
||||
Vector3 move_toward(const Vector3 &p_to, const real_t p_delta) const;
|
||||
|
||||
|
|
@ -265,6 +266,18 @@ Vector3 Vector3::bezier_interpolate(const Vector3 &p_control_1, const Vector3 &p
|
|||
return res * omt3 + p_control_1 * omt2 * p_t * 3.0 + p_control_2 * omt * t2 * 3.0 + p_end * t3;
|
||||
}
|
||||
|
||||
Vector3 Vector3::bezier_derivative(const Vector3 &p_control_1, const Vector3 &p_control_2, const Vector3 &p_end, const real_t p_t) const {
|
||||
Vector3 res = *this;
|
||||
|
||||
/* Formula from Wikipedia article on Bezier curves. */
|
||||
real_t omt = (1.0 - p_t);
|
||||
real_t omt2 = omt * omt;
|
||||
real_t t2 = p_t * p_t;
|
||||
|
||||
Vector3 d = (p_control_1 - res) * 3.0 * omt2 + (p_control_2 - p_control_1) * 6.0 * omt * p_t + (p_end - p_control_2) * 3.0 * t2;
|
||||
return d;
|
||||
}
|
||||
|
||||
real_t Vector3::distance_to(const Vector3 &p_to) const {
|
||||
return (p_to - *this).length();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue