#include <msp/datafile/collection.h>
#include <msp/time/units.h>
#include "animation.h"
+#include "armature.h"
#include "keyframe.h"
+#include "pose.h"
using namespace std;
-#include <msp/io/print.h>
-
namespace Msp {
namespace GL {
Animation::Animation():
+ armature(0),
looping(false)
{ }
+void Animation::set_armature(const Armature &a)
+{
+ armature = &a;
+}
+
void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf)
{
if(!keyframes.empty() && t<keyframes.back().time)
keyframes.push_back(tkf);
}
+void Animation::set_looping(bool l)
+{
+ looping = l;
+}
+
void Animation::prepare_keyframe(TimedKeyFrame &tkf)
{
tkf.prev = (keyframes.empty() ? 0 : &keyframes.back());
return;
tkf.prepare();
-
}
{
delta_t = time-prev->time;
matrix = MatrixInterpolation(prev->keyframe->get_matrix(), keyframe->get_matrix());
+ if(animation.armature)
+ {
+ unsigned max_index = animation.armature->get_max_link_index();
+ pose_matrices.resize(max_index+1);
+ const Pose *pose1 = prev->keyframe->get_pose();
+ const Pose *pose2 = keyframe->get_pose();
+ static Matrix identity;
+ for(unsigned i=0; i<=max_index; ++i)
+ {
+ const Matrix &matrix1 = (pose1 ? pose1->get_link_matrix(i) : identity);
+ const Matrix &matrix2 = (pose2 ? pose2->get_link_matrix(i) : identity);
+ pose_matrices[i] = MatrixInterpolation(matrix1, matrix2);
+ }
+ }
}
return iter->matrix.get(time_since_keyframe/iter->delta_t);
}
+Matrix Animation::Iterator::get_pose_matrix(unsigned link) const
+{
+ if(!animation.armature)
+ throw logic_error("Animation::Iterator::get_pose_matrix");
+ if(link>animation.armature->get_max_link_index())
+ throw out_of_range("Animation::Iterator::get_pose_matrix");
+
+ if(!iter->prev)
+ {
+ if(const Pose *pose = iter->keyframe->get_pose())
+ return pose->get_link_matrix(link);
+ else
+ return Matrix();
+ }
+
+ // We must redo the base point correction since interpolation throws if off
+ Matrix result = iter->pose_matrices[link].get(time_since_keyframe/iter->delta_t);
+ const Vector3 &base = animation.armature->get_link(link).get_base();
+ Vector3 new_base = result*base;
+ result = Matrix::translation(base.x-new_base.x, base.y-new_base.y, base.z-new_base.z)*result;
+ return result;
+}
+
Animation::Loader::Loader(Animation &a):
DataFile::CollectionObjectLoader<Animation>(a, 0)
void Animation::Loader::init()
{
+ add("armature", &Animation::armature);
add("interval", &Loader::interval);
add("keyframe", &Loader::keyframe);
add("keyframe", &Loader::keyframe_inline);
void Animation::Loader::keyframe_inline()
{
RefPtr<KeyFrame> kf = new KeyFrame;
- load_sub(*kf);
+ if(coll)
+ load_sub(*kf, get_collection());
+ else
+ load_sub(*kf);
TimedKeyFrame tkf(obj);
tkf.time = current_time;