#include <cmath>
+#include <msp/core/maputils.h>
#include <msp/datafile/collection.h>
#include <msp/time/units.h>
#include "animation.h"
#include "armature.h"
#include "error.h"
-#include "keyframe.h"
#include "pose.h"
using namespace std;
armature = &a;
}
+unsigned Animation::get_slot_for_uniform(const string &n) const
+{
+ for(unsigned i=0; i<uniforms.size(); ++i)
+ if(uniforms[i].name==n)
+ return i;
+ throw key_error(n);
+}
+
+const string &Animation::get_uniform_name(unsigned i) const
+{
+ if(i>=uniforms.size())
+ throw out_of_range("Animation::get_uniform_name");
+ return uniforms[i].name;
+}
+
void Animation::add_keyframe(const Time::TimeDelta &t, const KeyFrame &kf)
{
if(!keyframes.empty() && t<keyframes.back().time)
void Animation::prepare_keyframe(TimedKeyFrame &tkf)
{
tkf.prev = (keyframes.empty() ? 0 : &keyframes.back());
- if(!tkf.prev)
- return;
+
+ const KeyFrame::UniformMap &kf_uniforms = tkf.keyframe->get_uniforms();
+ for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i)
+ {
+ bool found = false;
+ for(unsigned j=0; (!found && j<uniforms.size()); ++j)
+ if(uniforms[j].name==i->first)
+ {
+ if(uniforms[j].size!=i->second.size)
+ throw invalid_operation("Animation::prepare_keyframe");
+ found = true;
+ }
+
+ if(!found)
+ uniforms.push_back(UniformInfo(i->first, i->second.size));
+ }
tkf.prepare();
}
scale(0)
{ }
-Animation::AxisInterpolation::AxisInterpolation(const double *axis1, const double *axis2)
+Animation::AxisInterpolation::AxisInterpolation(const float *axis1, const float *axis2)
{
// Compute a normalized vector halfway between the two endpoints
- double half[3];
- double a1_len = 0;
- double h_len = 0;
+ float half[3];
+ float a1_len = 0;
+ float h_len = 0;
for(unsigned i=0; i<3; ++i)
{
half[i] = (axis1[i]+axis2[i])/2;
}
// Compute correction factors for smooth interpolation
- double cos_half = (axis1[0]*half[0]+axis1[1]*half[1]+axis1[2]*half[2])/sqrt(a1_len*h_len);
- double angle = acos(cos_half);
+ float cos_half = (axis1[0]*half[0]+axis1[1]*half[1]+axis1[2]*half[2])/sqrt(a1_len*h_len);
+ float angle = acos(cos_half);
slope = (angle ? angle/tan(angle) : 1);
scale = cos_half;
}
matrix1(&m1),
matrix2(&m2)
{
- const double *m1_data = matrix1->data();
- 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);
}
{
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)
{
void Animation::TimedKeyFrame::prepare()
{
+ const KeyFrame::UniformMap &kf_uniforms = keyframe->get_uniforms();
+ for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i)
+ {
+ unsigned j = animation.get_slot_for_uniform(i->first);
+ uniforms.reserve(j+1);
+ for(unsigned k=uniforms.size(); k<=j; ++k)
+ uniforms.push_back(KeyFrame::AnimatedUniform(animation.uniforms[k].size, 0.0f));
+
+ uniforms[j] = i->second;
+ }
+
+ if(!prev)
+ return;
+
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();
}
+Animation::UniformInfo::UniformInfo(const string &n, unsigned s):
+ name(n),
+ size(s)
+{ }
+
+
Animation::Iterator::Iterator(const Animation &a):
animation(a),
iter(animation.keyframes.begin()),
return iter->matrix.get(time_since_keyframe/iter->delta_t);
}
+KeyFrame::AnimatedUniform Animation::Iterator::get_uniform(unsigned i) const
+{
+ if(!iter->prev)
+ {
+ if(iter->uniforms.size()>i)
+ return iter->uniforms[i];
+ else
+ return KeyFrame::AnimatedUniform(animation.uniforms[i].size, 0.0f);
+ }
+
+ 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;
+ return result;
+}
+
Matrix Animation::Iterator::get_pose_matrix(unsigned link) const
{
if(!animation.armature)