diff options
author | Silc Renew <tokage.it.lab@gmail.com> | 2022-08-26 11:42:00 +0900 |
---|---|---|
committer | Silc Renew <tokage.it.lab@gmail.com> | 2022-08-27 07:58:22 +0900 |
commit | 931fb4dc11509357297bcdcc6a8d6b11638ff585 (patch) | |
tree | cd078a938be475cc20bba35ac856103b9e524239 /scene/animation | |
parent | 4808d01b2bcda54db15e1e2649e0a38c37886ee1 (diff) |
Add linear/cubic angle interpolation to Animation interpolation type
Diffstat (limited to 'scene/animation')
-rw-r--r-- | scene/animation/animation_tree.cpp | 30 | ||||
-rw-r--r-- | scene/animation/animation_tree.h | 1 |
2 files changed, 29 insertions, 2 deletions
diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index ee552e695e..d06324f0aa 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -602,6 +602,8 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track_value->object = child; } + track_value->is_using_angle = anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE; + track_value->subpath = leftover_path; track_value->object_id = track_value->object->get_instance_id(); @@ -804,6 +806,10 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { default: { } } + } else if (track_cache_type == Animation::TYPE_VALUE) { + // If it has at least one angle interpolation, it also uses angle interpolation for blending. + TrackCacheValue *track_value = memnew(TrackCacheValue); + track_value->is_using_angle |= anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE; } track->setup_pass = setup_pass; @@ -1353,8 +1359,28 @@ void AnimationTree::_process_graph(double p_delta) { t->value = t->init_value; } - Variant::sub(value, t->init_value, value); - Variant::blend(t->value, value, blend, t->value); + // Special case for angle interpolation. + if (t->is_using_angle) { + // For blending consistency, it prevents rotation of more than 180 degrees from init_value. + // This is the same as for Quaternion blends. + float rot_a = t->value; + float rot_b = value; + float rot_init = t->init_value; + rot_a = Math::fposmod(rot_a, (float)Math_TAU); + rot_b = Math::fposmod(rot_b, (float)Math_TAU); + rot_init = Math::fposmod(rot_init, (float)Math_TAU); + if (rot_init < Math_PI) { + rot_a = rot_a > rot_init + Math_PI ? rot_a - Math_TAU : rot_a; + rot_b = rot_b > rot_init + Math_PI ? rot_b - Math_TAU : rot_b; + } else { + rot_a = rot_a < rot_init - Math_PI ? rot_a + Math_TAU : rot_a; + rot_b = rot_b < rot_init - Math_PI ? rot_b + Math_TAU : rot_b; + } + t->value = Math::fposmod(rot_a + (rot_b - rot_init) * (float)blend, (float)Math_TAU); + } else { + Variant::sub(value, t->init_value, value); + Variant::blend(t->value, value, blend, t->value); + } } else { if (blend < CMP_EPSILON) { continue; //nothing to blend diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index ee51a54557..ee0c0303dc 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -233,6 +233,7 @@ private: Variant init_value; Variant value; Vector<StringName> subpath; + bool is_using_angle = false; TrackCacheValue() { type = Animation::TYPE_VALUE; } }; |