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
1.2.15