SLProject  4.2.000
A platform independent 3D computer graphics framework for desktop OS, Android, iOS and online in web browsers
SLAnimPlayback.cpp
Go to the documentation of this file.
1 /**
2  * \file SLAnimPlay.cpp
3  * \date Autumn 2014
4  * \remarks Please use clangformat to format the code. See more code style on
5  * https://github.com/cpvrlab/SLProject4/wiki/SLProject-Coding-Style
6  * \authors Marc Wacker, Marcus Hudritsch
7  * \copyright http://opensource.org/licenses/GPL-3.0
8 */
9 
10 #include <SLAnimPlayback.h>
11 #include <SLAnimation.h>
12 
13 //-----------------------------------------------------------------------------
14 /*! Constructor
15  */
17  : _animation(parent),
18  _localTime(0.0f),
19  _weight(weight),
20  _playbackRate(1.0f),
21  _playbackDir(1),
22  _enabled(true),
23  _easing(EC_linear),
24  _linearLocalTime(0.0f),
25  _loopingBehaviour(AL_loop)
26 {
27 }
28 //-----------------------------------------------------------------------------
29 /*! Advances the time of the playback play based on its different easing parameters.
30  */
32 {
33  if (!_enabled)
34  return;
35 
36  if (delta == 0.0f)
37  return;
38 
39  // preserve time before update
40  SLfloat prevTime = _linearLocalTime;
41 
43 
44  // fix invalid inputs
46  {
47  // wrap around on loop, else just stay on last frame
48  switch (_loopingBehaviour)
49  {
50  case AL_once:
52  _enabled = false;
53  break;
54  case AL_loop:
55  _linearLocalTime = 0.0f;
56  break;
57  case AL_pingPong:
58  case AL_pingPongLoop:
60  _playbackDir *= -1;
61  break;
62  }
63  }
64 
65  // fix negative inputs, playback rate could be negative
66  else if (_linearLocalTime < 0.0f)
67  {
68  while (_linearLocalTime < 0.0f)
70 
71  switch (_loopingBehaviour)
72  {
73  case AL_once:
74  _linearLocalTime = 0.0f;
75  _enabled = false;
76  break;
77  case AL_loop: _linearLocalTime = _animation->lengthSec(); break;
78  case AL_pingPong:
79  _linearLocalTime = 0.0f;
80  _enabled = false;
81  break; // at the moment pingPong stops when reaching 0, if we start with a reverse direction this is illogical
82  case AL_pingPongLoop:
83  _linearLocalTime = 0.0f;
84  _playbackDir *= -1;
85  break;
86  }
87  }
88 
89  // don't go any further, nothing's changed
90  if (Utils::abs(_linearLocalTime - prevTime) < 0.0001f)
91  return;
92 
93  // mark the playback as changed
94  _gotChanged = true;
95 
96  // update the final eased local time
98 }
99 //-----------------------------------------------------------------------------
100 /*! Set this playback to be playing forward.
101  */
103 {
104  _enabled = true;
105  _playbackDir = 1;
106 }
107 //-----------------------------------------------------------------------------
108 /*! Set this playback to be playing backward.
109  */
111 {
112  _enabled = true;
113  _playbackDir = -1;
114 }
115 //-----------------------------------------------------------------------------
116 /*! Set this playback to be paused.
117  */
119 {
120  // a paused anmation is an enabled animation that has a 0 direction multiplier
121  _enabled = true;
122  _playbackDir = 0;
123 }
124 //-----------------------------------------------------------------------------
125 /*! Set the local time of this playback to be on the time of the next keyframe.
126  */
128 {
130  localTime(time);
131 }
132 //-----------------------------------------------------------------------------
133 /*! Set the local time of this playback to be on the time of the previous keyframe.
134  */
136 {
138  localTime(time);
139 }
140 //-----------------------------------------------------------------------------
141 /*! Set the local time of this playback to the starting time.
142  */
144 {
145  localTime(0.0f);
146 }
147 //-----------------------------------------------------------------------------
148 /*! Set the local time of this animation to the end time.
149  */
151 {
153 }
154 //-----------------------------------------------------------------------------
155 /*! Setter for the local time parameter. Takes the currently active easing
156 curve into consideration.
157 */
159 {
160  // Set the eased time
161  _localTime = time;
162 
163  // calculate the equivalent linear time from the new eased time
165 
166  // mark changed
167  _gotChanged = true;
168 }
169 //-----------------------------------------------------------------------------
170 //! Applies the easing time curve to the input time.
171 /*! See also the declaration of the SLEasingCurve enumeration for the different
172 easing curve type that are taken from Qt QAnimation and QEasingCurve class.
173 See http://qt-project.org/doc/qt-4.8/qeasingcurve.html#Type-enum
174 */
176 {
177  SLfloat x = time / _animation->lengthSec();
178  SLfloat y = 0.0f;
179 
180  switch (_easing)
181  {
182  case EC_linear: y = x; break;
183 
184  case EC_inQuad: y = pow(x, 2.0f); break;
185  case EC_outQuad: y = -pow(x - 1.0f, 2.0f) + 1.0f; break;
186  case EC_inOutQuad: y = (x < 0.5f) ? 2.0f * pow(x, 2.0f) : -2.0f * pow(x - 1.0f, 2.0f) + 1.0f; break;
187  case EC_outInQuad: y = (x < 0.5f) ? -2.0f * pow(x - 0.5f, 2.0f) + 0.5f : 2.0f * pow(x - 0.5f, 2.0f) + 0.5f; break;
188 
189  case EC_inCubic: y = pow(x, 3.0f); break;
190  case EC_outCubic: y = pow(x - 1.0f, 3.0f) + 1.0f; break;
191  case EC_inOutCubic: y = (x < 0.5f) ? 4.0f * pow(x, 3.0f) : 4.0f * pow(x - 1.0f, 3.0f) + 1.0f; break;
192  case EC_outInCubic: y = 4.0f * pow(x - 0.5f, 3.0f) + 0.5f; break;
193 
194  case EC_inQuart: y = pow(x, 4.0f); break;
195  case EC_outQuart: y = -pow(x - 1.0f, 4.0f) + 1.0f; break;
196  case EC_inOutQuart: y = (x < 0.5f) ? 8.0f * pow(x, 4.0f) : -8.0f * pow(x - 1.0f, 4.0f) + 1.0f; break;
197  case EC_outInQuart: y = (x < 0.5f) ? -8.0f * pow(x - 0.5f, 4.0f) + 0.5f : 8.0f * pow(x - 0.5f, 4.0f) + 0.5f; break;
198 
199  case EC_inQuint: y = pow(x, 5.0f); break;
200  case EC_outQuint: y = pow(x - 1.0f, 5.0f) + 1.0f; break;
201  case EC_inOutQuint: y = (x < 0.5f) ? 16.0f * pow(x, 5.0f) : 16.0f * pow(x - 1.0f, 5.0f) + 1.0f; break;
202  case EC_outInQuint: y = 16.0f * pow(x - 0.5f, 5.0f) + 0.5f; break;
203 
204  case EC_inSine: y = sin(x * Utils::PI * 0.5f - Utils::PI * 0.5f) + 1.0f; break;
205  case EC_outSine: y = sin(x * Utils::PI * 0.5f); break;
206  case EC_inOutSine: y = 0.5f * sin(x * Utils::PI - Utils::PI * 0.5f) + 0.5f; break;
207  case EC_outInSine: y = (x < 0.5f) ? 0.5f * sin(x * Utils::PI) : 0.5f * sin(x * Utils::PI - Utils::PI) + 1.0f; break;
208  }
209 
210  return y * _animation->lengthSec();
211 }
212 //-----------------------------------------------------------------------------
213 /*! Inverse functions for the above easing curve functions.
214  */
216 {
217  SLfloat x = time / _animation->lengthSec();
218  SLfloat y = 0.0f;
219 
220  switch (_easing)
221  {
222  case EC_linear: y = x; break;
223 
224  case EC_inQuad: y = sqrt(x); break;
225  case EC_outQuad: y = 1.0f - sqrt(1.0f - x); break;
226  case EC_inOutQuad: y = (x < 0.5f) ? sqrt(x) / sqrt(2.0f) : 1.0f - sqrt(1.0f - x) / sqrt(2.0f); break;
227  case EC_outInQuad: y = (x < 0.5f) ? 0.5f - 0.25f * sqrt(4.0f - 8.0f * x) : 0.5f + 0.25f * sqrt(8.0f * x - 4.0f); break;
228 
229  case EC_inCubic: y = pow(x, 1.0f / 3.0f); break;
230  case EC_outCubic: y = 1.0f - pow(1.0f - x, 1.0f / 3.0f); break;
231  case EC_inOutCubic: y = (x < 0.5f) ? pow(x, 1.0f / 3.0f) / pow(4.0f, 1.0f / 3.0f) : 1.0f - pow(1.0f - x, 1.0f / 3.0f) / pow(4.0f, 1.0f / 3.0f); break;
232  case EC_outInCubic: y = (x < 0.5f) ? -pow((0.5f - x) / 4.0f, 1.0f / 3.0f) + 0.5f : pow((x - 0.5f) / 4.0f, 1.0f / 3.0f) + 0.5f; break;
233 
234  case EC_inQuart: y = pow(x, 1.0f / 4.0f); break;
235  case EC_outQuart: y = 1.0f - pow(1.0f - x, 1.0f / 4.0f); break;
236  case EC_inOutQuart: y = (x < 0.5f) ? pow(x, 1.0f / 4.0f) / pow(8.0f, 1.0f / 4.0f) : 1.0f - pow(1.0f - x, 1.0f / 4.0f) / pow(8.0f, 1.0f / 4.0f); break;
237  case EC_outInQuart: y = (x < 0.5f) ? -pow(0.5f - x, 1.0f / 4.0f) / pow(8.0f, 1.0f / 4.0f) + 0.5f : pow(x - 0.5f, 1.0f / 4.0f) / pow(8.0f, 1.0f / 4.0f) + 0.5f; break;
238 
239  case EC_inQuint: y = pow(x, 1.0f / 5.0f); break;
240  case EC_outQuint: y = 1.0f - pow(1.0f - x, 1.0f / 5.0f); break;
241  case EC_inOutQuint: y = (x < 0.5f) ? pow(x, 1.0f / 5.0f) / pow(16.0f, 1.0f / 5.0f) : 1.0f - pow(1.0f - x, 1.0f / 5.0f) / pow(16.0f, 1.0f / 5.0f); break;
242  case EC_outInQuint: y = (x < 0.5f) ? -pow(0.5f - x, 1.0f / 5.0f) / pow(16.0f, 1.0f / 5.0f) + 0.5f : pow(x - 0.5f, 1.0f / 5.0f) / pow(16.0f, 1.0f / 5.0f) + 0.5f; break;
243 
244  case EC_inSine: y = -2.0f * asin(1.0f - x) * Utils::ONEOVERPI + 1.0f; break;
245  case EC_outSine: y = -2.0f * acos(x) * Utils::ONEOVERPI + 1.0f; break;
246  case EC_inOutSine: y = acos(1.0f - 2.0f * x) * Utils::ONEOVERPI; break;
247  case EC_outInSine: y = (x < 0.5f) ? asin(2.0f * x) * Utils::ONEOVERPI : asin(2.0f * (x - 1.0f)) * Utils::ONEOVERPI + 1.0f; break;
248  }
249 
250  return y * _animation->lengthSec();
251 }
252 //-----------------------------------------------------------------------------
float SLfloat
Definition: SL.h:173
@ EC_inOutQuart
quartic easing in and then out
Definition: SLEnums.h:192
@ EC_inCubic
cubic in easing in, acceleration from zero velocity
Definition: SLEnums.h:186
@ EC_outQuart
quartic easing out, decelerating to zero velocity
Definition: SLEnums.h:191
@ EC_outInQuint
quintic easing out and then in
Definition: SLEnums.h:197
@ EC_inOutCubic
cubic easing in and then out
Definition: SLEnums.h:188
@ EC_outCubic
cubic easing out, decelerating to zero velocity
Definition: SLEnums.h:187
@ EC_outInSine
sine easing out and then in
Definition: SLEnums.h:201
@ EC_outInQuad
quadratic easing out and then in
Definition: SLEnums.h:185
@ EC_inOutQuad
quadratic easing in and then out
Definition: SLEnums.h:184
@ EC_inOutSine
sine easing in and then out
Definition: SLEnums.h:200
@ EC_outInCubic
cubic easing out and then in
Definition: SLEnums.h:189
@ EC_inSine
sine easing in, acceleration from zero velocity
Definition: SLEnums.h:198
@ EC_inQuart
quartic easing in, acceleration from zero velocity
Definition: SLEnums.h:190
@ EC_outQuint
quintic easing out, decelerating to zero velocity
Definition: SLEnums.h:195
@ EC_outQuad
quadratic easing out, decelerating to zero velocity
Definition: SLEnums.h:183
@ EC_linear
linear easing with constant velocity
Definition: SLEnums.h:181
@ EC_inOutQuint
quintic easing in and then out
Definition: SLEnums.h:196
@ EC_outInQuart
quartic easing out and then in
Definition: SLEnums.h:193
@ EC_inQuad
quadratic easing in, acceleration from zero velocity
Definition: SLEnums.h:182
@ EC_inQuint
quintic easing in, acceleration from zero velocity
Definition: SLEnums.h:194
@ EC_outSine
sine easing out, decelerating to zero velocity
Definition: SLEnums.h:199
@ AL_loop
loop
Definition: SLEnums.h:169
@ AL_pingPongLoop
loop forward and backwards
Definition: SLEnums.h:171
@ AL_once
play once
Definition: SLEnums.h:168
@ AL_pingPong
play once in two directions
Definition: SLEnums.h:170
SLfloat _localTime
the current local timestamp (eased time)
SLEasingCurve _easing
easing modifier curve (to customize start and end point easing)
SLshort _playbackDir
the current playback direction
SLfloat localTime() const
SLfloat _playbackRate
the current playback speed
SLbool _gotChanged
Did this playback change in the last frame.
SLbool _enabled
is this animation running
SLfloat _linearLocalTime
linear local time used for _easing propert
SLAnimLooping _loopingBehaviour
We support different looping behaviours.
SLfloat calcEasingTimeInv(SLfloat time) const
void advanceTime(SLfloat delta)
SLAnimation * _animation
the animation this plays is referencing
SLAnimPlayback(SLAnimation *parent, SLfloat weight=1.0f)
SLfloat calcEasingTime(SLfloat time) const
Applies the easing time curve to the input time.
SLAnimation is the base container for all animation data.
Definition: SLAnimation.h:33
SLfloat lengthSec() const
Definition: SLAnimation.h:72
SLfloat prevKeyframeTime(SLfloat time)
Definition: SLAnimation.cpp:57
SLfloat nextKeyframeTime(SLfloat time)
Definition: SLAnimation.cpp:38
T abs(T a)
Definition: Utils.h:249
static const float ONEOVERPI
Definition: Utils.h:241
static const float PI
Definition: Utils.h:237