]> git.tdb.fi Git - libs/gl.git/blob - source/animationplayer.cpp
Refactor AnimationPlayer ticking
[libs/gl.git] / source / animationplayer.cpp
1 #include "animatedobject.h"
2 #include "animationplayer.h"
3 #include "armature.h"
4 #include "programdata.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace GL {
10
11 AnimationPlayer::Target &AnimationPlayer::get_slot(AnimatedObject &obj)
12 {
13         ObjectMap::iterator i = objects.find(&obj);
14         if(i!=objects.end())
15                 return i->second;
16
17         return objects.insert(ObjectMap::value_type(&obj, Target(obj))).first->second;
18 }
19
20 void AnimationPlayer::play(AnimatedObject &obj, const Animation &anim)
21 {
22         Target &target = get_slot(obj);
23         target.animations.clear();
24         target.base_matrix = Matrix();
25         target.stacked = false;
26         target.armature = anim.get_armature();
27         target.animations.push_back(PlayingAnimation(anim));
28 }
29
30 void AnimationPlayer::play_stacked(AnimatedObject &obj, const Animation &anim)
31 {
32         Target &target = get_slot(obj);
33         if(target.animations.empty())
34                 target.base_matrix = *obj.get_matrix();
35         // TODO check for incompatible armature
36         target.stacked = true;
37         target.armature = anim.get_armature();
38         target.animations.push_back(PlayingAnimation(anim));
39 }
40
41 unsigned AnimationPlayer::get_n_active_animations(const AnimatedObject &obj) const
42 {
43         ObjectMap::const_iterator i = objects.find(&obj);
44         return (i!=objects.end() ? i->second.animations.size() : 0);
45 }
46
47 void AnimationPlayer::stop(AnimatedObject &obj)
48 {
49         objects.erase(&obj);
50 }
51
52 void AnimationPlayer::stop(AnimatedObject &obj, const Animation &anim)
53 {
54         ObjectMap::iterator i = objects.find(&obj);
55         if(i==objects.end())
56                 return;
57
58         for(vector<PlayingAnimation>::iterator j=i->second.animations.begin(); j!=i->second.animations.end(); ++j)
59                 if(j->animation==&anim)
60                 {
61                         i->second.animations.erase(j);
62                         break;
63                 }
64
65         if(i->second.animations.empty())
66                 objects.erase(i);
67 }
68
69 void AnimationPlayer::tick(const Time::TimeDelta &dt)
70 {
71         for(ObjectMap::iterator i=objects.begin(); i!=objects.end(); )
72         {
73                 if(i->second.stacked)
74                         tick_stacked(i->second, dt);
75                 else
76                         tick_single(i->second, dt);
77
78                 if(i->second.animations.empty())
79                         objects.erase(i++);
80                 else
81                         ++i;
82         }
83 }
84
85 void AnimationPlayer::tick_single(Target &target, const Time::TimeDelta &dt)
86 {
87         PlayingAnimation &anim = target.animations.front();
88         anim.iterator += dt;
89         target.object.set_matrix(anim.iterator.get_matrix());
90
91         unsigned n_uniforms = anim.animation->get_n_uniforms();
92         for(unsigned i=0; i<n_uniforms; ++i)
93                 set_object_uniform(target.object, anim.animation->get_uniform_name(i), anim.iterator.get_uniform(i));
94
95         if(target.armature)
96         {
97                 unsigned max_index = target.armature->get_max_link_index();
98                 for(unsigned i=0; i<=max_index; ++i)
99                         target.object.set_pose_matrix(i, anim.iterator.get_pose_matrix(i));
100         }
101
102         if(!anim.iterator.is_end())
103                 target.animations.clear();
104 }
105
106 void AnimationPlayer::tick_stacked(Target &target, const Time::TimeDelta &dt)
107 {
108         Matrix matrix = target.base_matrix;
109         for(vector<PlayingAnimation>::iterator i=target.animations.begin(); i!=target.animations.end(); ++i)
110         {
111                 i->iterator += dt;
112                 matrix *= i->iterator.get_matrix();
113
114                 unsigned n_uniforms = i->animation->get_n_uniforms();
115                 for(unsigned j=0; j<n_uniforms; ++j)
116                         set_object_uniform(target.object, i->animation->get_uniform_name(j), i->iterator.get_uniform(j));
117         }
118         target.object.set_matrix(matrix);
119
120         if(target.armature)
121         {
122                 unsigned max_index = target.armature->get_max_link_index();
123                 for(unsigned i=0; i<=max_index; ++i)
124                 {
125                         matrix = Matrix();
126                         /* XXX This is in all likelihood incorrect.  The stacking should be
127                         performed on local matrices. */
128                         for(vector<PlayingAnimation>::iterator j=target.animations.begin(); j!=target.animations.end(); ++j)
129                                 if(j->animation->get_armature())
130                                         matrix *= j->iterator.get_pose_matrix(i);
131                         target.object.set_pose_matrix(i, matrix);
132                 }
133         }
134
135         for(vector<PlayingAnimation>::iterator i=target.animations.begin(); i!=target.animations.end(); )
136         {
137                 if(i->iterator.is_end())
138                         i = target.animations.erase(i);
139                 else
140                         ++i;
141         }
142
143         if(target.animations.empty())
144                 target.stacked = false;
145 }
146
147 void AnimationPlayer::set_object_uniform(AnimatedObject &obj, const string &name, const KeyFrame::AnimatedUniform &uni)
148 {
149         ProgramData &shdata = obj.get_shader_data();
150
151         if(uni.size==1)
152                 shdata.uniform(name, uni.values[0]);
153         else if(uni.size==2)
154                 shdata.uniform2(name, uni.values);
155         else if(uni.size==2)
156                 shdata.uniform3(name, uni.values);
157         else if(uni.size==4)
158                 shdata.uniform4(name, uni.values);
159 }
160
161
162 AnimationPlayer::Target::Target(AnimatedObject &o):
163         object(o),
164         armature(0),
165         stacked(false)
166 { }
167
168
169 AnimationPlayer::PlayingAnimation::PlayingAnimation(const Animation &a):
170         animation(&a),
171         iterator(*animation)
172 { }
173
174 } // namespace GL
175 } // namespace Msp