00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
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 )
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)
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
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
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)
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
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
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452 void CPSRibbonBase::computeLinearCstSizeRibbon(uint index, NLMISC::CVector *dest, uint stride )
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
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
00512
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 )
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
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
00593
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 )
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];
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;
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);
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
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 }
00822