}
void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf)
+{
+ RefPtr<const KeyFrame> kfr(&kf);
+ kfr.keep();
+ add_keyframe(t, kfr);
+}
+
+void Animation::add_keyframe(const Time::TimeDelta &t, const RefPtr<const KeyFrame> &kf)
{
if(!keyframes.empty() && t<keyframes.back().time)
throw invalid_argument("Animation::add_keyframe");
- TimedKeyFrame tkf(*this);
+ bool realloc = (keyframes.size()>=keyframes.capacity());
+
+ keyframes.push_back(TimedKeyFrame());
+ TimedKeyFrame &tkf = keyframes.back();
tkf.time = t;
- tkf.keyframe = &kf;
- tkf.keyframe.keep();
+ tkf.keyframe = kf;
+
+ if(realloc)
+ {
+ for(unsigned i=1; i<keyframes.size(); ++i)
+ keyframes[i].prev = &keyframes[i-1];
+ }
+ else if(keyframes.size()>1)
+ tkf.prev = &tkf-1;
+
prepare_keyframe(tkf);
- keyframes.push_back(tkf);
}
void Animation::set_looping(bool l)
void Animation::prepare_keyframe(TimedKeyFrame &tkf)
{
- tkf.prev = (keyframes.empty() ? 0 : &keyframes.back());
-
const KeyFrame::UniformMap &kf_uniforms = tkf.keyframe->get_uniforms();
for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i)
{
uniforms.push_back(UniformInfo(i->first, i->second.size));
}
- tkf.prepare();
+ tkf.prepare(*this);
}
}
-Animation::TimedKeyFrame::TimedKeyFrame(const Animation &a):
- animation(a),
+Animation::TimedKeyFrame::TimedKeyFrame():
prev(0)
{ }
-void Animation::TimedKeyFrame::prepare()
+void Animation::TimedKeyFrame::prepare(const Animation &animation)
{
const KeyFrame::UniformMap &kf_uniforms = keyframe->get_uniforms();
for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i)
Animation::Iterator::Iterator(const Animation &a):
- animation(a),
- iter(animation.keyframes.begin()),
+ animation(&a),
+ iter(animation->keyframes.begin()),
end(false)
{ }
time_since_keyframe += t;
while(time_since_keyframe>iter->delta_t)
{
- KeyFrameList::const_iterator next = iter;
+ vector<TimedKeyFrame>::const_iterator next = iter;
++next;
- if(next==animation.keyframes.end())
+ if(next==animation->keyframes.end())
{
- if(animation.looping)
- next = animation.keyframes.begin();
+ if(animation->looping)
+ next = animation->keyframes.begin();
else
{
end = true;
if(iter->uniforms.size()>i)
return iter->uniforms[i];
else
- return KeyFrame::AnimatedUniform(animation.uniforms[i].size, 0.0f);
+ return KeyFrame::AnimatedUniform(animation->uniforms[i].size, 0.0f);
}
- unsigned size = animation.uniforms[i].size;
+ 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)
Matrix Animation::Iterator::get_pose_matrix(unsigned link) const
{
- if(!animation.armature)
+ if(!animation->armature)
throw invalid_operation("Animation::Iterator::get_pose_matrix");
- if(link>animation.armature->get_max_link_index())
+ if(link>animation->armature->get_max_link_index())
throw out_of_range("Animation::Iterator::get_pose_matrix");
if(!iter->prev)
// We must redo the base point correction since interpolation throws if off
// XXX This should probably be done on local matrices
Matrix result = iter->pose_matrices[link].get(time_since_keyframe/iter->delta_t);
- const Vector3 &base = animation.armature->get_link(link).get_base();
+ const Vector3 &base = animation->armature->get_link(link).get_base();
Vector3 new_base = result*base;
result = Matrix::translation(base-new_base)*result;
return result;
else
load_sub(*kf);
- TimedKeyFrame tkf(obj);
- tkf.time = current_time;
- tkf.keyframe = kf;
- obj.prepare_keyframe(tkf);
- obj.keyframes.push_back(tkf);
+ obj.add_keyframe(current_time, kf);
}
void Animation::Loader::interval(float t)