From 3f7c493e13b7108098539078b729cffc095c304b Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 31 Jul 2015 14:21:46 +0300 Subject: [PATCH] Support animation of uniform variables --- source/animatedobject.cpp | 18 ++++++++++ source/animatedobject.h | 2 ++ source/animation.cpp | 74 ++++++++++++++++++++++++++++++++++++-- source/animation.h | 17 ++++++++- source/animationplayer.cpp | 5 +++ source/keyframe.cpp | 47 ++++++++++++++++++++++++ source/keyframe.h | 25 +++++++++++++ 7 files changed, 184 insertions(+), 4 deletions(-) diff --git a/source/animatedobject.cpp b/source/animatedobject.cpp index 8b030978..269665f6 100644 --- a/source/animatedobject.cpp +++ b/source/animatedobject.cpp @@ -1,6 +1,7 @@ #include #include #include "animatedobject.h" +#include "error.h" #include "object.h" #include "programdata.h" #include "renderer.h" @@ -41,6 +42,23 @@ void AnimatedObject::set_pose_matrix(unsigned link, const Matrix &m) } } +void AnimatedObject::set_uniform(const string &name, const KeyFrame::AnimatedUniform &uni) +{ + if(!shdata) + throw invalid_operation("AnimatedObject::set_uniform"); + + if(uni.size==1) + shdata->uniform(name, uni.values[0]); + else if(uni.size==2) + shdata->uniform2(name, uni.values); + else if(uni.size==3) + shdata->uniform3(name, uni.values); + else if(uni.size==4) + shdata->uniform4(name, uni.values); + else + throw invalid_argument("AnimatedObject::set_uniform"); +} + void AnimatedObject::setup_render(Renderer &renderer, const Tag &) const { renderer.transform(matrix); diff --git a/source/animatedobject.h b/source/animatedobject.h index 4782951d..b7f48005 100644 --- a/source/animatedobject.h +++ b/source/animatedobject.h @@ -3,6 +3,7 @@ #include #include +#include "keyframe.h" #include "matrix.h" #include "objectinstance.h" @@ -39,6 +40,7 @@ public: void set_matrix(const Matrix &); void set_pose_matrix(unsigned, const Matrix &); + void set_uniform(const std::string &, const KeyFrame::AnimatedUniform &); virtual const Matrix *get_matrix() const { return &matrix; } diff --git a/source/animation.cpp b/source/animation.cpp index b1d639e7..8f7dea03 100644 --- a/source/animation.cpp +++ b/source/animation.cpp @@ -1,10 +1,10 @@ #include +#include #include #include #include "animation.h" #include "armature.h" #include "error.h" -#include "keyframe.h" #include "pose.h" using namespace std; @@ -26,6 +26,21 @@ void Animation::set_armature(const Armature &a) armature = &a; } +unsigned Animation::get_slot_for_uniform(const string &n) const +{ + for(unsigned i=0; 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() && tget_uniforms(); + for(KeyFrame::UniformMap::const_iterator i=kf_uniforms.begin(); i!=kf_uniforms.end(); ++i) + { + bool found = false; + for(unsigned j=0; (!found && jfirst) + { + 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(); } @@ -148,8 +177,23 @@ Animation::TimedKeyFrame::TimedKeyFrame(const Animation &a): 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(); @@ -167,6 +211,12 @@ void Animation::TimedKeyFrame::prepare() } +Animation::UniformInfo::UniformInfo(const string &n, unsigned s): + name(n), + size(s) +{ } + + Animation::Iterator::Iterator(const Animation &a): animation(a), iter(animation.keyframes.begin()), @@ -207,6 +257,24 @@ Matrix Animation::Iterator::get_matrix() const 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; jprev->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) diff --git a/source/animation.h b/source/animation.h index 63b13f72..1ae571e7 100644 --- a/source/animation.h +++ b/source/animation.h @@ -4,12 +4,12 @@ #include #include #include +#include "keyframe.h" namespace Msp { namespace GL { class Armature; -class KeyFrame; class Matrix; class Pose; @@ -66,6 +66,7 @@ private: Time::TimeDelta delta_t; RefPtr keyframe; MatrixInterpolation matrix; + std::vector uniforms; std::vector pose_matrices; TimedKeyFrame(const Animation &); @@ -74,6 +75,14 @@ private: typedef std::list KeyFrameList; + struct UniformInfo + { + std::string name; + unsigned size; + + UniformInfo(const std::string &, unsigned); + }; + public: class Iterator { @@ -90,6 +99,7 @@ public: bool is_end() const { return end; } Matrix get_matrix() const; + KeyFrame::AnimatedUniform get_uniform(unsigned) const; Matrix get_pose_matrix(unsigned) const; }; @@ -97,6 +107,7 @@ private: const Armature *armature; KeyFrameList keyframes; bool looping; + std::vector uniforms; public: Animation(); @@ -105,6 +116,10 @@ public: void set_armature(const Armature &); const Armature *get_armature() const { return armature; } + unsigned get_n_uniforms() const { return uniforms.size(); } + unsigned get_slot_for_uniform(const std::string &) const; + const std::string &get_uniform_name(unsigned) const; + void add_keyframe(const Time::TimeDelta &, const KeyFrame &); private: void prepare_keyframe(TimedKeyFrame &); diff --git a/source/animationplayer.cpp b/source/animationplayer.cpp index 6148ed00..9db88e78 100644 --- a/source/animationplayer.cpp +++ b/source/animationplayer.cpp @@ -71,6 +71,11 @@ bool AnimationPlayer::tick_single(ObjectSlot &slot, const Time::TimeDelta &dt) AnimationSlot &anim = slot.animations.front(); anim.iterator += dt; obj.set_matrix(anim.iterator.get_matrix()); + + unsigned n_uniforms = anim.animation.get_n_uniforms(); + for(unsigned i=0; iget_max_link_index(); diff --git a/source/keyframe.cpp b/source/keyframe.cpp index 8e0d7904..dd4adf16 100644 --- a/source/keyframe.cpp +++ b/source/keyframe.cpp @@ -26,6 +26,16 @@ void KeyFrame::set_pose(const Pose &p) } +KeyFrame::AnimatedUniform::AnimatedUniform(unsigned s, float v0, float v1, float v2, float v3): + size(s) +{ + values[0] = v0; + values[1] = v1; + values[2] = v2; + values[3] = v3; +} + + KeyFrame::Loader::Loader(KeyFrame &k): DataFile::CollectionObjectLoader(k, 0) { @@ -46,6 +56,7 @@ void KeyFrame::Loader::init() add("rotation", &Loader::rotation); add("scaling", &Loader::scaling_uniform); add("scaling", &Loader::scaling); + add("uniforms", &Loader::uniforms); } void KeyFrame::Loader::pose(const string &n) @@ -81,5 +92,41 @@ void KeyFrame::Loader::scaling(float x, float y, float z) obj.matrix.scale(x, y, z); } +void KeyFrame::Loader::uniforms() +{ + UniformsLoader ldr(obj); + load_sub_with(ldr); +} + + +KeyFrame::UniformsLoader::UniformsLoader(KeyFrame &k): + DataFile::ObjectLoader(k) +{ + add("uniform1f", &UniformsLoader::uniform1f); + add("uniform2f", &UniformsLoader::uniform2f); + add("uniform3f", &UniformsLoader::uniform3f); + add("uniform4f", &UniformsLoader::uniform4f); +} + +void KeyFrame::UniformsLoader::uniform1f(const string &n, float v) +{ + obj.uniforms.insert(UniformMap::value_type(n, AnimatedUniform(1, v))); +} + +void KeyFrame::UniformsLoader::uniform2f(const string &n, float v0, float v1) +{ + obj.uniforms.insert(UniformMap::value_type(n, AnimatedUniform(2, v0, v1))); +} + +void KeyFrame::UniformsLoader::uniform3f(const string &n, float v0, float v1, float v2) +{ + obj.uniforms.insert(UniformMap::value_type(n, AnimatedUniform(3, v0, v1, v2))); +} + +void KeyFrame::UniformsLoader::uniform4f(const string &n, float v0, float v1, float v2, float v3) +{ + obj.uniforms.insert(UniformMap::value_type(n, AnimatedUniform(4, v0, v1, v2, v3))); +} + } // namespace GL } // namespace Msp diff --git a/source/keyframe.h b/source/keyframe.h index 6a8c5a44..7854a928 100644 --- a/source/keyframe.h +++ b/source/keyframe.h @@ -30,10 +30,34 @@ public: void rotation(float, float, float, float); void scaling_uniform(float); void scaling(float, float, float); + void uniforms(); }; + class UniformsLoader: public DataFile::ObjectLoader + { + public: + UniformsLoader(KeyFrame &); + + private: + void uniform1f(const std::string &, float); + void uniform2f(const std::string &, float, float); + void uniform3f(const std::string &, float, float, float); + void uniform4f(const std::string &, float, float, float, float); + }; + + struct AnimatedUniform + { + unsigned size; + float values[4]; + + AnimatedUniform(unsigned, float, float = 0.0f, float = 0.0f, float = 0.0f); + }; + + typedef std::map UniformMap; + private: Matrix matrix; + UniformMap uniforms; RefPtr pose; public: @@ -43,6 +67,7 @@ public: void set_matrix(const Matrix &); void set_pose(const Pose &); const Matrix &get_matrix() const { return matrix; } + const UniformMap &get_uniforms() const { return uniforms; } const Pose *get_pose() const { return pose.get(); } }; -- 2.43.0