# Home    # nevrax.com   
Nevrax
Nevrax.org
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
Docs
 
Documentation  
Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  

track_keyframer.h

Go to the documentation of this file.
00001 
00007 /* Copyright, 2001 Nevrax Ltd.
00008  *
00009  * This file is part of NEVRAX NEL.
00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014 
00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00018  * General Public License for more details.
00019 
00020  * You should have received a copy of the GNU General Public License
00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00023  * MA 02111-1307, USA.
00024  */
00025 
00026 #ifndef NL_TRACK_KEYFRAMER_H
00027 #define NL_TRACK_KEYFRAMER_H
00028 
00029 #include "nel/misc/types_nl.h"
00030 #include "3d/track.h"
00031 #include "3d/key.h"
00032 #include <map>
00033 #include <memory>
00034 #include "nel/misc/matrix.h"
00035 
00036 
00037 
00038 namespace NL3D
00039 {
00040 
00041 
00042 // ***************************************************************************
00043 // ***************************************************************************
00044 // Templates for KeyFramer tracks.
00045 // ***************************************************************************
00046 // ***************************************************************************
00047 
00048 
00049 
00050 // ***************************************************************************
00060 template<class CKeyT>
00061 class ITrackKeyFramer : public ITrack, public UTrackKeyframer
00062 {
00063 public:
00064         // Some types
00065         typedef std::map <TAnimationTime, CKeyT>        TMapTimeCKey;
00066 
00067 
00069         ITrackKeyFramer ()
00070         {
00071                 _Dirty= false;
00072                 _RangeLock= true;
00073                 _LoopMode= false;
00074         }
00075 
00076 
00078         ~ITrackKeyFramer ()
00079         {
00080         }
00081 
00090         void addKey (const CKeyT &key, TAnimationTime time)
00091         {
00092                 // Insert the key in the map
00093                 _MapKey.insert (TMapTimeCKey::value_type (time, key));
00094 
00095                 // must precalc at next eval.
00096                 _Dirty= true;
00097         }
00098 
00100         void    unlockRange(TAnimationTime begin, TAnimationTime end)
00101         {
00102                 _RangeLock= false;
00103                 _RangeBegin= begin;
00104                 _RangeEnd= end;
00105                 _Dirty= true;
00106         }
00107 
00109         void    lockRange()
00110         {
00111                 _RangeLock= true;
00112                 _Dirty= true;
00113         }
00114 
00116         bool    isRangeLocked() const {return _RangeLock;}
00117 
00118 
00120         TAnimationTime  getRangeDelta() const
00121         {
00122                 // update track.
00123                 testAndClean();
00124 
00125                 return _RangeDelta;
00126         }
00127 
00128 
00130         void    setLoopMode(bool loop) {_LoopMode= loop; _Dirty= true;}
00131 
00133         virtual bool getLoopMode() const {return _LoopMode;}
00134 
00135 
00137         virtual void eval (const TAnimationTime& inDate)
00138         {
00139                 float   date= inDate;
00140                 const CKeyT *previous=NULL;
00141                 const CKeyT *next=NULL;
00142                 TAnimationTime datePrevious = 0;
00143                 TAnimationTime dateNext = 0;
00144 
00145                 // must precalc ??
00146                 testAndClean();
00147 
00148                 // No keys?
00149                 if(_MapKey.empty())
00150                         return;
00151 
00152 
00153                 // Loop gestion.
00154                 if(_LoopMode && _MapKey.size()>1 )
00155                 {
00156                         nlassert(_LoopEnd > _LoopStart);
00157 
00158                         // force us to be in interval [_LoopStart, _LoopEnd[.
00159                         if( date<_LoopStart || date>=_LoopEnd )
00160                         {
00161                                 double  d= (date-_LoopStart)*_OOTotalRange;
00162 
00163                                 // floor(d) is the truncated number of loops.
00164                                 d= date- floor(d)*_TotalRange;
00165                                 date= (float)d;
00166 
00167                                 // For precision problems, ensure correct range.
00168                                 if(date<_LoopStart || date >= _LoopEnd)
00169                                         date= _LoopStart;
00170                         }
00171                 }
00172 
00173 
00174                 // Return upper key
00175                 TMapTimeCKey::iterator ite=_MapKey.upper_bound (date);
00176 
00177                 // First next ?
00178                 if (ite!=_MapKey.end())
00179                 {
00180                         // Next
00181                         next= &(ite->second);
00182                         dateNext=ite->first;
00183                 }
00184                 // loop mgt.
00185                 else if (_LoopMode && _MapKey.size()>1 )
00186                 {
00187                         // loop to first!!
00188                         next= &(_MapKey.begin()->second);
00189                         // must slerp from last to first, 
00190                         dateNext= _LoopEnd;
00191                 }
00192                 else if (!_LoopMode && _MapKey.size()>=1 )
00193                 {
00194                         // clamp to the last
00195                         TMapTimeCKey::iterator iteLast= ite;
00196                         iteLast--;
00197                         next= &(iteLast->second);
00198                 }
00199 
00200 
00201                 // First previous ?
00202                 if ((!_MapKey.empty())&&(ite!=_MapKey.begin()))
00203                 {
00204                         if (ite!=_MapKey.end())
00205                         {
00206                                 // Previous
00207                                 ite--;
00208                                 previous= &(ite->second);
00209                                 datePrevious=ite->first;
00210                         }
00211                 }
00212                 else if (!_MapKey.empty())
00213                 {
00214                         // Clamp at beginTime
00215                         next= &(ite->second);
00216                         dateNext=ite->first;
00217                 }
00218 
00219                 // Call evalutation fonction
00220                 evalKey (previous, next, datePrevious, dateNext, date);
00221         }
00222 
00223 
00224         virtual TAnimationTime getBeginTime () const
00225         {
00226                 // must precalc ??
00227                 testAndClean();
00228 
00229                 return _RangeBegin;
00230         }
00231         virtual TAnimationTime getEndTime () const
00232         {
00233                 // must precalc ??
00234                 testAndClean();
00235 
00236                 return _RangeEnd;
00237         }
00238 
00239 
00241         virtual void serial (NLMISC::IStream& f) throw (NLMISC::EStream)
00242         {
00243                 // Serial version
00244                 (void)f.serialVersion (0);
00245 
00246                 f.serialCont(_MapKey);
00247                 f.serial(_RangeLock, _RangeBegin, _RangeEnd);
00248                 f.serial(_LoopMode);
00249 
00250                 if(f.isReading())
00251                         _Dirty= true;
00252         }
00253 
00257         void getKeysInRange(TAnimationTime t1, TAnimationTime t2, std::vector<TAnimationTime> &result);
00258 
00259 
00260 private:
00261         mutable bool            _Dirty;
00262         bool                            _LoopMode;
00263         bool                            _RangeLock;
00264         float                           _RangeBegin;    // if RangeLock==true, valid only when track cleaned.
00265         float                           _RangeEnd;              // if RangeLock==true, valid only when track cleaned.
00266         // Valid only when cleaned.
00267         float                           _RangeDelta;
00268         float                           _LoopStart;
00269         float                           _LoopEnd;
00270         float                           _TotalRange;
00271         float                           _OOTotalRange;
00272 
00273 
00274         // update track if necessary.
00275         void            testAndClean() const
00276         {
00277                 if(_Dirty)
00278                 {
00279                         ITrackKeyFramer<CKeyT>  *self= const_cast<ITrackKeyFramer<CKeyT>*>(this);
00280                         self->compile();
00281                         _Dirty= false;
00282                 }
00283         }
00284 
00285 
00286 protected:
00287         TMapTimeCKey            _MapKey;
00288 
00289 
00291         float   getCompiledRangeDelta()
00292         {
00293                 return _RangeDelta;
00294         }
00295 
00296 
00302         virtual void compile   ()
00303         {
00304                 float   timeFirstKey;
00305                 float   timeLastKey;
00306 
00307                 // Compute time of first/last key.
00308                 if( !_MapKey.empty() )
00309                 {
00310                         TMapTimeCKey::const_iterator ite;
00311 
00312                         // Get first key
00313                         ite=_MapKey.begin ();
00314                         timeFirstKey= ite->first;
00315 
00316                         // Get last key
00317                         ite=_MapKey.end ();
00318                         ite--;
00319                         timeLastKey= ite->first;
00320                 }
00321                 else
00322                 {
00323                         timeFirstKey= 0.0f;
00324                         timeLastKey= 0.0f;
00325                 }
00326 
00327 
00328                 // Compute RangeBegin / RangeEnd. (if not user provided).
00329                 if(_RangeLock)
00330                 {
00331                         _RangeBegin= timeFirstKey;
00332                         _RangeEnd= timeLastKey;
00333                 }
00334 
00335 
00336                 // Compute _RangeDelta.
00337                 if(_RangeLock)
00338                 {
00339                         _RangeDelta= 0;
00340                 }
00341                 else
00342                 {
00343                         _RangeDelta= (_RangeEnd - _RangeBegin) - (timeLastKey - timeFirstKey);
00344                 }
00345 
00346                 // Misc range.
00347                 _TotalRange= _RangeEnd - _RangeBegin;
00348                 if(_TotalRange>0.0f)
00349                         _OOTotalRange= 1.0f/_TotalRange;
00350                 // start of loop / ned.
00351                 _LoopStart= timeFirstKey;
00352                 _LoopEnd= timeFirstKey + _TotalRange;
00353 
00354 
00355                 // After _RangeDelta computed, compute OO delta times.
00356                 TMapTimeCKey::iterator  it= _MapKey.begin();
00357                 for(;it!=_MapKey.end();it++)
00358                 {
00359                         TMapTimeCKey::iterator  next= it;
00360                         next++;
00361                         if(next!=_MapKey.end())
00362                                 it->second.OODeltaTime= 1.0f/(next->first - it->first);
00363                         else if(_RangeDelta>0.0f)
00364                                 // after last key, must slerp to first key.
00365                                 it->second.OODeltaTime= 1.0f/_RangeDelta;
00366                         else
00367                                 it->second.OODeltaTime= 0.0f;
00368                 }
00369 
00370         }
00371 
00380         virtual void evalKey   (const CKeyT* previous, const CKeyT* next,
00381                                                         TAnimationTime datePrevious, TAnimationTime dateNext, 
00382                                                         TAnimationTime date ) =0;
00383 
00384 };
00385 
00386 
00387 // ***************************************************************************
00388 // Key Tools.
00389 // separated to just change this in RGBA and sint32 special implementation.
00390 
00391 // just copy the content of a value issued from key interpolation, into a value.
00392 template<class T, class TKeyVal> inline void    copyToValue(T &value, const TKeyVal &keyval)
00393 {
00394         value = keyval;
00395 }
00396 
00397 
00398 // Vector to RGBA version.
00399 inline void     copyToValue(NLMISC::CRGBA &col, const CVector &v)
00400 {
00401         sint    i;
00402 
00403         i= (sint)(v.x*255); NLMISC::clamp(i,0,255); col.R= (uint8) i;
00404         i= (sint)(v.y*255); NLMISC::clamp(i,0,255); col.G= (uint8) i;
00405         i= (sint)(v.z*255); NLMISC::clamp(i,0,255); col.B= (uint8) i;
00406         col.A=255;
00407 }
00408 
00409 
00410 // float to sint32 version.
00411 inline void     copyToValue(sint32 &value, const float &f)
00412 {
00413         value= (sint32)floor(f+0.5f);
00414 }
00415 
00416 
00417 // ***************************************************************************
00418 // ***************************************************************************
00419 // Constant Keyframer.
00420 // ***************************************************************************
00421 // ***************************************************************************
00422 
00423 
00424 
00425 // ***************************************************************************
00433 template<class CKeyT, class T>
00434 class CTrackKeyFramerConstNotBlendable : public ITrackKeyFramer<CKeyT>
00435 {
00436 public:
00437 
00439         virtual const IAnimatedValue& getValue () const
00440         {
00441                 return _Value;
00442         }
00443         
00445         virtual void evalKey (  const CKeyT* previous, const CKeyT* next,
00446                                                         TAnimationTime datePrevious, TAnimationTime dateNext,
00447                                                         TAnimationTime date )
00448         {
00449                 // Const key.
00450                 if (previous)
00451                         copyToValue(_Value.Value, previous->Value);
00452                 else
00453                         if (next)
00454                                 copyToValue(_Value.Value, next->Value);
00455         }
00456 
00457 private:
00458         CAnimatedValueNotBlendable<T>           _Value;
00459 };
00460 
00461 
00462 // ***************************************************************************
00470 template<class CKeyT, class T>
00471 class CTrackKeyFramerConstBlendable : public ITrackKeyFramer<CKeyT>
00472 {
00473 public:
00474 
00476         virtual const IAnimatedValue& getValue () const
00477         {
00478                 return _Value;
00479         }
00480         
00482         virtual void evalKey (  const CKeyT* previous, const CKeyT* next,
00483                                                         TAnimationTime datePrevious, TAnimationTime dateNext,
00484                                                         TAnimationTime date )
00485         {
00486                 // Const key.
00487                 if (previous)
00488                         copyToValue(_Value.Value, previous->Value);
00489                 else
00490                         if (next)
00491                                 copyToValue(_Value.Value, next->Value);
00492         }
00493 
00494 private:
00495         CAnimatedValueBlendable<T>              _Value;
00496 };
00497 
00498 
00499 // ***************************************************************************
00500 // ***************************************************************************
00501 // Linear Keyframer.
00502 // ***************************************************************************
00503 // ***************************************************************************
00504 
00505 
00506 // ***************************************************************************
00514 template<class CKeyT, class T>
00515 class CTrackKeyFramerLinear : public ITrackKeyFramer<CKeyT>
00516 {
00517 public:
00518 
00520         virtual const IAnimatedValue& getValue () const
00521         {
00522                 return _Value;
00523         }
00524         
00526         virtual void evalKey (  const CKeyT* previous, const CKeyT* next,
00527                                                         TAnimationTime datePrevious, TAnimationTime dateNext,
00528                                                         TAnimationTime date )
00529         {
00530                 if(previous && next)
00531                 {
00532                         // lerp from previous to cur.
00533                         date-= datePrevious;
00534                         date*= previous->OODeltaTime;
00535                         NLMISC::clamp(date, 0,1);
00536                         
00537                         // NB: in case of <CKeyInt,sint32> important that second terme is a float, so copyToValue(sint32, float) is used.
00538                         copyToValue(_Value.Value, previous->Value*(1.f-(float)date) + next->Value*(float)date);
00539                 }
00540                 else
00541                 {
00542                         if (previous)
00543                                 copyToValue(_Value.Value, previous->Value);
00544                         else
00545                                 if (next)
00546                                         copyToValue(_Value.Value, next->Value);
00547                 }
00548 
00549         }
00550 
00551 private:
00552         CAnimatedValueBlendable<T>      _Value;
00553 };
00554 
00555 
00556 
00557 // ***************************************************************************
00565 class CTrackKeyFramerLinear<CKeyQuat, CQuat> : public ITrackKeyFramer<CKeyQuat>
00566 {
00567 public:
00568 
00570         virtual const IAnimatedValue& getValue () const
00571         {
00572                 return _Value;
00573         }
00574         
00576         virtual void evalKey (  const CKeyQuat* previous, const CKeyQuat* next, 
00577                                                         TAnimationTime datePrevious, TAnimationTime dateNext,
00578                                                         TAnimationTime date )
00579         {
00580                 if(previous && next)
00581                 {
00582                         // slerp from previous to cur.
00583                         date-= datePrevious;
00584                         date*= previous->OODeltaTime;
00585                         NLMISC::clamp(date, 0,1);
00586                         _Value.Value= CQuat::slerp(previous->Value, next->Value, date);
00587                 }
00588                 else
00589                 {
00590                         if (previous)
00591                                 _Value.Value=previous->Value;
00592                         else
00593                                 if (next)
00594                                         _Value.Value=next->Value;
00595                 }
00596         }
00597 
00598 private:
00599         CAnimatedValueBlendable<CQuat>  _Value;
00600 };
00601 
00602 
00603 // ***************************************************************************
00611 class CTrackKeyFramerLinear<CKeyRGBA, NLMISC::CRGBA>: public ITrackKeyFramer<CKeyRGBA>
00612 {
00613 public:
00614 
00616         virtual const IAnimatedValue& getValue () const
00617         {
00618                 return _Value;
00619         }
00620         
00622         virtual void evalKey (  const CKeyRGBA* previous, const CKeyRGBA* next,
00623                                                         TAnimationTime datePrevious, TAnimationTime dateNext,
00624                                                         TAnimationTime date )
00625         {
00626                 if(previous && next)
00627                 {
00628                         // lerp from previous to cur.
00629                         date-= datePrevious;
00630                         date*= previous->OODeltaTime;
00631                         NLMISC::clamp(date, 0,1);
00632                         
00633                         // blend.
00634                         _Value.Value.blendFromui(previous->Value, next->Value, (uint)(date*256));
00635                 }
00636                 else
00637                 {
00638                         if (previous)
00639                                 _Value.Value= previous->Value;
00640                         else
00641                                 if (next)
00642                                         _Value.Value= next->Value;
00643                 }
00644         }
00645 
00646 private:
00647         CAnimatedValueBlendable<NLMISC::CRGBA>  _Value;
00648 };
00649 
00650 
00651 
00652 // ***************************************************************************
00653 // ***************************************************************************
00654 // TCB / Bezier Keyframer.
00655 // ***************************************************************************
00656 // ***************************************************************************
00657 
00658 
00659 // Template implementation for TCB and Bezier.
00660 #include "track_tcb.h"
00661 #include "track_bezier.h"
00662 
00663 
00664 
00665 // ***************************************************************************
00666 // ***************************************************************************
00667 // Predefined types for KeyFramer tracks.
00668 // ***************************************************************************
00669 // ***************************************************************************
00670 
00671 
00672 // Const tracks.
00673 class CTrackKeyFramerConstFloat : public CTrackKeyFramerConstBlendable<CKeyFloat,float>
00674 {
00675 public:
00676         NLMISC_DECLARE_CLASS (CTrackKeyFramerConstFloat);
00677 };
00678 class CTrackKeyFramerConstVector : public CTrackKeyFramerConstBlendable<CKeyVector, CVector>
00679 {
00680 public:
00681         NLMISC_DECLARE_CLASS (CTrackKeyFramerConstVector);
00682 };
00683 class CTrackKeyFramerConstQuat : public CTrackKeyFramerConstBlendable<CKeyQuat, CQuat>
00684 {
00685 public:
00686         NLMISC_DECLARE_CLASS (CTrackKeyFramerConstQuat);
00687 };
00688 class CTrackKeyFramerConstInt : public CTrackKeyFramerConstBlendable<CKeyInt, sint32>
00689 {
00690 public:
00691         NLMISC_DECLARE_CLASS (CTrackKeyFramerConstInt);
00692 };
00693 class CTrackKeyFramerConstRGBA : public CTrackKeyFramerConstBlendable<CKeyRGBA, NLMISC::CRGBA>
00694 {
00695 public:
00696         NLMISC_DECLARE_CLASS (CTrackKeyFramerConstRGBA);
00697 };
00698 
00699 class CTrackKeyFramerConstString : public CTrackKeyFramerConstNotBlendable<CKeyString, std::string>
00700 {
00701 public:
00702         NLMISC_DECLARE_CLASS (CTrackKeyFramerConstString);
00703 };
00704 class CTrackKeyFramerConstBool : public CTrackKeyFramerConstNotBlendable<CKeyBool, bool>
00705 {
00706 public:
00707         NLMISC_DECLARE_CLASS (CTrackKeyFramerConstBool);
00708 };
00709 
00710 
00711 // Linear tracks.
00712 class CTrackKeyFramerLinearFloat : public CTrackKeyFramerLinear<CKeyFloat, float>
00713 {
00714 public:
00715         NLMISC_DECLARE_CLASS (CTrackKeyFramerLinearFloat);
00716 };
00717 class CTrackKeyFramerLinearVector : public CTrackKeyFramerLinear<CKeyVector, CVector>
00718 {
00719 public:
00720         NLMISC_DECLARE_CLASS (CTrackKeyFramerLinearVector);
00721 };
00722 class CTrackKeyFramerLinearQuat : public CTrackKeyFramerLinear<CKeyQuat, CQuat>
00723 {
00724 public:
00725         NLMISC_DECLARE_CLASS (CTrackKeyFramerLinearQuat);
00726 };
00727 class CTrackKeyFramerLinearInt : public CTrackKeyFramerLinear<CKeyInt, sint32>
00728 {
00729 public:
00730         NLMISC_DECLARE_CLASS (CTrackKeyFramerLinearInt);
00731 };
00732 class CTrackKeyFramerLinearRGBA : public CTrackKeyFramerLinear<CKeyRGBA, NLMISC::CRGBA>
00733 {
00734 public:
00735         NLMISC_DECLARE_CLASS (CTrackKeyFramerLinearRGBA);
00736 };
00737 
00738 
00739 // TCB tracks.
00740 class CTrackKeyFramerTCBFloat : public CTrackKeyFramerTCB<CKeyTCBFloat, float>
00741 {
00742 public:
00743         NLMISC_DECLARE_CLASS (CTrackKeyFramerTCBFloat);
00744 };
00745 class CTrackKeyFramerTCBVector : public CTrackKeyFramerTCB<CKeyTCBVector, CVector>
00746 {
00747 public:
00748         NLMISC_DECLARE_CLASS (CTrackKeyFramerTCBVector);
00749 };
00750 class CTrackKeyFramerTCBQuat : public CTrackKeyFramerTCB<CKeyTCBQuat, NLMISC::CAngleAxis>
00751 {
00752 public:
00753         NLMISC_DECLARE_CLASS (CTrackKeyFramerTCBQuat);
00754 };
00755 class CTrackKeyFramerTCBInt : public CTrackKeyFramerTCB<CKeyTCBFloat, sint32>
00756 {
00757 public:
00758         NLMISC_DECLARE_CLASS (CTrackKeyFramerTCBInt);
00759 };
00760 class CTrackKeyFramerTCBRGBA : public CTrackKeyFramerTCB<CKeyTCBVector, NLMISC::CRGBA>
00761 {
00762 public:
00763         NLMISC_DECLARE_CLASS (CTrackKeyFramerTCBRGBA);
00764 };
00765 
00766 
00767 // Bezier tracks.
00768 class CTrackKeyFramerBezierFloat : public CTrackKeyFramerBezier<CKeyBezierFloat, float>
00769 {
00770 public:
00771         NLMISC_DECLARE_CLASS (CTrackKeyFramerBezierFloat);
00772 };
00773 class CTrackKeyFramerBezierVector : public CTrackKeyFramerBezier<CKeyBezierVector, CVector>
00774 {
00775 public:
00776         NLMISC_DECLARE_CLASS (CTrackKeyFramerBezierVector);
00777 };
00778 class CTrackKeyFramerBezierQuat : public CTrackKeyFramerBezier<CKeyBezierQuat, CQuat>
00779 {
00780 public:
00781         NLMISC_DECLARE_CLASS (CTrackKeyFramerBezierQuat);
00782 };
00783 class CTrackKeyFramerBezierInt : public CTrackKeyFramerBezier<CKeyBezierFloat, sint32>
00784 {
00785 public:
00786         NLMISC_DECLARE_CLASS (CTrackKeyFramerBezierInt);
00787 };
00788 class CTrackKeyFramerBezierRGBA : public CTrackKeyFramerBezier<CKeyBezierVector, NLMISC::CRGBA>
00789 {
00790 public:
00791         NLMISC_DECLARE_CLASS (CTrackKeyFramerBezierRGBA);
00792 };
00793 
00794 
00795 
00796 
00797 
00798 } // NL3D
00799 
00800 
00801 #endif // NL_TRACK_KEYFRAMER_H
00802 
00803 /* End of track_keyframer.h */