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