ps_ribbon_base.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2001 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "std3d.h"
00025 
00026 #include "nel/misc/common.h"
00027 #include "nel/3d/ps_ribbon_base.h"
00028 #include "nel/3d/particle_system.h"
00029 
00030 namespace NL3D
00031 {
00032 
00034 //  CPSRibbonBase implementation  //
00036 
00037 
00039 static inline void BuildHermiteVector(const NLMISC::CVector &P0,
00040                                const NLMISC::CVector &P1,
00041                                const NLMISC::CVector &T0,
00042                                const NLMISC::CVector &T1,
00043                                      NLMISC::CVector &dest,
00044                                float lambda
00045                                )
00046 {
00047     NL_PS_FUNC(BuildHermiteVector)
00048     const float lambda2 = lambda * lambda;
00049     const float lambda3 = lambda2 * lambda;
00050     const float h1 = 2 * lambda3 - 3 * lambda2 + 1;
00051     const float h2 = - 2 * lambda3 + 3 * lambda2;
00052     const float h3 = lambda3 - 2 * lambda2 + lambda;
00053     const float h4 = lambda3 - lambda2;
00055     dest.set (h1 * P0.x + h2 * P1.x + h3 * T0.x + h4 * T1.x,
00056               h1 * P0.y + h2 * P1.y + h3 * T0.y + h4 * T1.y,
00057               h1 * P0.z + h2 * P1.z + h3 * T0.z + h4 * T1.z);
00058 
00059 }
00060 
00062 static inline void BuildLinearVector(const NLMISC::CVector &P0,
00063                                      const NLMISC::CVector &P1,
00064                                      NLMISC::CVector &dest,
00065                                      float lambda,
00066                                      float oneMinusLambda
00067                                     )
00068 {
00069     NL_PS_FUNC(BuildLinearVector)
00070     dest.set (lambda * P1.x + oneMinusLambda * P0.x,
00071               lambda * P1.y + oneMinusLambda * P0.y,
00072               lambda * P1.z + oneMinusLambda * P0.z);
00073 }
00074 
00075 
00076 const uint EndRibbonStorage = 1;
00077 
00078 
00079 //=======================================================
00080 CPSRibbonBase::CPSRibbonBase() : _NbSegs(8),
00081                                  _SegDuration(0.02f),
00082                                  _Parametric(false),
00083                                  _RibbonIndex(0),
00084                                  _MatrixMode(FatherMatrix),
00085                                  _LastUpdateDate(0),
00086                                  _RibbonMode(VariableSize),
00087                                  _InterpolationMode(Hermitte),
00088                                  _RibbonLength(1),
00089                                  _SegLength(_RibbonLength / _NbSegs),
00090                                  _LODDegradation(1)
00091 
00092 {
00093     NL_PS_FUNC(CPSRibbonBase_CPSRibbonBase)
00094     initDateVect();
00095 }
00096 
00097 //=======================================================
00098 void CPSRibbonBase::setMatrixMode(TMatrixMode matrixMode)
00099 {
00100     NL_PS_FUNC(CPSRibbonBase_setMatrixMode)
00101     if (matrixMode == _MatrixMode) return;
00102     if (_Owner) resetFromOwner();
00103     _MatrixMode = matrixMode;
00104 }
00105 
00106 //=======================================================
00107 void    CPSRibbonBase::setRibbonLength(float length)
00108 {
00109     NL_PS_FUNC(CPSRibbonBase_setRibbonLength)
00110     nlassert(length > 0.f);
00111     _RibbonLength = length;
00112     _SegLength = length / _NbSegs;
00113 }
00114 
00115 //=======================================================
00116 void    CPSRibbonBase::setRibbonMode(TRibbonMode mode)
00117 {
00118     NL_PS_FUNC(CPSRibbonBase_setRibbonMode)
00119     nlassert(mode < RibbonModeLast);
00120     _RibbonMode = mode;
00121 }
00122 
00123 
00124 //=======================================================
00125 void    CPSRibbonBase::setInterpolationMode(TInterpolationMode mode)
00126 {
00127     NL_PS_FUNC(CPSRibbonBase_setInterpolationMode)
00128     nlassert(mode < InterpModeLast);
00129     _InterpolationMode = mode;
00130 }
00131 
00132 //=======================================================
00133 void    CPSRibbonBase::setTailNbSeg(uint32 nbSegs)
00134 {
00135     NL_PS_FUNC(CPSRibbonBase_setTailNbSeg)
00136     nlassert(nbSegs >= 1);
00137     _NbSegs = nbSegs;
00138     _RibbonIndex = 0;
00139     if (_Owner)
00140     {
00141         resize(_Owner->getMaxSize());
00142     }
00143     initDateVect();
00144 }
00145 
00146 
00147 //=======================================================
00148 void    CPSRibbonBase::setSegDuration(TAnimationTime ellapsedTime)
00149 {
00150     NL_PS_FUNC(CPSRibbonBase_setSegDuration)
00151     _SegDuration = ellapsedTime;
00152 
00153 }
00154 
00155 //=======================================================
00156 void    CPSRibbonBase::updateGlobals()
00157 {
00158     NL_PS_FUNC(CPSRibbonBase_updateGlobals)
00159     nlassert(!_Parametric);
00160     nlassert(_Owner);
00161     const uint size = _Owner->getSize();
00162     if (!size) return;
00163     const TAnimationTime currDate = _Owner->getOwner()->getSystemDate() + CParticleSystem::RealEllapsedTime;
00164     if (currDate  - _LastUpdateDate >= _SegDuration)
00165     {
00166         if (_RibbonIndex == 0) _RibbonIndex = _NbSegs + EndRibbonStorage;
00167         else --_RibbonIndex;
00168 
00170         ::memmove(&_SamplingDate[1], &_SamplingDate[0], sizeof(float) * (_NbSegs + EndRibbonStorage));
00171         _LastUpdateDate = currDate;
00172     }
00173 
00175     _SamplingDate[0] = currDate;
00176 
00178     TPSMatrixMode mm = convertMatrixMode();
00179     if (mm == _Owner->getMatrixMode())
00180     {
00181         // trail reside in the same coord system -> no conversion needed
00182         TPSAttribVector::iterator posIt = _Owner->getPos().begin();
00183         NLMISC::CVector *currIt = &_Ribbons[_RibbonIndex];
00184         uint k = size;
00185         for (;;)
00186         {
00187             *currIt = *posIt;
00188             --k;
00189             if (!k) break;
00190             ++posIt;
00191             currIt += (_NbSegs + 1 + EndRibbonStorage);
00192         }
00193     }
00194     else
00195     {
00196         nlassert(_Owner->getOwner());
00197         const CMatrix &mat = CPSLocated::getConversionMatrix(*_Owner->getOwner(), mm, _Owner->getMatrixMode());
00198         TPSAttribVector::iterator posIt = _Owner->getPos().begin();
00199         NLMISC::CVector *currIt = &_Ribbons[_RibbonIndex];
00200         uint k = size;
00201         for (;;)
00202         {
00203             *currIt = mat * *posIt;
00204             --k;
00205             if (!k) break;
00206             ++posIt;
00207             currIt += (_NbSegs + 1 + EndRibbonStorage);
00208         }
00209     }
00210 }
00211 
00212 
00213 //=======================================================
00214 void    CPSRibbonBase::computeHermitteRibbon(uint index, NLMISC::CVector *dest, uint stride /* = sizeof(NLMISC::CVector)*/)
00215 {
00216     NL_PS_FUNC(CPSRibbonBase_CVector )
00217     nlassert(!_Parametric);
00218     NLMISC::CVector *startIt = &_Ribbons[(_NbSegs + 1 + EndRibbonStorage) * index];
00219     NLMISC::CVector *endIt   = startIt + (_NbSegs + 1 + EndRibbonStorage);
00220     NLMISC::CVector *currIt  = startIt + _RibbonIndex;
00221     const NLMISC::CVector *firstIt = currIt;
00222     NLMISC::CVector *nextIt  = currIt + 1;
00223     if (nextIt == endIt) nextIt = startIt;
00224     NLMISC::CVector *nextNextIt = nextIt + 1;
00225     if (nextNextIt == endIt) nextNextIt = startIt;
00226     float *date = &_SamplingDate[0];
00227 
00228     NLMISC::CVector t0 = (*nextIt - *currIt);
00229     NLMISC::CVector t1 = 0.5f * (*nextNextIt - *currIt);
00230 
00231     uint leftToDo = _UsedNbSegs + 1;
00232 
00233     float lambda = 0.f;
00234     float lambdaStep = 1.f;
00235 
00236 
00237     for (;;)
00238     {
00239         float dt = date[0] - date[1];
00240 
00241         if (dt < 10E-6f) // we reached the start of ribbon
00242         {
00243 
00244             do
00245             {
00246                 *dest = *currIt;
00247                 #ifdef NL_DEBUG
00248                     nlassert(NLMISC::isValidDouble(dest->x));
00249                     nlassert(NLMISC::isValidDouble(dest->y));
00250                     nlassert(NLMISC::isValidDouble(dest->z));
00251                 #endif
00252                 dest  = (NLMISC::CVector *) ((uint8 *) dest + stride);
00253             }
00254             while (--leftToDo);
00255             return;
00256         }
00257 
00258         float newLambdaStep = _UsedSegDuration / dt;
00259         // readapt lambda
00260         lambda *= newLambdaStep / lambdaStep;
00261         lambdaStep = newLambdaStep;
00262         for(;;)
00263         {
00264             if (lambda >= 1.f) break;
00266             BuildHermiteVector(*currIt, *nextIt, t0, t1, *dest, lambda);
00267             #ifdef NL_DEBUG
00268                 nlassert(NLMISC::isValidDouble(dest->x));
00269                 nlassert(NLMISC::isValidDouble(dest->y));
00270                 nlassert(NLMISC::isValidDouble(dest->z));
00271             #endif
00272             dest  = (NLMISC::CVector *) ((uint8 *) dest + stride);
00273             -- leftToDo;
00274             if (!leftToDo) return;
00275             lambda += lambdaStep;
00276         }
00277 
00278         ++date;
00279         lambda -= 1.f;
00280 
00281         // Start new segment and compute new tangents
00282         t0 = t1;
00283         currIt = nextIt;
00284         nextIt = nextNextIt;
00285         ++nextNextIt;
00286         if (nextNextIt == endIt) nextNextIt = startIt;
00287         if (nextNextIt == firstIt)
00288         {
00289             t1 = *nextIt - *currIt;
00290         }
00291         else
00292         {
00293             t1 = 0.5f * (*nextNextIt - *currIt);
00294         }
00295     }
00296 }
00297 
00298 //=======================================================
00299 void CPSRibbonBase::computeLinearRibbon(uint index, NLMISC::CVector *dest, uint stride)
00300 {
00301     NL_PS_FUNC(CPSRibbonBase_computeLinearRibbon)
00302     nlassert(!_Parametric);
00303     NLMISC::CVector *startIt = &_Ribbons[(_NbSegs + 1 + EndRibbonStorage) * index];
00304     NLMISC::CVector *endIt   = startIt + (_NbSegs + 1 + EndRibbonStorage);
00305     NLMISC::CVector *currIt  = startIt + _RibbonIndex;
00306     NLMISC::CVector *nextIt  = currIt + 1;
00307     if (nextIt == endIt) nextIt = startIt;
00308     NLMISC::CVector *nextNextIt = nextIt + 1;
00309     if (nextNextIt == endIt) nextNextIt = startIt;
00310     float *date = &_SamplingDate[0];
00311 
00312     uint leftToDo = _UsedNbSegs + 1;
00313 
00314     float lambda = 0.f;
00315     float lambdaStep = 1.f;
00316 
00317     for (;;)
00318     {
00319         float dt = date[0] - date[1];
00320 
00321         if (dt < 10E-6f) // we reached the start of ribbon
00322         {
00323             do
00324             {
00325                 *dest = *currIt;
00326                 #ifdef NL_DEBUG
00327                     nlassert(NLMISC::isValidDouble(dest->x));
00328                     nlassert(NLMISC::isValidDouble(dest->y));
00329                     nlassert(NLMISC::isValidDouble(dest->z));
00330                 #endif
00331                 dest  = (NLMISC::CVector *) ((uint8 *) dest + stride);
00332 
00333             }
00334             while (--leftToDo);
00335             return;
00336         }
00337 
00338 
00339         float newLambdaStep = _UsedSegDuration / dt;
00340         // readapt lambda
00341         lambda *= newLambdaStep / lambdaStep;
00342         lambdaStep = newLambdaStep;
00343 
00344         float oneMinusLambda = 1.f - lambda;
00345         for(;;)
00346         {
00347             if (lambda >= 1.f) break;
00349             BuildLinearVector(*currIt, *nextIt, *dest, lambda, oneMinusLambda);
00350             #ifdef NL_DEBUG
00351                 nlassert(NLMISC::isValidDouble(dest->x));
00352                 nlassert(NLMISC::isValidDouble(dest->y));
00353                 nlassert(NLMISC::isValidDouble(dest->z));
00354             #endif
00355             dest  = (NLMISC::CVector *) ((uint8 *) dest + stride);
00356             -- leftToDo;
00357             if (!leftToDo) return;
00358             lambda += lambdaStep;
00359             oneMinusLambda -= lambdaStep;
00360         }
00361 
00362         ++date;
00363         lambda -= 1.f;
00364 
00365         currIt = nextIt;
00366         nextIt = nextNextIt;
00367         ++nextNextIt;
00368         if (nextNextIt == endIt) nextNextIt = startIt;
00369 
00370     }
00371 }
00372 
00373 /*
00374 void CPSRibbonBase::computeLinearRibbon(uint index, NLMISC::CVector *dest, uint stride)
00375 {
00376     nlassert(!_Parametric);
00377     NLMISC::CVector *startIt = &_Ribbons[(_NbSegs + 1 + EndRibbonStorage) * index];
00378     NLMISC::CVector *endIt   = startIt + (_NbSegs + 1 + EndRibbonStorage);
00379     NLMISC::CVector *currIt  = startIt + _RibbonIndex;
00380     NLMISC::CVector *nextIt  = currIt + 1;
00381     if (nextIt == endIt) nextIt = startIt;
00382     NLMISC::CVector *nextNextIt = nextIt + 1;
00383     if (nextNextIt == endIt) nextNextIt = startIt;
00384     float *date = &_SamplingDate[0];
00385 
00386     uint leftToDo = _UsedNbSegs + 1;
00387 
00388     float lambda = 0.f;
00389 
00390 
00391     float dt = date[0] - date[1];
00392     if (dt < 10E-6f) // we reached the start of ribbon
00393     {
00394         do
00395         {
00396             *dest = *currIt;
00397             dest  = (NLMISC::CVector *) ((uint8 *) dest + stride);
00398         }
00399         while (--leftToDo);
00400         return;
00401     }
00402     float lambdaStep = _UsedSegDuration / dt;
00403     BuildLinearVector(*currIt, *nextIt, *dest, 0.f, 1.f);
00404     dest  = (NLMISC::CVector *) ((uint8 *) dest + stride);
00405     -- leftToDo;
00406     // snap lambda to nearest time step
00407     lambda = lambdaStep * fmodf(date[0], _UsedSegDuration) / _UsedSegDuration;
00408     for (;;)
00409     {
00410         float oneMinusLambda = 1.f - lambda;
00411         for(;;)
00412         {
00413             if (lambda >= 1.f) break;
00415             BuildLinearVector(*currIt, *nextIt, *dest, lambda, oneMinusLambda);
00416             dest  = (NLMISC::CVector *) ((uint8 *) dest + stride);
00417             -- leftToDo;
00418             if (!leftToDo) return;
00419             lambda += lambdaStep;
00420             oneMinusLambda -= lambdaStep;
00421         }
00422 
00423         ++date;
00424         lambda -= 1.f;
00425 
00426         currIt = nextIt;
00427         nextIt = nextNextIt;
00428         ++nextNextIt;
00429         if (nextNextIt == endIt) nextNextIt = startIt;
00430         float dt = date[0] - date[1];
00431         if (dt < 10E-6f) // we reached the start of ribbon
00432         {
00433             do
00434             {
00435                 *dest = *currIt;
00436                 dest  = (NLMISC::CVector *) ((uint8 *) dest + stride);
00437             }
00438             while (--leftToDo);
00439             return;
00440         }
00441         float newLambdaStep = _UsedSegDuration / dt;
00442         // readapt lambda
00443         lambda *= newLambdaStep / lambdaStep;
00444         lambdaStep = newLambdaStep;
00445     }
00446 
00447 }
00448 */
00449 
00450 
00451 //=======================================================
00452 void CPSRibbonBase::computeLinearCstSizeRibbon(uint index, NLMISC::CVector *dest, uint stride /* = sizeof(NLMISC::CVector)*/)
00453 {
00454     NL_PS_FUNC(CPSRibbonBase_CVector )
00455     nlassert(!_Parametric);
00456     CVector *startIt = &_Ribbons[(_NbSegs + 1 + EndRibbonStorage) * index];
00457     NLMISC::CVector *endIt   = startIt + (_NbSegs + 1 + EndRibbonStorage);
00458     NLMISC::CVector *currIt  = startIt + _RibbonIndex;
00459     NLMISC::CVector *firstIt = currIt;
00460     NLMISC::CVector *nextIt  = currIt + 1;
00461     if (nextIt == endIt) nextIt = startIt;
00462     NLMISC::CVector *nextNextIt = nextIt + 1;
00463     if (nextNextIt == endIt) nextNextIt = startIt;
00464 
00465     uint leftToDo = _UsedNbSegs + 1;
00466 
00467     float lambda = 0.f;
00468     float lambdaStep = 1.f;
00469 
00470 
00472     for (;;)
00473     {
00475         const float sampleLength = (*nextIt - *currIt).norm();
00476         if (sampleLength > 10E-6f)
00477         {
00479             float newLambdaStep = _UsedSegLength / sampleLength;
00480             // readapt lambda
00481             lambda *= newLambdaStep / lambdaStep;
00482             lambdaStep = newLambdaStep;
00483 
00484             float oneMinusLambda = 1.f - lambda;
00485             for(;;)
00486             {
00487                 if (lambda >= 1.f) break;
00489                 BuildLinearVector(*currIt, *nextIt, *dest, lambda, oneMinusLambda);
00490                 #ifdef NL_DEBUG
00491                     nlassert(NLMISC::isValidDouble(dest->x));
00492                     nlassert(NLMISC::isValidDouble(dest->y));
00493                     nlassert(NLMISC::isValidDouble(dest->z));
00494                 #endif
00495                 dest  = (NLMISC::CVector *) ((uint8 *) dest + stride);
00496                 -- leftToDo;
00497                 if (!leftToDo) return;
00498                 lambda += lambdaStep;
00499                 oneMinusLambda -= lambdaStep;
00500             }
00501             lambda -= 1.f;
00502         }
00503 
00505         currIt = nextIt;
00506         nextIt = nextNextIt;
00507         ++nextNextIt;
00508         if (nextNextIt == endIt) nextNextIt = startIt;
00509         if (nextNextIt == firstIt)
00510         {
00511             // The length of the sampling curve is too short
00512             // must truncate the ribbon.
00513             NLMISC::CVector &toDup = *nextIt;
00514             while (leftToDo --)
00515             {
00516                 *dest = toDup;
00517                 #ifdef NL_DEBUG
00518                     nlassert(NLMISC::isValidDouble(dest->x));
00519                     nlassert(NLMISC::isValidDouble(dest->y));
00520                     nlassert(NLMISC::isValidDouble(dest->z));
00521                 #endif
00522                 dest  = (NLMISC::CVector *) ((uint8 *) dest + stride);
00523             }
00524             return;
00525         }
00526     }
00527 }
00528 
00529 //=======================================================
00530 void CPSRibbonBase::computeHermitteCstSizeRibbon(uint index, NLMISC::CVector *dest, uint stride /* = sizeof(NLMISC::CVector)*/)
00531 {
00532     NL_PS_FUNC(CPSRibbonBase_CVector )
00533     nlassert(!_Parametric);
00534     NLMISC::CVector *startIt = &_Ribbons[(_NbSegs + 1 + EndRibbonStorage) * index];
00535     NLMISC::CVector *endIt   = startIt + (_NbSegs + 1 + EndRibbonStorage);
00536     NLMISC::CVector *currIt  = startIt + _RibbonIndex;
00537     NLMISC::CVector *firstIt = currIt;
00538     NLMISC::CVector *nextIt  = currIt + 1;
00539     if (nextIt == endIt) nextIt = startIt;
00540     NLMISC::CVector *nextNextIt = nextIt + 1;
00541     if (nextNextIt == endIt) nextNextIt = startIt;
00542 
00543     NLMISC::CVector t0 = (*nextIt - *currIt);
00544     NLMISC::CVector t1 = 0.5f * (*nextNextIt - *currIt);
00545 
00546     uint leftToDo = _UsedNbSegs + 1;
00547 
00548     float lambda = 0.f;
00549     float lambdaStep = 1.f;
00550 
00551 
00554     for (;;)
00555     {
00557         const float sampleLength = (*nextIt - *currIt).norm();
00558         if (sampleLength > 10E-6f)
00559         {
00561             float newLambdaStep = _UsedSegLength / sampleLength;
00562             // readapt lambda
00563             lambda *= newLambdaStep / lambdaStep;
00564             lambdaStep = newLambdaStep;
00565 
00566             for(;;)
00567             {
00568                 if (lambda >= 1.f) break;
00570                 BuildHermiteVector(*currIt, *nextIt, t0, t1, *dest, lambda);
00571                 #ifdef NL_DEBUG
00572                     nlassert(NLMISC::isValidDouble(dest->x));
00573                     nlassert(NLMISC::isValidDouble(dest->y));
00574                     nlassert(NLMISC::isValidDouble(dest->z));
00575                 #endif
00576 
00577                 dest  = (NLMISC::CVector *) ((uint8 *) dest + stride);
00578                 -- leftToDo;
00579                 if (!leftToDo) return;
00580                 lambda += lambdaStep;
00581             }
00582             lambda -= 1.f;
00583         }
00584 
00586         currIt = nextIt;
00587         nextIt = nextNextIt;
00588         ++nextNextIt;
00589         if (nextNextIt == endIt) nextNextIt = startIt;
00590         if (nextNextIt == firstIt)
00591         {
00592             // The length of the sampling curve is too short
00593             // must truncate the ribbon.
00594             NLMISC::CVector &toDup = *nextIt;
00595             while (leftToDo --)
00596             {
00597                 *dest = toDup;
00598                 #ifdef NL_DEBUG
00599                     nlassert(NLMISC::isValidDouble(dest->x));
00600                     nlassert(NLMISC::isValidDouble(dest->y));
00601                     nlassert(NLMISC::isValidDouble(dest->z));
00602                 #endif
00603                 dest  = (NLMISC::CVector *) ((uint8 *) dest + stride);
00604             }
00605             return;
00606         }
00608         t0 = t1;
00609         t1 = 0.5f * (*nextNextIt - *currIt);
00610     }
00611 }
00612 
00613 
00614 //=======================================================
00615 void CPSRibbonBase::computeRibbon(uint index, NLMISC::CVector *dest, uint stride /* = sizeof(NLMISC::CVector)*/)
00616 {
00617     NL_PS_FUNC(CPSRibbonBase_CVector )
00618     switch (_InterpolationMode)
00619     {
00620         case Linear:
00621             if (_RibbonMode == VariableSize)
00622             {
00623                 computeLinearRibbon(index, dest, stride);
00624             }
00625             else
00626             {
00627                 computeLinearCstSizeRibbon(index, dest, stride);
00628             }
00629         break;
00630         case Hermitte:
00631             if (_RibbonMode == VariableSize)
00632             {
00633                 computeHermitteRibbon(index, dest, stride);
00634 
00635             }
00636             else
00637             {
00638                 computeHermitteCstSizeRibbon(index, dest, stride);
00639             }
00640         break;
00641         default:
00642             nlassert(0);
00643         break;
00644     }
00645 }
00646 
00647 
00648 //=======================================================
00649 void    CPSRibbonBase::dupRibbon(uint dest, uint src)
00650 {
00651     NL_PS_FUNC(CPSRibbonBase_dupRibbon)
00652     nlassert(!_Parametric);
00653     nlassert(_Owner);
00654     const uint size = _Owner->getSize();
00655     nlassert(dest < size && src < size);
00656     ::memcpy(&_Ribbons[dest * (_NbSegs + EndRibbonStorage + 1)], &_Ribbons[src * (_NbSegs + EndRibbonStorage + 1)], sizeof(NLMISC::CVector) * (_NbSegs + 1 + EndRibbonStorage));
00657 }
00658 
00659 //=======================================================
00660 void    CPSRibbonBase::newElement(const CPSEmitterInfo &info)
00661 {
00662     NL_PS_FUNC(CPSRibbonBase_newElement)
00663     if (_Parametric) return;
00665     const uint index = _Owner->getNewElementIndex();
00666     const NLMISC::CVector &pos = _Owner->getPos()[index]; // get the pos of the new element;
00667     resetSingleRibbon(index, pos);
00668 }
00669 
00670 //=======================================================
00671 void    CPSRibbonBase::deleteElement(uint32 index)
00672 {
00673     NL_PS_FUNC(CPSRibbonBase_deleteElement)
00674     if (_Parametric) return;
00675     const uint32 size = _Owner->getSize();
00676     if(index == (size - 1)) return; // was the last element, no permutation needed.
00677     dupRibbon(index, size - 1);
00678 }
00679 
00680 //=======================================================
00681 void    CPSRibbonBase::resize(uint32 size)
00682 {
00683     NL_PS_FUNC(CPSRibbonBase_resize)
00684     nlassert(size < (1 << 16));
00685     if (_Parametric) return;
00686     _Ribbons.resize(size * (_NbSegs + 1 + EndRibbonStorage));
00687     resetFromOwner();
00688 }
00689 
00690 
00691 //=======================================================
00692 void CPSRibbonBase::resetSingleRibbon(uint index, const NLMISC::CVector &pos)
00693 {
00694     NL_PS_FUNC(CPSRibbonBase_resetSingleRibbon)
00695     nlassert(!_Parametric);
00696     TPSMatrixMode mm = convertMatrixMode();
00697     NLMISC::CVector *it = &_Ribbons[(index * (_NbSegs + 1 + EndRibbonStorage))];
00698     if (mm == _Owner->getMatrixMode())
00699     {
00700         std::fill(it, it + (_NbSegs + 1 + EndRibbonStorage), pos);
00701     }
00702     else
00703     {
00704         nlassert(_Owner->getOwner());
00705         const CMatrix &mat = CPSLocated::getConversionMatrix(*_Owner->getOwner(), mm, _Owner->getMatrixMode());
00706         std::fill(it, it + (_NbSegs + 1 + EndRibbonStorage), mat * pos);
00707     }
00708 }
00709 
00710 
00711 
00712 //=======================================================
00713 void CPSRibbonBase::resetFromOwner()
00714 {
00715     NL_PS_FUNC(CPSRibbonBase_resetFromOwner)
00716     nlassert(!_Parametric);
00717     TPSAttribVector::iterator posIt = _Owner->getPos().begin();
00718     TPSAttribVector::iterator endPosIt = _Owner->getPos().end();
00719     for (uint k = 0; posIt != endPosIt; ++posIt, ++k)
00720     {
00721         resetSingleRibbon(k, *posIt);
00722     }
00723 }
00724 
00725 //=======================================================
00726 void CPSRibbonBase::motionTypeChanged(bool parametric)
00727 {
00728     NL_PS_FUNC(CPSRibbonBase_motionTypeChanged)
00729     _Parametric = parametric;
00730     if (parametric)
00731     {
00732         NLMISC::contReset(_Ribbons); // kill the vector
00733     }
00734     else
00735     {
00736         nlassert(_Owner);
00737         resize(_Owner->getMaxSize());
00738         initDateVect();
00739         resetFromOwner();
00740     }
00741 }
00742 
00743 
00744 //=======================================================
00745 void CPSRibbonBase::initDateVect()
00746 {
00747     NL_PS_FUNC(CPSRibbonBase_initDateVect)
00748     _SamplingDate.resize( _NbSegs + 1 + EndRibbonStorage);
00749     std::fill(_SamplingDate.begin(), _SamplingDate.begin() + (_NbSegs + 1 + EndRibbonStorage), 0.f);
00750 }
00751 
00752 
00753 //=======================================================
00754 void CPSRibbonBase::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00755 {
00756     NL_PS_FUNC(CPSRibbonBase_serial)
00757     CPSParticle::serial(f);
00758     // version 2 : added matrix mode
00759     sint ver = f.serialVersion(2);
00760     f.serialEnum(_RibbonMode);
00761     f.serialEnum(_InterpolationMode);
00762     f.serial(_NbSegs, _SegDuration);
00763     if (_RibbonMode == FixedSize)
00764     {
00765         f.serial(_RibbonLength);
00766         if (f.isReading())
00767         {
00768             _SegLength = _RibbonLength / _NbSegs;
00769         }
00770     }
00771     if (f.isReading())
00772     {
00773         if (_Owner)
00774         {
00775             resize(_Owner->getMaxSize());
00776             initDateVect();
00777             resetFromOwner();
00778         }
00779     }
00780     if (ver >= 1)
00781     {
00782         f.serial(_LODDegradation);
00783     }
00784     if (ver >= 2)
00785     {
00786         f.serialEnum(_MatrixMode);
00787     }
00788 }
00789 
00790 
00791 //=======================================================
00792 void CPSRibbonBase::updateLOD()
00793 {
00794     NL_PS_FUNC(CPSRibbonBase_updateLOD)
00795     nlassert(_Owner);
00796     float ratio = _Owner->getOwner()->getOneMinusCurrentLODRatio();
00797     float squaredRatio = ratio * ratio;
00798     float lodRatio = _LODDegradation + (1.f - _LODDegradation ) * squaredRatio * squaredRatio * squaredRatio;
00799 
00800     _UsedNbSegs = (uint) (_NbSegs * lodRatio);
00801     NLMISC::clamp(_UsedNbSegs, 0u, _NbSegs);
00802     const float epsilon = 10E-4f;
00803     _UsedSegDuration =  _SegDuration / std::max(epsilon, lodRatio);
00804     _UsedSegLength   =  _SegLength / std::max(epsilon, lodRatio);
00805 
00806 }
00807 
00808 //=======================================================
00809 void CPSRibbonBase::systemDateChanged()
00810 {
00811     NL_PS_FUNC(CPSRibbonBase_systemDateChanged)
00812     nlassert(_Owner->getOwner());
00813     _Owner->getOwner()->getSystemDate();
00814     float date = _Owner->getOwner()->getSystemDate();
00815     std::fill(_SamplingDate.begin(), _SamplingDate.end(), date);
00816     _LastUpdateDate = date;
00817 }
00818 
00819 
00820 
00821 } // NL3D
00822 

Generated on Thu Jan 7 08:26:29 2010 for NeL by  doxygen 1.6.1