Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

c:/home/kevn/src/animaniac/ani/KeyFrame/KeyFramer.h

Go to the documentation of this file.
00001 
00002 /*************** <auto-copyright.pl BEGIN do not edit this line> **************
00003  *
00004  * Animaniac is (C) Copyright 2000,2001 Kevin Meinert
00005  *
00006  * Original Authors:
00007  *   Kevin Meinert
00008  *
00009  *
00010  *
00011  * This library is free software; you can redistribute it and/or
00012  * modify it under the terms of the GNU Library General Public
00013  * License as published by the Free Software Foundation; either
00014  * version 2 of the License, or (at your option) any later version.
00015  *
00016  * This library is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Library General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Library General Public
00022  * License along with this library; if not, write to the
00023  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00024  * Boston, MA 02111-1307, USA.
00025  *
00026  * -----------------------------------------------------------------
00027  * File:          $RCSfile: KeyFramer.h,v $
00028  * Date modified: $Date: 2002/05/06 05:18:22 $
00029  * Version:       $Revision: 1.5 $
00030  * -----------------------------------------------------------------
00031  *
00032  *************** <auto-copyright.pl END do not edit this line> ***************/
00033 
00034 
00035 // NOTE: for best results, read this file using an editor that supports
00036 // color syntax highlighting.  (i.e. nedit, gvim, visual studio, visual 
00037 // slick edit)
00038 
00039 #ifndef ANIMATION_KEY_FRAMER
00040 #define ANIMATION_KEY_FRAMER
00041 
00042 
00043 
00044 #include <map>
00045 #include <assert.h>
00046 #include <gmtl/Vec.h>
00047 #include <gmtl/VecOps.h>
00048 #include <gmtl/Quat.h>
00049 #include <gmtl/QuatOps.h>
00050 #include <gmtl/Matrix.h>
00051 #include <gmtl/MatrixOps.h>
00052 
00053 namespace ani
00054 {
00055    // example to create a new KeyFramer:
00056    //
00057    //     KeyFramer<PosQuatKey> keyFramer;
00058    //
00059    // It is morphable to any key type, currently only PosQuat key is available
00060    // but I'd like to add bones or polygonal mesh sometime soon.  
00061    template <class _keyType>
00062    class KeyFramer
00063    {
00064    public:
00065       //: default constructor
00066       KeyFramer()
00067       {
00068          // initial state.
00069          this->clear();
00070          this->stop();
00071       }
00072       
00073       //: play forward
00074       // resume from a pause(), restart from a stop(), 
00075       // change directions from an rplay()
00076       void play() 
00077       {
00078          mIsPlaying = true;
00079          mReverse = false;
00080       }
00081 
00082       //: play backward
00083       // resume from a pause(), restart from a stop(), 
00084       // change directions from a play()
00085       void rplay()
00086       {
00087          mIsPlaying = true;
00088          mReverse = true;
00089       }
00090 
00091       //: pause to stop, play or rplay to resume
00092       void pause()
00093       {
00094          mIsPlaying = false;
00095       }
00096 
00097       //: jump to begin
00098       void rewind()
00099       {
00100          mCurrentTime = this->begintime();
00101          mFutureTime = this->begintime();
00102       }
00103       
00104       //: jump to end
00105       void fastforward()
00106       {
00107          mCurrentTime = this->length();
00108          mFutureTime = this->length();
00109       }
00110       
00111       //: stop anim, resetting to beginning.
00112       void stop()
00113       {
00114          mIsPlaying = false;
00115          mCurrentTime = this->begintime();
00116          mFutureTime = this->begintime();
00117          mLoopsLeft = mLoops;
00118       }
00119       
00120       void clear()
00121       {
00122          mKeys.clear();
00123          mPlayFactor = 1.0f;  // 1X (normal play) is default
00124          mLoops = 1;          // loop once is default
00125          mCurrentTime = this->begintime();
00126          mFutureTime = this->begintime();  
00127          mLoopsLeft = 1;
00128       }  
00129           
00130       //: update func.
00131       // take one time-step of the animation
00132       // advances one frame of the animation, 
00133       // give the current time between frames in seconds...
00134       void step( float timeOfKey )
00135       {
00136          if (mIsPlaying)
00137          {         
00138             mCurrentTime = mFutureTime;
00139             
00140             // if time is out of bounds,
00141             if (mCurrentTime > this->length() || mCurrentTime < 0)
00142             {
00143                // if we're counting loops, then decrement counter.
00144                if (mLoopsLeft > 0)
00145                   --mLoopsLeft;
00146 
00147                // and there are loops left, then rewind
00148                if (mLoopsLeft != 0)
00149                {
00150                   if (mReverse == false)
00151                      this->rewind();
00152                   else
00153                      this->fastforward();
00154                }
00155                // otherwise there are no loops left, so stop
00156                else
00157                {
00158                   this->stop();
00159                   return;
00160                }               
00161             }
00162             
00163             this->jump( mCurrentTime );
00164             
00165             // time passes in the direction of play (forward|reverse)
00166             // multiply play speed by the set factor...
00167             if (mReverse == false)
00168                mFutureTime += timeOfKey * mPlayFactor;
00169             else
00170                mFutureTime -= timeOfKey * mPlayFactor;            
00171          }
00172       }      
00173 
00174 
00175       //: set the speed at which to play (factor > 0)
00176       // normal play:  1.0
00177       // double speed: 2.0
00178       // half speed:   0.5
00179       void setSpeed( float factor = 1.0f )
00180       {
00181          assert( factor > 0.0f && "use reverseplay() and play() to change direction (if factor < 0), use stop() to stop (if factor == 0)" );
00182          mPlayFactor = factor;
00183       }
00184       
00185       //: number of times to loop
00186       //  loop once:      1 (default) 
00187       //  loop infinite: -1
00188       //  loop n times:   n > 0
00189       // NOTE: enter 0 and the animation will never run...
00190       void setLoops( int numTimesToLoop = 1 )
00191       {
00192          mLoops = numTimesToLoop;
00193          mLoopsLeft = mLoops;
00194       }
00195       
00196       //: add a key to the keyframer.
00197       void addkey( const _keyType& key )
00198       {
00199          mKeys[key.time()] = key;
00200       }
00201       
00202 // state querys
00203 public:
00204       //: access all the keys in the system (non-const version)
00205       //  useful in case you need to write your own data traverser
00206       std::map<float, _keyType>& keys() { return mKeys; }
00207       
00208       //: access all the keys in the system (const version)
00209       //  useful in case you need to write your own data traverser
00210       const std::map<float, _keyType>& keys() const { return mKeys; }
00211 
00212       //: what is the time at the first key (start time of the animation)
00213       float begintime() const
00214       {
00215          return (*(mKeys.begin())).first;
00216       }
00217 
00218       //: what is the time at the last key (end time of the animation)
00219       float endtime() const
00220       {
00221          return (*(mKeys.rbegin())).first;
00222       }
00223       
00224       //: returns animation time in seconds
00225       float length() 
00226       { 
00227          if (mKeys.size() == 0) 
00228             return 0.0f; // if no keys, then there is no length to the animation
00229          
00230          return this->endtime() - this->begintime(); 
00231       }
00232       
00233       bool isPlaying() { return mIsPlaying; }
00234       
00235       //: speed of play (factor > 0)
00236       // normal play:  1.0
00237       // double speed: 2.0
00238       // half speed:   0.5
00239       float speed() const
00240       {
00241          return mPlayFactor;
00242       }
00243       
00244       //: Total number of Loops
00245       // get the number of times the animation is set to repeat
00246       int loops() { return mLoops; }
00247       
00248       //: Number of loops left
00249       // get the number of times the animation has yet to repeat
00250       int loopsLeft() { return mLoopsLeft; }
00251       
00252       //: get the current interpolated key
00253       const _keyType& key() const { return mCurrentKey; }
00254       
00255       //: get the current interpolated key's quaternion rotation
00256       const gmtl::Quatf& rotation() const { return mCurrentKey.rotation(); }
00257       
00258       //: get the current interpolated key's position
00259       const gmtl::Vec3f& position() const { return mCurrentKey.position(); }
00260       
00261       //: get the time of the current interpolated key
00262       const float& time() const
00263       {
00264          //assert( mCurrentTime == mCurrentKey.time() && "should be equal" );
00265          return mCurrentKey.time();
00266       }
00267 
00268 private:
00269       // util func
00270       //void output( _keyType& key )
00271       //{
00272       //   printf( "KEY %f: %4.1f, \t%4.1f, \t%4.1f, |#| %4.1f, %4.1f, %4.1f, %4.1f\n", key.time(), key.position()[0], key.position()[1], key.position()[2], key.rotation()[0], key.rotation()[1], key.rotation()[2], key.rotation()[3] );
00273       //}
00274 public:
00275 
00276       //: jump to arbitrary time
00277       // O( lg n )
00278       // seekToTime: time that you want to jump to in the animation 
00279       //             must be in the range: [0 <= x <= length()]
00280       // post: time() returns time
00281       void jump( float seekToTime )
00282       {
00283          if (mKeys.size() <= 0)
00284             return;
00285 
00286          assert( seekToTime <= this->length() );
00287          
00288          // grab the two keys that come before and after the requested time.
00289          std::map<float, _keyType>::iterator first, second;
00290          second = mKeys.lower_bound( seekToTime );// will always return a valid it because of the assert above.
00291          first = second;
00292          --first;
00293          if (first == mKeys.end())
00294          {
00295             first = second;
00296          }         
00297          
00298          // if out of bounds, then fix it...
00299          float a = (*first).first, b = (*second).first;
00300          if (seekToTime < a || seekToTime > b)
00301          {
00302             seekToTime = (*first).first;
00303          }
00304          
00305          // interpolate (set the current key)
00306          const _keyType& key_one = (*first).second; assert( key_one.time() == (*first).first && "not good" );
00307          const _keyType& key_two = (*second).second; assert( key_two.time() == (*second).first && "not good" );
00308          mCurrentKey.setInterpolate( seekToTime, key_one, key_two );
00309          
00310          //output( mCurrentKey );
00311          
00312          // set the current time.
00313          mCurrentTime = seekToTime;
00314       }
00315       
00316 
00317 private:
00318       // map a time to a key (binary tree, O(lg n) lookup)
00319       std::map<float, _keyType>  mKeys; 
00320       bool           mIsPlaying, mReverse;
00321       
00322       // how fast to play
00323       float          mPlayFactor;
00324       
00325       // -1 is continuous, 0 is none, n is number of times.
00326       int            mLoops, mLoopsLeft;
00327       
00328       // position in animation...
00329       float          mCurrentTime, mFutureTime;
00330       
00331       // the current key (interpolated)
00332       _keyType       mCurrentKey;
00333    };
00334 }; //namespace ani
00335 
00336 #endif

Generated on Wed Jun 12 01:54:02 2002 for Animaniac by doxygen1.2.15