}
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");
keyframes.push_back(TimedKeyFrame());
TimedKeyFrame &tkf = keyframes.back();
tkf.time = t;
+ tkf.start_slope = ss;
+ tkf.end_slope = es;
tkf.keyframe = kf;
if(realloc)
Animation::TimedKeyFrame::TimedKeyFrame():
- prev(0)
+ prev(0),
+ start_slope(1),
+ end_slope(1)
{ }
void Animation::TimedKeyFrame::prepare(const Animation &animation)
animation(&a),
iter(animation->keyframes.begin()),
event_iter(animation->events.begin()),
+ x(0),
end(false)
{ }
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;
}
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
}
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;
}
// 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;
void Animation::Loader::init()
{
+ start_slope = 1;
+ end_slope = 1;
add("armature", &Animation::armature);
add("event", &Loader::event);
add("event", &Loader::event1i);
add("keyframe", &Loader::keyframe);
add("keyframe", &Loader::keyframe_inline);
add("looping", &Animation::looping);
+ add("slopes", &Loader::slopes);
}
void Animation::Loader::event(const string &n)
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()
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
{
private:
Time::TimeDelta current_time;
+ float start_slope;
+ float end_slope;
public:
Loader(Animation &);
void interval(float);
void keyframe(const std::string &);
void keyframe_inline();
+ void slopes(float, float);
};
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;
std::vector<TimedKeyFrame>::const_iterator iter;
std::vector<Event>::const_iterator event_iter;
Time::TimeDelta time_since_keyframe;
+ float x;
bool end;
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());