From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- .../nel/animation__optimizer_8cpp-source.html | 694 +++++++++++++++++++++ 1 file changed, 694 insertions(+) create mode 100644 docs/doxygen/nel/animation__optimizer_8cpp-source.html (limited to 'docs/doxygen/nel/animation__optimizer_8cpp-source.html') diff --git a/docs/doxygen/nel/animation__optimizer_8cpp-source.html b/docs/doxygen/nel/animation__optimizer_8cpp-source.html new file mode 100644 index 00000000..44086727 --- /dev/null +++ b/docs/doxygen/nel/animation__optimizer_8cpp-source.html @@ -0,0 +1,694 @@ + + + + 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  
+

animation_optimizer.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2000-2002 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 #include "std3d.h"
+00027 
+00028 #include "3d/animation_optimizer.h"
+00029 #include "nel/misc/mem_stream.h"
+00030 #include "nel/misc/vectord.h"
+00031 #include "3d/track.h"
+00032 #include "3d/track_keyframer.h"
+00033 #include "3d/animation.h"
+00034 #include "3d/track_sampled_quat.h"
+00035 #include "3d/track_sampled_vector.h"
+00036 
+00037 
+00038 using   namespace NLMISC;
+00039 using   namespace std;
+00040 
+00041 
+00042 namespace NL3D 
+00043 {
+00044 
+00045 
+00046 // ***************************************************************************
+00047 CAnimationOptimizer::CAnimationOptimizer()
+00048 {
+00049         _SampleFrameRate= 30;
+00050         _QuaternionThresholdLowPrec= 1.0 - 0.0001;
+00051         _QuaternionThresholdHighPrec= 1.0 - 0.000001;
+00052         _VectorThresholdLowPrec= 0.001;
+00053         _VectorThresholdHighPrec= 0.0001;
+00054 }
+00055 
+00056 
+00057 // ***************************************************************************
+00058 void            CAnimationOptimizer::setQuaternionThreshold(double lowPrecThre, double highPrecThre)
+00059 {
+00060         nlassert(lowPrecThre>=0);
+00061         nlassert(highPrecThre>=0);
+00062         _QuaternionThresholdLowPrec= 1.0 - lowPrecThre;
+00063         _QuaternionThresholdHighPrec= 1.0 - highPrecThre;
+00064 }
+00065 
+00066 
+00067 // ***************************************************************************
+00068 void            CAnimationOptimizer::setVectorThreshold(double lowPrecThre, double highPrecThre)
+00069 {
+00070         nlassert(lowPrecThre>=0);
+00071         nlassert(highPrecThre>=0);
+00072         _VectorThresholdLowPrec= lowPrecThre;
+00073         _VectorThresholdHighPrec= highPrecThre;
+00074 }
+00075 
+00076 
+00077 // ***************************************************************************
+00078 void            CAnimationOptimizer::setSampleFrameRate(float frameRate)
+00079 {
+00080         nlassert(frameRate>0);
+00081         _SampleFrameRate= frameRate;
+00082 }
+00083 
+00084 
+00085 // ***************************************************************************
+00086 void            CAnimationOptimizer::optimize(const CAnimation &animIn, CAnimation &animOut)
+00087 {
+00088         // reset animOut
+00089         contReset(animOut);
+00090 
+00091         // Parse all tracks of the animation.
+00092         set<string>             setString;
+00093         animIn.getTrackNames (setString);
+00094         set<string>::iterator   it;
+00095 
+00096         for(it=setString.begin();it!=setString.end();it++)
+00097         {
+00098                 const string    &trackName= *it;
+00099                 uint    trackId= animIn.getIdTrackByName(trackName);
+00100                 nlassert(trackId!=CAnimation::NotFound);
+00101                 const ITrack    *track= animIn.getTrack(trackId);
+00102 
+00103                 // If the track is optimisable.
+00104                 ITrack  *newTrack;
+00105                 if(isTrackOptimisable(track))
+00106                 {
+00107                         // choose the threshold according to precision wanted
+00108                         if( isLowPrecisionTrack(trackName) )
+00109                         {
+00110                                 _QuaternionThreshold= _QuaternionThresholdLowPrec;
+00111                                 _VectorThreshold= _VectorThresholdLowPrec;
+00112                         }
+00113                         else
+00114                         {
+00115                                 _QuaternionThreshold= _QuaternionThresholdHighPrec;
+00116                                 _VectorThreshold= _VectorThresholdHighPrec;
+00117                         }
+00118 
+00119                         // optimize it.
+00120                         newTrack= optimizeTrack(track);
+00121                 }
+00122                 else
+00123                 {
+00124                         // just clone it.
+00125                         newTrack= cloneTrack(track);
+00126                 }
+00127 
+00128                 // Add it to the animation
+00129                 animOut.addTrack(trackName, newTrack);
+00130         }
+00131 
+00132         // Set min animation length
+00133         animOut.setMinEndTime (animIn.getEndTime ());
+00134         nlassert (animOut.getEndTime() == animIn.getEndTime());
+00135 }
+00136 
+00137 // ***************************************************************************
+00138 ITrack          *CAnimationOptimizer::cloneTrack(const ITrack   *trackIn)
+00139 {
+00140         CMemStream      memStream;
+00141 
+00142         // write to the stream.
+00143         ITrack  *trackInSerial= const_cast<ITrack*>(trackIn);
+00144         memStream.serialPolyPtr(trackInSerial);
+00145 
+00146         // read from the stream.
+00147         memStream.invert();
+00148         ITrack  *ret= NULL;
+00149         memStream.serialPolyPtr(ret);
+00150 
+00151         return ret;
+00152 }
+00153 
+00154 
+00155 // ***************************************************************************
+00156 bool            CAnimationOptimizer::isTrackOptimisable(const ITrack    *trackIn)
+00157 {
+00158         nlassert(trackIn);
+00159 
+00160         // If the track is a Linear, Bezier or a TCB track, suppose we can optimize it. Constant may not be interressant....
+00161         if(     dynamic_cast<const CTrackKeyFramerTCBQuat*>(trackIn) || 
+00162                 dynamic_cast<const CTrackKeyFramerBezierQuat*>(trackIn) ||
+00163                 dynamic_cast<const CTrackKeyFramerLinearQuat*>(trackIn) )
+00164                 return true;
+00165 
+00166         // If the track is a Linear, Bezier or a TCB track, suppose we can optimize it. Constant may not be interressant....
+00167         if(     dynamic_cast<const CTrackKeyFramerTCBVector*>(trackIn) || 
+00168                 dynamic_cast<const CTrackKeyFramerBezierVector*>(trackIn) ||
+00169                 dynamic_cast<const CTrackKeyFramerLinearVector*>(trackIn) )
+00170                 return true;
+00171 
+00172         return false;
+00173 }
+00174 
+00175 
+00176 // ***************************************************************************
+00177 ITrack          *CAnimationOptimizer::optimizeTrack(const ITrack        *trackIn)
+00178 {
+00179         // Get track param.
+00180         float beginTime= trackIn->getBeginTime();
+00181         float endTime= trackIn->getEndTime();
+00182         nlassert(endTime>=beginTime);
+00183 
+00184         // Get num Sample 
+00185         uint    numSamples= (uint)ceil( (endTime-beginTime)*_SampleFrameRate);
+00186         numSamples= max(1U, numSamples);
+00187         nlassert(numSamples<65535);
+00188 
+00189 
+00190         // Optimize Quaternion track??
+00191         //================
+00192         if( dynamic_cast<const CAnimatedValueQuat *>(&trackIn->getValue()) )
+00193         {
+00194                 // sample the animation. Store result in _TimeList/_QuatKeyList
+00195                 sampleQuatTrack(trackIn, beginTime, endTime, numSamples);
+00196 
+00197                 // check if the sampled track can be reduced to a TrackDefaultQuat. Test _QuatKeyList.
+00198                 if( testConstantQuatTrack() )
+00199                 {
+00200                         // create a default Track Quat.
+00201                         CTrackDefaultQuat       *trackDefault= new CTrackDefaultQuat;
+00202                         // setup the uniform value.
+00203                         trackDefault->setValue(_QuatKeyList[0]);
+00204 
+00205                         // return the result.
+00206                         return trackDefault;
+00207                 }
+00208                 // else optimize the sampled animation, and build.
+00209                 else
+00210                 {
+00211                         // optimize.
+00212                         optimizeQuatTrack();
+00213 
+00214                         // Create a sampled quaternion track
+00215                         CTrackSampledQuat       *trackSQ= new CTrackSampledQuat;
+00216 
+00217                         // Copy loop from track.
+00218                         trackSQ->setLoopMode(trackIn->getLoopMode());
+00219 
+00220                         // Build it.
+00221                         trackSQ->build(_TimeList, _QuatKeyList, beginTime, endTime);
+00222 
+00223                         // return result.
+00224                         return trackSQ;
+00225                 }
+00226         }
+00227         // Optimize Position track??
+00228         //================
+00229         else if( dynamic_cast<const CAnimatedValueVector *>(&trackIn->getValue()) )
+00230         {
+00231                 // sample the animation. Store result in _TimeList/_VectorKeyList
+00232                 sampleVectorTrack(trackIn, beginTime, endTime, numSamples);
+00233 
+00234                 // check if the sampled track can be reduced to a TrackDefaultVector. Test _VectorKeyList.
+00235                 if( testConstantVectorTrack() )
+00236                 {
+00237                         // create a default Track Vector.
+00238                         CTrackDefaultVector     *trackDefault= new CTrackDefaultVector;
+00239                         // setup the uniform value.
+00240                         trackDefault->setValue(_VectorKeyList[0]);
+00241 
+00242                         // return the result.
+00243                         return trackDefault;
+00244                 }
+00245                 // else optimize the sampled animation, and build.
+00246                 else
+00247                 {
+00248                         // optimize.
+00249                         optimizeVectorTrack();
+00250 
+00251                         // Create a sampled Vector track
+00252                         CTrackSampledVector     *trackSV= new CTrackSampledVector;
+00253 
+00254                         // Copy loop from track.
+00255                         trackSV->setLoopMode(trackIn->getLoopMode());
+00256 
+00257                         // Build it.
+00258                         trackSV->build(_TimeList, _VectorKeyList, beginTime, endTime);
+00259 
+00260                         // return result.
+00261                         return trackSV;
+00262                 }
+00263         }
+00264         else
+00265         {
+00266                 // Must be a quaternion track or vector track for now.
+00267                 nlstop;
+00268                 // Avoid warning.
+00269                 return cloneTrack(trackIn);
+00270         }
+00271 }
+00272 
+00273 
+00274 // ***************************************************************************
+00275 // ***************************************************************************
+00276 // Quaternion optimisation
+00277 // ***************************************************************************
+00278 // ***************************************************************************
+00279 
+00280 
+00281 // ***************************************************************************
+00282 void            CAnimationOptimizer::sampleQuatTrack(const ITrack *trackIn, float beginTime, float endTime, uint numSamples)
+00283 {
+00284         // resize tmp samples
+00285         _TimeList.resize(numSamples);
+00286         _QuatKeyList.resize(numSamples);
+00287 
+00288         // Sample the animation.
+00289         float   t= beginTime;
+00290         float   dt= 0;
+00291         if(numSamples>1)
+00292                 dt= (endTime-beginTime)/(numSamples-1);
+00293         for(uint i=0;i<numSamples; i++, t+=dt)
+00294         {
+00295                 CQuat   quat;
+00296 
+00297                 // make exact endTime match (avoid precision problem)
+00298                 if(i==numSamples-1)
+00299                         t= endTime;
+00300 
+00301                 // evaluate the track
+00302                 const_cast<ITrack*>(trackIn)->interpolate(t, quat);
+00303 
+00304                 // normalize this quaternion
+00305                 quat.normalize();
+00306 
+00307                 // force on same hemisphere according to precedent frame.
+00308                 if(i>0)
+00309                 {
+00310                         quat.makeClosest(_QuatKeyList[i-1]);
+00311                 }
+00312 
+00313                 // store time and key.
+00314                 _TimeList[i]= i;
+00315                 _QuatKeyList[i]= quat;
+00316         }
+00317 
+00318 }
+00319 
+00320 // ***************************************************************************
+00321 bool            CAnimationOptimizer::testConstantQuatTrack()
+00322 {
+00323         uint    numSamples= _QuatKeyList.size();
+00324         nlassert(numSamples>0);
+00325 
+00326         // Get the first sample as the reference quaternion, and test others from this one.
+00327         CQuat   quatRef= _QuatKeyList[0];
+00328         for(uint i=0;i<numSamples;i++)
+00329         {
+00330                 // All values must be nearly equal to the reference quaternion.
+00331                 if(!nearlySameQuaternion(quatRef, _QuatKeyList[i]))
+00332                         return false;
+00333         }
+00334 
+00335         // ok.
+00336         return true;
+00337 }
+00338 
+00339 
+00340 // ***************************************************************************
+00341 void            CAnimationOptimizer::optimizeQuatTrack()
+00342 {
+00343         uint    numSamples= _QuatKeyList.size();
+00344         nlassert(numSamples>0);
+00345 
+00346         // <=2 key? => no opt possible..
+00347         if(numSamples<=2)
+00348                 return;
+00349 
+00350         // prepare dest opt
+00351         std::vector<uint16>             optTimeList;
+00352         std::vector<CQuat>              optKeyList;
+00353         optTimeList.reserve(numSamples);
+00354         optKeyList.reserve(numSamples);
+00355 
+00356         // Add the first key.
+00357         optTimeList.push_back(_TimeList[0]);
+00358         optKeyList.push_back(_QuatKeyList[0]);
+00359         double  timeRef= _TimeList[0];
+00360         CQuatD  quatRef= _QuatKeyList[0];
+00361 
+00362         // For all keys, but the first and the last, test if can remove them.
+00363         for(uint i=1; i<numSamples-1; i++)
+00364         {
+00365                 CQuatD  quatCur= _QuatKeyList[i];
+00366                 CQuatD  quatNext= _QuatKeyList[i+1];
+00367                 double  timeCur= _TimeList[i];
+00368                 double  timeNext= _TimeList[i+1];
+00369 
+00370                 // must add the key?
+00371                 bool    mustAdd= false;
+00372 
+00373                 // If the Delta time are too big, abort (CTrackSampledQuat limitation)
+00374                 if(timeNext-timeRef>255)
+00375                 {
+00376                         mustAdd= true;
+00377                 }
+00378                 // If the next quaternion or the current quaternion are not on same hemisphere than ref, abort.
+00379                 else if( CQuatD::dotProduct(quatCur, quatRef)<0 || CQuatD::dotProduct(quatNext, quatRef)<0 )
+00380                 {
+00381                         mustAdd= true;
+00382                 }
+00383                 // else, test interpolation
+00384                 else
+00385                 {
+00386                         // If the 3 quats are nearly equals, it is ok (avoid interpolation)
+00387                         if( nearlySameQuaternion(quatRef, quatCur) && nearlySameQuaternion(quatRef, quatNext) )
+00388                                 mustAdd= false;
+00389                         else
+00390                         {
+00391                                 // interpolate.
+00392                                 CQuatD  quatInterpolated;
+00393                                 double  t= (timeCur-timeRef)/(timeNext/timeRef);
+00394                                 quatInterpolated= CQuatD::slerp(quatRef, quatNext, (float)t);
+00395 
+00396                                 // test if cur and interpolate are equal.
+00397                                 if( !nearlySameQuaternion(quatCur, quatInterpolated) )
+00398                                         mustAdd= true;
+00399                         }
+00400                 }
+00401 
+00402                 // If must add the key to the optimized track.
+00403                 if(mustAdd)
+00404                 {
+00405                         optTimeList.push_back(_TimeList[i]);
+00406                         optKeyList.push_back(_QuatKeyList[i]);
+00407                         timeRef= _TimeList[i];
+00408                         quatRef= _QuatKeyList[i];
+00409                 }
+00410         }
+00411 
+00412         // Add the last key.
+00413         optTimeList.push_back(_TimeList[numSamples-1]);
+00414         optKeyList.push_back(_QuatKeyList[numSamples-1]);
+00415 
+00416         // copy the optimized track to the main one.
+00417         _TimeList= optTimeList;
+00418         _QuatKeyList= optKeyList;
+00419 }
+00420 
+00421 
+00422 // ***************************************************************************
+00423 bool            CAnimationOptimizer::nearlySameQuaternion(const CQuatD &quat0, const CQuatD &quat1)
+00424 {
+00425         // true if exactly same, or exactly inverse
+00426         if(quat0==quat1 || quat0==-quat1)
+00427                 return true;
+00428 
+00429         // Else compute the rotation to go from qRef to q. Use double for better presion.
+00430         CQuatD  quatDif;
+00431         quatDif= quat1 * quat0.conjugate();
+00432         // inverse the quaternion if necessary. ie make closest to the identity quaternion.
+00433         if(quatDif.w<0)
+00434                 quatDif= -quatDif;
+00435 
+00436         // compare "angle threshold"
+00437         return (quatDif.w >= _QuaternionThreshold);
+00438 }
+00439 
+00440 
+00441 // ***************************************************************************
+00442 // ***************************************************************************
+00443 // Vector optimisation
+00444 // ***************************************************************************
+00445 // ***************************************************************************
+00446 
+00447 
+00448 // ***************************************************************************
+00449 void            CAnimationOptimizer::sampleVectorTrack(const ITrack *trackIn, float beginTime, float endTime, uint numSamples)
+00450 {
+00451         // resize tmp samples
+00452         _TimeList.resize(numSamples);
+00453         _VectorKeyList.resize(numSamples);
+00454 
+00455         // Sample the animation.
+00456         float   t= beginTime;
+00457         float   dt= 0;
+00458         if(numSamples>1)
+00459                 dt= (endTime-beginTime)/(numSamples-1);
+00460         for(uint i=0;i<numSamples; i++, t+=dt)
+00461         {
+00462                 CVector vector;
+00463 
+00464                 // make exact endTime match (avoid precision problem)
+00465                 if(i==numSamples-1)
+00466                         t= endTime;
+00467 
+00468                 // evaluate the track
+00469                 const_cast<ITrack*>(trackIn)->interpolate(t, vector);
+00470 
+00471                 // store time and key.
+00472                 _TimeList[i]= i;
+00473                 _VectorKeyList[i]= vector;
+00474         }
+00475 
+00476 }
+00477 
+00478 // ***************************************************************************
+00479 bool            CAnimationOptimizer::testConstantVectorTrack()
+00480 {
+00481         uint    numSamples= _VectorKeyList.size();
+00482         nlassert(numSamples>0);
+00483 
+00484         // Get the first sample as the reference Vectorer, and test others from this one.
+00485         CVector vectorRef= _VectorKeyList[0];
+00486         for(uint i=0;i<numSamples;i++)
+00487         {
+00488                 // All values must be nearly equal to the reference vector.
+00489                 if(!nearlySameVector(vectorRef, _VectorKeyList[i]))
+00490                         return false;
+00491         }
+00492 
+00493         // ok.
+00494         return true;
+00495 }
+00496 
+00497 
+00498 // ***************************************************************************
+00499 void            CAnimationOptimizer::optimizeVectorTrack()
+00500 {
+00501         uint    numSamples= _VectorKeyList.size();
+00502         nlassert(numSamples>0);
+00503 
+00504         // <=2 key? => no opt possible..
+00505         if(numSamples<=2)
+00506                 return;
+00507 
+00508         // prepare dest opt
+00509         std::vector<uint16>             optTimeList;
+00510         std::vector<CVector>    optKeyList;
+00511         optTimeList.reserve(numSamples);
+00512         optKeyList.reserve(numSamples);
+00513 
+00514         // Add the first key.
+00515         optTimeList.push_back(_TimeList[0]);
+00516         optKeyList.push_back(_VectorKeyList[0]);
+00517         double          timeRef= _TimeList[0];
+00518         CVectorD        vectorRef= _VectorKeyList[0];
+00519 
+00520         // For all keys, but the first and the last, test if can remove them.
+00521         for(uint i=1; i<numSamples-1; i++)
+00522         {
+00523                 CVectorD        vectorCur= _VectorKeyList[i];
+00524                 CVectorD        vectorNext= _VectorKeyList[i+1];
+00525                 double  timeCur= _TimeList[i];
+00526                 double  timeNext= _TimeList[i+1];
+00527 
+00528                 // must add the key?
+00529                 bool    mustAdd= false;
+00530 
+00531                 // If the Delta time are too big, abort (CTrackSampledVector limitation)
+00532                 if(timeNext-timeRef>255)
+00533                 {
+00534                         mustAdd= true;
+00535                 }
+00536                 // else, test interpolation
+00537                 else
+00538                 {
+00539                         // If the 3 Vectors are nearly equals, it is ok (avoid interpolation)
+00540                         if( nearlySameVector(vectorRef, vectorCur) && nearlySameVector(vectorRef, vectorNext) )
+00541                                 mustAdd= false;
+00542                         else
+00543                         {
+00544                                 // interpolate.
+00545                                 CVectorD        vectorInterpolated;
+00546                                 double  t= (timeCur-timeRef)/(timeNext/timeRef);
+00547                                 vectorInterpolated= vectorRef*(1-t) + vectorNext*t;
+00548 
+00549                                 // test if cur and interpolate are equal.
+00550                                 if( !nearlySameVector(vectorCur, vectorInterpolated) )
+00551                                         mustAdd= true;
+00552                         }
+00553                 }
+00554 
+00555                 // If must add the key to the optimized track.
+00556                 if(mustAdd)
+00557                 {
+00558                         optTimeList.push_back(_TimeList[i]);
+00559                         optKeyList.push_back(_VectorKeyList[i]);
+00560                         timeRef= _TimeList[i];
+00561                         vectorRef= _VectorKeyList[i];
+00562                 }
+00563         }
+00564 
+00565         // Add the last key.
+00566         optTimeList.push_back(_TimeList[numSamples-1]);
+00567         optKeyList.push_back(_VectorKeyList[numSamples-1]);
+00568 
+00569         // copy the optimized track to the main one.
+00570         _TimeList= optTimeList;
+00571         _VectorKeyList= optKeyList;
+00572 }
+00573 
+00574 
+00575 // ***************************************************************************
+00576 bool            CAnimationOptimizer::nearlySameVector(const CVectorD &v0, const CVectorD &v1)
+00577 {
+00578         // true if exactly same
+00579         if(v0==v1)
+00580                 return true;
+00581 
+00582         // Else compute the dif, use double for better precision
+00583         CVectorD        vDif;
+00584         vDif= v1-v0;
+00585 
+00586         // compare norm
+00587         return (vDif.norm() <= _VectorThreshold);
+00588 }
+00589 
+00590 
+00591 // ***************************************************************************
+00592 // ***************************************************************************
+00593 // LowPrecisionTrack
+00594 // ***************************************************************************
+00595 // ***************************************************************************
+00596 
+00597 
+00598 // ***************************************************************************
+00599 void            CAnimationOptimizer::addLowPrecisionTrack(const std::string &name)
+00600 {
+00601         _LowPrecTrackKeyName.push_back(name);
+00602 }
+00603 
+00604 // ***************************************************************************
+00605 void            CAnimationOptimizer::clearLowPrecisionTracks()
+00606 {
+00607         _LowPrecTrackKeyName.clear();
+00608 }
+00609 
+00610 // ***************************************************************************
+00611 bool            CAnimationOptimizer::isLowPrecisionTrack(const std::string &trackName)
+00612 {
+00613         for(uint i=0; i<_LowPrecTrackKeyName.size(); i++)
+00614         {
+00615                 // if find a substr of the key, it is a low prec track
+00616                 if( trackName.find(_LowPrecTrackKeyName[i]) != string::npos )
+00617                         return true;
+00618         }
+00619 
+00620         // no key found
+00621         return false;
+00622 }
+00623 
+00624 
+00625 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1