]> git.tdb.fi Git - libs/gl.git/commitdiff
Support slopes in keyframe interpolation
authorMikko Rasa <tdb@tdb.fi>
Sun, 1 Jul 2018 22:01:27 +0000 (01:01 +0300)
committerMikko Rasa <tdb@tdb.fi>
Sun, 1 Jul 2018 22:01:27 +0000 (01:01 +0300)
source/animation.cpp
source/animation.h

index c7e23b8e3b26f8bda1332cafcf3efb3d3680845b..f0e2630a502f6f43339ef7cbd1be8bcbe3aed7a3 100644 (file)
@@ -43,13 +43,23 @@ const string &Animation::get_uniform_name(unsigned i) const
 }
 
 void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf)
+{
+       add_keyframe(t, kf, 1.0f, 1.0f);
+}
+
+void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float slope)
+{
+       add_keyframe(t, kf, slope, slope);
+}
+
+void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float ss, float es)
 {
        RefPtr<const KeyFrame> kfr(&kf);
        kfr.keep();
-       add_keyframe(t, kfr);
+       add_keyframe(t, kfr, ss, es);
 }
 
-void Animation::add_keyframe(const Time::TimeDelta &t, const RefPtr<const KeyFrame> &kf)
+void Animation::add_keyframe(const Time::TimeDelta &t, const RefPtr<const KeyFrame> &kf, float ss, float es)
 {
        if(!keyframes.empty() && t<keyframes.back().time)
                throw invalid_argument("Animation::add_keyframe");
@@ -59,6 +69,8 @@ void Animation::add_keyframe(const Time::TimeDelta &t, const RefPtr<const KeyFra
        keyframes.push_back(TimedKeyFrame());
        TimedKeyFrame &tkf = keyframes.back();
        tkf.time = t;
+       tkf.start_slope = ss;
+       tkf.end_slope = es;
        tkf.keyframe = kf;
 
        if(realloc)
@@ -197,7 +209,9 @@ Matrix Animation::MatrixInterpolation::get(float t) const
 
 
 Animation::TimedKeyFrame::TimedKeyFrame():
-       prev(0)
+       prev(0),
+       start_slope(1),
+       end_slope(1)
 { }
 
 void Animation::TimedKeyFrame::prepare(const Animation &animation)
@@ -246,6 +260,7 @@ Animation::Iterator::Iterator(const Animation &a):
        animation(&a),
        iter(animation->keyframes.begin()),
        event_iter(animation->events.begin()),
+       x(0),
        end(false)
 { }
 
@@ -272,6 +287,9 @@ Animation::Iterator &Animation::Iterator::operator+=(const Time::TimeDelta &t)
                iter = next;
        }
 
+       x = time_since_keyframe/iter->delta_t;
+       x += (iter->start_slope-1)*((x-2)*x+1)*x + (1-iter->end_slope)*(1-x)*x*x;
+
        return *this;
 }
 
@@ -298,7 +316,7 @@ Matrix Animation::Iterator::get_matrix() const
        if(!iter->prev)
                return iter->keyframe->get_matrix();
 
-       return iter->matrix.get(time_since_keyframe/iter->delta_t);
+       return iter->matrix.get(x);
 }
 
 KeyFrame::AnimatedUniform Animation::Iterator::get_uniform(unsigned i) const
@@ -312,10 +330,9 @@ KeyFrame::AnimatedUniform Animation::Iterator::get_uniform(unsigned i) const
        }
 
        unsigned size = animation->uniforms[i].size;
-       float t = time_since_keyframe/iter->delta_t;
        KeyFrame::AnimatedUniform result(size, 0.0f);
        for(unsigned j=0; j<size; ++j)
-               result.values[j] = iter->prev->uniforms[i].values[j]*(1-t)+iter->uniforms[i].values[j]*t;
+               result.values[j] = iter->prev->uniforms[i].values[j]*(1-x)+iter->uniforms[i].values[j]*x;
        return result;
 }
 
@@ -336,7 +353,7 @@ Matrix Animation::Iterator::get_pose_matrix(unsigned link) const
 
        // We must redo the base point correction since interpolation throws it off
        // XXX This should probably be done on local matrices
-       Matrix result = iter->pose_matrices[link].get(time_since_keyframe/iter->delta_t);
+       Matrix result = iter->pose_matrices[link].get(x);
        const Vector3 &base = animation->armature->get_link(link).get_base();
        Vector3 new_base = result*base;
        result = Matrix::translation(base-new_base)*result;
@@ -358,6 +375,8 @@ Animation::Loader::Loader(Animation &a, Collection &c):
 
 void Animation::Loader::init()
 {
+       start_slope = 1;
+       end_slope = 1;
        add("armature", &Animation::armature);
        add("event", &Loader::event);
        add("event", &Loader::event1i);
@@ -369,6 +388,7 @@ void Animation::Loader::init()
        add("keyframe", &Loader::keyframe);
        add("keyframe", &Loader::keyframe_inline);
        add("looping", &Animation::looping);
+       add("slopes", &Loader::slopes);
 }
 
 void Animation::Loader::event(const string &n)
@@ -408,7 +428,9 @@ void Animation::Loader::interval(float t)
 
 void Animation::Loader::keyframe(const string &n)
 {
-       obj.add_keyframe(current_time, get_collection().get<KeyFrame>(n));
+       obj.add_keyframe(current_time, get_collection().get<KeyFrame>(n), start_slope, end_slope);
+       start_slope = end_slope;
+       end_slope = 1;
 }
 
 void Animation::Loader::keyframe_inline()
@@ -419,7 +441,15 @@ void Animation::Loader::keyframe_inline()
        else
                load_sub(*kf);
 
-       obj.add_keyframe(current_time, kf);
+       obj.add_keyframe(current_time, kf, start_slope, end_slope);
+       start_slope = end_slope;
+       end_slope = 1;
+}
+
+void Animation::Loader::slopes(float s, float e)
+{
+       start_slope = s;
+       end_slope = e;
 }
 
 } // namespace GL
index 3404f45bd9f8c446f5110844e2cae7114fffe6ea..e3fb79ee3aff2bdcf019e79c03628066aed605c2 100644 (file)
@@ -25,6 +25,8 @@ public:
        {
        private:
                Time::TimeDelta current_time;
+               float start_slope;
+               float end_slope;
 
        public:
                Loader(Animation &);
@@ -41,6 +43,7 @@ public:
                void interval(float);
                void keyframe(const std::string &);
                void keyframe_inline();
+               void slopes(float, float);
        };
 
 private:
@@ -70,6 +73,8 @@ private:
                const TimedKeyFrame *prev;
                Time::TimeDelta time;
                Time::TimeDelta delta_t;
+               float start_slope;
+               float end_slope;
                RefPtr<const KeyFrame> keyframe;
                MatrixInterpolation matrix;
                std::vector<KeyFrame::AnimatedUniform> uniforms;
@@ -102,6 +107,7 @@ public:
                std::vector<TimedKeyFrame>::const_iterator iter;
                std::vector<Event>::const_iterator event_iter;
                Time::TimeDelta time_since_keyframe;
+               float x;
                bool end;
 
        public:
@@ -135,8 +141,10 @@ 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);
 private:
-       void add_keyframe(const Time::TimeDelta &, const RefPtr<const KeyFrame> &);
+       void add_keyframe(const Time::TimeDelta &, const RefPtr<const KeyFrame> &, float, float);
        void prepare_keyframe(TimedKeyFrame &);
 public:
        void add_event(const Time::TimeDelta &, const std::string &, const Variant & = Variant());