From: Mikko Rasa Date: Sat, 8 Jun 2019 06:47:24 +0000 (+0300) Subject: Add compatibility support for slope-based animation interpolation X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=22ed49c0b233566fc5d72b7c9769fd3ba543ab40 Add compatibility support for slope-based animation interpolation --- diff --git a/source/animation.cpp b/source/animation.cpp index 900542dd..aa3e1b86 100644 --- a/source/animation.cpp +++ b/source/animation.cpp @@ -52,12 +52,14 @@ void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf) void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float slope) { - add_keyframe(t, kf, slope, slope); + add_keyframe(t, &kf, slope, slope, false); + create_curves(); } -void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float, float) +void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float ss, float es) { - add_keyframe(t, kf); + add_keyframe(t, &kf, ss, es, false); + create_curves(); } void Animation::add_control_keyframe(const KeyFrame &kf) @@ -68,6 +70,50 @@ void Animation::add_control_keyframe(const KeyFrame &kf) add_keyframe(keyframes.back().time, &kf, true, false); } +void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame *kf, float ss, float es, bool owned) +{ + if(keyframes.empty()) + return add_keyframe(t, kf, false, owned); + + if(keyframes.back().control) + throw invalid_operation("Animation::add_keyframe"); + + const KeyFrame &last = *keyframes.back().keyframe; + const Transform &trn = kf->get_transform(); + const Transform &last_trn = last.get_transform(); + const KeyFrame::UniformMap &kf_unis = kf->get_uniforms(); + const KeyFrame::UniformMap &last_unis = last.get_uniforms(); + for(unsigned i=1; i<=2; ++i) + { + float x = (i==1 ? ss/3 : 1-es/3); + KeyFrame *ckf = new KeyFrame; + Transform ctrn; + ctrn.set_position(last_trn.get_position()*(1-x)+trn.get_position()*x); + const Transform::AngleVector3 &e1 = last_trn.get_euler(); + const Transform::AngleVector3 &e2 = trn.get_euler(); + ctrn.set_euler(Transform::AngleVector3(e1.x*(1-x)+e2.x*x, e1.y*(1-x)+e2.y*x, e1.z*(1-x)+e2.z*x)); + ctrn.set_scale(last_trn.get_scale()*(1-x)+trn.get_scale()*x); + ckf->set_transform(ctrn); + + for(KeyFrame::UniformMap::const_iterator j=kf_unis.begin(); j!=kf_unis.end(); ++j) + { + KeyFrame::UniformMap::const_iterator k = last_unis.find(j->first); + if(k==last_unis.end()) + continue; + + KeyFrame::AnimatedUniform uni(j->second.size, 0.0f); + for(unsigned c=0; csecond.values[c]*(1-x)+j->second.values[c]*x; + + ckf->set_uniform(j->first, uni); + } + + add_keyframe(t, ckf, true, true); + } + + add_keyframe(t, kf, false, owned); +} + void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame *kf, bool c, bool owned) { if(c && keyframes.empty()) @@ -367,6 +413,7 @@ void Animation::Loader::init() { start_slope = 1; end_slope = 1; + slopes_set = 0; add("armature", &Animation::armature); add("control_keyframe", &Loader::control_keyframe); add("control_keyframe", &Loader::control_keyframe_inline); @@ -388,9 +435,27 @@ void Animation::Loader::finish() obj.create_curves(); } +void Animation::Loader::check_slopes_and_control(bool s, bool c) +{ + if(s && c) + throw logic_error("can't use both slopes and control keyframes in same segment"); +} + +void Animation::Loader::add_kf(const KeyFrame *kf, bool c, bool owned) +{ + if(slopes_set && !c) + obj.add_keyframe(current_time, kf, start_slope, end_slope, owned); + else + obj.add_keyframe(current_time, kf, c, owned); + + start_slope = end_slope; + end_slope = 1; + slopes_set = (slopes_set<<1)&3; +} + void Animation::Loader::load_kf(const string &n, bool c) { - obj.add_keyframe(current_time, &get_collection().get(n), c, false); + add_kf(&get_collection().get(n), c, false); } void Animation::Loader::load_kf_inline(bool c) @@ -401,17 +466,21 @@ void Animation::Loader::load_kf_inline(bool c) else load_sub(*kf); - obj.add_keyframe(current_time, *kf, c, true); + add_kf(kf.get(), c, true); kf.release(); } void Animation::Loader::control_keyframe(const string &n) { + slopes_set &= 1; + check_slopes_and_control(slopes_set, true); load_kf(n, true); } void Animation::Loader::control_keyframe_inline() { + slopes_set &= 1; + check_slopes_and_control(slopes_set, true); load_kf_inline(true); } @@ -462,8 +531,11 @@ void Animation::Loader::keyframe_inline() void Animation::Loader::slopes(float s, float e) { + check_slopes_and_control(true, (!obj.keyframes.empty() && obj.keyframes.back().control)); + start_slope = s; end_slope = e; + slopes_set = 1; } } // namespace GL diff --git a/source/animation.h b/source/animation.h index 7b86eca9..7c277f43 100644 --- a/source/animation.h +++ b/source/animation.h @@ -28,6 +28,7 @@ public: Time::TimeDelta current_time; float start_slope; float end_slope; + int slopes_set; public: Loader(Animation &); @@ -36,6 +37,8 @@ public: void init(); virtual void finish(); + void check_slopes_and_control(bool, bool); + void add_kf(const KeyFrame *, bool, bool); void load_kf(const std::string &, bool); void load_kf_inline(bool); @@ -164,10 +167,11 @@ public: const std::string &get_uniform_name(unsigned) const; void add_keyframe(const Time::TimeDelta &, const KeyFrame &); - void add_keyframe(const Time::TimeDelta &, const KeyFrame &, float); - void add_keyframe(const Time::TimeDelta &, const KeyFrame &, float, float); + DEPRECATED void add_keyframe(const Time::TimeDelta &, const KeyFrame &, float); + DEPRECATED void add_keyframe(const Time::TimeDelta &, const KeyFrame &, float, float); void add_control_keyframe(const KeyFrame &); private: + void add_keyframe(const Time::TimeDelta &, const KeyFrame *, float, float, bool); void add_keyframe(const Time::TimeDelta &, const KeyFrame *, bool, bool); void prepare_keyframe(TimedKeyFrame &); void create_curves();