00001 00002 // Copyright (C) 2004-2007 by The Allacrost Project 00003 // All Rights Reserved 00004 // 00005 // This code is licensed under the GNU GPL version 2. It is free software 00006 // and you may modify it and/or redistribute it under the terms of this license. 00007 // See http://www.gnu.org/copyleft/gpl.html for details. 00009 00010 #include "utils.h" 00011 #include <cassert> 00012 #include <cstdarg> 00013 #include "video.h" 00014 #include <math.h> 00015 00016 using namespace std; 00017 using namespace hoa_utils; 00018 using namespace hoa_video::private_video; 00019 00020 00021 namespace hoa_video 00022 { 00023 00024 // controls how slow the slow transform is. The greater the number, the "slower" it is. 00025 const float VIDEO_SLOW_TRANSFORM_POWER = 2.0f; 00026 00027 // controls how fast the fast transform is. The smaller the number, the "faster" it is. 00028 const float VIDEO_FAST_TRANSFORM_POWER = 0.3f; 00029 00030 00031 //----------------------------------------------------------------------------- 00032 // Interpolator constructor 00033 //----------------------------------------------------------------------------- 00034 00035 Interpolator::Interpolator() 00036 { 00037 _method = VIDEO_INTERPOLATE_LINEAR; 00038 _current_time = _end_time = 0; 00039 _a = _b = 0.0f; 00040 _finished = true; // no interpolation in progress 00041 _current_value = 0.0f; 00042 } 00043 00044 00045 //----------------------------------------------------------------------------- 00046 // Start: begins an interpolation using a and b as inputs, in the given amount 00047 // of time. 00048 // 00049 // Note: not all interpolation methods mean "going from A to B". In the case of 00050 // linear, constant, fast, slow, they do start at A and go to B. But, 00051 // ease interpolations go from A to B and then back. And constant 00052 // interpolation means just staying at either A or B. 00053 //----------------------------------------------------------------------------- 00054 00055 bool Interpolator::Start(float a, float b, int32 milliseconds) 00056 { 00057 if(!_ValidMethod()) 00058 { 00059 if(VIDEO_DEBUG) 00060 cerr << "VIDEO ERROR: tried to start interpolation with invalid method!" << endl; 00061 return false; 00062 } 00063 00064 if(milliseconds < 0) 00065 { 00066 if(VIDEO_DEBUG) 00067 cerr << "VIDEO ERROR: passed negative time value to Interpolator::Start()!" << endl; 00068 return false; 00069 } 00070 00071 _a = a; 00072 _b = b; 00073 00074 _current_time = 0; 00075 _end_time = milliseconds; 00076 _finished = false; 00077 00078 Update(0); // do initial update so we have a valid value for GetValue() 00079 return true; 00080 } 00081 00082 00083 //----------------------------------------------------------------------------- 00084 // SetMethod: sets the current interpolation method. Two things will cause 00085 // this to fail: 00086 // 00087 // 1. You pass in an invalid method 00088 // 2. You change the method while an interpolation is in progress 00089 //----------------------------------------------------------------------------- 00090 00091 bool Interpolator::SetMethod(InterpolationMethod method) 00092 { 00093 if(!_finished) 00094 { 00095 if(VIDEO_DEBUG) 00096 cerr << "VIDEO ERROR: tried to call SetMethod() on an interpolator that was still in progress!" << endl; 00097 return false; 00098 } 00099 00100 if(!_ValidMethod()) 00101 { 00102 if(VIDEO_DEBUG) 00103 cerr << "VIDEO ERROR: passed an invalid method to Interpolator::SetMethod()!" << endl; 00104 return false; 00105 } 00106 00107 _method = method; 00108 return true; 00109 } 00110 00111 00112 //----------------------------------------------------------------------------- 00113 // GetValue: returns the current value of the interpolator. The current value 00114 // gets set when Update() is called so make sure to never call 00115 // GetValue() before updating 00116 //----------------------------------------------------------------------------- 00117 00118 float Interpolator::GetValue() 00119 { 00120 return _current_value; 00121 } 00122 00123 00124 //----------------------------------------------------------------------------- 00125 // Update: updates the interpolation by frameTime milliseconds. 00126 // If we reach the end of the interpolation, then IsFinished() 00127 // will return true. 00128 // This function will return false if the method is invalid. 00129 //----------------------------------------------------------------------------- 00130 00131 bool Interpolator::Update(int32 frame_time) 00132 { 00133 if(frame_time < 0) 00134 { 00135 if(VIDEO_DEBUG) 00136 cerr << "VIDEO ERROR: called Interpolator::Update() with negative frameTime!" << endl; 00137 return false; 00138 } 00139 00140 if(!_ValidMethod()) 00141 { 00142 if(VIDEO_DEBUG) 00143 cerr << "VIDEO ERROR: called Interpolator::Update(), but method was invalid!" << endl; 00144 return false; 00145 } 00146 00147 // update current time 00148 _current_time += frame_time; 00149 00150 if(_current_time > _end_time) 00151 { 00152 _current_time = _end_time; 00153 _finished = true; 00154 } 00155 00156 // calculate a value from 0.0f to 1.0f of how far we are in the interpolation 00157 float t; 00158 00159 if(_end_time == 0) 00160 { 00161 t = 1.0f; 00162 } 00163 else 00164 { 00165 t = (float)_current_time / (float)_end_time; 00166 } 00167 00168 if(t > 1.0f) 00169 { 00170 if(VIDEO_DEBUG) 00171 cerr << "VIDEO ERROR: calculated value of 't' was more than 1.0!" << endl; 00172 t = 1.0f; 00173 } 00174 00175 // now apply a transformation based on the interpolation method 00176 00177 switch(_method) 00178 { 00179 case VIDEO_INTERPOLATE_EASE: 00180 t = _EaseTransform(t); 00181 break; 00182 case VIDEO_INTERPOLATE_SRCA: 00183 t = 0.0f; 00184 break; 00185 case VIDEO_INTERPOLATE_SRCB: 00186 t = 1.0f; 00187 break; 00188 case VIDEO_INTERPOLATE_FAST: 00189 t = _FastTransform(t); 00190 break; 00191 case VIDEO_INTERPOLATE_SLOW: 00192 t = _SlowTransform(t); 00193 break; 00194 case VIDEO_INTERPOLATE_LINEAR: 00195 // nothing to do, just use t value as it is! 00196 break; 00197 default: 00198 { 00199 if(VIDEO_DEBUG) 00200 cerr << "VIDEO ERROR: in Interpolator::Update(), current method didn't match supported methods!" << endl; 00201 return false; 00202 } 00203 }; 00204 00205 _current_value = Lerp(t, _a, _b); 00206 00207 return true; 00208 } 00209 00210 00211 //----------------------------------------------------------------------------- 00212 // _FastTransform: rescales the range of t so that it looks like a sqrt function 00213 // from 0.0 to 1.0, i.e. it increases quickly then levels off 00214 //----------------------------------------------------------------------------- 00215 00216 float Interpolator::_FastTransform(float t) 00217 { 00218 // the fast transform power is some number above 0.0 and less than 1.0 00219 return powf(t, VIDEO_FAST_TRANSFORM_POWER); 00220 } 00221 00222 00223 //----------------------------------------------------------------------------- 00224 // _SlowTransform: rescales the range of t so it looks like a power function 00225 // from 0.0 to 1.0, i.e. it increases slowly then rockets up 00226 //----------------------------------------------------------------------------- 00227 00228 float Interpolator::_SlowTransform(float t) 00229 { 00230 // the slow transform power is a number above 1.0 00231 return powf(t, VIDEO_SLOW_TRANSFORM_POWER); 00232 } 00233 00234 00235 //----------------------------------------------------------------------------- 00236 // _EaseTransform: rescales the range of t so it increases slowly, rises to 1.0 00237 // then falls back to 0.0 00238 //----------------------------------------------------------------------------- 00239 00240 float Interpolator::_EaseTransform(float t) 00241 { 00242 return 0.5f * (1.0f + sinf(UTILS_2PI * (t - 0.25f))); 00243 } 00244 00245 00246 //----------------------------------------------------------------------------- 00247 // IsFinished: returns true if the interpolator is done with the current 00248 // interpolation 00249 //----------------------------------------------------------------------------- 00250 00251 bool Interpolator::IsFinished() 00252 { 00253 return _finished; 00254 } 00255 00256 00257 //----------------------------------------------------------------------------- 00258 // _ValidMethod: private function to check that the current method is valid 00259 //----------------------------------------------------------------------------- 00260 00261 bool Interpolator::_ValidMethod() 00262 { 00263 return (_method < VIDEO_INTERPOLATE_TOTAL && 00264 _method > VIDEO_INTERPOLATE_INVALID); 00265 } 00266 00267 00268 } // namespace hoa_video
1.5.1