X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fanimation.cpp;h=b1d639e7c957dbffb3ce73f43256be5e0ba52c8a;hb=fa5b232a16e11d7950e80764497f0167ec9e3b41;hp=53543d1b89b8426f576305604c046651cea156a7;hpb=1eed7ffeb576674535661a09d298cff62f2cf96a;p=libs%2Fgl.git diff --git a/source/animation.cpp b/source/animation.cpp index 53543d1b..b1d639e7 100644 --- a/source/animation.cpp +++ b/source/animation.cpp @@ -2,19 +2,30 @@ #include #include #include "animation.h" +#include "armature.h" +#include "error.h" #include "keyframe.h" +#include "pose.h" using namespace std; -#include - namespace Msp { namespace GL { Animation::Animation(): + armature(0), looping(false) { } +// Avoid synthesizing ~RefPtr in files including animation.h +Animation::~Animation() +{ } + +void Animation::set_armature(const Armature &a) +{ + armature = &a; +} + void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf) { if(!keyframes.empty() && tdata(); - const double *m2_data = matrix2->data(); + const float *m1_data = matrix1->data(); + const float *m2_data = matrix2->data(); for(unsigned i=0; i<3; ++i) axes[i] = AxisInterpolation(m1_data+i*4, m2_data+i*4); } @@ -85,12 +99,12 @@ Matrix Animation::MatrixInterpolation::get(float t) const { float u = t*2.0f-1.0f; - double matrix[16]; + float matrix[16]; for(unsigned i=0; i<4; ++i) { - const double *m1_col = matrix1->data()+i*4; - const double *m2_col = matrix2->data()+i*4; - double *out_col = matrix+i*4; + const float *m1_col = matrix1->data()+i*4; + const float *m2_col = matrix2->data()+i*4; + float *out_col = matrix+i*4; if(i<3) { @@ -136,6 +150,20 @@ void Animation::TimedKeyFrame::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); + } + } } @@ -179,6 +207,30 @@ Matrix Animation::Iterator::get_matrix() const return iter->matrix.get(time_since_keyframe/iter->delta_t); } +Matrix Animation::Iterator::get_pose_matrix(unsigned link) const +{ + if(!animation.armature) + throw invalid_operation("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 + // 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(); + Vector3 new_base = result*base; + result = Matrix::translation(base-new_base)*result; + return result; +} + Animation::Loader::Loader(Animation &a): DataFile::CollectionObjectLoader(a, 0) @@ -194,6 +246,7 @@ Animation::Loader::Loader(Animation &a, Collection &c): void Animation::Loader::init() { + add("armature", &Animation::armature); add("interval", &Loader::interval); add("keyframe", &Loader::keyframe); add("keyframe", &Loader::keyframe_inline); @@ -208,7 +261,10 @@ void Animation::Loader::keyframe(const string &n) void Animation::Loader::keyframe_inline() { RefPtr kf = new KeyFrame; - load_sub(*kf); + if(coll) + load_sub(*kf, get_collection()); + else + load_sub(*kf); TimedKeyFrame tkf(obj); tkf.time = current_time;