X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fanimation.cpp;h=c58a33d818f5d588a4ced081d35c1ec56ba2f23c;hp=4be00d73b3299012df11280df62e677f52039852;hb=49f1812b3e5ad73748015df52d0e4dee17246036;hpb=ff85f90d33023d908c534b0bf5d9a65e9fc2cce2 diff --git a/source/animation.cpp b/source/animation.cpp index 4be00d73..c58a33d8 100644 --- a/source/animation.cpp +++ b/source/animation.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include "animation.h" #include "animationeventobserver.h" #include "armature.h" @@ -46,7 +46,10 @@ 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); + RefPtr kfr(&kf); + kfr.keep(); + add_keyframe(t, kfr, false); + create_curves(); } void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float slope) @@ -54,16 +57,25 @@ void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float add_keyframe(t, kf, slope, slope); } -void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float ss, float es) +void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf, float, float) +{ + add_keyframe(t, kf); +} + +void Animation::add_control_keyframe(const KeyFrame &kf) { + if(keyframes.empty()) + throw invalid_operation("Animation::add_control_keyframe"); + RefPtr kfr(&kf); kfr.keep(); - add_keyframe(t, kfr, ss, es); - create_curves(); + add_keyframe(keyframes.back().time, kfr, true); } -void Animation::add_keyframe(const Time::TimeDelta &t, const RefPtr &kf, float ss, float es) +void Animation::add_keyframe(const Time::TimeDelta &t, const RefPtr &kf, bool c) { + if(c && keyframes.empty()) + throw invalid_argument("Animation::add_keyframe"); if(keyframes.empty() && t!=Time::zero) throw invalid_argument("Animation::add_keyframe"); if(!keyframes.empty() && t::Knot Knot; vector knots; + unsigned n_control = 0; for(vector::const_iterator i=keyframes.begin(); i!=keyframes.end(); ++i) { + if(i->control && knots.empty()) + continue; + typename Interpolate::SplineValue::Type value; if(extract(*i->keyframe, value)) - knots.push_back(Knot(i->time/Time::sec, value)); + { + float x = i->time/Time::sec; + if(i->control) + { + ++n_control; + if(n_control>2) + throw logic_error("too many control keyframes"); + } + else + { + if(n_control==1) + { + typename Knot::Value cv = knots.back().y; + knots.back().y = (knots[knots.size()-2].y+cv*2.0f)/3.0f; + knots.push_back(Knot(x, (value+cv*2.0f)/3.0f)); + } + else if(n_control==0 && !knots.empty()) + { + typename Knot::Value prev = knots.back().y; + knots.push_back(Knot(knots.back().x, (prev*2.0f+value)/3.0f)); + knots.push_back(Knot(x, (prev+value*2.0f)/3.0f)); + } + n_control = 0; + } + knots.push_back(Knot(x, value)); + } } + + while(n_control--) + knots.pop_back(); curves.push_back(new ValueCurve(target, knots)); } @@ -191,7 +234,7 @@ Animation::Curve::Curve(CurveTarget t): template Animation::ValueCurve::ValueCurve(CurveTarget t, const vector &k): Curve(t), - spline(Interpolate::LinearSpline(k)) + spline(Interpolate::BezierSpline(k)) { } template @@ -327,6 +370,8 @@ void Animation::Loader::init() start_slope = 1; end_slope = 1; add("armature", &Animation::armature); + add("control_keyframe", &Loader::control_keyframe); + add("control_keyframe", &Loader::control_keyframe_inline); add("event", &Loader::event); add("event", &Loader::event1i); add("event", &Loader::event1f); @@ -345,6 +390,32 @@ void Animation::Loader::finish() obj.create_curves(); } +void Animation::Loader::load_kf(const string &n, bool c) +{ + obj.add_keyframe(current_time, get_collection().get(n), c); +} + +void Animation::Loader::load_kf_inline(bool c) +{ + RefPtr kf = new KeyFrame; + if(coll) + load_sub(*kf, get_collection()); + else + load_sub(*kf); + + obj.add_keyframe(current_time, kf, c); +} + +void Animation::Loader::control_keyframe(const string &n) +{ + load_kf(n, true); +} + +void Animation::Loader::control_keyframe_inline() +{ + load_kf_inline(true); +} + void Animation::Loader::event(const string &n) { obj.add_event(current_time, n); @@ -382,22 +453,12 @@ void Animation::Loader::interval(float t) void Animation::Loader::keyframe(const string &n) { - obj.add_keyframe(current_time, get_collection().get(n), start_slope, end_slope); - start_slope = end_slope; - end_slope = 1; + load_kf(n, false); } void Animation::Loader::keyframe_inline() { - RefPtr kf = new KeyFrame; - if(coll) - load_sub(*kf, get_collection()); - else - load_sub(*kf); - - obj.add_keyframe(current_time, kf, start_slope, end_slope); - start_slope = end_slope; - end_slope = 1; + load_kf_inline(false); } void Animation::Loader::slopes(float s, float e)