+#include <msp/strings/format.h>
#include "animatedobject.h"
+#include "object.h"
+#include "programdata.h"
#include "renderer.h"
+#include "technique.h"
namespace Msp {
namespace GL {
AnimatedObject::AnimatedObject(const Object &o):
- ObjectInstance(o)
-{ }
+ ObjectInstance(o),
+ shdata(0)
+{
+ if(const Technique *tech = object.get_technique())
+ {
+ // XXX Should create separate ProgramData for each pass
+ const RenderPass &pass = tech->get_pass(Tag());
+ if(const Program *shprog = pass.get_shader_program())
+ shdata = new ProgramData(*shprog);
+ }
+}
void AnimatedObject::set_matrix(const Matrix &m)
{
matrix = m;
}
+void AnimatedObject::set_pose_matrix(unsigned link, const Matrix &m)
+{
+ if(shdata)
+ shdata->uniform_matrix4(format("pose[%d]", link), m);
+}
+
void AnimatedObject::setup_render(Renderer &renderer, const Tag &) const
{
renderer.matrix_stack() *= matrix;
+ if(shdata)
+ renderer.add_shader_data(shdata);
}
} // namespace GL
{
private:
Matrix matrix;
+ ProgramData *shdata;
public:
AnimatedObject(const Object &);
void set_matrix(const Matrix &);
+ void set_pose_matrix(unsigned, const Matrix &);
virtual void setup_render(Renderer &, const Tag &) const;
};
#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)
{
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();
+ 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");
+
+ return iter->pose_matrices[link].get(time_since_keyframe/iter->delta_t);
+}
+
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);
namespace Msp {
namespace GL {
+class Armature;
class KeyFrame;
class Matrix;
+class Pose;
/**
An Animation is a sequence of KeyFrames combined with timing information. The
Time::TimeDelta delta_t;
RefPtr<const KeyFrame> keyframe;
MatrixInterpolation matrix;
+ std::vector<MatrixInterpolation> pose_matrices;
TimedKeyFrame(const Animation &);
void prepare();
bool is_end() const { return end; }
Matrix get_matrix() const;
+ Matrix get_pose_matrix(unsigned) const;
};
private:
+ const Armature *armature;
KeyFrameList keyframes;
bool looping;
public:
Animation();
+ void set_armature(const Armature &);
+ const Armature *get_armature() const { return armature; }
+
void add_keyframe(const Time::TimeDelta &, const KeyFrame &);
private:
void prepare_keyframe(TimedKeyFrame &);
#include "animatedobject.h"
#include "animationplayer.h"
+#include "armature.h"
using namespace std;
{
i->iterator += dt;
i->object.set_matrix(i->iterator.get_matrix());
+ if(const Armature *armature = i->animation.get_armature())
+ {
+ unsigned max_index = armature->get_max_link_index();
+ for(unsigned j=0; j<max_index; ++j)
+ i->object.set_pose_matrix(j, i->iterator.get_pose_matrix(j));
+ }
if(i->iterator.is_end())
slots.erase(i++);
+#include <msp/datafile/collection.h>
#include "keyframe.h"
+#include "pose.h"
+
+using namespace std;
namespace Msp {
namespace GL {
matrix = m;
}
+void KeyFrame::set_pose(const Pose &p)
+{
+ pose = &p;
+ pose.keep();
+}
+
+
KeyFrame::Loader::Loader(KeyFrame &k):
- DataFile::ObjectLoader<KeyFrame>(k)
+ DataFile::CollectionObjectLoader<KeyFrame>(k, 0)
{
+ init();
+}
+
+KeyFrame::Loader::Loader(KeyFrame &k, Collection &c):
+ DataFile::CollectionObjectLoader<KeyFrame>(k, &c)
+{
+ init();
+}
+
+void KeyFrame::Loader::init()
+{
+ add("pose", &Loader::pose);
+ add("pose", &Loader::pose_inline);
add("position", &Loader::position);
add("rotation", &Loader::rotation);
add("scaling", &Loader::scaling_uniform);
add("scaling", &Loader::scaling);
}
+void KeyFrame::Loader::pose(const string &n)
+{
+ obj.pose = &get_collection().get<Pose>(n);
+ obj.pose.keep();
+}
+
+void KeyFrame::Loader::pose_inline()
+{
+ RefPtr<Pose> p = new Pose;
+ load_sub(*p, get_collection());
+ obj.pose = p;
+}
+
void KeyFrame::Loader::position(float x, float y, float z)
{
obj.matrix.translate(x, y, z);
#ifndef MSP_GL_KEYFRAME_H_
#define MSP_GL_KEYFRAME_H_
+#include <msp/core/refptr.h>
#include <msp/datafile/objectloader.h>
#include "matrix.h"
namespace Msp {
namespace GL {
+class Pose;
+
/**
Keyframes are used to encapsulate object state for animation.
*/
class KeyFrame
{
public:
- class Loader: public DataFile::ObjectLoader<KeyFrame>
+ class Loader: public DataFile::CollectionObjectLoader<KeyFrame>
{
public:
Loader(KeyFrame &);
+ Loader(KeyFrame &, Collection &);
private:
+ void init();
+
+ void pose(const std::string &);
+ void pose_inline();
void position(float, float, float);
void rotation(float, float, float, float);
void scaling_uniform(float);
private:
Matrix matrix;
+ RefPtr<const Pose> pose;
public:
void set_matrix(const Matrix &);
+ void set_pose(const Pose &);
const Matrix &get_matrix() const { return matrix; }
+ const Pose *get_pose() const { return pose.get(); }
};
} // namespace GL