]> git.tdb.fi Git - libs/gl.git/blobdiff - source/animation.cpp
Fix axis interpolation to work with scaling
[libs/gl.git] / source / animation.cpp
index e7174adc1bdab351a9799edb9af197d1b840c25f..8135cb5995a406e5f9b722f5ca242b3c60eecb96 100644 (file)
@@ -3,6 +3,7 @@
 #include <msp/time/units.h>
 #include "animation.h"
 #include "armature.h"
+#include "error.h"
 #include "keyframe.h"
 #include "pose.h"
 
@@ -46,7 +47,6 @@ void Animation::prepare_keyframe(TimedKeyFrame &tkf)
                return;
 
        tkf.prepare();
-
 }
 
 
@@ -59,18 +59,17 @@ Animation::AxisInterpolation::AxisInterpolation(const double *axis1, const doubl
 {
        // Compute a normalized vector halfway between the two endpoints
        double half[3];
-       double len = 0;
+       double a1_len = 0;
+       double h_len = 0;
        for(unsigned i=0; i<3; ++i)
        {
                half[i] = (axis1[i]+axis2[i])/2;
-               len += half[i]*half[i];
+               a1_len += axis1[i]*axis1[i];
+               h_len += half[i]*half[i];
        }
-       len = sqrt(len);
-       for(unsigned i=0; i<3; ++i)
-               half[i] /= len;
 
        // Compute correction factors for smooth interpolation
-       double cos_half = axis1[0]*half[0]+axis1[1]*half[1]+axis1[2]*half[2];
+       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);
        slope = (angle ? angle/tan(angle) : 1);
        scale = cos_half;
@@ -153,7 +152,7 @@ void Animation::TimedKeyFrame::prepare()
                pose_matrices.resize(max_index+1);
                const Pose *pose1 = prev->keyframe->get_pose();
                const Pose *pose2 = keyframe->get_pose();
-               Matrix identity;
+               static Matrix identity;
                for(unsigned i=0; i<=max_index; ++i)
                {
                        const Matrix &matrix1 = (pose1 ? pose1->get_link_matrix(i) : identity);
@@ -207,11 +206,24 @@ Matrix Animation::Iterator::get_matrix() const
 Matrix Animation::Iterator::get_pose_matrix(unsigned link) const
 {
        if(!animation.armature)
-               throw logic_error("Animation::Iterator::get_pose_matrix");
+               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");
 
-       return iter->pose_matrices[link].get(time_since_keyframe/iter->delta_t);
+       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;
 }
 
 
@@ -244,7 +256,10 @@ void Animation::Loader::keyframe(const string &n)
 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;