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
00027
00028 #include <algorithm>
00029 #include "nel/misc/aabbox.h"
00030 #include "nel/misc/matrix.h"
00031 #include "nel/misc/common.h"
00032 #include "nel/3d/ps_util.h"
00033 #include "nel/3d/particle_system.h"
00034 #include "nel/3d/ps_zone.h"
00035 #include "nel/3d/driver.h"
00036 #include "nel/3d/material.h"
00037 #include "nel/3d/dru.h"
00038 #include "nel/3d/ps_located.h"
00039 #include "nel/3d/ps_particle.h"
00040 #include "nel/3d/ps_force.h"
00041 #include "nel/3d/ps_emitter.h"
00042 #include "nel/3d/ps_misc.h"
00043
00044 #include "nel/misc/line.h"
00045 #include "nel/misc/system_info.h"
00046 #include "nel/misc/common.h"
00047
00048
00049 #include "nel/3d/particle_system_model.h"
00050
00051
00052 #ifdef NL_DEBUG
00053 #define CHECK_PS_INTEGRITY checkIntegrity();
00054 #else
00055 #define CHECK_PS_INTEGRITY
00056 #endif
00057
00058 namespace NL3D {
00059
00060
00061 std::vector<CPSCollisionInfo> CPSLocated::_Collisions;
00062 CPSCollisionInfo *CPSLocated::_FirstCollision = NULL;
00063
00064
00065
00067
00070 CPSLocated::CPSLocated() :
00071 _Size(0),
00072 _MaxSize(DefaultMaxLocatedInstance),
00073 _CollisionInfoNbRef(0),
00074 _CollisionNextPos(NULL),
00075 _InitialLife(1.f),
00076 _LifeScheme(NULL),
00077 _InitialMass(1.f),
00078 _MassScheme(NULL),
00079 _LODDegradation(false),
00080 _ParametricMotion(false),
00081 _TriggerOnDeath(false),
00082 _LastForever(true),
00083 _TriggerID((uint32) 'NONE'),
00084 _NonIntegrableForceNbRefs(0),
00085 _NumIntegrableForceWithDifferentBasis(0)
00086 {
00087 NL_PS_FUNC(CPSLocated_CPSLocated)
00088 }
00089
00090
00091
00092 const NLMISC::CMatrix &CPSLocated::getLocalToWorldMatrix() const
00093 {
00094 NL_PS_FUNC(CPSLocated_getLocalToWorldMatrix)
00095 nlassert(_Owner);
00096 switch(getMatrixMode())
00097 {
00098 case PSFXWorldMatrix: return _Owner->getSysMat();
00099 case PSIdentityMatrix: return NLMISC::CMatrix::Identity;
00100 case PSUserMatrix: return _Owner->getUserMatrix();
00101 default:
00102 nlassert(0);
00103 }
00104 nlassert(0);
00105 return NLMISC::CMatrix::Identity;
00106 }
00107
00108
00109 const NLMISC::CMatrix &CPSLocated::getWorldToLocalMatrix() const
00110 {
00111 NL_PS_FUNC(CPSLocated_getWorldToLocalMatrix)
00112 nlassert(_Owner);
00113 switch(getMatrixMode())
00114 {
00115 case PSFXWorldMatrix: return _Owner->getInvertedSysMat();
00116 case PSIdentityMatrix: return NLMISC::CMatrix::Identity;
00117 case PSUserMatrix: return _Owner->getInvertedUserMatrix();
00118 default:
00119 nlassert(0);
00120 }
00121 nlassert(0);
00122 return NLMISC::CMatrix::Identity;
00123 }
00124
00125
00127 float CPSLocated::evalMaxDuration() const
00128 {
00129 NL_PS_FUNC(CPSLocated_evalMaxDuration)
00130 if (_LastForever) return -1.f;
00131 return _LifeScheme ? _LifeScheme->getMaxValue() : _InitialLife;
00132 }
00133
00134
00136 void CPSLocated::checkIntegrity() const
00137 {
00138 NL_PS_FUNC(CPSLocated_checkIntegrity)
00139 nlassert(_InvMass.getMaxSize() == _Pos.getMaxSize());
00140 nlassert(_Pos.getMaxSize() == _Speed.getMaxSize());
00141 nlassert(_Speed.getMaxSize() == _Time.getMaxSize());
00142 nlassert(_Time.getMaxSize() == _TimeIncrement.getMaxSize());
00143
00144 nlassert(_InvMass.getSize() == _Pos.getSize());
00145 nlassert(_Pos.getSize() == _Speed.getSize());
00146 nlassert(_Speed.getSize() == _Time.getSize());
00147 nlassert(_Time.getSize() == _TimeIncrement.getSize());
00148
00149 if (hasCollisionInfos())
00150 {
00151 nlassert(_CollisionNextPos->getSize() == _Pos.getSize());
00152 nlassert(_CollisionNextPos->getMaxSize() == _Pos.getMaxSize());
00153 }
00154
00155 }
00156
00158 bool CPSLocated::setLastForever()
00159 {
00160 NL_PS_FUNC(CPSLocated_setLastForever)
00161 CHECK_PS_INTEGRITY
00162 _LastForever = true;
00163 if (_Owner && _Owner->getBypassMaxNumIntegrationSteps())
00164 {
00165
00166 if (!_Owner->canFinish())
00167 {
00168 _LastForever = false;
00169 nlwarning("<CPSLocated::setLastForever> Can't set flag : this causes the system to last forever, and it has been flagged with 'BypassMaxNumIntegrationSteps'. Flag is not set");
00170 return false;
00171 }
00172 }
00173 CHECK_PS_INTEGRITY
00174 return true;
00175 }
00176
00177
00179 void CPSLocated::systemDateChanged()
00180 {
00181 NL_PS_FUNC(CPSLocated_systemDateChanged)
00182 CHECK_PS_INTEGRITY
00183 for(TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00184 {
00185 (*it)->systemDateChanged();
00186 }
00187 CHECK_PS_INTEGRITY
00188 }
00189
00190
00192 void CPSLocated::releaseRefTo(const CParticleSystemProcess *other)
00193 {
00194 NL_PS_FUNC(CPSLocated_releaseRefTo)
00195 CHECK_PS_INTEGRITY
00196
00197 {
00198 for(TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00199 {
00200 (*it)->releaseRefTo(other);
00201 }
00202 }
00203
00204 {
00205
00206 for(TDtorObserversVect::iterator it = _DtorObserversVect.begin(); it != _DtorObserversVect.end(); ++it)
00207 {
00208 if ((*it)->getOwner() == other)
00209 {
00210 CPSLocatedBindable *refMaker = *it;
00211 refMaker->notifyTargetRemoved(this);
00212 break;
00213 }
00214 }
00215 }
00216 CHECK_PS_INTEGRITY
00217 }
00218
00220 void CPSLocated::releaseAllRef()
00221 {
00222 NL_PS_FUNC(CPSLocated_releaseAllRef)
00223 CHECK_PS_INTEGRITY
00224
00225 {
00226 for(TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00227 {
00228 (*it)->releaseAllRef();
00229 }
00230 }
00231
00232
00233 TDtorObserversVect copyVect(_DtorObserversVect.begin(), _DtorObserversVect.end());
00234
00235 for (TDtorObserversVect::iterator it = copyVect.begin(); it != copyVect.end(); ++it)
00236 {
00237 (*it)->notifyTargetRemoved(this);
00238 }
00239 _DtorObserversVect.clear();
00240
00241 nlassert(_CollisionInfoNbRef == 0);
00242
00243
00244
00245 nlassert(_IntegrableForces.size() == 0);
00246 nlassert(_NonIntegrableForceNbRefs == 0);
00247 CHECK_PS_INTEGRITY
00248 }
00249
00250
00252 void CPSLocated::notifyMotionTypeChanged(void)
00253 {
00254 NL_PS_FUNC(CPSLocated_notifyMotionTypeChanged)
00255 CHECK_PS_INTEGRITY
00256 for (TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00257 {
00258 (*it)->motionTypeChanged(_ParametricMotion);
00259 }
00260 CHECK_PS_INTEGRITY
00261 }
00262
00263
00265 void CPSLocated::integrateSingle(float startDate, float deltaT, uint numStep,
00266 uint32 indexInLocated,
00267 NLMISC::CVector *destPos,
00268 uint stride) const
00269 {
00270 NL_PS_FUNC(CPSLocated_integrateSingle)
00271 CHECK_PS_INTEGRITY
00272 nlassert(supportParametricMotion() && _ParametricMotion);
00273 if (_IntegrableForces.size() != 0)
00274 {
00275 bool accumulate = false;
00276 for (TForceVect::const_iterator it = _IntegrableForces.begin(); it != _IntegrableForces.end(); ++it)
00277 {
00278 nlassert((*it)->isIntegrable());
00279 (*it)->integrateSingle(startDate, deltaT, numStep, this, indexInLocated, destPos, accumulate, stride);
00280 accumulate = true;
00281 }
00282 }
00283 else
00284 {
00285 #ifdef NL_DEBUG
00286 NLMISC::CVector *endPos = (NLMISC::CVector *) ( (uint8 *) destPos + stride * numStep);
00287 #endif
00288 const CPSLocated::CParametricInfo &pi = _PInfo[indexInLocated];
00289 destPos = FillBufUsingSubdiv(pi.Pos, pi.Date, startDate, deltaT, numStep, destPos, stride);
00290 if (numStep != 0)
00291 {
00292 float currDate = startDate - pi.Date;
00293 nlassert(currDate >= 0);
00294 do
00295 {
00296 #ifdef NL_DEBUG
00297 nlassert(destPos < endPos);
00298 #endif
00299 destPos->x = pi.Pos.x + currDate * pi.Speed.x;
00300 destPos->y = pi.Pos.y + currDate * pi.Speed.y;
00301 destPos->z = pi.Pos.z + currDate * pi.Speed.z;
00302 currDate += deltaT;
00303 destPos = (NLMISC::CVector *) ( (uint8 *) destPos + stride);
00304 }
00305 while (--numStep);
00306 }
00307 }
00308 CHECK_PS_INTEGRITY
00309 }
00310
00311
00313 void CPSLocated::performParametricMotion(TAnimationTime date)
00314 {
00315 NL_PS_FUNC(CPSLocated_performParametricMotion)
00316 CHECK_PS_INTEGRITY
00317 if (!_Size) return;
00318 nlassert(supportParametricMotion() && _ParametricMotion);
00319
00320 if (_IntegrableForces.size() != 0)
00321 {
00322 bool accumulate = false;
00323 for (TForceVect::iterator it = _IntegrableForces.begin(); it != _IntegrableForces.end(); ++it)
00324 {
00325 nlassert((*it)->isIntegrable());
00326 (*it)->integrate(date, this, 0, _Size, &_Pos[0], &_Speed[0], accumulate);
00327 accumulate = true;
00328 }
00329 }
00330 else
00331 {
00332 CPSLocated::TPSAttribParametricInfo::const_iterator it = _PInfo.begin(),
00333 endIt = _PInfo.end();
00334 TPSAttribVector::iterator posIt = _Pos.begin();
00335 float deltaT;
00336 do
00337 {
00338 deltaT = date - it->Date;
00339 posIt->x = it->Pos.x + deltaT * it->Speed.x;
00340 posIt->y = it->Pos.y + deltaT * it->Speed.y;
00341 posIt->z = it->Pos.z + deltaT * it->Speed.z;
00342 ++posIt;
00343 ++it;
00344 }
00345 while (it != endIt);
00346 }
00347 CHECK_PS_INTEGRITY
00348 }
00349
00352 void CPSLocated::allocateParametricInfos(void)
00353 {
00354 NL_PS_FUNC(CPSLocated_allocateParametricInfos)
00355 CHECK_PS_INTEGRITY
00356 if (_ParametricMotion) return;
00357 nlassert(supportParametricMotion());
00358 nlassert(_Owner);
00359 const float date = _Owner->getSystemDate();
00360 _PInfo.resize(_MaxSize);
00361
00362 TPSAttribVector::const_iterator posIt = _Pos.begin(), endPosIt = _Pos.end();
00363 TPSAttribVector::const_iterator speedIt = _Speed.begin();
00364 while (posIt != endPosIt)
00365 {
00366 _PInfo.insert( CParametricInfo(*posIt, *speedIt, date) );
00367 ++posIt;
00368 }
00369 _ParametricMotion = true;
00370 notifyMotionTypeChanged();
00371 CHECK_PS_INTEGRITY
00372 }
00373
00376 void CPSLocated::releaseParametricInfos(void)
00377 {
00378 NL_PS_FUNC(CPSLocated_releaseParametricInfos)
00379 CHECK_PS_INTEGRITY
00380 if (!_ParametricMotion) return;
00381 NLMISC::contReset(_PInfo);
00382 _ParametricMotion = false;
00383 notifyMotionTypeChanged();
00384 CHECK_PS_INTEGRITY
00385 }
00386
00389 bool CPSLocated::supportParametricMotion(void) const
00390 {
00391 NL_PS_FUNC(CPSLocated_supportParametricMotion)
00392 return _NonIntegrableForceNbRefs == 0 && _NumIntegrableForceWithDifferentBasis == 0;
00393 }
00394
00396
00399 void CPSLocated::enableParametricMotion(bool enable )
00400 {
00401 NL_PS_FUNC(CPSLocated_enableParametricMotion)
00402 CHECK_PS_INTEGRITY
00403 nlassert(supportParametricMotion());
00404 if (enable)
00405 {
00406 allocateParametricInfos();
00407 }
00408 else
00409 {
00410 releaseParametricInfos();
00411 }
00412 CHECK_PS_INTEGRITY
00413 }
00414
00416 void CPSLocated::setMatrixMode(TPSMatrixMode matrixMode)
00417 {
00418 NL_PS_FUNC(CPSLocated_setMatrixMode)
00419 CHECK_PS_INTEGRITY
00420 if (matrixMode != getMatrixMode())
00421 {
00422 for (TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00423 {
00424 (*it)->basisChanged(matrixMode);
00425 }
00426
00427 CParticleSystemProcess::setMatrixMode(matrixMode);
00428 for (TForceVect::iterator fIt = _IntegrableForces.begin(); fIt != _IntegrableForces.end(); ++fIt)
00429 {
00430 integrableForceBasisChanged( (*fIt)->getOwner()->getMatrixMode() );
00431 }
00432 }
00433 CHECK_PS_INTEGRITY
00434 }
00435
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00451
00452
00453
00454
00455
00456
00457
00459 uint CPSLocated::getNumWantedTris() const
00460 {
00461 NL_PS_FUNC(CPSLocated_getNumWantedTris)
00462 CHECK_PS_INTEGRITY
00463 if (!_Owner) return 0;
00464 uint numWantedTris = 0;
00465 for (TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00466 {
00467 if ((*it)->getType() == PSParticle)
00468 {
00469 numWantedTris += NLMISC::safe_cast<CPSParticle *>(*it)->getNumWantedTris();
00470 }
00471 }
00472 CHECK_PS_INTEGRITY
00473 return numWantedTris;
00474 }
00475
00476
00478
00479
00480
00481
00482
00483
00486 bool CPSLocated::hasParticles(void) const
00487 {
00488 NL_PS_FUNC(CPSLocated_hasParticles)
00489 CHECK_PS_INTEGRITY
00490 for (TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00491 {
00492 if ((*it)->getType() == PSParticle && (*it)->hasParticles()) return true;
00493 }
00494 CHECK_PS_INTEGRITY
00495 return false;
00496 }
00497
00500 bool CPSLocated::hasEmitters(void) const
00501 {
00502 NL_PS_FUNC(CPSLocated_hasEmitters)
00503 CHECK_PS_INTEGRITY
00504 for (TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00505 {
00506 if ((*it)->getType() == PSEmitter && (*it)->hasEmitters()) return true;
00507 }
00508 CHECK_PS_INTEGRITY
00509 return false;
00510 }
00511
00513 void CPSLocated::getLODVect(NLMISC::CVector &v, float &offset, TPSMatrixMode matrixMode)
00514 {
00515 NL_PS_FUNC(CPSLocated_getLODVect)
00516 nlassert(_Owner);
00517 CHECK_PS_INTEGRITY
00518 _Owner->getLODVect(v, offset, matrixMode);
00519 CHECK_PS_INTEGRITY
00520 }
00521
00523 float CPSLocated::getUserParam(uint numParam) const
00524 {
00525 NL_PS_FUNC(CPSLocated_getUserParam)
00526 nlassert(_Owner);
00527 CHECK_PS_INTEGRITY
00528 return _Owner->getUserParam(numParam);
00529 }
00530
00532 CScene *CPSLocated::getScene(void)
00533 {
00534 NL_PS_FUNC(CPSLocated_getScene)
00535 nlassert(_Owner);
00536 CHECK_PS_INTEGRITY
00537 return _Owner->getScene();
00538 }
00539
00541 void CPSLocated::incrementNbDrawnParticles(uint num)
00542 {
00543 NL_PS_FUNC(CPSLocated_incrementNbDrawnParticles)
00544 CHECK_PS_INTEGRITY
00545 CParticleSystem::NbParticlesDrawn += num;
00546 }
00547
00549 void CPSLocated::setInitialLife(TAnimationTime lifeTime)
00550 {
00551 NL_PS_FUNC(CPSLocated_setInitialLife)
00552 CHECK_PS_INTEGRITY
00553 _LastForever = false;
00554 _InitialLife = lifeTime;
00555 delete _LifeScheme;
00556 _LifeScheme = NULL;
00557
00561 for (uint k = 0; k < _Size; ++k)
00562 {
00563 _Time[k] = 0.f;
00564 }
00565
00566 if (_Owner)
00567 {
00568 _Owner->systemDurationChanged();
00569 }
00570 CHECK_PS_INTEGRITY
00571 }
00572
00574 void CPSLocated::setLifeScheme(CPSAttribMaker<float> *scheme)
00575 {
00576 NL_PS_FUNC(CPSLocated_setLifeScheme)
00577 CHECK_PS_INTEGRITY
00578 nlassert(scheme);
00579 nlassert(!scheme->hasMemory());
00580 _LastForever = false;
00581 delete _LifeScheme;
00582 _LifeScheme = scheme;
00583
00584 if (_Owner)
00585 {
00586 _Owner->systemDurationChanged();
00587 }
00588 CHECK_PS_INTEGRITY
00589 }
00590
00592 void CPSLocated::setInitialMass(float mass)
00593 {
00594 NL_PS_FUNC(CPSLocated_setInitialMass)
00595 CHECK_PS_INTEGRITY
00596 _InitialMass = mass;
00597 delete _MassScheme;
00598 _MassScheme = NULL;
00599 CHECK_PS_INTEGRITY
00600 }
00601
00603 void CPSLocated::setMassScheme(CPSAttribMaker<float> *scheme)
00604 {
00605 NL_PS_FUNC(CPSLocated_setMassScheme)
00606 CHECK_PS_INTEGRITY
00607 nlassert(scheme);
00608 nlassert(!scheme->hasMemory());
00609 delete _MassScheme;
00610 _MassScheme = scheme;
00611 CHECK_PS_INTEGRITY
00612 }
00613
00616 const NLMISC::CMatrix &CPSLocated::getConversionMatrix(const CParticleSystem &ps, TPSMatrixMode destMode, TPSMatrixMode srcMode)
00617 {
00618 NL_PS_FUNC(CPSLocated_getConversionMatrix)
00619 switch(destMode)
00620 {
00621 case PSFXWorldMatrix:
00622 switch(srcMode)
00623 {
00624 case PSFXWorldMatrix: return NLMISC::CMatrix::Identity;
00625 case PSIdentityMatrix: return ps.getInvertedSysMat();
00626 case PSUserMatrix: return ps.getUserToFXMatrix();
00627 default:
00628 nlassert(0);
00629 }
00630 break;
00631 case PSIdentityMatrix:
00632 switch(srcMode)
00633 {
00634 case PSFXWorldMatrix: return ps.getSysMat();
00635 case PSIdentityMatrix: return NLMISC::CMatrix::Identity;
00636 case PSUserMatrix: return ps.getUserMatrix();
00637 default:
00638 nlassert(0);
00639 }
00640 break;
00641 case PSUserMatrix:
00642 switch(srcMode)
00643 {
00644 case PSFXWorldMatrix: return ps.getFXToUserMatrix();
00645 case PSIdentityMatrix: return ps.getInvertedUserMatrix();
00646 case PSUserMatrix: return NLMISC::CMatrix::Identity;
00647 default:
00648 nlassert(0);
00649 }
00650 break;
00651 default:
00652 nlassert(0);
00653 }
00654 nlassert(0);
00655 return NLMISC::CMatrix::Identity;
00656 }
00657
00659 NLMISC::CVector CPSLocated::computeI(void) const
00660 {
00661 NL_PS_FUNC(CPSLocated_computeI)
00662 CHECK_PS_INTEGRITY
00663 const NLMISC::CMatrix &sysMat = _Owner->getSysMat();
00664 if (getMatrixMode() == PSIdentityMatrix)
00665 {
00666 if (!sysMat.hasScalePart())
00667 {
00668 return _Owner->getInvertedViewMat().getI();
00669 }
00670 else
00671 {
00672 return sysMat.getScaleUniform() * _Owner->getInvertedViewMat().getI();
00673 }
00674 }
00675 else
00676 {
00677 if (!sysMat.hasScalePart())
00678 {
00679
00680 return getWorldToLocalMatrix().mulVector(_Owner->getInvertedViewMat().getI());
00681 }
00682 else
00683 {
00684 return sysMat.getScaleUniform() * getWorldToLocalMatrix().mulVector(_Owner->getInvertedViewMat().getI());
00685 }
00686 }
00687 }
00688
00690 NLMISC::CVector CPSLocated::computeIWithZAxisAligned(void) const
00691 {
00692 NL_PS_FUNC(CPSLocated_computeIWithZAxisAligned)
00693 CHECK_PS_INTEGRITY
00694 const NLMISC::CMatrix &sysMat = _Owner->getSysMat();
00695 const CVector &camI = _Owner->getInvertedViewMat().getI();
00696 CVector I(camI.x, camI.y, 0.f);
00697 I.normalize();
00698 if (getMatrixMode() == PSIdentityMatrix)
00699 {
00700 if (!sysMat.hasScalePart())
00701 {
00702 return I;
00703 }
00704 else
00705 {
00706 return sysMat.getScaleUniform() * I;
00707 }
00708 }
00709 else
00710 {
00711 if (!sysMat.hasScalePart())
00712 {
00713
00714 return getWorldToLocalMatrix().mulVector(I);
00715 }
00716 else
00717 {
00718 return sysMat.getScaleUniform() * getWorldToLocalMatrix().mulVector(I);
00719 }
00720 }
00721 }
00722
00724 NLMISC::CVector CPSLocated::computeJ(void) const
00725 {
00726 NL_PS_FUNC(CPSLocated_computeJ)
00727 CHECK_PS_INTEGRITY
00728 const NLMISC::CMatrix &sysMat = _Owner->getSysMat();
00729 if (getMatrixMode() == PSIdentityMatrix)
00730 {
00731 if (!sysMat.hasScalePart())
00732 {
00733 return _Owner->getInvertedViewMat().getJ();
00734 }
00735 else
00736 {
00737 return sysMat.getScaleUniform() * _Owner->getInvertedViewMat().getJ();
00738 }
00739 }
00740 else
00741 {
00742 if (!sysMat.hasScalePart())
00743 {
00744
00745 return getWorldToLocalMatrix().mulVector(_Owner->getInvertedViewMat().getJ());
00746 }
00747 else
00748 {
00749 return sysMat.getScaleUniform() * getWorldToLocalMatrix().mulVector(_Owner->getInvertedViewMat().getJ());
00750 }
00751 }
00752 }
00753
00755 NLMISC::CVector CPSLocated::computeK(void) const
00756 {
00757 NL_PS_FUNC(CPSLocated_computeK)
00758 CHECK_PS_INTEGRITY
00759 const NLMISC::CMatrix &sysMat = _Owner->getSysMat();
00760 if (getMatrixMode() == PSIdentityMatrix)
00761 {
00762
00763 if (!sysMat.hasScalePart())
00764 {
00765 return _Owner->getInvertedViewMat().getK();
00766 }
00767 else
00768 {
00769 return sysMat.getScaleUniform() * _Owner->getInvertedViewMat().getK();
00770 }
00771 }
00772 else
00773 {
00774 if (!sysMat.hasScalePart())
00775 {
00776
00777 return getWorldToLocalMatrix().mulVector(_Owner->getInvertedViewMat().getK());
00778 }
00779 else
00780 {
00781 return sysMat.getScaleUniform() * getWorldToLocalMatrix().mulVector(_Owner->getInvertedViewMat().getK());
00782 }
00783 }
00784 }
00785
00787 NLMISC::CVector CPSLocated::computeKWithZAxisAligned(void) const
00788 {
00789 NL_PS_FUNC(CPSLocated_computeKWithZAxisAligned)
00790 CHECK_PS_INTEGRITY
00791 const NLMISC::CMatrix &sysMat = _Owner->getSysMat();
00792 if (getMatrixMode() == PSIdentityMatrix)
00793 {
00794 if (!sysMat.hasScalePart())
00795 {
00796 return CVector::K;
00797 }
00798 else
00799 {
00800 return CVector(0.f, 0.f, sysMat.getScaleUniform());
00801 }
00802 }
00803 else
00804 {
00805 if (!sysMat.hasScalePart())
00806 {
00807
00808 return getWorldToLocalMatrix().mulVector(CVector::K);
00809 }
00810 else
00811 {
00812 return getWorldToLocalMatrix().mulVector(CVector(0.f, 0.f, sysMat.getScaleUniform()));
00813 }
00814 }
00815 }
00816
00818 IDriver *CPSLocated::getDriver() const
00819 {
00820 NL_PS_FUNC(CPSLocated_getDriver)
00821 CHECK_PS_INTEGRITY
00822 nlassert(_Owner);
00823 nlassert (_Owner->getDriver() );
00824 return _Owner->getDriver();
00825 }
00826
00829 CPSLocated::~CPSLocated()
00830 {
00831 NL_PS_FUNC(CPSLocated_CPSLocated)
00832 CHECK_PS_INTEGRITY
00833
00834 TDtorObserversVect copyVect(_DtorObserversVect.begin(), _DtorObserversVect.end());
00835
00836 for (TDtorObserversVect::iterator it = copyVect.begin(); it != copyVect.end(); ++it)
00837 {
00838 (*it)->notifyTargetRemoved(this);
00839 }
00840
00841 nlassert(_CollisionInfoNbRef == 0);
00842
00843
00844
00845 nlassert(_IntegrableForces.size() == 0);
00846 nlassert(_NonIntegrableForceNbRefs == 0);
00847
00848
00849 for (TLocatedBoundCont::iterator it2 = _LocatedBoundCont.begin(); it2 != _LocatedBoundCont.end(); ++it2)
00850 {
00851 (*it2)->finalize();
00852 delete *it2;
00853 }
00854 _LocatedBoundCont.clear();
00855
00856 delete _LifeScheme;
00857 delete _MassScheme;
00858 delete _CollisionNextPos;
00859 CHECK_PS_INTEGRITY
00860 }
00861
00863
00866 bool CPSLocated::bind(CPSLocatedBindable *lb)
00867 {
00868 NL_PS_FUNC(CPSLocated_bind)
00869 CHECK_PS_INTEGRITY
00870 nlassert(std::find(_LocatedBoundCont.begin(), _LocatedBoundCont.end(), lb) == _LocatedBoundCont.end());
00871 TLocatedBoundCont::iterator it = _LocatedBoundCont.begin();
00872 while (it != _LocatedBoundCont.end() && **it < *lb)
00873 {
00874 ++it;
00875 }
00876
00877 _LocatedBoundCont.insert(it, lb);
00878 lb->setOwner(this);
00879 lb->resize(_MaxSize);
00880
00881
00882
00883
00884 uint32 initialSize = _Size;
00885 CPSEmitterInfo ei;
00886 ei.setDefaults();
00887 for (uint k = 0; k < initialSize; ++k)
00888 {
00889 _Size = k;
00890 lb->newElement(ei);
00891 }
00892 _Size = initialSize;
00893
00894
00895 if (_ParametricMotion) lb->motionTypeChanged(true);
00896
00898
00899
00900 if (_Owner)
00901 {
00902 CParticleSystem *ps = _Owner;
00903 if (ps->getBypassMaxNumIntegrationSteps())
00904 {
00905 if (!ps->canFinish())
00906 {
00907 unbind(getIndexOf(lb));
00908 nlwarning("<CPSLocated::bind> Can't bind the located : this causes the system to last forever, and it has been flagged with 'BypassMaxNumIntegrationSteps'. Located is not bound.");
00909 return false;
00910 }
00911 }
00912
00913 if (lb->getExternID() != 0)
00914 {
00915
00916 ps->registerLocatedBindableExternID(lb->getExternID(), lb);
00917 }
00918 _Owner->systemDurationChanged();
00919 }
00920
00921 CHECK_PS_INTEGRITY
00922 return true;
00923 }
00924
00926 void CPSLocated::remove(const CPSLocatedBindable *p)
00927 {
00928 NL_PS_FUNC(CPSLocated_remove)
00929 CHECK_PS_INTEGRITY
00930 TLocatedBoundCont::iterator it = std::find(_LocatedBoundCont.begin(), _LocatedBoundCont.end(), p);
00931 nlassert(it != _LocatedBoundCont.end());
00932 (*it)->finalize();
00933 delete *it;
00934 _LocatedBoundCont.erase(it);
00935 if (_Owner)
00936 {
00937 _Owner->systemDurationChanged();
00938 }
00939 CHECK_PS_INTEGRITY
00940 }
00941
00943 void CPSLocated::registerDtorObserver(CPSLocatedBindable *anObserver)
00944 {
00945 NL_PS_FUNC(CPSLocated_registerDtorObserver)
00946 CHECK_PS_INTEGRITY
00947
00948 nlassert(std::find(_DtorObserversVect.begin(), _DtorObserversVect.end(), anObserver) == _DtorObserversVect.end());
00949 _DtorObserversVect.push_back(anObserver);
00950 CHECK_PS_INTEGRITY
00951 }
00952
00954 void CPSLocated::unregisterDtorObserver(CPSLocatedBindable *anObserver)
00955 {
00956 NL_PS_FUNC(CPSLocated_unregisterDtorObserver)
00957 CHECK_PS_INTEGRITY
00958
00959 TDtorObserversVect::iterator it = std::find(_DtorObserversVect.begin(), _DtorObserversVect.end(), anObserver);
00960 nlassert(it != _DtorObserversVect.end());
00961 _DtorObserversVect.erase(it);
00962 CHECK_PS_INTEGRITY
00963 }
00964
00965
00967 void CPSLocated::postNewElement(const NLMISC::CVector &pos,
00968 const NLMISC::CVector &speed,
00969 CPSLocated &emitterLocated,
00970 uint32 indexInEmitter,
00971 TPSMatrixMode speedCoordSystem,
00972 TAnimationTime lifeTime)
00973 {
00974 NL_PS_FUNC(CPSLocated_postNewElement)
00975 nlassert(CParticleSystem::InsideSimLoop);
00976
00977
00978
00979 float emitterLife;
00980 if (!emitterLocated.getLastForever())
00981 {
00982 if (emitterLocated._LifeScheme)
00983 {
00984 emitterLife = emitterLocated._Time[indexInEmitter] - lifeTime * CParticleSystem::RealEllapsedTimeRatio * emitterLocated._TimeIncrement[indexInEmitter];
00985 if (emitterLife >= 1.f)
00986 {
00987 return;
00988 }
00989 }
00990 else
00991 {
00992 emitterLife = emitterLocated._Time[indexInEmitter] * emitterLocated._InitialLife - lifeTime * CParticleSystem::RealEllapsedTimeRatio;
00993 if (emitterLife >= emitterLocated._InitialLife)
00994 {
00995 return;
00996 }
00997 if (emitterLocated._InitialLife != 0.f)
00998 {
00999 emitterLife /= emitterLocated._InitialLife;
01000 }
01001 }
01002 }
01003 else
01004 {
01005 emitterLife = emitterLocated.getTime()[indexInEmitter];
01006 }
01007
01008
01009 if (emitterLocated.hasCollisionInfos())
01010 {
01011 const CPSCollisionInfo &ci = _Collisions[indexInEmitter];
01012 if (ci.Dist != -1.f)
01013 {
01014
01015 if ((emitterLocated.getPos()[indexInEmitter] - ci.NewPos) * (pos - ci.NewPos) > 0.f) return;
01016 }
01017 }
01018
01019
01020
01021 CParticleSystem::CSpawnVect &sp = *CParticleSystem::_Spawns[getIndex()];
01022 if (!_Owner->getAutoCountFlag() && sp.MaxNumSpawns == sp.SpawnInfos.size()) return;
01023 if (getMaxSize() >= ((1 << 16) - 1)) return;
01024 sp.SpawnInfos.resize(sp.SpawnInfos.size() + 1);
01025 CPSSpawnInfo &si = sp.SpawnInfos.back();
01026 si.EmitterInfo.Pos = emitterLocated.getPos()[indexInEmitter];
01027 si.EmitterInfo.Speed = emitterLocated.getSpeed()[indexInEmitter];
01028 si.EmitterInfo.InvMass = emitterLocated.getInvMass()[indexInEmitter];
01029 si.EmitterInfo.Life = emitterLife;
01030 si.EmitterInfo.Loc = &emitterLocated;
01031 si.SpawnPos = pos;
01032 si.Speed = speed;
01033 si.SpeedCoordSystem = speedCoordSystem;
01034 si.LifeTime = lifeTime;
01035 }
01036
01037
01039 sint32 CPSLocated::newElement(const CPSSpawnInfo &si, bool doEmitOnce , TAnimationTime ellapsedTime)
01040 {
01041 NL_PS_FUNC(CPSLocated_newElement)
01042 CHECK_PS_INTEGRITY
01043 sint32 creationIndex;
01044
01045
01046
01047 if (_MaxSize == _Size)
01048 {
01049 if (_Owner && _Owner->getAutoCountFlag() && getMaxSize() < ((1 << 16) - 1) )
01050 {
01051
01052
01053 uint maxSize = getMaxSize();
01054 resize((uint32) std::min((uint) NLMISC::raiseToNextPowerOf2(maxSize + 1), (uint) ((1 << 16) - 1)));
01055 resize(maxSize + 1);
01056 CParticleSystem::_SpawnPos.resize(maxSize + 1);
01057 }
01058 else
01059 {
01060 return -1;
01061 }
01062 }
01063
01064
01065
01066
01067 switch(si.EmitterInfo.Loc ? si.EmitterInfo.Loc->getMatrixMode() : this->getMatrixMode())
01068 {
01069 case PSFXWorldMatrix:
01070 switch(this->getMatrixMode())
01071 {
01072 case PSFXWorldMatrix:
01073 {
01074 creationIndex =_Pos.insert(si.SpawnPos);
01075 }
01076 break;
01077 case PSIdentityMatrix:
01078 {
01079 CVector fxPosDelta;
01080 _Owner->interpolateFXPosDelta(fxPosDelta, si.LifeTime);
01081 creationIndex =_Pos.insert(_Owner->getSysMat() * si.SpawnPos + fxPosDelta);
01082 }
01083 break;
01084 case PSUserMatrix:
01085 {
01086 CVector fxPosDelta;
01087 _Owner->interpolateFXPosDelta(fxPosDelta, si.LifeTime);
01088 CVector userMatrixPosDelta;
01089 _Owner->interpolateUserPosDelta(userMatrixPosDelta, si.LifeTime);
01090 creationIndex =_Pos.insert(_Owner->getInvertedUserMatrix() * (_Owner->getSysMat() * si.SpawnPos + fxPosDelta - userMatrixPosDelta));
01091 }
01092 break;
01093 default:
01094 nlassert(0);
01095 }
01096 break;
01097 case PSIdentityMatrix:
01098 switch(this->getMatrixMode())
01099 {
01100 case PSFXWorldMatrix:
01101 {
01102 CVector fxPosDelta;
01103 _Owner->interpolateFXPosDelta(fxPosDelta, si.LifeTime);
01104 creationIndex =_Pos.insert(_Owner->getInvertedSysMat() * (si.SpawnPos - fxPosDelta));
01105 }
01106 break;
01107 case PSIdentityMatrix:
01108 {
01109 creationIndex =_Pos.insert(si.SpawnPos);
01110 }
01111 break;
01112 case PSUserMatrix:
01113 {
01114 CVector userMatrixPosDelta;
01115 _Owner->interpolateUserPosDelta(userMatrixPosDelta, si.LifeTime);
01116 creationIndex =_Pos.insert(_Owner->getInvertedUserMatrix() * (si.SpawnPos - userMatrixPosDelta));
01117 }
01118 break;
01119 default:
01120 nlassert(0);
01121 }
01122 break;
01123 case PSUserMatrix:
01124 switch(this->getMatrixMode())
01125 {
01126 case PSFXWorldMatrix:
01127 {
01128 CVector fxPosDelta;
01129 _Owner->interpolateFXPosDelta(fxPosDelta, si.LifeTime);
01130 CVector userMatrixPosDelta;
01131 _Owner->interpolateUserPosDelta(userMatrixPosDelta, si.LifeTime);
01132 creationIndex =_Pos.insert(_Owner->getInvertedSysMat() * (_Owner->getUserMatrix() * si.SpawnPos + userMatrixPosDelta- fxPosDelta));
01133 }
01134 break;
01135 case PSIdentityMatrix:
01136 {
01137 CVector userMatrixPosDelta;
01138 _Owner->interpolateUserPosDelta(userMatrixPosDelta, si.LifeTime);
01139 creationIndex =_Pos.insert(_Owner->getUserMatrix() * si.SpawnPos + userMatrixPosDelta);
01140 }
01141 break;
01142 case PSUserMatrix:
01143 {
01144 creationIndex =_Pos.insert(si.SpawnPos);
01145 }
01146 break;
01147 default:
01148 nlassert(0);
01149 }
01150 break;
01151 default:
01152 nlassert(0);
01153 }
01154
01155
01156 nlassert(creationIndex != -1);
01157
01158 if (si.SpeedCoordSystem == this->getMatrixMode())
01159 {
01160 _Speed.insert(si.Speed);
01161 }
01162 else
01163 {
01164
01165 nlassert(_Owner);
01166 const NLMISC::CMatrix &convMat = getConversionMatrix(*_Owner, this->getMatrixMode(), si.SpeedCoordSystem);
01167 _Speed.insert(convMat.mulVector(si.Speed));
01168 }
01169
01170 _InvMass.insert(1.f / ((_MassScheme && si.EmitterInfo.Loc) ? _MassScheme->get(si.EmitterInfo) : _InitialMass ) );
01171 if (CParticleSystem::InsideSimLoop)
01172 {
01173 CParticleSystem::_SpawnPos[creationIndex] = _Pos[creationIndex];
01174 }
01175
01176 if (getLastForever())
01177 {
01178
01179 _Time.insert(CParticleSystem::RealEllapsedTimeRatio * si.LifeTime);
01180 _TimeIncrement.insert(_InitialLife != 0.f ? 1.f / _InitialLife : 1.f);
01181 }
01182 else
01183 {
01184 const float totalLifeTime = (_LifeScheme && si.EmitterInfo.Loc) ? _LifeScheme->get(si.EmitterInfo) : _InitialLife ;
01185 float timeIncrement = totalLifeTime ? 1.f / totalLifeTime : 10E6f;
01186 _TimeIncrement.insert(timeIncrement);
01187 _Time.insert(CParticleSystem::RealEllapsedTimeRatio * si.LifeTime * timeIncrement);
01188 }
01189
01190
01191
01192 if (_ParametricMotion)
01193 {
01194 _PInfo.insert( CParametricInfo(_Pos[creationIndex], _Speed[creationIndex], _Owner->getSystemDate() + CParticleSystem::RealEllapsedTime - CParticleSystem::RealEllapsedTimeRatio * si.LifeTime) );
01195 }
01196 else
01197 {
01198 _Pos[creationIndex] += si.LifeTime * _Speed[creationIndex];
01199 }
01200
01202
01204 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01205 {
01206 (*it)->newElement(si.EmitterInfo);
01207
01208 if ((*it)->getType() == PSEmitter)
01209 {
01210 CPSEmitter *pEmit = NLMISC::safe_cast<CPSEmitter *>(*it);
01211 pEmit->_Phase[creationIndex] -= std::max(0.f, (ellapsedTime - si.LifeTime));
01212 }
01213 }
01214 if (doEmitOnce && !CPSEmitter::getBypassEmitOnDeath())
01215 {
01216
01217 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01218 {
01219 if ((*it)->getType() == PSEmitter)
01220 {
01221 CPSEmitter *pEmit = NLMISC::safe_cast<CPSEmitter *>(*it);
01222 if (pEmit->getEmissionType() == CPSEmitter::once)
01223 {
01224 for(uint k = 0; k < getSize(); ++k)
01225 {
01226 pEmit->singleEmit(k, 1);
01227 }
01228 }
01229 }
01230 }
01231 }
01232 if (_CollisionNextPos)
01233 {
01234 _CollisionNextPos->insert();
01235 }
01236 ++_Size;
01237
01238
01239
01240
01241 CHECK_PS_INTEGRITY
01242 return creationIndex;
01243 }
01244
01245
01247 sint32 CPSLocated::newElement(const CVector &pos, const CVector &speed, CPSLocated *emitter, uint32 indexInEmitter,
01248 TPSMatrixMode speedCoordSystem, bool doEmitOnce )
01249 {
01250 NL_PS_FUNC(CPSLocated_newElement)
01251 CPSSpawnInfo si;
01252 si.EmitterInfo.Loc = emitter;
01253 if (emitter)
01254 {
01255 si.EmitterInfo.Pos = emitter->getPos()[indexInEmitter];
01256 si.EmitterInfo.Speed = emitter->getSpeed()[indexInEmitter];
01257 si.EmitterInfo.InvMass = emitter->getInvMass()[indexInEmitter];
01258 si.EmitterInfo.Life = emitter->getTime()[indexInEmitter];
01259 }
01260 else
01261 {
01262 si.EmitterInfo.Pos = NLMISC::CVector::Null;
01263 si.EmitterInfo.Speed = NLMISC::CVector::Null;
01264 si.EmitterInfo.InvMass = 1.f;
01265 si.EmitterInfo.Life = 0.f;
01266 }
01267 si.SpawnPos = pos;
01268 si.Speed = speed;
01269 si.SpeedCoordSystem = speedCoordSystem;
01270 si.LifeTime = 0.f;
01271 return newElement(si, doEmitOnce, 0.f);
01272 }
01273
01274
01276 static inline uint32 IDToLittleEndian(uint32 input)
01277 {
01278 NL_PS_FUNC(IDToLittleEndian)
01279 #ifdef NL_LITTLE_ENDIAN
01280 return input;
01281 #else
01282 return ((input & (0xff<<24))>>24)
01283 || ((input & (0xff<<16))>>8)
01284 || ((input & (0xff<<8))<<8)
01285 || ((input & 0xff)<<24);
01286 #endif
01287 }
01288
01290 inline void CPSLocated::deleteElementBase(uint32 index)
01291 {
01292 NL_PS_FUNC(CPSLocated_deleteElementBase)
01293
01294 _InvMass.remove(index);
01295 _Pos.remove(index);
01296 _Speed.remove(index);
01297 _Time.remove(index);
01298 _TimeIncrement.remove(index);
01299 if (_CollisionNextPos)
01300 {
01301 _CollisionNextPos->remove(index);
01302 }
01303 if (_ParametricMotion)
01304 {
01305 _PInfo.remove(index);
01306 }
01307 --_Size;
01308 if (_TriggerOnDeath)
01309 {
01310 const uint32 id = IDToLittleEndian(_TriggerID);
01311 nlassert(_Owner);
01312 uint numLb = _Owner->getNumLocatedBindableByExternID(id);
01313 for (uint k = 0; k < numLb; ++k)
01314 {
01315 CPSLocatedBindable *lb = _Owner->getLocatedBindableByExternID(id, k);
01316 if (lb->getType() == PSEmitter)
01317 {
01318 CPSEmitter *e = NLMISC::safe_cast<CPSEmitter *>(lb);
01319 e->setEmitTrigger();
01320 }
01321 }
01322 }
01323 CHECK_PS_INTEGRITY
01324 }
01325
01327 void CPSLocated::deleteElement(uint32 index)
01328 {
01329 NL_PS_FUNC(CPSLocated_deleteElement)
01330 #ifdef NL_DEBUG
01331 if (CParticleSystem::InsideSimLoop)
01332 {
01333 nlassert(CParticleSystem::InsideRemoveLoop);
01334 }
01335 #endif
01336 CHECK_PS_INTEGRITY
01337 nlassert(index < _Size);
01338 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01339 {
01340 (*it)->deleteElement(index);
01341 }
01342 deleteElementBase(index);
01343 }
01344
01345
01347 void CPSLocated::deleteElement(uint32 index, TAnimationTime timeToNextSimStep)
01348 {
01349 NL_PS_FUNC(CPSLocated_deleteElement)
01350 #ifdef NL_DEBUG
01351 if (CParticleSystem::InsideSimLoop)
01352 {
01353 nlassert(CParticleSystem::InsideRemoveLoop);
01354 }
01355 #endif
01356 nlassert(index < _Size);
01357 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01358 {
01359 (*it)->deleteElement(index, timeToNextSimStep);
01360 }
01361 deleteElementBase(index);
01362 }
01363
01366 void CPSLocated::resize(uint32 newSize)
01367 {
01368 NL_PS_FUNC(CPSLocated_resize)
01369 CHECK_PS_INTEGRITY
01370 nlassert(newSize < (1 << 16));
01371 if (newSize < _Size)
01372 {
01373 for (uint32 k = _Size - 1; k >= newSize; --k)
01374 {
01375 deleteElement(k);
01376
01377 if (k == 0) break;
01378 }
01379 _Size = newSize;
01380 }
01381
01382
01383 _MaxSize = newSize;
01384 _InvMass.resize(newSize);
01385 _Pos.resize(newSize);
01386 _Speed.resize(newSize);
01387 _Time.resize(newSize);
01388 _TimeIncrement.resize(newSize);
01389
01390 if (_ParametricMotion)
01391 {
01392 _PInfo.resize(newSize);
01393 }
01394
01395 if (_CollisionNextPos)
01396 {
01397 _CollisionNextPos->resize(newSize);
01398 }
01399
01400
01401
01402 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01403 {
01404 (*it)->resize(newSize);
01405 }
01406
01407
01409
01410 CHECK_PS_INTEGRITY
01411 }
01412
01413
01414 class CDummyCollision
01415 {
01416 public:
01417 void serial(NLMISC::IStream &f) throw(NLMISC::EStream)
01418 {
01419 NL_PS_FUNC(CDummyCollision_serial)
01420 f.serialVersion(1);
01421 float dummyDist = 0.f;
01422 NLMISC::CVector dummyNewPos, dummyNewSpeed;
01423 f.serial(dummyDist, dummyNewPos, dummyNewSpeed);
01424 };
01425 };
01426
01428 void CPSLocated::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
01429 {
01430 NL_PS_FUNC(CPSLocated_serial)
01431
01432
01433
01434
01435
01436
01437 sint ver = f.serialVersion(7);
01438 CParticleSystemProcess::serial(f);
01439
01440 if (f.isReading() && !CParticleSystem::getSerializeIdentifierFlag())
01441 {
01442
01443 sint32 len;
01444 f.serial(len);
01445 f.seek(len, NLMISC::IStream::current);
01446 }
01447 else
01448 {
01449 f.serial(_Name);
01450 }
01451
01452 f.serial(_InvMass);
01453 f.serial(_Pos);
01454 f.serial(_Speed);
01455 f.serial(_Time);
01456 if (f.isReading())
01457 {
01458
01459
01460
01461 uint timeSize = _Time.getSize();
01462 if (timeSize != 0)
01463 {
01464 std::fill(&_Time[0], &_Time[0] + timeSize, 0.f);
01465 }
01466 }
01467 f.serial(_TimeIncrement);
01468 f.serial(_Size);
01469 f.serial(_MaxSize);
01470
01471 bool lastForever = _LastForever;
01472 f.serial(lastForever);
01473 _LastForever = lastForever;
01474
01475 if (ver < 7)
01476 {
01477 nlassert(f.isReading());
01478
01479 uint64 dummyPtr;
01480 f.serial(dummyPtr);
01481 if (dummyPtr)
01482 {
01483 #ifdef PS_FAST_ALLOC
01484 extern NLMISC::CContiguousBlockAllocator *PSBlockAllocator;
01485 NLMISC::CContiguousBlockAllocator *oldAlloc = PSBlockAllocator;
01486 PSBlockAllocator = NULL;
01487 #endif
01488 static CPSAttrib<CDummyCollision> col;
01489 col.clear();
01490 f.serial(col);
01491 #ifdef PS_FAST_ALLOC
01492 PSBlockAllocator = oldAlloc;
01493 #endif
01494 }
01495 }
01496 f.serial(_CollisionInfoNbRef);
01497
01498 if (f.isReading())
01499 {
01500 if (_CollisionInfoNbRef)
01501 {
01502 _CollisionNextPos = new TPSAttribVector;
01503 _CollisionNextPos->resize(_Pos.getMaxSize());
01504 for(uint k = 0; k < _Size; ++k)
01505 {
01506 _CollisionNextPos->insert();
01507 }
01508 }
01509 }
01510
01511 if (f.isReading())
01512 {
01513 delete _LifeScheme;
01514 delete _MassScheme;
01515
01516 bool useScheme;
01517 f.serial(useScheme);
01518 if (useScheme)
01519 {
01520 f.serialPolyPtr(_LifeScheme);
01521 }
01522 else
01523 {
01524 f.serial(_InitialLife);
01525 _LifeScheme = NULL;
01526 }
01527
01528 f.serial(useScheme);
01529 if (useScheme)
01530 {
01531 f.serialPolyPtr(_MassScheme);
01532 }
01533 else
01534 {
01535 f.serial(_InitialMass);
01536 nlassert(_InitialMass > 0);
01537 _MassScheme = NULL;
01538 }
01539 }
01540 else
01541 {
01542 bool bFalse = false, bTrue = true;
01543 if (_LifeScheme)
01544 {
01545 f.serial(bTrue);
01546 f.serialPolyPtr(_LifeScheme);
01547 }
01548 else
01549 {
01550 f.serial(bFalse);
01551 f.serial(_InitialLife);
01552 }
01553 if (_MassScheme)
01554 {
01555 f.serial(bTrue);
01556 f.serialPolyPtr(_MassScheme);
01557 }
01558 else
01559 {
01560 f.serial(bFalse);
01561 nlassert(_InitialMass > 0);
01562 f.serial(_InitialMass);
01563 }
01564 }
01565
01566 if (ver < 7)
01567 {
01568 uint32 dummy = 0;
01569 f.serial(dummy);
01570 }
01571
01572 f.serialContPolyPtr(_DtorObserversVect);
01573
01574 if (ver < 7)
01575 {
01576 nlassert(f.isReading());
01577
01578 uint32 size;
01579 f.serial(size);
01580 nlassert(size == 0);
01581
01582
01583
01584
01585
01586
01587
01588
01589 }
01590
01591 if (ver < 7)
01592 {
01593 nlassert(f.isReading());
01594 bool dummy;
01595 f.serial(dummy);
01596 }
01597
01598 f.serialContPolyPtr(_LocatedBoundCont);
01599
01600
01601
01602 #ifdef NL_DEBUG
01603 for(uint k = 0; k < _LocatedBoundCont.size(); ++k)
01604 {
01605 nlassert(_LocatedBoundCont[k]->getOwner() == this);
01606 }
01607 #endif
01608
01609 if (ver > 1)
01610 {
01611 bool lodDegradation = _LODDegradation;
01612 f.serial(lodDegradation);
01613 _LODDegradation = lodDegradation;
01614 }
01615
01616 if (ver > 2)
01617 {
01618 bool parametricMotion = _ParametricMotion;
01619 f.serial(parametricMotion);
01620 _ParametricMotion = parametricMotion;
01621 }
01622
01623 if (f.isReading())
01624 {
01625
01626
01627
01628 if (_ParametricMotion)
01629 {
01630 _ParametricMotion = false;
01631 allocateParametricInfos();
01632 _ParametricMotion = true;
01633 }
01634 }
01635
01636 if (ver > 3)
01637 {
01638 bool triggerOnDeath = _TriggerOnDeath;
01639 f.serial(triggerOnDeath);
01640 _TriggerOnDeath = triggerOnDeath;
01641 f.serial(_TriggerID);
01642 }
01643 CHECK_PS_INTEGRITY
01644 }
01645
01647
01648 static void IntegrateSpeed(uint count, float *src1, const float *src2, float *dest, float ellapsedTime)
01649 {
01650 NL_PS_FUNC(IntegrateSpeed)
01651 #if 0 // this works, but is not enabled for now. The precision is not that good...
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723 #endif
01724 {
01725
01726
01727
01728 uint countDiv8 = count>>3;
01729 count &= 7;
01730
01731 if (dest == src1)
01732 {
01733 while (countDiv8 --)
01734 {
01735 src1[0] += ellapsedTime * src2[0];
01736 src1[1] += ellapsedTime * src2[1];
01737 src1[2] += ellapsedTime * src2[2];
01738 src1[3] += ellapsedTime * src2[3];
01739
01740 src1[4] += ellapsedTime * src2[4];
01741 src1[5] += ellapsedTime * src2[5];
01742 src1[6] += ellapsedTime * src2[6];
01743 src1[7] += ellapsedTime * src2[7];
01744
01745 src2 += 8;
01746 src1 += 8;
01747 }
01748 while (count--)
01749 {
01750 *src1++ += ellapsedTime * *src2++;
01751 }
01752 }
01753 else
01754 {
01755 while (countDiv8 --)
01756 {
01757 dest[0] = src1[0] + ellapsedTime * src2[0];
01758 dest[1] = src1[1] + ellapsedTime * src2[1];
01759 dest[2] = src1[2] + ellapsedTime * src2[2];
01760 dest[3] = src1[3] + ellapsedTime * src2[3];
01761 dest[4] = src1[4] + ellapsedTime * src2[4];
01762 dest[5] = src1[5] + ellapsedTime * src2[5];
01763 dest[6] = src1[6] + ellapsedTime * src2[6];
01764 dest[7] = src1[7] + ellapsedTime * src2[7];
01765 src2 += 8;
01766 src1 += 8;
01767 dest += 8;
01768 }
01769 while (count--)
01770 {
01771 *dest++ = *src1++ + ellapsedTime * *src2++;
01772 }
01773 }
01774 }
01775 }
01776
01778 void CPSLocated::computeMotion()
01779 {
01780 NL_PS_FUNC(CPSLocated_computeMotion)
01781 nlassert(_Size);
01782
01783 if (!_CollisionNextPos)
01784 {
01785 {
01786 MINI_TIMER(PSMotion3)
01787 if (_Size != 0)
01788 IntegrateSpeed(_Size * 3, &_Pos[0].x, &_Speed[0].x, &_Pos[0].x, CParticleSystem::EllapsedTime);
01789 }
01790 }
01791 else
01792 {
01793 {
01794 MINI_TIMER(PSMotion4)
01795
01796 IntegrateSpeed(_Size * 3, &_Pos[0].x, &_Speed[0].x, &(*_CollisionNextPos)[0].x, CParticleSystem::EllapsedTime);
01797 nlassert(CPSLocated::_Collisions.size() >= _Size);
01798 computeCollisions(0, &_Pos[0], &(*_CollisionNextPos)[0]);
01799
01800 _CollisionNextPos->swap(_Pos);
01801 }
01802 }
01803 }
01804
01805
01806
01808 void CPSLocated::computeNewParticleMotion(uint firstInstanceIndex)
01809 {
01810 NL_PS_FUNC(CPSLocated_computeNewParticleMotion)
01811 nlassert(_CollisionNextPos);
01812 resetCollisions(_Size);
01813 computeCollisions(firstInstanceIndex, &CParticleSystem::_SpawnPos[0], &_Pos[0]);
01814 }
01815
01817 void CPSLocated::resetCollisions(uint numInstances)
01818 {
01819 NL_PS_FUNC(CPSLocated_resetCollisions)
01820 CPSCollisionInfo *currCollision = _FirstCollision;
01821 while (currCollision)
01822 {
01823 currCollision->Dist = -1.f;
01824 currCollision = currCollision->Next;
01825 }
01826 _FirstCollision = NULL;
01827 if (numInstances > _Collisions.size())
01828 {
01829 uint oldSize = (uint) _Collisions.size();
01830 _Collisions.resize(numInstances);
01831 for(uint k = oldSize; k < numInstances; ++k)
01832 {
01833 _Collisions[k].Index = k;
01834 }
01835 }
01836 }
01837
01839 void CPSLocated::updateCollisions()
01840 {
01841 NL_PS_FUNC(CPSLocated_updateCollisions)
01842 CPSCollisionInfo *currCollision = _FirstCollision;
01843 if (getLastForever())
01844 {
01845 while (currCollision)
01846 {
01847 _Pos[currCollision->Index] = currCollision->NewPos;
01848 std::swap(_Speed[currCollision->Index], currCollision->NewSpeed);
01849
01850 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01851 {
01852 (*it)->bounceOccured(currCollision->Index, computeDateFromCollisionToNextSimStep(currCollision->Index, getAgeInSeconds(currCollision->Index)));
01853 }
01854 if (currCollision->CollisionZone->getCollisionBehaviour() == CPSZone::destroy)
01855 {
01856 #ifdef NL_DEBUG
01857 nlassert(CParticleSystem::_ParticleRemoveListIndex[currCollision->Index] == -1);
01858 #endif
01859 CParticleSystem::_ParticleToRemove.push_back(currCollision->Index);
01860 #ifdef NL_DEBUG
01861 nlassert(CParticleSystem::_ParticleToRemove.size() <= _Size);
01862 #endif
01863 CParticleSystem::_ParticleRemoveListIndex[currCollision->Index] = CParticleSystem::_ParticleToRemove.size() - 1;
01864
01865 }
01866 currCollision = currCollision->Next;
01867 }
01868 }
01869 else
01870 {
01871 while (currCollision)
01872 {
01873 if (_Time[currCollision->Index] >= 1.f)
01874 {
01875
01876 float timeToCollision = currCollision->Dist / _Speed[currCollision->Index].norm();
01877 if (_Time[currCollision->Index] / _TimeIncrement[currCollision->Index] - timeToCollision * CParticleSystem::RealEllapsedTimeRatio >= 1.f)
01878 {
01879
01880 currCollision->Dist = -1.f;
01881 currCollision = currCollision->Next;
01882 continue;
01883 }
01884 }
01885
01886 _Pos[currCollision->Index] = currCollision->NewPos;
01887 std::swap(_Speed[currCollision->Index], currCollision->NewSpeed);
01888
01889 if (!_LocatedBoundCont.empty())
01890 {
01891 TAnimationTime timeFromcollisionToNextSimStep = computeDateFromCollisionToNextSimStep(currCollision->Index, getAgeInSeconds(currCollision->Index));
01892 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01893 {
01894 (*it)->bounceOccured(currCollision->Index, timeFromcollisionToNextSimStep);
01895 }
01896 }
01897 if (currCollision->CollisionZone->getCollisionBehaviour() == CPSZone::destroy)
01898 {
01899 if (_Time[currCollision->Index] < 1.f)
01900 {
01901
01902 #ifdef NL_DEBUG
01903 nlassert(CParticleSystem::_ParticleRemoveListIndex[currCollision->Index] == -1);
01904 #endif
01905 CParticleSystem::_ParticleToRemove.push_back(currCollision->Index);
01906 #ifdef NL_DEBUG
01907 nlassert(CParticleSystem::_ParticleToRemove.size() <= _Size);
01908 #endif
01909 CParticleSystem::_ParticleRemoveListIndex[currCollision->Index] = CParticleSystem::_ParticleToRemove.size() - 1;
01910 }
01911 }
01912 currCollision = currCollision->Next;
01913 }
01914 }
01915
01916 }
01917
01919 void CPSLocated::doLODDegradation()
01920 {
01921 NL_PS_FUNC(CPSLocated_doLODDegradation)
01922 nlassert(CParticleSystem::InsideSimLoop);
01923 nlassert(!CParticleSystem::InsideRemoveLoop);
01924 CParticleSystem::InsideRemoveLoop = true;
01925 if (CParticleSystem::EllapsedTime > 0)
01926 {
01927 nlassert(_Owner);
01928
01929 const uint maxToHave = (uint) (_MaxSize * _Owner->getOneMinusCurrentLODRatio());
01930 if (_Size > maxToHave)
01931 {
01932
01933
01934
01935 uint pos = maxToHave ? rand() % maxToHave : 0;
01936 uint step = maxToHave ? rand() % maxToHave : 0;
01937
01938 do
01939 {
01940 deleteElement(pos);
01941 pos += step;
01942 if (pos >= maxToHave) pos -= maxToHave;
01943 }
01944 while (_Size !=maxToHave);
01945 }
01946 }
01947 CParticleSystem::InsideRemoveLoop = false;
01948 }
01949
01951 void CPSLocated::step(TPSProcessPass pass)
01952 {
01953 NL_PS_FUNC(CPSLocated_step)
01954 CHECK_PS_INTEGRITY
01955 if (!_Size) return;
01956
01957 if (pass != PSMotion)
01958 {
01959 {
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01974 {
01975 if ((*it)->isActive())
01976 {
01977 if ((*it)->getLOD() == PSLod1n2 || _Owner->getLOD() == (*it)->getLOD())
01978 {
01979 (*it)->step(pass);
01980 }
01981 }
01982 }
01983 }
01984 }
01985 else
01986 {
01987 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01988 {
01989 if ((*it)->isActive())
01990 {
01991 (*it)->step(pass);
01992 }
01993 }
01994
01995 }
01996 CHECK_PS_INTEGRITY
01997 }
01998
02000 void CPSLocated::updateLife()
02001 {
02002 NL_PS_FUNC(CPSLocated_updateLife)
02003 CHECK_PS_INTEGRITY
02004 if (!_Size) return;
02005 if (! _LastForever)
02006 {
02007 if (_LifeScheme != NULL)
02008 {
02009 TPSAttribTime::iterator itTime = _Time.begin(), itTimeInc = _TimeIncrement.begin();
02010 for (uint32 k = 0; k < _Size; ++k)
02011 {
02012 *itTime += CParticleSystem::RealEllapsedTime * *itTimeInc;
02013 if (*itTime >= 1.0f)
02014 {
02015 #ifdef NL_DEBUG
02016 nlassert(CParticleSystem::_ParticleRemoveListIndex[k] == -1);
02017 #endif
02018 CParticleSystem::_ParticleToRemove.push_back(k);
02019 #ifdef NL_DEBUG
02020 nlassert(CParticleSystem::_ParticleToRemove.size() <= _Size);
02021 #endif
02022 CParticleSystem::_ParticleRemoveListIndex[k] = CParticleSystem::_ParticleToRemove.size() - 1;
02023 }
02024 ++itTime;
02025 ++itTimeInc;
02026 }
02027 }
02028 else
02029 {
02030 if (_InitialLife != 0)
02031 {
02032 nlassert(_Owner);
02033 float timeInc = CParticleSystem::RealEllapsedTime / _InitialLife;
02034 if (_Owner->getSystemDate() + 0.1f + 2.f * timeInc >= (_InitialLife - CParticleSystem::RealEllapsedTime))
02035 {
02036
02037 TPSAttribTime::iterator itTime = _Time.begin();
02038 for (uint32 k = 0; k < _Size; ++k)
02039 {
02040 *itTime += timeInc;
02041 if (*itTime >= 1.0f)
02042 {
02043 #ifdef NL_DEBUG
02044 nlassert(CParticleSystem::_ParticleRemoveListIndex[k] == -1);
02045 #endif
02046 CParticleSystem::_ParticleToRemove.push_back(k);
02047 #ifdef NL_DEBUG
02048 nlassert(CParticleSystem::_ParticleToRemove.size() <= _Size);
02049 #endif
02050 CParticleSystem::_ParticleRemoveListIndex[k] = CParticleSystem::_ParticleToRemove.size() - 1;
02051 }
02052 ++ itTime;
02053 }
02054 }
02055 else
02056 {
02057
02058 TPSAttribTime::iterator itTime = _Time.begin(), itEndTime = _Time.end();
02059 do
02060 {
02061 *itTime += timeInc;
02062 ++itTime;
02063 }
02064 while (itTime != itEndTime);
02065 }
02066 }
02067 else
02068 {
02069 for(uint k = 0; k < _Size; ++k)
02070 {
02071 #ifdef NL_DEBUG
02072 nlassert(CParticleSystem::_ParticleRemoveListIndex[k] == -1);
02073 #endif
02074 CParticleSystem::_ParticleToRemove.push_back(k);
02075 #ifdef NL_DEBUG
02076 nlassert(CParticleSystem::_ParticleToRemove.size() <= _Size);
02077 #endif
02078 CParticleSystem::_ParticleRemoveListIndex[k] = CParticleSystem::_ParticleToRemove.size() - 1;
02079 }
02080 }
02081 }
02082 }
02083 else
02084 {
02085
02086 TPSAttribTime::iterator itTime = _Time.begin(), endItTime = _Time.end();
02087 for (; itTime != endItTime; ++itTime)
02088 {
02089 *itTime += CParticleSystem::RealEllapsedTime;
02090 }
02091 }
02092 CHECK_PS_INTEGRITY
02093 }
02094
02095
02097
02098
02099 static inline void removeParticleFromRemoveList(uint indexToRemove, uint arraySize)
02100 {
02101 NL_PS_FUNC(removeParticleFromRemoveList)
02102 if (indexToRemove != arraySize)
02103 {
02104 if (CParticleSystem::_ParticleRemoveListIndex[arraySize] != -1)
02105 {
02106
02107
02108 CParticleSystem::_ParticleToRemove[CParticleSystem::_ParticleRemoveListIndex[arraySize]] = indexToRemove;
02109 CParticleSystem::_ParticleRemoveListIndex[indexToRemove] = CParticleSystem::_ParticleRemoveListIndex[arraySize];
02110 CParticleSystem::_ParticleRemoveListIndex[arraySize] = -1;
02111 }
02112 else
02113 {
02114 CParticleSystem::_ParticleRemoveListIndex[indexToRemove] = -1;
02115 }
02116 }
02117 else
02118 {
02119 CParticleSystem::_ParticleRemoveListIndex[arraySize] = -1;
02120 }
02121 }
02122
02123 void checkRemoveArray(uint size)
02124 {
02125 NL_PS_FUNC(checkRemoveArray)
02126 for(uint k = 0; k < size; ++k)
02127 {
02128 if (CParticleSystem::_ParticleRemoveListIndex[k] != -1)
02129 {
02130 nlassert(std::find(CParticleSystem::_ParticleRemoveListIndex.begin(), CParticleSystem::_ParticleRemoveListIndex.end(), CParticleSystem::_ParticleRemoveListIndex[k]) != CParticleSystem::_ParticleRemoveListIndex.end());
02131 }
02132 }
02133 for(uint k = 0; k < CParticleSystem::_ParticleToRemove.size(); ++k)
02134 {
02135 nlassert(CParticleSystem::_ParticleRemoveListIndex[CParticleSystem::_ParticleToRemove[k]] == (sint) k);
02136 }
02137
02138 }
02139
02140
02142 #ifndef NL_DEBUG
02143 inline
02144 #endif
02145 TAnimationTime CPSLocated::computeDateFromCollisionToNextSimStep(uint particleIndex, float particleAgeInSeconds)
02146 {
02147 NL_PS_FUNC( CPSLocated_computeDateFromCollisionToNextSimStep)
02148
02149 float ageAtStart = CParticleSystem::RealEllapsedTime > particleAgeInSeconds ? CParticleSystem::RealEllapsedTime - particleAgeInSeconds : 0.f;
02150 ageAtStart /= CParticleSystem::RealEllapsedTimeRatio;
02151
02152 float norm = _Collisions[particleIndex].NewSpeed.norm();
02153 if (norm == 0.f) return 0.f;
02154 float timeToCollision = _Collisions[particleIndex].Dist / norm;
02155
02156 TAnimationTime result = CParticleSystem::EllapsedTime - ageAtStart - timeToCollision;
02157 return std::max(0.f, result);
02158 }
02159
02161 void CPSLocated::removeOldParticles()
02162 {
02163 NL_PS_FUNC(CPSLocated_removeOldParticles)
02164 nlassert(CParticleSystem::RealEllapsedTime > 0.f);
02165 #ifdef NL_DEBUG
02166 CParticleSystem::InsideRemoveLoop = true;
02167 checkRemoveArray(_Size);
02168 #endif
02169
02170
02171 if (getLastForever())
02172 {
02173
02174
02175 if (hasCollisionInfos())
02176 {
02177 for(std::vector<uint>::iterator it = CParticleSystem::_ParticleToRemove.begin(); it != CParticleSystem::_ParticleToRemove.end(); ++it)
02178 {
02179 if (_Collisions[*it].Dist != -1.f)
02180 {
02181 deleteElement(*it, computeDateFromCollisionToNextSimStep(*it, _Time[*it]));
02182 }
02183 else
02184 {
02185 deleteElement(*it);
02186 }
02187 removeParticleFromRemoveList(*it, _Size);
02188 }
02189 }
02190 }
02191 else
02192 if (hasCollisionInfos())
02193 {
02194 float ellapsedTimeRatio = CParticleSystem::EllapsedTime / CParticleSystem::RealEllapsedTime;
02195 for(std::vector<uint>::iterator it = CParticleSystem::_ParticleToRemove.begin(); it != CParticleSystem::_ParticleToRemove.end(); ++it)
02196 {
02197 TAnimationTime timeUntilNextSimStep;
02198 if (_Collisions[*it].Dist == -1.f)
02199 {
02200
02201 if (_Time[*it] > 1.f)
02202 {
02203
02204 if (_LifeScheme)
02205 {
02206 _Pos[*it] -= _Speed[*it] * ((_Time[*it] - 1.f) / _TimeIncrement[*it]) * ellapsedTimeRatio;
02207 timeUntilNextSimStep = (_Time[*it] - 1.f) / _TimeIncrement[*it];
02208 }
02209 else
02210 {
02211 _Pos[*it] -= _Speed[*it] * ((_Time[*it] - 1.f) * _InitialLife) * ellapsedTimeRatio;
02212 timeUntilNextSimStep = (_Time[*it] - 1.f) * _InitialLife;
02213 }
02214 _Time[*it] = 0.9999f;
02215 }
02216 else
02217 {
02218 timeUntilNextSimStep = 0.f;
02219 }
02220 }
02221 else
02222 {
02223
02224 if (_LifeScheme)
02225 {
02226 timeUntilNextSimStep = computeDateFromCollisionToNextSimStep(*it, _Time[*it] / _TimeIncrement[*it]);
02227
02228 _Time[*it] -= timeUntilNextSimStep * _TimeIncrement[*it];
02229 NLMISC::clamp(_Time[*it], 0.f, 1.f);
02230 }
02231 else
02232 {
02233 timeUntilNextSimStep = computeDateFromCollisionToNextSimStep(*it, _Time[*it] * _InitialLife);
02234
02235 _Time[*it] -= timeUntilNextSimStep / (_InitialLife == 0.f ? 1.f : _InitialLife);
02236 NLMISC::clamp(_Time[*it], 0.f, 1.f);
02237 }
02238
02239
02240 }
02241 deleteElement(*it, timeUntilNextSimStep);
02242 removeParticleFromRemoveList(*it, _Size);
02243 }
02244 }
02245 else
02246 {
02247 float ellapsedTimeRatio = CParticleSystem::EllapsedTime / CParticleSystem::RealEllapsedTime;
02248 if (!isParametricMotionEnabled())
02249 {
02250 if (_LifeScheme)
02251 {
02252 for(std::vector<uint>::iterator it = CParticleSystem::_ParticleToRemove.begin(); it != CParticleSystem::_ParticleToRemove.end(); ++it)
02253 {
02254 #ifdef NL_DEBUG
02255 for(std::vector<uint>::iterator it2 = it; it2 != CParticleSystem::_ParticleToRemove.end(); ++it2)
02256 {
02257 nlassert(*it2 < _Size);
02258 }
02259 #endif
02260 TAnimationTime timeUntilNextSimStep;
02261 if (_Time[*it] > 1.f)
02262 {
02263
02264 timeUntilNextSimStep = ((_Time[*it] - 1.f) / _TimeIncrement[*it]) * ellapsedTimeRatio;
02265 _Pos[*it] -= _Speed[*it] * timeUntilNextSimStep;
02266
02267
02268 _Time[*it] = 0.9999f;
02269 }
02270 else
02271 {
02272 timeUntilNextSimStep = 0.f;
02273 }
02274 deleteElement(*it, timeUntilNextSimStep);
02275 removeParticleFromRemoveList(*it, _Size);
02276 #ifdef NL_DEBUG
02277 for(std::vector<uint>::iterator it2 = it + 1; it2 != CParticleSystem::_ParticleToRemove.end(); ++it2)
02278 {
02279 nlassert(*it2 < _Size);
02280 }
02281 #endif
02282 }
02283 }
02284 else
02285 {
02286 for(std::vector<uint>::iterator it = CParticleSystem::_ParticleToRemove.begin(); it != CParticleSystem::_ParticleToRemove.end(); ++it)
02287 {
02288 TAnimationTime timeUntilNextSimStep;
02289 if (_Time[*it] > 1.f)
02290 {
02291
02292 timeUntilNextSimStep = (_Time[*it] - 1.f) * _InitialLife * ellapsedTimeRatio;
02293 _Pos[*it] -= _Speed[*it] * timeUntilNextSimStep;
02294
02295 _Time[*it] = 0.9999f;
02296 }
02297 else
02298 {
02299 timeUntilNextSimStep = 0.f;
02300 }
02301 deleteElement(*it, timeUntilNextSimStep);
02302 removeParticleFromRemoveList(*it, _Size);
02303 }
02304 }
02305 }
02306 else
02307 {
02308
02309 if (_LifeScheme)
02310 {
02311 for(std::vector<uint>::iterator it = CParticleSystem::_ParticleToRemove.begin(); it != CParticleSystem::_ParticleToRemove.end(); ++it)
02312 {
02313 TAnimationTime timeUntilNextSimStep;
02314 if (_Time[*it] > 1.f)
02315 {
02316
02317 timeUntilNextSimStep = (_Time[*it] - 1.f) / _TimeIncrement[*it];
02318 computeParametricPos(_Owner->getSystemDate() + CParticleSystem::RealEllapsedTime - timeUntilNextSimStep, *it, _Pos[*it]);
02319 timeUntilNextSimStep *= ellapsedTimeRatio;
02320
02321 _Time[*it] = 0.9999f;
02322 }
02323 else
02324 {
02325 timeUntilNextSimStep = 0.f;
02326 }
02327 deleteElement(*it, timeUntilNextSimStep);
02328 removeParticleFromRemoveList(*it, _Size);
02329 }
02330 }
02331 else
02332 {
02333 for(std::vector<uint>::iterator it = CParticleSystem::_ParticleToRemove.begin(); it != CParticleSystem::_ParticleToRemove.end(); ++it)
02334 {
02335 TAnimationTime timeUntilNextSimStep;
02336 if (_Time[*it] > 1.f)
02337 {
02338
02339 timeUntilNextSimStep = (_Time[*it] - 1.f) * _InitialLife;
02340 computeParametricPos(_Owner->getSystemDate() + CParticleSystem::RealEllapsedTime - timeUntilNextSimStep, *it, _Pos[*it]);
02341 timeUntilNextSimStep *= ellapsedTimeRatio;
02342
02343 _Time[*it] = 0.9999f;
02344 }
02345 else
02346 {
02347 timeUntilNextSimStep = 0.f;
02348 }
02349 deleteElement(*it, timeUntilNextSimStep);
02350 removeParticleFromRemoveList(*it, _Size);
02351 }
02352 }
02353 }
02354 }
02355 #ifdef NL_DEBUG
02356 CParticleSystem::InsideRemoveLoop = false;
02357 #endif
02358 CParticleSystem::_ParticleToRemove.clear();
02359 #ifdef NL_DEBUG
02360 if (!_LastForever)
02361 {
02362 for(uint k = 0; k < _Size; ++k)
02363 {
02364 nlassert(_Time[k] >= 0.f && _Time[k] <= 1.f);
02365 }
02366 }
02367 #endif
02368 }
02369
02371 void CPSLocated::addNewlySpawnedParticles()
02372 {
02373 NL_PS_FUNC(CPSLocated_addNewlySpawnedParticles)
02374 #ifdef NL_DEBUG
02375 CParticleSystem::InsideNewElementsLoop = true;
02376 #endif
02377 CParticleSystem::CSpawnVect &spawns = *CParticleSystem::_Spawns[getIndex()];
02378 if (spawns.SpawnInfos.empty()) return;
02379 uint numSpawns = 0;
02380 if (!_Owner->getAutoCountFlag())
02381 {
02382 CParticleSystem::_SpawnPos.resize(getMaxSize());
02383 numSpawns = std::min((uint) (_MaxSize - _Size), (uint) spawns.SpawnInfos.size());
02384 }
02385 else
02386 {
02387 numSpawns = (uint) spawns.SpawnInfos.size();
02388 }
02389 CParticleSystem::TSpawnInfoVect::const_iterator endIt = spawns.SpawnInfos.begin() + numSpawns;
02390 if (_LastForever)
02391 {
02392 for (CParticleSystem::TSpawnInfoVect::const_iterator it = spawns.SpawnInfos.begin(); it !=endIt; ++it)
02393 {
02394
02395 newElement(*it, false, CParticleSystem::EllapsedTime);
02396 }
02397 }
02398 else
02399 {
02400
02401
02402 for (CParticleSystem::TSpawnInfoVect::const_iterator it = spawns.SpawnInfos.begin(); it !=endIt; ++it)
02403 {
02404 sint32 insertionIndex = newElement(*it, false, CParticleSystem::EllapsedTime);
02405 #ifdef NL_DEBUG
02406 nlassert(insertionIndex != -1)
02407 #endif
02408 if (_Time[insertionIndex] >= 1.f)
02409 {
02410 #ifdef NL_DEBUG
02411 nlassert(CParticleSystem::_ParticleRemoveListIndex[insertionIndex] == -1);
02412 #endif
02413 CParticleSystem::_ParticleToRemove.push_back(insertionIndex);
02414 #ifdef NL_DEBUG
02415 nlassert(CParticleSystem::_ParticleToRemove.size() <= _Size);
02416 #endif
02417 CParticleSystem::_ParticleRemoveListIndex[insertionIndex] = CParticleSystem::_ParticleToRemove.size() - 1;
02418 }
02419 }
02420
02421 }
02422 spawns.SpawnInfos.clear();
02423 #ifdef NL_DEBUG
02424 CParticleSystem::InsideNewElementsLoop = false;
02425 #endif
02426 }
02427
02429 bool CPSLocated::computeBBox(NLMISC::CAABBox &box) const
02430 {
02431 NL_PS_FUNC(CPSLocated_computeBBox)
02432 CHECK_PS_INTEGRITY
02433 if (!_Size) return false;
02434
02435
02436 TLocatedBoundCont::const_iterator it;
02437 TPSAttribVector::const_iterator it2;
02438
02439
02440
02441 for (it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
02442 {
02443 if ((*it)->doesProduceBBox())
02444 {
02445 break;
02446 }
02447 }
02448
02449 if (it == _LocatedBoundCont.end())
02450 {
02451 return false;
02452 }
02453
02454 CVector min = _Pos[0], max = _Pos[0];
02455
02456 for (it2 = _Pos.begin(); it2 != _Pos.end(); ++ it2)
02457 {
02458 const CVector &v = (*it2);
02459 min.minof(min, v);
02460 max.maxof(max, v);
02461 }
02462
02463 box.setMinMax(min, max);
02464
02465
02466
02467
02468
02469 NLMISC::CAABBox tmpBox, startBox = box;
02470
02471 for (it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
02472 {
02473 if ((*it)->doesProduceBBox())
02474 {
02475 tmpBox = startBox;
02476 if ((*it)->completeBBox(tmpBox))
02477 {
02478 box = NLMISC::CAABBox::computeAABBoxUnion(tmpBox, box);
02479 }
02480 }
02481 }
02482 CHECK_PS_INTEGRITY
02483 return true;
02484 }
02485
02486
02489 void CPSLocated::setupDriverModelMatrix(void)
02490 {
02491 NL_PS_FUNC(CPSLocated_setupDriverModelMatrix)
02492 CHECK_PS_INTEGRITY
02493 getDriver()->setupModelMatrix(getLocalToWorldMatrix());
02494 CHECK_PS_INTEGRITY
02495 }
02496
02498 void CPSLocated::queryCollisionInfo(void)
02499 {
02500 NL_PS_FUNC(CPSLocated_queryCollisionInfo)
02501 CHECK_PS_INTEGRITY
02502 if (_CollisionInfoNbRef)
02503 {
02504 ++ _CollisionInfoNbRef;
02505 }
02506 else
02507 {
02508 _CollisionNextPos = new TPSAttribVector;
02509 _CollisionInfoNbRef = 1;
02510 _CollisionNextPos ->resize(_MaxSize);
02511 for(uint k = 0; k < _Size; ++k)
02512 {
02513 _CollisionNextPos->insert();
02514 }
02515 }
02516 CHECK_PS_INTEGRITY
02517 }
02518
02520 void CPSLocated::releaseCollisionInfo(void)
02521 {
02522 NL_PS_FUNC(CPSLocated_releaseCollisionInfo)
02523 CHECK_PS_INTEGRITY
02524 nlassert(_CollisionInfoNbRef);
02525
02526 --_CollisionInfoNbRef;
02527 if (_CollisionInfoNbRef == 0)
02528 {
02529 delete _CollisionNextPos;
02530 _CollisionNextPos = NULL;
02531 }
02532 CHECK_PS_INTEGRITY
02533 }
02534
02535
02536
02538 void CPSLocated::registerIntegrableForce(CPSForce *f)
02539 {
02540 NL_PS_FUNC(CPSLocated_registerIntegrableForce)
02541 CHECK_PS_INTEGRITY
02542 nlassert(std::find(_IntegrableForces.begin(), _IntegrableForces.end(), f) == _IntegrableForces.end());
02543 _IntegrableForces.push_back(f);
02544 if (getMatrixMode() != f->getOwner()->getMatrixMode())
02545 {
02546 ++_NumIntegrableForceWithDifferentBasis;
02547 releaseParametricInfos();
02548 }
02549 CHECK_PS_INTEGRITY
02550 }
02551
02552
02554 void CPSLocated::unregisterIntegrableForce(CPSForce *f)
02555 {
02556 NL_PS_FUNC(CPSLocated_unregisterIntegrableForce)
02557 CHECK_PS_INTEGRITY
02558 nlassert(f->getOwner());
02559 CPSVector<CPSForce *>::V::iterator it = std::find(_IntegrableForces.begin(), _IntegrableForces.end(), f);
02560 nlassert(it != _IntegrableForces.end() );
02561 _IntegrableForces.erase(it);
02562 if (getMatrixMode() != f->getOwner()->getMatrixMode())
02563 {
02564 --_NumIntegrableForceWithDifferentBasis;
02565 }
02566 CHECK_PS_INTEGRITY
02567 }
02568
02570 void CPSLocated::addNonIntegrableForceRef(void)
02571 {
02572 NL_PS_FUNC(CPSLocated_addNonIntegrableForceRef)
02573 CHECK_PS_INTEGRITY
02574 ++_NonIntegrableForceNbRefs;
02575 releaseParametricInfos();
02576 CHECK_PS_INTEGRITY
02577 }
02578
02580 void CPSLocated::releaseNonIntegrableForceRef(void)
02581 {
02582 NL_PS_FUNC(CPSLocated_releaseNonIntegrableForceRef)
02583 CHECK_PS_INTEGRITY
02584 nlassert(_NonIntegrableForceNbRefs != 0);
02585 --_NonIntegrableForceNbRefs;
02586 CHECK_PS_INTEGRITY
02587 }
02588
02589
02591 void CPSLocated::integrableForceBasisChanged(TPSMatrixMode matrixMode)
02592 {
02593 NL_PS_FUNC(CPSLocated_integrableForceBasisChanged)
02594 CHECK_PS_INTEGRITY
02595 if (getMatrixMode() != matrixMode)
02596 {
02597 ++_NumIntegrableForceWithDifferentBasis;
02598 releaseParametricInfos();
02599 }
02600 else
02601 {
02602 --_NumIntegrableForceWithDifferentBasis;
02603 }
02604 CHECK_PS_INTEGRITY
02605 }
02606
02607
02609 CPSLocatedBindable *CPSLocated::unbind(uint index)
02610 {
02611 NL_PS_FUNC(CPSLocated_unbind)
02612 CHECK_PS_INTEGRITY
02613 nlassert(index < _LocatedBoundCont.size());
02614 CPSLocatedBindable *lb = _LocatedBoundCont[index];
02615 lb->setOwner(NULL);
02616 _LocatedBoundCont.erase(_LocatedBoundCont.begin() + index);
02617 return lb;
02618 CHECK_PS_INTEGRITY
02619 }
02620
02622 bool CPSLocated::isBound(const CPSLocatedBindable *lb) const
02623 {
02624 NL_PS_FUNC(CPSLocated_isBound)
02625 CHECK_PS_INTEGRITY
02626 TLocatedBoundCont::const_iterator it = std::find(_LocatedBoundCont.begin(), _LocatedBoundCont.end(), lb);
02627 return it != _LocatedBoundCont.end();
02628 }
02629
02631 uint CPSLocated::getIndexOf(const CPSLocatedBindable *lb) const
02632 {
02633 NL_PS_FUNC(CPSLocated_getIndexOf)
02634 CHECK_PS_INTEGRITY
02635 for(uint k = 0; k < _LocatedBoundCont.size(); ++k)
02636 {
02637 if (_LocatedBoundCont[k] == lb) return k;
02638 }
02639 nlassert(0);
02640 return 0;
02641 }
02642
02643
02644
02646
02648
02649
02651 CPSLocatedBindable::CPSLocatedBindable() : _Owner(NULL), _ExternID(0), _LOD(PSLod1n2), _Active(true)
02652 {
02653 NL_PS_FUNC(CPSLocatedBindable_CPSLocatedBindable)
02654 _Owner = NULL;
02655 }
02656
02658 void CPSLocatedBindable::setOwner(CPSLocated *psl)
02659 {
02660 NL_PS_FUNC(CPSLocatedBindable_setOwner)
02661 if (psl == _Owner) return;
02662 if (psl == NULL)
02663 {
02664 releaseAllRef();
02665 if (_Owner)
02666 {
02667
02668 for (uint k = 0; k < _Owner->getSize(); ++k)
02669 {
02670 deleteElement(0);
02671 }
02672 }
02673 }
02674 if (_Owner && _Owner->getOwner())
02675 {
02676 _Owner->getOwner()->releaseRefForUserSysCoordInfo(getUserMatrixUsageCount());
02677 }
02678 _Owner = psl;
02679 if (_Owner && _Owner->getOwner())
02680 {
02681 _Owner->getOwner()->addRefForUserSysCoordInfo(getUserMatrixUsageCount());
02682 }
02683 }
02684
02686 void CPSLocatedBindable::finalize(void)
02687 {
02688 NL_PS_FUNC(CPSLocatedBindable_finalize)
02689 if (_Owner && _Owner->getOwner())
02690 {
02691 _Owner->getOwner()->releaseRefForUserSysCoordInfo(getUserMatrixUsageCount());
02692 }
02693 }
02694
02696 CPSLocatedBindable::~CPSLocatedBindable()
02697 {
02698 NL_PS_FUNC(CPSLocatedBindable_CPSLocatedBindableDtor)
02699 if (_ExternID)
02700 {
02701 if (_Owner && _Owner->getOwner())
02702 {
02703 _Owner->getOwner()->unregisterLocatedBindableExternID(this);
02704 }
02705 }
02706 }
02707
02709 void CPSLocatedBindable::notifyTargetRemoved(CPSLocated *ptr)
02710 {
02711 NL_PS_FUNC(CPSLocatedBindable_notifyTargetRemoved)
02712 ptr->unregisterDtorObserver(this);
02713 }
02714
02716 void CPSLocatedBindable::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
02717 {
02718 NL_PS_FUNC(CPSLocatedBindable_IStream )
02719 sint ver = f.serialVersion(4);
02720 f.serialPtr(_Owner);
02721 if (ver > 1) f.serialEnum(_LOD);
02722 if (ver > 2)
02723 {
02724 if (f.isReading() && !CParticleSystem::getSerializeIdentifierFlag())
02725 {
02726
02727 sint32 len;
02728 f.serial(len);
02729 f.seek(len, NLMISC::IStream::current);
02730 }
02731 else
02732 {
02733 f.serial(_Name);
02734 }
02735 }
02736 if (ver > 3)
02737 {
02738 if (f.isReading())
02739 {
02740 uint32 id;
02741 f.serial(id);
02742 setExternID(id);
02743 }
02744 else
02745 {
02746 f.serial(_ExternID);
02747 }
02748 }
02749
02750 }
02751
02753 void CPSLocatedBindable::displayIcon2d(const CVector tab[], uint nbSegs, float scale)
02754 {
02755 NL_PS_FUNC(CPSLocatedBindable_displayIcon2d)
02756 uint32 size = _Owner->getSize();
02757 if (!size) return;
02758 setupDriverModelMatrix();
02759
02760 const CVector I = computeI();
02761 const CVector K = computeK();
02762
02763 static std::vector<NLMISC::CLine> lines;
02764
02765 lines.clear();
02766
02767
02768 for (uint k = 0; k < size; ++k)
02769 {
02770
02771 const CVector p = _Owner->getPos()[k];
02772
02773
02774
02775 for (uint l = 0; l < nbSegs; ++l)
02776 {
02777 NLMISC::CLine li;
02778 li.V0 = p + scale * (tab[l << 1].x * I + tab[l << 1].y * K);
02779 li.V1 = p + scale * (tab[(l << 1) + 1].x * I + tab[(l << 1) + 1].y * K);
02780 lines.push_back(li);
02781 }
02782
02783 CMaterial mat;
02784
02785 mat.setBlendFunc(CMaterial::one, CMaterial::one);
02786 mat.setZWrite(false);
02787 mat.setLighting(false);
02788 mat.setBlend(true);
02789 mat.setZFunc(CMaterial::less);
02790
02791
02792
02793 CPSLocated *loc;
02794 uint32 index;
02795 CPSLocatedBindable *lb;
02796 _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
02797
02798 mat.setColor((lb == NULL || this == lb) && loc == _Owner && index == k ? CRGBA::Red : CRGBA(127, 127, 127));
02799
02800
02801 CDRU::drawLinesUnlit(lines, mat, *getDriver() );
02802 }
02803
02804 }
02805
02807 CFontManager *CPSLocatedBindable::getFontManager(void)
02808 {
02809 NL_PS_FUNC(CPSLocatedBindable_getFontManager)
02810 nlassert(_Owner);
02811 return _Owner->getFontManager();
02812 }
02813
02816 const CFontManager *CPSLocatedBindable::getFontManager(void) const
02817 {
02818 NL_PS_FUNC(CPSLocatedBindable_getFontManager)
02819 nlassert(_Owner);
02820 return _Owner->getFontManager();
02821 }
02822
02823
02825
02826 const NLMISC::CMatrix &CPSLocatedBindable::getSysMat(void) const
02827 {
02828 NL_PS_FUNC( CPSLocatedBindable_getSysMat)
02829 nlassert(_Owner);
02830 return _Owner->getOwner()->getSysMat();
02831 }
02832
02835 const NLMISC::CMatrix &CPSLocatedBindable::getInvertedSysMat(void) const
02836 {
02837 NL_PS_FUNC(CPSLocatedBindable_getInvertedSysMat)
02838 nlassert(_Owner);
02839 return _Owner->getOwner()->getInvertedSysMat();
02840
02841 }
02842
02845 const NLMISC::CMatrix &CPSLocatedBindable::getViewMat(void) const
02846 {
02847 NL_PS_FUNC(CPSLocatedBindable_getViewMat)
02848 nlassert(_Owner);
02849 return _Owner->getOwner()->getViewMat();
02850 }
02851
02852
02855 const NLMISC::CMatrix &CPSLocatedBindable::getInvertedViewMat(void) const
02856 {
02857 NL_PS_FUNC(CPSLocatedBindable_getInvertedViewMat)
02858 nlassert(_Owner);
02859 return _Owner->getOwner()->getInvertedViewMat();
02860 }
02861
02864 void CPSLocatedBindable::setupDriverModelMatrix(void)
02865 {
02866 NL_PS_FUNC(CPSLocatedBindable_setupDriverModelMatrix)
02867 nlassert(_Owner);
02868 _Owner->setupDriverModelMatrix();
02869 }
02870
02872 void CPSLocatedBindable::setExternID(uint32 id)
02873 {
02874 NL_PS_FUNC(CPSLocatedBindable_setExternID)
02875 if (id == _ExternID) return;
02876 CParticleSystem *ps = NULL;
02877 if (_Owner && _Owner->getOwner())
02878 {
02879 ps = _Owner->getOwner();
02880 }
02881 if (ps)
02882 {
02883 ps->unregisterLocatedBindableExternID(this);
02884 _ExternID = 0;
02885 }
02886 if (id != 0)
02887 {
02888 if (ps) ps->registerLocatedBindableExternID(id, this);
02889 _ExternID = id;
02890 }
02891 }
02892
02894 void CPSLocatedBindable::releaseAllRef()
02895 {
02896 NL_PS_FUNC(CPSLocatedBindable_releaseAllRef)
02897 }
02898
02899
02900
02901
02902
02904
02906
02908 void CPSTargetLocatedBindable::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
02909 {
02910 NL_PS_FUNC(CPSTargetLocatedBindable_serial)
02911 (void)f.serialVersion(1);
02912 f.serialPtr(_Owner);
02913 f.serial(_Name);
02914 if (f.isReading())
02915 {
02916
02917 for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
02918 {
02919 delete (*it);
02920 }
02921 _Targets.clear();
02922 }
02923 f.serialContPolyPtr(_Targets);
02924 }
02925
02926
02928 void CPSTargetLocatedBindable::attachTarget(CPSLocated *ptr)
02929 {
02930 NL_PS_FUNC(CPSTargetLocatedBindable_attachTarget)
02931
02932
02933 #ifdef NL_DEBUG
02934 if (_Owner)
02935 {
02936 nlassert(_Owner->getOwner() == ptr->getOwner());
02937 }
02938 #endif
02939
02940
02941 nlassert(std::find(_Targets.begin(), _Targets.end(), ptr) == _Targets.end());
02942 _Targets.push_back(ptr);
02943
02944
02945 ptr->registerDtorObserver(this);
02946 }
02947
02948
02950 void CPSTargetLocatedBindable::notifyTargetRemoved(CPSLocated *ptr)
02951 {
02952 NL_PS_FUNC(CPSTargetLocatedBindable_notifyTargetRemoved)
02953 TTargetCont::iterator it = std::find(_Targets.begin(), _Targets.end(), ptr);
02954 nlassert(it != _Targets.end());
02955 releaseTargetRsc(*it);
02956 _Targets.erase(it);
02957
02958 CPSLocatedBindable::notifyTargetRemoved(ptr);
02959 }
02960
02961
02962
02963
02964
02966 void CPSTargetLocatedBindable::finalize(void)
02967 {
02968 NL_PS_FUNC(CPSTargetLocatedBindable_finalize)
02972 for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
02973 {
02974 releaseTargetRsc(*it);
02975 }
02976 CPSLocatedBindable::finalize();
02977 }
02978
02980 CPSTargetLocatedBindable::~CPSTargetLocatedBindable()
02981 {
02982 NL_PS_FUNC(CPSTargetLocatedBindable_CPSTargetLocatedBindable)
02983
02984 for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
02985 {
02986 (*it)->unregisterDtorObserver(this);
02987 }
02988 }
02989
02991 void CPSTargetLocatedBindable::releaseRefTo(const CParticleSystemProcess *other)
02992 {
02993 NL_PS_FUNC(CPSTargetLocatedBindable_releaseRefTo)
02994 TTargetCont::iterator it = std::find(_Targets.begin(), _Targets.end(), other);
02995 if (it == _Targets.end()) return;
02996 releaseTargetRsc(*it);
02997 (*it)->unregisterDtorObserver(this);
02998 _Targets.erase(it);
02999 nlassert(std::find(_Targets.begin(), _Targets.end(), other) == _Targets.end());
03000 }
03001
03003 void CPSTargetLocatedBindable::releaseAllRef()
03004 {
03005 NL_PS_FUNC(CPSTargetLocatedBindable_releaseAllRef)
03006 for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
03007 {
03008 releaseTargetRsc(*it);
03009 (*it)->unregisterDtorObserver(this);
03010 }
03011 _Targets.clear();
03012 CPSLocatedBindable::releaseAllRef();
03013 }
03014
03016 uint CPSLocated::getUserMatrixUsageCount() const
03017 {
03018 NL_PS_FUNC(CPSLocated_getUserMatrixUsageCount)
03019 uint count = 0;
03020 for(TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
03021 {
03022 count += (*it)->getUserMatrixUsageCount();
03023 }
03024 return count + CParticleSystemProcess::getUserMatrixUsageCount();
03025 }
03026
03028 void CPSLocated::enumTexs(std::vector<NLMISC::CSmartPtr<ITexture> > &dest, IDriver &drv)
03029 {
03030 NL_PS_FUNC(CPSLocated_enumTexs)
03031 for(TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
03032 {
03033 (*it)->enumTexs(dest, drv);
03034 }
03035 }
03036
03038 void CPSLocated::setZBias(float value)
03039 {
03040 NL_PS_FUNC(CPSLocated_setZBias)
03041 for(TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
03042 {
03043 (*it)->setZBias(value);
03044 }
03045 }
03046
03048 void CPSLocated::computeCollisions(uint firstInstanceIndex, const NLMISC::CVector *posBefore, const NLMISC::CVector *posAfter)
03049 {
03050 NL_PS_FUNC(CPSLocated_computeCollisions)
03051 for(TDtorObserversVect::iterator it = _DtorObserversVect.begin(); it != _DtorObserversVect.end(); ++it)
03052 {
03053 if ((*it)->getType() == PSZone)
03054 {
03055 static_cast<CPSZone *>(*it)->computeCollisions(*this, firstInstanceIndex, posBefore, posAfter);
03056 }
03057 }
03058 }
03059
03061 void CPSLocated::computeSpawns(uint firstInstanceIndex, bool includeEmitOnce)
03062 {
03063 NL_PS_FUNC(CPSLocated_computeSpawns)
03064 nlassert(CParticleSystem::InsideSimLoop);
03065 for(TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
03066 {
03067 if (!(*it)->isActive()) continue;
03068 if ((*it)->getType() == PSEmitter)
03069 {
03070 CPSEmitter *emit = static_cast<CPSEmitter *>(*it);
03071 emit->updateEmitTrigger();
03072 switch(emit->getEmissionType())
03073 {
03074 case CPSEmitter::regular:
03075 emit->computeSpawns(firstInstanceIndex);
03076 break;
03077 case CPSEmitter::once:
03078
03079 nlassert(_Owner);
03080 if (_Owner->getSystemDate() == 0.f || includeEmitOnce)
03081 {
03082
03083
03084 emit->doEmitOnce(firstInstanceIndex);
03085 }
03086 break;
03087 default:
03088 break;
03089 }
03090 }
03091 }
03092 }
03093
03095 void CPSLocated::computeForces()
03096 {
03097 NL_PS_FUNC(CPSLocated_computeForces)
03098 nlassert(CParticleSystem::InsideSimLoop);
03099 for(TDtorObserversVect::iterator it = _DtorObserversVect.begin(); it != _DtorObserversVect.end(); ++it)
03100 {
03101 if ((*it)->getType() == PSForce)
03102 {
03103 CPSForce *force = static_cast<CPSForce *>(*it);
03104 force->computeForces(*this);
03105 }
03106 }
03107 }
03108
03110 void CPSCollisionInfo::update(const CPSCollisionInfo &other)
03111 {
03112 NL_PS_FUNC(CPSCollisionInfo_update)
03113 if (Dist == -1)
03114 {
03115
03116 Next = CPSLocated::_FirstCollision;
03117 CPSLocated::_FirstCollision = this;
03118 Dist = other.Dist;
03119 NewPos = other.NewPos;
03120 NewSpeed = other.NewSpeed;
03121 CollisionZone = other.CollisionZone;
03122 }
03123 else if (other.Dist < Dist)
03124 {
03125 Dist = other.Dist;
03126 NewPos = other.NewPos;
03127 NewSpeed = other.NewSpeed;
03128 CollisionZone = other.CollisionZone;
03129 }
03130 }
03131
03133 void CPSLocated::checkLife() const
03134 {
03135 NL_PS_FUNC(CPSLocated_checkLife)
03136 if (!getLastForever())
03137 {
03138 for(uint k = 0; k < getSize(); ++k)
03139 {
03140 nlassert(getTime()[k] >= 0.f);
03141 nlassert(getTime()[k] <= 1.f);
03142 }
03143 }
03144 }
03145
03147 void CPSLocated::onShow(bool shown)
03148 {
03149 for(TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
03150 {
03151 (*it)->onShow(shown);
03152 }
03153 }
03154
03155
03156 }