1 ///////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2011 by The Allacrost Project
3 //            Copyright (C) 2012-2016 by Bertram (Valyria Tear)
4 //                         All Rights Reserved
5 //
6 // This code is licensed under the GNU GPL version 2. It is free software
7 // and you may modify it and/or redistribute it under the terms of this license.
8 // See http://www.gnu.org/copyleft/gpl.html for details.
9 ///////////////////////////////////////////////////////////////////////////////
10 
11 /** ****************************************************************************
12 *** \file    interpolator.h
13 *** \author  Raj Sharma, roos@allacrost.org
14 *** \author  Yohann Ferreira, yohann ferreira orange fr
15 *** \brief   Source file for Interpolator class
16 *** ***************************************************************************/
17 
18 #include "interpolator.h"
19 
20 #include "utils/utils_common.h"
21 #include "utils/utils_numeric.h"
22 
23 #include <cmath>
24 
25 namespace vt_mode_manager
26 {
27 
28 extern bool MODE_MANAGER_DEBUG;
29 
30 // Controls how slow the slow transform is. The greater the number, the "slower" it is. Should be greater than 1.0f
31 const float SLOW_TRANSFORM_POWER = 2.0f;
32 
33 // Controls how fast the fast transform is. The smaller the number, the "faster" it is. Should be between 0.0f and 1.0f
34 const float FAST_TRANSFORM_POWER = 0.3f;
35 
36 /** \brief Interpolates logarithmically. Increases quickly and then levels off.
37 *** \param initial_value The initial value to interpolate. Should be between 0.0f and 1.0f (inclusive)
38 *** \return The interpolated value
39 **/
_FastTransform(float initial_value)40 static float _FastTransform(float initial_value)
41 {
42     return pow(initial_value, FAST_TRANSFORM_POWER);
43 }
44 
45 /** \brief Interpolates exponentially. Increases slowly and then sky rockets.
46 *** \param initial_value The initial value to interpolate. Should be between 0.0f and 1.0f (inclusive)
47 *** \return The interpolated value
48 **/
_SlowTransform(float initial_value)49 static float _SlowTransform(float initial_value)
50 {
51     return pow(initial_value, SLOW_TRANSFORM_POWER);
52 }
53 
54 /** \brief Interpolates periodically. Increases slowly to 1.0f then back down to 0.0f via a sine function.
55 *** \param initial_value The initial value to interpolate. Should be between 0.0f and 1.0f (inclusive)
56 *** \return The interpolated value
57 **/
_EaseTransform(float initial_value)58 static float _EaseTransform(float initial_value)
59 {
60     return 0.5f * (1.0f + sinf(vt_utils::UTILS_2PI * (initial_value - 0.25f)));
61 }
62 
Interpolator()63 Interpolator::Interpolator() :
64     _method(INTERPOLATE_LINEAR),
65     _a(0.0f),
66     _b(0.0f),
67     _current_time(0),
68     _end_time(0),
69     _current_value(0.0f),
70     _finished(true) // no interpolation is in progress
71 {}
72 
73 
74 
Start(float a,float b,uint32_t milliseconds)75 void Interpolator::Start(float a, float b, uint32_t milliseconds)
76 {
77     if(_ValidMethod() == false) {
78         IF_PRINT_WARNING(MODE_MANAGER_DEBUG)
79                 << " was called when an invalid interpolation method was set" << std::endl;
80         return;
81     }
82 
83     _a = a;
84     _b = b;
85 
86     _current_time = 0;
87     _end_time = milliseconds;
88     _finished = false;
89 
90     Update(0);  // Do an initial update so that we have a valid value for GetValue()
91 }
92 
93 
94 
SetMethod(InterpolationMethod method)95 void Interpolator::SetMethod(InterpolationMethod method)
96 {
97     if(_finished == false) {
98         IF_PRINT_WARNING(MODE_MANAGER_DEBUG)
99                 << " was called when an interpolation was still in progress" << std::endl;
100         return;
101     }
102 
103     _method = method;
104     if(_ValidMethod() == false) {
105         IF_PRINT_WARNING(MODE_MANAGER_DEBUG)
106                 << " was passed an invalid method argument" << std::endl;
107     }
108 }
109 
110 
111 
Update(uint32_t frame_time)112 void Interpolator::Update(uint32_t frame_time)
113 {
114     if(_ValidMethod() == false) {
115         IF_PRINT_WARNING(MODE_MANAGER_DEBUG)
116                 << " was called when an invalid method was set" << std::endl;
117         return;
118     }
119 
120     // update current time
121     _current_time += frame_time;
122 
123     if(_current_time > _end_time) {
124         _current_time = _end_time;
125         _finished = true;
126     }
127 
128     // Calculate a value from 0.0f to 1.0f that tells how far we are in the interpolation
129     float progress;
130 
131     if(_end_time == 0) {
132         progress = 1.0f;
133     } else {
134         progress = static_cast<float>(_current_time) / static_cast<float>(_end_time);
135     }
136 
137     if(progress > 1.0f) {
138         IF_PRINT_WARNING(MODE_MANAGER_DEBUG)
139                 << " calculated a progress value greater than 1.0" << std::endl;
140         progress = 1.0f;
141     }
142 
143     // Apply a transformation based on the interpolation method
144     switch(_method) {
145     case INTERPOLATE_EASE:
146         progress = _EaseTransform(progress);
147         break;
148     case INTERPOLATE_SRCA:
149         progress = 0.0f;
150         break;
151     case INTERPOLATE_SRCB:
152         progress = 1.0f;
153         break;
154     case INTERPOLATE_FAST:
155         progress = _FastTransform(progress);
156         break;
157     case INTERPOLATE_SLOW:
158         progress = _SlowTransform(progress);
159         break;
160     case INTERPOLATE_LINEAR:
161         // Nothing to do, just use progress value as it is
162         break;
163     default:
164         IF_PRINT_WARNING(MODE_MANAGER_DEBUG)
165                 << " the current method did not match any supported methods" << std::endl;
166         return;
167     };
168 
169     _current_value = vt_utils::Lerp(progress, _a, _b);
170 } // void Interpolator::Update(uint32_t frame_time)
171 
172 }  // namespace vt_video
173