interpolator.cpp

Go to the documentation of this file.
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

Generated on Fri Jul 6 23:11:16 2007 for Hero of Allacrost by  doxygen 1.5.1