]> git.tdb.fi Git - libs/gl.git/blob - source/animationplayer.cpp
Allow direct access to AnimatedObject's ProgramData
[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::ObjectSlot &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, ObjectSlot(obj))).first->second;
18 }
19
20 void AnimationPlayer::play(AnimatedObject &obj, const Animation &anim)
21 {
22         ObjectSlot &obj_slot = get_slot(obj);
23         obj_slot.animations.clear();
24         obj_slot.base_matrix = Matrix();
25         obj_slot.stacked = false;
26         obj_slot.armature = anim.get_armature();
27         obj_slot.animations.push_back(AnimationSlot(anim));
28 }
29
30 void AnimationPlayer::play_stacked(AnimatedObject &obj, const Animation &anim)
31 {
32         ObjectSlot &obj_slot = get_slot(obj);
33         if(obj_slot.animations.empty())
34                 obj_slot.base_matrix = *obj.get_matrix();
35         // TODO check for incompatible armature
36         obj_slot.stacked = true;
37         obj_slot.armature = anim.get_armature();
38         obj_slot.animations.push_back(AnimationSlot(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(AnimationList::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                 bool keep = false;
74                 if(i->second.stacked)
75                         keep = tick_stacked(i->second, dt);
76                 else
77                         keep = tick_single(i->second, dt);
78
79                 if(!keep)
80                         objects.erase(i++);
81                 else
82                         ++i;
83         }
84 }
85
86 bool AnimationPlayer::tick_single(ObjectSlot &slot, const Time::TimeDelta &dt)
87 {
88         AnimatedObject &obj = slot.object;
89         AnimationSlot &anim = slot.animations.front();
90         anim.iterator += dt;
91         obj.set_matrix(anim.iterator.get_matrix());
92
93         unsigned n_uniforms = anim.animation.get_n_uniforms();
94         for(unsigned i=0; i<n_uniforms; ++i)
95                 set_object_uniform(obj, anim.animation.get_uniform_name(i), anim.iterator.get_uniform(i));
96
97         if(slot.armature)
98         {
99                 unsigned max_index = slot.armature->get_max_link_index();
100                 for(unsigned i=0; i<=max_index; ++i)
101                         obj.set_pose_matrix(i, anim.iterator.get_pose_matrix(i));
102         }
103
104         return !anim.iterator.is_end();
105 }
106
107 bool AnimationPlayer::tick_stacked(ObjectSlot &slot, const Time::TimeDelta &dt)
108 {
109         Matrix matrix = slot.base_matrix;
110         for(AnimationList::iterator i=slot.animations.begin(); i!=slot.animations.end(); ++i)
111         {
112                 i->iterator += dt;
113                 matrix *= i->iterator.get_matrix();
114
115                 unsigned n_uniforms = i->animation.get_n_uniforms();
116                 for(unsigned j=0; j<n_uniforms; ++j)
117                         set_object_uniform(slot.object, i->animation.get_uniform_name(j), i->iterator.get_uniform(j));
118         }
119         slot.object.set_matrix(matrix);
120
121         if(slot.armature)
122         {
123                 unsigned max_index = slot.armature->get_max_link_index();
124                 for(unsigned i=0; i<=max_index; ++i)
125                 {
126                         matrix = Matrix();
127                         /* XXX This is in all likelihood incorrect.  The stacking should be
128                         performed on local matrices. */
129                         for(AnimationList::iterator j=slot.animations.begin(); j!=slot.animations.end(); ++j)
130                                 if(j->animation.get_armature())
131                                         matrix *= j->iterator.get_pose_matrix(i);
132                         slot.object.set_pose_matrix(i, matrix);
133                 }
134         }
135
136         for(AnimationList::iterator i=slot.animations.begin(); i!=slot.animations.end(); )
137         {
138                 if(i->iterator.is_end())
139                         slot.animations.erase(i++);
140                 else
141                         ++i;
142         }
143
144         return !slot.animations.empty();
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::ObjectSlot::ObjectSlot(AnimatedObject &o):
163         object(o),
164         armature(0),
165         stacked(false)
166 { }
167
168
169 AnimationPlayer::AnimationSlot::AnimationSlot(const Animation &a):
170         animation(a),
171         iterator(animation)
172 { }
173
174 } // namespace GL
175 } // namespace Msp