From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/track_tcb_h-source.html | 628 +++++++++++++++++++++++++++++++ 1 file changed, 628 insertions(+) create mode 100644 docs/doxygen/nel/track_tcb_h-source.html (limited to 'docs/doxygen/nel/track_tcb_h-source.html') diff --git a/docs/doxygen/nel/track_tcb_h-source.html b/docs/doxygen/nel/track_tcb_h-source.html new file mode 100644 index 00000000..b113a2ef --- /dev/null +++ b/docs/doxygen/nel/track_tcb_h-source.html @@ -0,0 +1,628 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# 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_tcb.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 
+00027 #ifndef NL_TRACK_H
+00028 #error "internal file included from track.h"
+00029 #endif
+00030 
+00031 // ***************************************************************************
+00032 // ***************************************************************************
+00033 // TCB Keyframes.
+00034 // ***************************************************************************
+00035 // ***************************************************************************
+00036 
+00037 
+00038 // ***************************************************************************
+00046 template<class CKeyT, class T, class TMapTimeCKey>
+00047 class CTCBTools
+00048 {
+00049 protected:
+00050         typedef typename TMapTimeCKey::iterator         TMapTimeCKeyIterator;
+00051 
+00052 
+00053 
+00055         void compileTCBEase(TMapTimeCKey &mapKey, bool loopMode)
+00056         {
+00057                 TMapTimeCKeyIterator    it= mapKey.begin();
+00058                 for(;it!=mapKey.end();it++)
+00059                 {
+00060                         TMapTimeCKeyIterator    next= it;
+00061                         next++;
+00062 
+00063                         // loop mgt. must compute ease from last to first (usefull if _RangeLock is false).
+00064                         if(next==mapKey.end() && loopMode && mapKey.size()>1)
+00065                                 next= mapKey.begin();
+00066 
+00067                         // Ease Precompute.
+00068                         //=================
+00069                         CKeyT   &key= it->second;
+00070                         if(next!=mapKey.end())
+00071                         {
+00072                                 float   e0= it->second.EaseFrom;
+00073                                 float   e1= next->second.EaseTo;
+00074                                 float   s =  e0 + e1;
+00075                                 
+00076                                 // "normalize".
+00077                                 if (s > 1.0f)
+00078                                 {
+00079                                         e0 = e0/s;
+00080                                         e1 = e1/s;
+00081                                 }
+00082 
+00083                                 // precalc ease factors.
+00084                                 key.Ease0= e0;
+00085                                 key.Ease1= e1;
+00086                                 key.EaseK= 1/(2.0f - e0 - e1);
+00087                                 if(e0)
+00088                                         key.EaseKOverEase0= key.EaseK / e0;
+00089                                 if(e1)
+00090                                         key.EaseKOverEase1= key.EaseK / e1;
+00091                         }
+00092                         else
+00093                         {
+00094                                 // force ease() to just return d (see ease()).
+00095                                 key.EaseK = 0.5f;
+00096                         }
+00097 
+00098                 }
+00099         }
+00100 
+00101         // ease time.
+00102         float ease(const CKeyT *key, float d)
+00103         {
+00104                 if (d==0.0f || d==1.0f) return d;
+00105                 // k==0.5f <=> e0+e1 == 0.
+00106                 if (key->EaseK == 0.5f) return d;
+00107 
+00108                 if (d < key->Ease0)
+00109                         return key->EaseKOverEase0 * d*d;
+00110                 else if (d < 1.0f - key->Ease1)
+00111                         return key->EaseK * (2.0f*d - key->Ease0);
+00112                 else
+00113                 {
+00114                         d = 1.0f - d;
+00115                         return 1.0f - key->EaseKOverEase1 * d*d;
+00116                 }
+00117         }
+00118 
+00119         // compute hermite factors.
+00120         void computeHermiteBasis(float d, float hb[4]) 
+00121         {
+00122                 float d2,d3,a;
+00123                 
+00124                 d2 = d*d;
+00125                 d3 = d2*d;
+00126                 a  = 3.0f*d2 - 2.0f*d3;
+00127                 hb[0] = 1.0f - a;
+00128                 hb[1] = a;
+00129                 hb[2] = d3 - 2.0f*d2 + d;
+00130                 hb[3] = d3 - d2;
+00131         }
+00132 
+00133 
+00134         // compute TCB tangents factors.
+00135         void computeTCBFactors(const CKeyT &key, float timeBefore, float time, float timeAfter, 
+00136                 float rangeDelta, bool firstKey, bool endKey, bool isLoop, float &ksm, float &ksp, float &kdm, float &kdp)
+00137         {
+00138                 float fp,fn;
+00139 
+00140                 if(isLoop || (!firstKey && !endKey))
+00141                 {
+00142                         float   dtm;
+00143                         // Compute Time deltas.
+00144                         if (firstKey)
+00145                         {
+00146                                 dtm = 0.5f * (rangeDelta + timeAfter - time);
+00147                                 fp = rangeDelta / dtm;
+00148                                 fn = (timeAfter - time) / dtm;
+00149                         }
+00150                         else if (endKey)
+00151                         {
+00152                                 dtm = 0.5f * (rangeDelta + time - timeBefore);
+00153                                 fp = rangeDelta / dtm;
+00154                                 fn = (time - timeBefore) / dtm;
+00155                         }
+00156                         else
+00157                         {
+00158                                 dtm = 0.5f * (timeAfter - timeBefore);
+00159                                 fp = (time - timeBefore) / dtm;
+00160                                 fn = (timeAfter - time) / dtm;
+00161                         }
+00162                         float   c= (float)fabs( key.Continuity );
+00163                         fp = fp + c - c * fp;
+00164                         fn = fn + c - c * fn;
+00165                 }
+00166                 else
+00167                 {
+00168                         // firstkey and lastkey of not loop track.
+00169                         fp = 1.0f;
+00170                         fn = 1.0f;
+00171                 }
+00172 
+00173                 // Compute tangents factors.
+00174                 float   tm,cm,cp,bm,bp,tmcm,tmcp;
+00175 
+00176                 cm = 1.0f - key.Continuity;
+00177                 tm = 0.5f * ( 1.0f - key.Tension );
+00178                 cp = 2.0f - cm;
+00179                 bm = 1.0f - key.Bias;
+00180                 bp = 2.0f - bm;
+00181                 tmcm = tm*cm;   tmcp = tm*cp;
+00182 
+00183                 // tgts factors.
+00184                 ksm = tmcm*bp*fp;       ksp = tmcp*bm*fp;
+00185                 kdm = tmcp*bp*fn;       kdp = tmcm*bm*fn;
+00186 
+00187         }
+00188 
+00189 };
+00190 
+00191 
+00192 // ***************************************************************************
+00200 template<class CKeyT, class T>
+00201 class CTrackKeyFramerTCB : public ITrackKeyFramer<CKeyT>, private CTCBTools<CKeyT, T, std::map<CAnimationTime, CKeyT> >
+00202 {
+00203 public:
+00204 
+00206         virtual const IAnimatedValue& getValue () const
+00207         {
+00208                 return _Value;
+00209         }
+00210         
+00211 protected:
+00212 
+00213 
+00214         typedef typename CKeyT::TValueType              TKeyValueType;
+00215 
+00216 
+00217 
+00219         // @{
+00220 
+00222         virtual void evalKey (  const CKeyT* previous, const CKeyT* next,
+00223                                                         CAnimationTime datePrevious, CAnimationTime dateNext,
+00224                                                         CAnimationTime date )
+00225         {
+00226                 if(previous && next)
+00227                 {
+00228                         // lerp from previous to cur.
+00229                         date-= datePrevious;
+00230                         date*= previous->OODeltaTime;
+00231                         NLMISC::clamp(date, 0,1);
+00232                         
+00233                         date = ease(previous, date);
+00234 
+00235                         float hb[4];
+00236                         computeHermiteBasis(date, hb);
+00237                         copyToValue(_Value.Value, 
+00238                                 previous->Value*hb[0] + next->Value*hb[1] + 
+00239                                 previous->TanFrom*hb[2] + next->TanTo*hb[3]);
+00240                 }
+00241                 else
+00242                 {
+00243                         if (previous)
+00244                                 copyToValue(_Value.Value, previous->Value);
+00245                         else
+00246                                 if (next)
+00247                                         copyToValue(_Value.Value, next->Value);
+00248                 }
+00249         }
+00250 
+00252         virtual void compile()
+00253         {
+00254                 ITrackKeyFramer<CKeyT>::compile();
+00255 
+00256                 // Ease Precompute.
+00257                 compileTCBEase(_MapKey, getLoopMode());
+00258 
+00259 
+00260                 // Tangents Precompute.
+00261                 sint    nKeys= _MapKey.size();
+00262                 if(nKeys<=1)
+00263                         return;
+00264 
+00265                 TMapTimeCKey::iterator  it= _MapKey.begin();                            // first key.
+00266                 TMapTimeCKey::iterator  itNext= it; itNext++;                           // second key.
+00267                 TMapTimeCKey::iterator  itPrev= _MapKey.end(); itPrev--;        // last key.
+00268 
+00269                 if(nKeys==2 && !getLoopMode())
+00270                 {
+00271                         computeTCBKeyLinear( it->second, itNext->second );
+00272                 }
+00273                 else
+00274                 {
+00275                         // rangeDelta is the length of effective Range - length of LastKey-FirstKey.
+00276                         // NB: if RangeLock, rangeDelta==0.
+00277                         float   rangeDelta;
+00278                         // NB: _RangeDelta has just been compiled in ITrackKeyFramer<CKeyT>::compile().
+00279                         rangeDelta= getCompiledRangeDelta();
+00280 
+00281                         // Compute all middle keys.
+00282                         for(;it!=_MapKey.end();)
+00283                         {
+00284                                 // Do the first key and the last key only in LoopMode.
+00285                                 // NB: we are the last if itNext==_MapKey.begin().
+00286                                 if(getLoopMode() || (it!=_MapKey.begin() && itNext!=_MapKey.begin()) )
+00287                                 {
+00288                                         computeTCBKey(itPrev->second, it->second, itNext->second, 
+00289                                                 itPrev->first, it->first, itNext->first, rangeDelta, 
+00290                                                 it==_MapKey.begin(), itNext==_MapKey.begin(), getLoopMode());
+00291                                 }
+00292 
+00293                                 // Next key!!
+00294                                 itPrev= it;
+00295                                 it++;
+00296                                 itNext++;
+00297                                 // loop.
+00298                                 if(itNext==_MapKey.end())
+00299                                         itNext= _MapKey.begin();
+00300                         }
+00301 
+00302                         // In not loop mode, compute first and last key, AFTER middle keys computed.
+00303                         if(!getLoopMode())
+00304                         {
+00305                                 TMapTimeCKey::iterator  it0= _MapKey.begin();                           // first key.
+00306                                 TMapTimeCKey::iterator  it1= it0; it1++;                                        // second key.
+00307                                 TMapTimeCKey::iterator  itLast= _MapKey.end();itLast--;         // last key.
+00308                                 TMapTimeCKey::iterator  itLastPrev= itLast;itLastPrev--;        // prev of last key.
+00309 
+00310                                 computeFirstKey(it0->second, it1->second);
+00311                                 computeLastKey(itLast->second, itLastPrev->second);
+00312                         }
+00313                 }
+00314         }
+00315 
+00316         // @}
+00317 
+00318 
+00319 // *****************
+00320 private:
+00321         CAnimatedValueBlendable<T>      _Value;
+00322 
+00323 
+00324 
+00325         void computeTCBKey(CKeyT &keyBefore, CKeyT &key, CKeyT &keyAfter, float timeBefore, float time, float timeAfter, 
+00326                 float rangeDelta, bool firstKey, bool endKey, bool isLoop)
+00327         {
+00328                 float   ksm,ksp,kdm,kdp;
+00329 
+00330                 // compute tangents factors.
+00331                 computeTCBFactors(key, timeBefore, time, timeAfter, rangeDelta, firstKey, endKey, isLoop, ksm,ksp,kdm,kdp);
+00332 
+00333                 // Delta.
+00334                 TKeyValueType   delm, delp;
+00335                 delm = key.Value - keyBefore.Value;
+00336                 delp = keyAfter.Value - key.Value;
+00337 
+00338                 // Tangents.
+00339                 key.TanTo       = delm*ksm + delp*ksp;
+00340                 key.TanFrom= delm*kdm + delp*kdp;
+00341 
+00342         }
+00343 
+00344         // compute 2 TCB keys for a not-loop track => "linear".
+00345         void computeTCBKeyLinear(CKeyT &key0, CKeyT &key1)
+00346         {
+00347                 float f0, f1;
+00348                 TKeyValueType   dv;
+00349                 
+00350                 f0 = 1.0f - key0.Tension;
+00351                 f1 = 1.0f - key1.Tension;
+00352                 dv = key1.Value - key0.Value;
+00353                 key0.TanFrom= dv * f0;
+00354                 key1.TanTo= dv * f1;
+00355         }
+00356 
+00357         // compute this AFTER computing key1.
+00358         void computeFirstKey(CKeyT &keyFirst, CKeyT &keyAfter)
+00359         {
+00360                 float tm;
+00361                 tm = 0.5f * (1.0f - keyFirst.Tension);
+00362                 keyFirst.TanFrom= tm * ((keyAfter.Value - keyFirst.Value) * 3.0f - keyAfter.TanTo);
+00363         }
+00364 
+00365         // compute this AFTER computing key(n-2).
+00366         void computeLastKey(CKeyT &keyLast, CKeyT &keyBefore)
+00367         {
+00368                 float tm;
+00369                 tm = 0.5f * (1.0f - keyLast.Tension);
+00370                 keyLast.TanTo= tm * ((keyLast.Value - keyBefore.Value) * 3.0f - keyBefore.TanFrom);
+00371         }
+00372 
+00373 
+00374 };
+00375 
+00376 
+00377 // ***************************************************************************
+00385 class CTrackKeyFramerTCB<CKeyTCBQuat, NLMISC::CAngleAxis> : public ITrackKeyFramer<CKeyTCBQuat>, 
+00386         private CTCBTools<CKeyTCBQuat, NLMISC::CAngleAxis, std::map<CAnimationTime, CKeyTCBQuat> >
+00387 {
+00388 public:
+00389 
+00391         virtual const IAnimatedValue& getValue () const
+00392         {
+00393                 return _Value;
+00394         }
+00395         
+00397         // @{
+00398 
+00400         virtual void evalKey (  const CKeyTCBQuat* previous, const CKeyTCBQuat* next, 
+00401                                                         CAnimationTime datePrevious, CAnimationTime dateNext,
+00402                                                         CAnimationTime date )
+00403         {
+00404                 if(previous && next)
+00405                 {
+00406                         // lerp from previous to cur.
+00407                         date-= datePrevious;
+00408                         date*= previous->OODeltaTime;
+00409                         NLMISC::clamp(date, 0,1);
+00410 
+00411                         // ease.
+00412                         date = ease(previous, date);
+00413 
+00414                         // quad slerp.
+00415                         _Value.Value= CQuat::squadrev(next->LocalAngleAxis, previous->Quat, previous->A, next->B, next->Quat, date);
+00416                 }
+00417                 else
+00418                 {
+00419                         if (previous)
+00420                                 _Value.Value= previous->Quat;
+00421                         else
+00422                                 if (next)
+00423                                         _Value.Value= next->Quat;
+00424                 }
+00425 
+00426         }
+00427 
+00429         virtual void compile()
+00430         {
+00431                 ITrackKeyFramer<CKeyTCBQuat>::compile();
+00432 
+00433                 // Ease Precompute.
+00434                 compileTCBEase(_MapKey, getLoopMode());
+00435 
+00436                 TMapTimeCKey::iterator  it;
+00437                 TMapTimeCKey::iterator  itNext;
+00438                 TMapTimeCKey::iterator  itPrev;
+00439 
+00440                 // Compute absolute quaternions.
+00441                 for (it= _MapKey.begin();it!=_MapKey.end();)
+00442                 {
+00443                         CKeyTCBQuat             &key= it->second;
+00444 
+00445                         // Compute Local AngleAxis.
+00446                         if(it!= _MapKey.begin())
+00447                         {
+00448                                 NLMISC::CMatrix         mat;
+00449                                 mat.setRot(itPrev->second.Quat);
+00450                                 mat.invert();
+00451                                 key.LocalAngleAxis.Axis= mat*key.Value.Axis;
+00452                                 key.LocalAngleAxis.Angle= key.Value.Angle;
+00453                         }
+00454                         else
+00455                                 key.LocalAngleAxis= key.Value;
+00456 
+00457 
+00458                         key.LocalAngleAxis.Axis.normalize();
+00459                         // make angle positive.
+00460                         if(key.LocalAngleAxis.Angle<0.f)
+00461                         {
+00462                                 key.LocalAngleAxis.Axis= -key.LocalAngleAxis.Axis;
+00463                                 key.LocalAngleAxis.Angle= -key.LocalAngleAxis.Angle;
+00464                         }
+00465 
+00466                         // relative quat
+00467                         key.Quat.setAngleAxis(key.LocalAngleAxis);
+00468 
+00469                         // absolute quat
+00470                         if (it!= _MapKey.begin())
+00471                                 key.Quat = itPrev->second.Quat * key.Quat;
+00472 
+00473                         // next key.
+00474                         itPrev= it;
+00475                         it++;
+00476                 }
+00477 
+00478                 // Tangents Precompute.
+00479                 sint    nKeys= _MapKey.size();
+00480                 if(nKeys<=1)
+00481                         return;
+00482 
+00483                 // rangeDelta is the length of effective Range - length of LastKey-FirstKey.
+00484                 // NB: if RangeLock, rangeDelta==0.
+00485                 float   rangeDelta;
+00486                 // NB: _RangeDelta has just been compiled in ITrackKeyFramer<CKeyTCBQuat>::compile().
+00487                 rangeDelta= getCompiledRangeDelta();
+00488 
+00489                 it= _MapKey.begin();                            // first key.
+00490                 itNext= it; itNext++;                           // second key.
+00491                 itPrev= _MapKey.end(); itPrev--;        // last key.
+00492 
+00493                 // Compute all keys.
+00494                 for(;it!=_MapKey.end();)
+00495                 {
+00496                         // NB: we are the last key if itNext==_MapKey.begin().
+00497                         computeTCBKey(itPrev->second, it->second, itNext->second, 
+00498                                 itPrev->first, it->first, itNext->first, rangeDelta, it==_MapKey.begin(), itNext==_MapKey.begin(), getLoopMode());
+00499 
+00500                         // Next key!!
+00501                         itPrev= it;
+00502                         it++;
+00503                         itNext++;
+00504                         // loop.
+00505                         if(itNext==_MapKey.end())
+00506                                 itNext= _MapKey.begin();
+00507                 }
+00508 
+00509         }
+00510 
+00511         // @}
+00512 
+00513 
+00514 // *****************
+00515 private:
+00516         CAnimatedValueBlendable<CQuat>  _Value;
+00517 
+00518 
+00519         void computeTCBKey(CKeyTCBQuat &keyBefore, CKeyTCBQuat &key, CKeyTCBQuat &keyAfter, float timeBefore, float time, float timeAfter, 
+00520                 float rangeDelta, bool firstKey, bool endKey, bool isLoop) 
+00521         {
+00522                 CQuat  qp, qm;
+00523                 
+00524                 // compute qm.
+00525                 if (!firstKey || isLoop)
+00526                 {
+00527                         float   angle= key.LocalAngleAxis.Angle;
+00528                         CVector &axis= key.LocalAngleAxis.Axis;
+00529 
+00530                         if (angle > 2*NLMISC::Pi- NLMISC::QuatEpsilon)
+00531                         {
+00532                                 qm.set(axis.x, axis.y, axis.z, 0.0f);
+00533                                 qm = qm.log();
+00534                         }
+00535                         else
+00536                         {
+00537                                 CQuat   qprev= keyBefore.Quat;
+00538                                 qprev.makeClosest(key.Quat);
+00539                                 qm = CQuat::lnDif(qprev, key.Quat);
+00540                         }
+00541                 }
+00542                 
+00543                 // compute qp.
+00544                 if (!endKey || isLoop)
+00545                 {
+00546                         float   angle= keyAfter.LocalAngleAxis.Angle;
+00547                         CVector &axis= keyAfter.LocalAngleAxis.Axis;
+00548 
+00549                         if (angle > 2*NLMISC::Pi- NLMISC::QuatEpsilon)
+00550                         {
+00551                                 qp.set(axis.x, axis.y, axis.z, 0.0f);
+00552                                 qp = qp.log();
+00553                         }
+00554                         else
+00555                         {
+00556                                 CQuat   qnext= keyAfter.Quat;
+00557                                 qnext.makeClosest(key.Quat);
+00558                                 qp = CQuat::lnDif(key.Quat, qnext);
+00559                         }
+00560                 }
+00561                 
+00562                 // not loop mgt.
+00563                 if (firstKey && !isLoop)
+00564                         qm = qp;
+00565                 if (endKey && !isLoop)
+00566                         qp = qm;
+00567 
+00568 
+00569                 // compute tangents factors.
+00570                 float   ksm, ksp, kdm, kdp;
+00571                 computeTCBFactors(key, timeBefore, time, timeAfter, rangeDelta, firstKey, endKey, isLoop, ksm,ksp,kdm,kdp);
+00572 
+00573 
+00574                 // A/B.
+00575                 CQuat   qa, qb;
+00576                 qb= (qm * (1.0f-ksm) + qp * (-ksp)        ) * 0.5f;
+00577                 qa= (qm * kdm            + qp * (kdp-1.0f) ) * 0.5f;
+00578                 qa = qa.exp();
+00579                 qb = qb.exp();
+00580 
+00581                 key.A = key.Quat * qa;
+00582                 key.B = key.Quat * qb;
+00583         }
+00584 
+00585 
+00586 
+00587 };
+00588 
+00589 
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1