1 ///////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2010 by The Allacrost Project
3 //                         All Rights Reserved
4 //
5 // This code is licensed under the GNU GPL version 2. It is free software
6 // and you may modify it and/or redistribute it under the terms of this license.
7 // See http://www.gnu.org/copyleft/gpl.html for details.
8 ///////////////////////////////////////////////////////////////////////////////
9 
10 /** ****************************************************************************
11 *** \file    interpolator.h
12 *** \author  Raj Sharma, roos@allacrost.org
13 *** \brief   Source file for Interpolator class
14 *** ***************************************************************************/
15 
16 #include <cassert>
17 #include <cstdarg>
18 #include <math.h>
19 
20 #include "video.h"
21 
22 using namespace std;
23 using namespace hoa_utils;
24 using namespace hoa_video::private_video;
25 
26 namespace hoa_video {
27 
28 // Controls how slow the slow transform is. The greater the number, the "slower" it is. Should be greater than 1.0f
29 const float VIDEO_SLOW_TRANSFORM_POWER = 2.0f;
30 
31 // Controls how fast the fast transform is. The smaller the number, the "faster" it is. Should be between 0.0f and 1.0f
32 const float VIDEO_FAST_TRANSFORM_POWER = 0.3f;
33 
34 
35 
Interpolator()36 Interpolator::Interpolator() :
37 	_method(VIDEO_INTERPOLATE_LINEAR),
38 	_a(0.0f),
39 	_b(0.0f),
40 	_current_time(0),
41 	_end_time(0),
42 	_current_value(0.0f),
43 	_finished(true) // no interpolation is in progress
44 {}
45 
46 
47 
Start(float a,float b,uint32 milliseconds)48 void Interpolator::Start(float a, float b, uint32 milliseconds) {
49 	if (_ValidMethod() == false) {
50 		if (VIDEO_DEBUG)
51 			cerr << "VIDEO WARNING: " << __FUNCTION__ << " was called when an invalid interpolation method was set" << endl;
52 		return;
53 	}
54 
55 	_a = a;
56 	_b = b;
57 
58 	_current_time = 0;
59 	_end_time = milliseconds;
60 	_finished = false;
61 
62 	Update(0);  // Do an initial update so that we have a valid value for GetValue()
63 }
64 
65 
66 
SetMethod(InterpolationMethod method)67 void Interpolator::SetMethod(InterpolationMethod method) {
68 	if (_finished == false) {
69 		if (VIDEO_DEBUG)
70 			cerr << "VIDEO WARNING: " << __FUNCTION__ << " was called when an interpolation was still in progress" << endl;
71 		return;
72 	}
73 
74 	_method = method;
75 	if (_ValidMethod() == false) {
76 		if (VIDEO_DEBUG)
77 			cerr << "VIDEO WARNING: " << __FUNCTION__ << " was passed an invalid method argument" << endl;
78 	}
79 }
80 
81 
82 
Update(uint32 frame_time)83 void Interpolator::Update(uint32 frame_time) {
84 	if (_ValidMethod() == false) {
85 		if (VIDEO_DEBUG)
86 			cerr << "VIDEO WARNING: " << __FUNCTION__ << " was called when an invalid method was set" << endl;
87 		return;
88 	}
89 
90 	// update current time
91 	_current_time += frame_time;
92 
93 	if (_current_time > _end_time) {
94 		_current_time = _end_time;
95 		_finished = true;
96 	}
97 
98 	// Calculate a value from 0.0f to 1.0f that tells how far we are in the interpolation
99 	float progress;
100 
101 	if (_end_time == 0) {
102 		progress = 1.0f;
103 	}
104 	else {
105 		progress = static_cast<float>(_current_time) / static_cast<float>(_end_time);
106 	}
107 
108 	if (progress > 1.0f) {
109 		if (VIDEO_DEBUG)
110 			cerr << "VIDEO WARNING: " << __FUNCTION__ << " calculated a progress value greater than 1.0" << endl;
111 		progress = 1.0f;
112 	}
113 
114 	// Apply a transformation based on the interpolation method
115 	switch(_method) {
116 		case VIDEO_INTERPOLATE_EASE:
117 			progress = _EaseTransform(progress);
118 			break;
119 		case VIDEO_INTERPOLATE_SRCA:
120 			progress = 0.0f;
121 			break;
122 		case VIDEO_INTERPOLATE_SRCB:
123 			progress = 1.0f;
124 			break;
125 		case VIDEO_INTERPOLATE_FAST:
126 			progress = _FastTransform(progress);
127 			break;
128 		case VIDEO_INTERPOLATE_SLOW:
129 			progress = _SlowTransform(progress);
130 			break;
131 		case VIDEO_INTERPOLATE_LINEAR:
132 			// Nothing to do, just use progress value as it is
133 			break;
134 		default:
135 			if (VIDEO_DEBUG)
136 				cerr << "VIDEO WARNING: " << __FUNCTION__ << " the current method did not match any supported methods" << endl;
137 			return;
138 	};
139 
140 	_current_value = Lerp(progress, _a, _b);
141 } // void Interpolator::Update(uint32 frame_time)
142 
143 
144 
_FastTransform(float initial_value)145 float Interpolator::_FastTransform(float initial_value) {
146 	return pow(initial_value, VIDEO_FAST_TRANSFORM_POWER);
147 }
148 
149 
150 
_SlowTransform(float initial_value)151 float Interpolator::_SlowTransform(float initial_value) {
152 	return pow(initial_value, VIDEO_SLOW_TRANSFORM_POWER);
153 }
154 
155 
156 
_EaseTransform(float initial_value)157 float Interpolator::_EaseTransform(float initial_value) {
158 	return 0.5f * (1.0f + sinf(UTILS_2PI * (initial_value - 0.25f)));
159 }
160 
161 }  // namespace hoa_video
162