}
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(*this));
+ 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)
{
will be in the range [-1, 1]. */
float w = (axes[i].slope+(1-axes[i].slope)*u*u)*u*0.5f+0.5f;
- /* The interpolate vectors will also be shorter than unit length. At
+ /* The interpolated vectors will also be shorter than unit length. At
the halfway point the length will be equal to the cosine of half the
angle, which was computed earlier. Use a second degree polynomial to
approximate. */
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)