00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "std3d.h"
00027
00028
00029
00030 #include <algorithm>
00031 #include "nel/misc/aabbox.h"
00032 #include "nel/misc/matrix.h"
00033 #include "3d/ps_util.h"
00034 #include "3d/particle_system.h"
00035 #include "3d/ps_zone.h"
00036 #include "3d/driver.h"
00037 #include "3d/material.h"
00038 #include "3d/dru.h"
00039 #include "3d/ps_located.h"
00040 #include "3d/ps_particle.h"
00041 #include "3d/ps_force.h"
00042 #include "3d/ps_emitter.h"
00043 #include "3d/ps_misc.h"
00044
00045 #include "nel/misc/line.h"
00046 #include "nel/misc/system_info.h"
00047 #include "nel/misc/common.h"
00048
00049 namespace NL3D {
00050
00051
00052
00053
00057 CPSLocated::CPSLocated() : _MaxNumFaces(0),
00058 _Name(std::string("located")),
00059 _NbFramesToSkip(0),
00060 _MaxSize(DefaultMaxLocatedInstance),
00061 _Size(0),
00062 _LastForever(true),
00063 _CollisionInfo(NULL),
00064 _CollisionInfoNbRef(0),
00065 _InitialLife(1.f),
00066 _LifeScheme(NULL),
00067 _InitialMass(1.f),
00068 _MassScheme(NULL),
00069 _UpdateLock(false),
00070 _LODDegradation(false),
00071 _NonIntegrableForceNbRefs(0),
00072 _NumIntegrableForceWithDifferentBasis(0),
00073 _TriggerOnDeath(false),
00074 _TriggerID((uint32) 'NONE'),
00075 _ParametricMotion(false)
00076 {
00077 }
00078
00079
00080
00082 void CPSLocated::releaseRefTo(const CParticleSystemProcess *other)
00083 {
00084
00085 {
00086 for(TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00087 {
00088 (*it)->releaseRefTo(other);
00089 }
00090 }
00091
00092 {
00093
00094 for(TDtorObserversVect::iterator it = _DtorObserversVect.begin(); it != _DtorObserversVect.end(); ++it)
00095 {
00096 if ((*it)->getOwner() == other)
00097 {
00098 CPSLocatedBindable *refMaker = *it;
00099 refMaker->notifyTargetRemoved(this);
00100 break;
00101 }
00102 }
00103 }
00104 }
00105
00107 void CPSLocated::releaseAllRef()
00108 {
00109
00110 {
00111 for(TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00112 {
00113 (*it)->releaseAllRef();
00114 }
00115 }
00116
00117
00118 TDtorObserversVect copyVect(_DtorObserversVect.begin(), _DtorObserversVect.end());
00119
00120 for (TDtorObserversVect::iterator it = copyVect.begin(); it != copyVect.end(); ++it)
00121 {
00122 (*it)->notifyTargetRemoved(this);
00123 }
00124 _DtorObserversVect.clear();
00125
00126 nlassert(_CollisionInfoNbRef == 0);
00127
00128
00129
00130 nlassert(_IntegrableForces.size() == 0);
00131 nlassert(_NonIntegrableForceNbRefs == 0);
00132 nlassert(!_CollisionInfo);
00133 }
00134
00135
00137 void CPSLocated::notifyMotionTypeChanged(void)
00138 {
00139 for (TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00140 {
00141 (*it)->motionTypeChanged(_ParametricMotion);
00142 }
00143 }
00144
00145
00147 void CPSLocated::integrateSingle(float startDate, float deltaT, uint numStep,
00148 uint32 indexInLocated,
00149 NLMISC::CVector *destPos,
00150 uint stride )
00151 {
00152 nlassert(supportParametricMotion() && _ParametricMotion);
00153 if (_IntegrableForces.size() != 0)
00154 {
00155 bool accumulate = false;
00156 for (TForceVect::iterator it = _IntegrableForces.begin(); it != _IntegrableForces.end(); ++it)
00157 {
00158 nlassert((*it)->isIntegrable());
00159 (*it)->integrateSingle(startDate, deltaT, numStep, this, indexInLocated, destPos, accumulate, stride);
00160 accumulate = true;
00161 }
00162 }
00163 else
00164 {
00165 #ifdef NL_DEBUG
00166 NLMISC::CVector *endPos = (NLMISC::CVector *) ( (uint8 *) destPos + stride * numStep);
00167 #endif
00168 const CPSLocated::CParametricInfo &pi = _PInfo[indexInLocated];
00169 destPos = FillBufUsingSubdiv(pi.Pos, pi.Date, startDate, deltaT, numStep, destPos, stride);
00170 if (numStep != 0)
00171 {
00172 float currDate = startDate - pi.Date;
00173 nlassert(currDate >= 0);
00174 do
00175 {
00176 #ifdef NL_DEBUG
00177 nlassert(destPos < endPos);
00178 #endif
00179 destPos->x = pi.Pos.x + currDate * pi.Speed.x;
00180 destPos->y = pi.Pos.y + currDate * pi.Speed.y;
00181 destPos->z = pi.Pos.z + currDate * pi.Speed.z;
00182 currDate += deltaT;
00183 destPos = (NLMISC::CVector *) ( (uint8 *) destPos + stride);
00184 }
00185 while (--numStep);
00186 }
00187 }
00188 }
00189
00190 void CPSLocated::performParametricMotion(TAnimationTime date, TAnimationTime ellapsedTime, TAnimationTime realEllapsedTime)
00191 {
00192 if (!_Size) return;
00193 nlassert(supportParametricMotion() && _ParametricMotion);
00194
00195 if (_IntegrableForces.size() != 0)
00196 {
00197 bool accumulate = false;
00198 for (TForceVect::iterator it = _IntegrableForces.begin(); it != _IntegrableForces.end(); ++it)
00199 {
00200 nlassert((*it)->isIntegrable());
00201 (*it)->integrate(date, this, 0, _Size, &_Pos[0], &_Speed[0], accumulate);
00202 accumulate = true;
00203 }
00204 }
00205 else
00206 {
00207 CPSLocated::TPSAttribParametricInfo::const_iterator it = _PInfo.begin(),
00208 endIt = _PInfo.end();
00209 TPSAttribVector::iterator posIt = _Pos.begin();
00210 float deltaT;
00211 do
00212 {
00213 deltaT = date - it->Date;
00214 posIt->x = it->Pos.x + deltaT * it->Speed.x;
00215 posIt->y = it->Pos.y + deltaT * it->Speed.y;
00216 posIt->z = it->Pos.z + deltaT * it->Speed.z;
00217 ++posIt;
00218 ++it;
00219 }
00220 while (it != endIt);
00221 }
00222
00223 }
00224
00226 void CPSLocated::allocateParametricInfos(void)
00227 {
00228 if (_ParametricMotion) return;
00229 nlassert(supportParametricMotion());
00230 nlassert(_Owner);
00231 const float date = _Owner->getSystemDate();
00232 _PInfo.resize(_MaxSize);
00233
00234 TPSAttribVector::const_iterator posIt = _Pos.begin(), endPosIt = _Pos.end();
00235 TPSAttribVector::const_iterator speedIt = _Speed.begin();
00236 while (posIt != endPosIt)
00237 {
00238 _PInfo.insert( CParametricInfo(*posIt, *speedIt, date) );
00239 ++posIt;
00240 }
00241 _ParametricMotion = true;
00242 notifyMotionTypeChanged();
00243 }
00244
00246 void CPSLocated::releaseParametricInfos(void)
00247 {
00248 if (!_ParametricMotion) return;
00249 NLMISC::contReset(_PInfo);
00250 _ParametricMotion = false;
00251 notifyMotionTypeChanged();
00252 }
00253
00254
00256 bool CPSLocated::supportParametricMotion(void) const
00257 {
00258 return _NonIntegrableForceNbRefs == 0 && _NumIntegrableForceWithDifferentBasis == 0;
00259 }
00260
00264 void CPSLocated::enableParametricMotion(bool enable )
00265 {
00266 nlassert(supportParametricMotion());
00267 if (enable)
00268 {
00269 allocateParametricInfos();
00270 }
00271 else
00272 {
00273 releaseParametricInfos();
00274 }
00275 }
00276
00277
00278 void CPSLocated::setSystemBasis(bool sysBasis)
00279 {
00280 if (sysBasis != isInSystemBasis())
00281 {
00282 for (TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00283 {
00284 (*it)->basisChanged(sysBasis);
00285 }
00286
00287 CParticleSystemProcess::setSystemBasis(sysBasis);
00288
00289 for (TForceVect::iterator fIt = _IntegrableForces.begin(); fIt != _IntegrableForces.end(); ++fIt)
00290 {
00291 integrableForceBasisChanged( (*fIt)->getOwner()->isInSystemBasis() );
00292 }
00293 }
00294 }
00295
00296 void CPSLocated::notifyMaxNumFacesChanged(void)
00297 {
00298 if (!_Owner) return;
00299
00300
00301 _MaxNumFaces = 0;
00302 for (TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00303 {
00304 if ((*it)->getType() == PSParticle)
00305 {
00306 uint maxNumFaces = ((CPSParticle *) (*it))->getMaxNumFaces();
00308 _MaxNumFaces += maxNumFaces;
00309 }
00310 }
00311 }
00312
00313
00314 uint CPSLocated::querryMaxWantedNumFaces(void)
00315 {
00316 return _MaxNumFaces;
00317 }
00318
00319
00321 bool CPSLocated::hasParticles(void) const
00322 {
00323 for (TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00324 {
00325 if ((*it)->getType() == PSParticle && (*it)->hasParticles()) return true;
00326 }
00327 return false;
00328 }
00329
00331 bool CPSLocated::hasEmitters(void) const
00332 {
00333 for (TLocatedBoundCont::const_iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00334 {
00335 if ((*it)->getType() == PSEmitter && (*it)->hasEmitters()) return true;
00336 }
00337 return false;
00338 }
00339
00340
00341 void CPSLocated::getLODVect(NLMISC::CVector &v, float &offset, bool systemBasis)
00342 {
00343 nlassert(_Owner);
00344 _Owner->getLODVect(v, offset, systemBasis);
00345 }
00346
00347
00348
00349 float CPSLocated::getUserParam(uint numParam) const
00350 {
00351 nlassert(_Owner);
00352 return _Owner->getUserParam(numParam);
00353 }
00354
00355 CScene *CPSLocated::getScene(void)
00356 {
00357 nlassert(_Owner);
00358 return _Owner->getScene();
00359 }
00360
00361
00362 void CPSLocated::incrementNbDrawnParticles(uint num)
00363 {
00364 CParticleSystem::NbParticlesDrawn += num;
00365 }
00366
00367 void CPSLocated::setInitialLife(TAnimationTime lifeTime)
00368 {
00369 _LastForever = false;
00370 _InitialLife = lifeTime;
00371 delete _LifeScheme;
00372 _LifeScheme = NULL;
00373
00377 for (uint k = 0; k < _Size; ++k)
00378 {
00379 _Time[k] = 0.f;
00380 }
00381
00382 }
00383 void CPSLocated::setLifeScheme(CPSAttribMaker<float> *scheme)
00384 {
00385 nlassert(scheme);
00386 nlassert(!scheme->hasMemory());
00387 _LastForever = false;
00388 delete _LifeScheme;
00389 _LifeScheme = scheme;
00390 }
00391 void CPSLocated::setInitialMass(float mass)
00392 {
00393 _InitialMass = mass;
00394 delete _MassScheme;
00395 _MassScheme = NULL;
00396 }
00397 void CPSLocated::setMassScheme(CPSAttribMaker<float> *scheme)
00398 {
00399 nlassert(scheme);
00400 nlassert(!scheme->hasMemory());
00401 delete _MassScheme;
00402 _MassScheme = scheme;
00403 }
00404
00405
00406
00408 const NLMISC::CMatrix &CPSLocated::getConversionMatrix(const CPSLocated *A, const CPSLocated *B)
00409 {
00410 nlassert(A->_Owner == B->_Owner);
00411 if (A->_SystemBasisEnabled == B->_SystemBasisEnabled)
00412 {
00413 return NLMISC::CMatrix::Identity;
00414 }
00415 else
00416 {
00417 if (B->_SystemBasisEnabled)
00418 {
00419 return B->_Owner->getSysMat();
00420 }
00421 else
00422 {
00423 return A->_Owner->getInvertedSysMat();
00424 }
00425 }
00426 }
00427
00428
00429 NLMISC::CVector CPSLocated::computeI(void) const
00430 {
00431 if (!_SystemBasisEnabled)
00432 {
00433 return _Owner->getInvertedViewMat().getI();
00434 }
00435 else
00436 {
00437
00438 return _Owner->getInvertedSysMat().mulVector(_Owner->getInvertedViewMat().getI());
00439 }
00440 }
00441
00442
00443 NLMISC::CVector CPSLocated::computeJ(void) const
00444 {
00445 if (!_SystemBasisEnabled)
00446 {
00447 return _Owner->getInvertedViewMat().getJ();
00448 }
00449 else
00450 {
00451
00452 return _Owner->getInvertedSysMat().mulVector(_Owner->getInvertedViewMat().getJ());
00453 }
00454 }
00455
00456
00457
00458 NLMISC::CVector CPSLocated::computeK(void) const
00459 {
00460 if (!_SystemBasisEnabled)
00461 {
00462 return _Owner->getInvertedViewMat().getK();
00463 }
00464 else
00465 {
00466
00467 return _Owner->getInvertedSysMat().mulVector(_Owner->getInvertedViewMat().getK());
00468 }
00469 }
00470
00471
00472
00473 IDriver *CPSLocated::getDriver() const
00474 {
00475 nlassert(_Owner);
00476 nlassert (_Owner->getDriver() );
00477 return _Owner->getDriver();
00478 }
00479
00481
00482 CPSLocated::~CPSLocated()
00483 {
00484
00485 TDtorObserversVect copyVect(_DtorObserversVect.begin(), _DtorObserversVect.end());
00486
00487 for (TDtorObserversVect::iterator it = copyVect.begin(); it != copyVect.end(); ++it)
00488 {
00489 (*it)->notifyTargetRemoved(this);
00490 }
00491
00492 nlassert(_CollisionInfoNbRef == 0);
00493
00494
00495
00496 nlassert(_IntegrableForces.size() == 0);
00497 nlassert(_NonIntegrableForceNbRefs == 0);
00498 nlassert(!_CollisionInfo);
00499
00500
00501
00502 for (TLocatedBoundCont::iterator it2 = _LocatedBoundCont.begin(); it2 != _LocatedBoundCont.end(); ++it2)
00503 {
00504 (*it2)->finalize();
00505 delete *it2;
00506 }
00507
00508
00509 delete _LifeScheme;
00510 delete _MassScheme;
00511 }
00512
00513
00514
00518 void CPSLocated::bind(CPSLocatedBindable *lb)
00519 {
00520 nlassert(std::find(_LocatedBoundCont.begin(), _LocatedBoundCont.end(), lb) == _LocatedBoundCont.end());
00521 TLocatedBoundCont::iterator it = _LocatedBoundCont.begin();
00522 while (it != _LocatedBoundCont.end() && **it < *lb)
00523 {
00524 ++it;
00525 }
00526
00527 _LocatedBoundCont.insert(it, lb);
00528 lb->setOwner(this);
00529 lb->resize(_MaxSize);
00530
00531
00532
00533
00534 uint32 initialSize = _Size;
00535 for (uint k = 0; k < initialSize; ++k)
00536 {
00537 _Size = k;
00538 lb->newElement(NULL, 0);
00539 }
00540 _Size = initialSize;
00541
00542
00543 if (_ParametricMotion) lb->motionTypeChanged(true);
00544
00546 notifyMaxNumFacesChanged();
00547 }
00548
00549
00550
00551 void CPSLocated::remove(const CPSLocatedBindable *p)
00552 {
00553 TLocatedBoundCont::iterator it = std::find(_LocatedBoundCont.begin(), _LocatedBoundCont.end(), p);
00554 nlassert(it != _LocatedBoundCont.end());
00555 (*it)->finalize();
00556 delete *it;
00557 _LocatedBoundCont.erase(it);
00558 }
00559
00560
00561 void CPSLocated::registerDtorObserver(CPSLocatedBindable *anObserver)
00562 {
00563
00564 nlassert(std::find(_DtorObserversVect.begin(), _DtorObserversVect.end(), anObserver) == _DtorObserversVect.end());
00565 _DtorObserversVect.push_back(anObserver);
00566 }
00567
00568 void CPSLocated::unregisterDtorObserver(CPSLocatedBindable *anObserver)
00569 {
00570
00571 TDtorObserversVect::iterator it = std::find(_DtorObserversVect.begin(), _DtorObserversVect.end(), anObserver);
00572 nlassert(it != _DtorObserversVect.end());
00573 _DtorObserversVect.erase(it);
00574 }
00575
00576
00577
00578
00579
00584 sint32 CPSLocated::newElement(const CVector &pos, const CVector &speed, CPSLocated *emitter, uint32 indexInEmitter, bool basisConversionForSpeed, TAnimationTime ellapsedTime )
00585 {
00586 if (_UpdateLock)
00587 {
00588 postNewElement(pos, speed);
00589 return -1;
00590 }
00591
00592
00593 if (_CollisionInfo)
00594 {
00595 _CollisionInfo->insert();
00596 }
00597
00598 sint32 creationIndex;
00599
00600
00601
00602
00603
00604
00605 if (_MaxSize == _Size) return -1;
00606
00607
00608
00609
00610 const CMatrix &convMat = emitter ? CPSLocated::getConversionMatrix(this, emitter)
00611 : CMatrix::Identity;
00612 if (!_SystemBasisEnabled && emitter && emitter->_SystemBasisEnabled)
00613 {
00614
00615
00616 #ifdef NL_DEBUG
00617 nlassert(_Owner);
00618 #endif
00619 CVector sysPosDelta;
00620 _Owner->interpolatePosDelta(sysPosDelta, ellapsedTime);
00621 creationIndex =_Pos.insert(convMat * pos + sysPosDelta);
00622 }
00623 else
00624 {
00625 creationIndex =_Pos.insert(convMat * pos);
00626 }
00627 nlassert(creationIndex != -1);
00628
00629 _Speed.insert(basisConversionForSpeed ? convMat.mulVector(speed) : speed);
00630
00631
00632
00633 _InvMass.insert(1.f / ((_MassScheme && emitter) ? _MassScheme->get(emitter, indexInEmitter) : _InitialMass ) );
00634 _Time.insert(0.0f);
00635 const float lifeTime = (_LifeScheme && emitter) ? _LifeScheme->get(emitter, indexInEmitter) : _InitialLife ;
00636 _TimeIncrement.insert( lifeTime ? 1.f / lifeTime : 10E6f);
00637
00638
00639 if (_ParametricMotion)
00640 {
00641 _PInfo.insert( CParametricInfo(_Pos[creationIndex], _Speed[creationIndex], _Owner->getSystemDate() ) );
00642 }
00643
00644
00646
00648
00649
00650
00651 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00652 {
00653 (*it)->newElement(emitter, indexInEmitter);
00654 }
00655
00656
00657 _UpdateLock = false;
00658 ++_Size;
00659
00660
00661
00662
00663
00664 return creationIndex;
00665 }
00666
00667 void CPSLocated::postNewElement(const CVector &pos, const CVector &speed)
00668 {
00669 _RequestStack.push(CPostNewElementRequestInfo(pos, speed));
00670 }
00671
00672
00673
00674 static inline uint32 IDToLittleEndian(uint32 input)
00675 {
00676 #ifdef NL_LITTLE_ENDIAN
00677 return input;
00678 #else
00679 return ((input & (0xff<<24))>>24)
00680 || ((input & (0xff<<16))>>8)
00681 || ((input & (0xff<<8))<<8)
00682 || ((input & 0xff)<<24);
00683 #endif
00684 }
00685
00690 void CPSLocated::deleteElement(uint32 index)
00691 {
00692 nlassert(index < _Size);
00693
00694
00695
00696
00697 _UpdateLock = true;
00698
00699
00700 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00701 {
00702 (*it)->deleteElement(index);
00703 }
00704
00705
00706 _UpdateLock = false;
00707
00708
00709
00710 _InvMass.remove(index);
00711 _Pos.remove(index);
00712 _Speed.remove(index);
00713 _Time.remove(index);
00714 _TimeIncrement.remove(index);
00715
00716 if (_CollisionInfo)
00717 {
00718 _CollisionInfo->remove(index);
00719 }
00720
00721 if (_ParametricMotion)
00722 {
00723 _PInfo.remove(index);
00724 }
00725
00726 --_Size;
00727
00728 if (_TriggerOnDeath)
00729 {
00730 const uint32 id = IDToLittleEndian(_TriggerID);
00731 nlassert(_Owner);
00732 uint numLb = _Owner->getNumLocatedBindableByExternID(id);
00733 for (uint k = 0; k < numLb; ++k)
00734 {
00735 CPSLocatedBindable *lb = _Owner->getLocatedBindableByExternID(id, k);
00736 if (lb->getType() == PSEmitter)
00737 {
00738 CPSEmitter *e = NLMISC::safe_cast<CPSEmitter *>(lb);
00739 nlassert(e->getOwner());
00740 uint nbInstances = e->getOwner()->getSize();
00741 for (uint l = 0; l < nbInstances; ++l)
00742 {
00743 e->singleEmit(l, 1);
00744 }
00745 }
00746 }
00747 }
00748 }
00749
00750
00752
00753 void CPSLocated::resize(uint32 newSize)
00754 {
00755 nlassert(newSize < (1 << 16));
00756 if (newSize < _Size)
00757 {
00758 for (uint32 k = _Size - 1; k >= newSize; --k)
00759 {
00760 deleteElement(k);
00761
00762 if (k == 0) break;
00763 }
00764 _Size = newSize;
00765 }
00766
00767
00768 _MaxSize = newSize;
00769 _InvMass.resize(newSize);
00770 _Pos.resize(newSize);
00771 _Speed.resize(newSize);
00772 _Time.resize(newSize);
00773 _TimeIncrement.resize(newSize);
00774
00775 if (_ParametricMotion)
00776 {
00777 _PInfo.resize(newSize);
00778 }
00779
00780 if (_CollisionInfo)
00781 {
00782 _CollisionInfo->resize(newSize);
00783 }
00784
00785
00786
00787
00788 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
00789 {
00790 (*it)->resize(newSize);
00791 }
00792
00793
00795 notifyMaxNumFacesChanged();
00796 }
00797
00798
00799 void CPSLocated::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
00800 {
00801 sint ver = f.serialVersion(4);
00802 CParticleSystemProcess::serial(f);
00803
00804 f.serial(_Name);
00805
00806 f.serial(_InvMass);
00807 f.serial(_Pos);
00808 f.serial(_Speed);
00809 f.serial(_Time);
00810 f.serial(_TimeIncrement);
00811
00812 f.serial(_Size);
00813 f.serial(_MaxSize);
00814
00815 f.serial(_LastForever);
00816
00817 f.serialPtr(_CollisionInfo);
00818 f.serial(_CollisionInfoNbRef);
00819
00820
00821 if (f.isReading())
00822 {
00823 delete _LifeScheme;
00824 delete _MassScheme;
00825
00826 bool useScheme;
00827 f.serial(useScheme);
00828 if (useScheme)
00829 {
00830 f.serialPolyPtr(_LifeScheme);
00831 }
00832 else
00833 {
00834 f.serial(_InitialLife);
00835 _LifeScheme = NULL;
00836 }
00837
00838 f.serial(useScheme);
00839 if (useScheme)
00840 {
00841 f.serialPolyPtr(_MassScheme);
00842 }
00843 else
00844 {
00845 f.serial(_InitialMass);
00846 nlassert(_InitialMass > 0);
00847 _MassScheme = NULL;
00848 }
00849 }
00850 else
00851 {
00852 bool bFalse = false, bTrue = true;
00853 if (_LifeScheme)
00854 {
00855 f.serial(bTrue);
00856 f.serialPolyPtr(_LifeScheme);
00857 }
00858 else
00859 {
00860 f.serial(bFalse);
00861 f.serial(_InitialLife);
00862 }
00863 if (_MassScheme)
00864 {
00865 f.serial(bTrue);
00866 f.serialPolyPtr(_MassScheme);
00867 }
00868 else
00869 {
00870 f.serial(bFalse);
00871 nlassert(_InitialMass > 0);
00872 f.serial(_InitialMass);
00873 }
00874 }
00875
00876
00877 f.serial(_NbFramesToSkip);
00878
00879 f.serialContPolyPtr(_DtorObserversVect);
00880
00881 if (f.isReading())
00882 {
00883 while(!_RequestStack.empty())
00884 {
00885 _RequestStack.pop();
00886 }
00887 uint32 size;
00888 f.serial(size);
00889 for (uint32 k = 0; k < size; ++k)
00890 {
00891 TNewElementRequestStack::value_type t;
00892 f.serial(t);
00893 _RequestStack.push(t);
00894 }
00895 }
00896 else
00897 {
00898
00899
00900 TNewElementRequestStack r2;
00901 uint32 size = (uint32) _RequestStack.size();
00902 f.serial(size);
00903
00904 while(!_RequestStack.empty())
00905 {
00906 r2.push(_RequestStack.top());
00907 _RequestStack.pop();
00908 }
00909
00910 while (!r2.empty())
00911 {
00912 f.serial(r2.top());
00913 _RequestStack.push(r2.top());
00914 r2.pop();
00915 }
00916
00917 }
00918
00919
00920
00921
00922 f.serial(_UpdateLock);
00923
00924 f.serialContPolyPtr(_LocatedBoundCont);
00925
00926 if (ver > 1)
00927 {
00928 f.serial(_LODDegradation);
00929 }
00930
00931 if (ver > 2)
00932 {
00933 f.serial(_ParametricMotion);
00934 }
00935
00936 if (f.isReading())
00937 {
00938
00939 notifyMaxNumFacesChanged();
00940
00941 if (_ParametricMotion)
00942 {
00943 allocateParametricInfos();
00944 }
00945 }
00946
00947 if (ver > 3)
00948 {
00949 f.serial(_TriggerOnDeath, _TriggerID);
00950 }
00951 }
00952
00953
00954
00955 static void IntegrateSpeed(uint count, float *src1, const float *src2 ,float ellapsedTime)
00956 {
00957 #if 0 // this works, but is not enabled for now. The precision is not that good...
00958 #ifdef NL_OS_WINDOWS
00959
00960
00961
00962 if (NLMISC::CCpuInfo::hasSSE()
00963 && ((uint) src1 & 15) == ((uint) src2 & 15)
00964 && ! ((uint) src1 & 3)
00965 && ! ((uint) src2 & 3)
00966 )
00967 {
00968
00969
00970
00971 uint alignCount = ((uint) src1 >> 2) & 3;
00972
00973 while (alignCount --)
00974 {
00975 *src1++ += ellapsedTime * *src2 ++;
00976 }
00977
00978
00979
00980 count -= alignCount;
00981 if (count > 3)
00982 {
00983 float et[4] = { ellapsedTime, ellapsedTime, ellapsedTime, ellapsedTime};
00984
00985 __asm
00986 {
00987 mov ecx, count
00988 shr ecx, 2
00989
00990
00991 xor edx, edx
00992
00993 mov eax, src1
00994 mov ebx, src2
00995 movups xmm0, et[0]
00996 myLoop:
00997 movaps xmm2, [ebx + 8 * edx]
00998 movaps xmm1, [eax + 8 * edx]
00999 mulps xmm2, xmm0
01000 addps xmm1, xmm2
01001 movaps [eax + 8 * edx], xmm1
01002 add edx, 2
01003 dec ecx
01004 jne myLoop
01005 }
01006 }
01007
01008 count &= 3;
01009
01010 if (count)
01011 {
01012 src1 += alignCount;
01013 src2 += alignCount;
01014 do
01015 {
01016 *src1 += ellapsedTime * *src2;
01017
01018 ++src1;
01019 ++src2;
01020 }
01021 while (--count);
01022 }
01023
01024 }
01025 else
01026 #endif
01027 #endif
01028 {
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038 uint countDiv8 = count>>3;
01039 count &= 7;
01040
01041 while (countDiv8 --)
01042 {
01043 src1[0] += ellapsedTime * src2[0];
01044 src1[1] += ellapsedTime * src2[1];
01045 src1[2] += ellapsedTime * src2[2];
01046 src1[3] += ellapsedTime * src2[3];
01047
01048 src1[4] += ellapsedTime * src2[4];
01049 src1[5] += ellapsedTime * src2[5];
01050 src1[6] += ellapsedTime * src2[6];
01051 src1[7] += ellapsedTime * src2[7];
01052
01053 src2 += 8;
01054 src1 += 8;
01055 }
01056
01057 while (count--)
01058 {
01059 *src1++ += ellapsedTime * *src2++;
01060 }
01061
01062
01063 }
01064 }
01065
01066
01067 void CPSLocated::step(TPSProcessPass pass, TAnimationTime ellapsedTime, TAnimationTime realEt)
01068 {
01069 if (!_Size) return;
01070
01071
01072 if (pass == PSMotion)
01073 {
01074
01075
01076
01077 if (_LODDegradation)
01078 {
01079 if (ellapsedTime > 0)
01080 {
01081 nlassert(_Owner);
01082
01083 const uint maxToHave = (uint) (_MaxSize * _Owner->getOneMinusCurrentLODRatio());
01084 if (_Size > maxToHave)
01085 {
01086
01087
01088
01089 uint pos = maxToHave ? rand() % maxToHave : 0;
01090 uint step = maxToHave ? rand() % maxToHave : 0;
01091
01092 do
01093 {
01094 deleteElement(pos);
01095 pos += step;
01096 if (pos >= maxToHave) pos -= maxToHave;
01097 }
01098 while (_Size !=maxToHave);
01099 }
01100 }
01101 }
01102
01103
01104
01105 if (!_NbFramesToSkip || !( (uint32) _Owner->getDate() % (_NbFramesToSkip + 1)))
01106 {
01107
01108
01109
01110 updateNewElementRequestStack();
01111
01112
01113
01114
01115 if (!_CollisionInfo)
01116 {
01117 if (_Size != 0)
01118 IntegrateSpeed(_Size * 3, &_Pos[0].x, &_Speed[0].x, ellapsedTime);
01119 }
01120 else
01121 {
01122
01123
01124 nlassert(_CollisionInfo);
01125 TPSAttribCollisionInfo::iterator itc = _CollisionInfo->begin();
01126 TPSAttribVector::iterator itSpeed = _Speed.begin();
01127 TPSAttribVector::iterator itPos = _Pos.begin();
01128
01129 for (uint k = 0; k < _Size;)
01130 {
01131 if (itc->dist != -1)
01132 {
01133 (*itPos) = itc->newPos;
01134 (*itSpeed) = itc->newSpeed;
01135
01136 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01137 {
01138 (*it)->bounceOccured(k);
01139 }
01140 switch(itc->collisionZone->getCollisionBehaviour())
01141 {
01142 case CPSZone::bounce:
01143 itc->reset();
01144 ++k, ++itPos, ++itSpeed, ++itc;
01145 break;
01146 case CPSZone::destroy:
01147 deleteElement(k);
01148 break;
01149 }
01150 }
01151 else
01152 {
01153 (*itPos) += ellapsedTime * (*itSpeed) * itc->TimeSliceRatio;
01154 itc->reset();
01155 ++k, ++itPos, ++itSpeed, ++itc;
01156 }
01157 }
01158
01159
01160
01162
01163 }
01164 }
01165 else
01166 {
01167 return;
01168 }
01169 }
01170
01171 if (pass != PSMotion)
01172 {
01173
01174 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01175 {
01176 if ((*it)->isActive())
01177 {
01178 if ((*it)->getLOD() == PSLod1n2 || _Owner->getLOD() == (*it)->getLOD())
01179 {
01180 (*it)->step(pass, ellapsedTime, realEt);
01181 }
01182 }
01183 }
01184 }
01185 else
01186 {
01187 for (TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01188 {
01189 if ((*it)->isActive())
01190 {
01191 (*it)->step(pass, ellapsedTime, realEt);
01192 }
01193 }
01194
01195 }
01196 }
01197
01198 void CPSLocated::updateLife(TAnimationTime ellapsedTime)
01199 {
01200 if (!_Size) return;
01201 if (! _LastForever)
01202 {
01203 if (_LifeScheme != NULL)
01204 {
01205 TPSAttribTime::iterator itTime = _Time.begin(), itTimeInc = _TimeIncrement.begin();
01206 for (uint32 k = 0; k < _Size;)
01207 {
01208 *itTime += ellapsedTime * *itTimeInc;
01209 if (*itTime >= 1.0f)
01210 {
01211 deleteElement(k);
01212 }
01213 else
01214 {
01215 ++k;
01216 ++itTime;
01217 ++itTimeInc;
01218 }
01219 }
01220 }
01221 else
01222 {
01223 if (_InitialLife != 0)
01224 {
01225 nlassert(_Owner);
01226 float timeInc = ellapsedTime * 1.f / _InitialLife;
01227 if (_Owner->getSystemDate() >= (_InitialLife - ellapsedTime))
01228 {
01229 TPSAttribTime::iterator itTime = _Time.begin();
01230 for (uint32 k = 0; k < _Size;)
01231 {
01232 *itTime += timeInc;
01233 if (*itTime >= 1.0f)
01234 {
01235 deleteElement(k);
01236 }
01237 else
01238 {
01239 ++k;
01240 ++itTime;
01241 }
01242 }
01243 }
01244 else
01245 {
01246 TPSAttribTime::iterator itTime = _Time.begin(), itEndTime = _Time.end();
01247 do
01248 {
01249 *itTime += timeInc;
01250 ++itTime;
01251 }
01252 while (itTime != itEndTime);
01253 }
01254 }
01255 else
01256 {
01257 uint size = _Size;
01258 do
01259 {
01260 deleteElement(0);
01261 }
01262 while (--size);
01263 }
01264 }
01265 }
01266 else
01267 {
01268
01269 TPSAttribTime::iterator itTime = _Time.begin(), endItTime = _Time.end();
01270 for (; itTime != endItTime; ++itTime)
01271 {
01272 *itTime += ellapsedTime;
01273 }
01274 }
01275 }
01276
01277
01278
01279
01280 void CPSLocated::updateNewElementRequestStack(void)
01281 {
01282 while (!_RequestStack.empty())
01283 {
01284 newElement(_RequestStack.top()._Pos, _RequestStack.top()._Speed);
01285 _RequestStack.pop();
01286 }
01287 }
01288
01289
01290 bool CPSLocated::computeBBox(NLMISC::CAABBox &box) const
01291 {
01292 if (!_Size) return false;
01293
01294
01295 TLocatedBoundCont::const_iterator it;
01296 TPSAttribVector::const_iterator it2;
01297
01298
01299
01300 for (it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01301 {
01302 if ((*it)->doesProduceBBox())
01303 {
01304 break;
01305 }
01306 }
01307
01308 if (it == _LocatedBoundCont.end())
01309 {
01310 return false;
01311 }
01312
01313 CVector min = _Pos[0], max = _Pos[0];
01314
01315 for (it2 = _Pos.begin(); it2 != _Pos.end(); ++ it2)
01316 {
01317 const CVector &v = (*it2);
01318 min.minof(min, v);
01319 max.maxof(max, v);
01320 }
01321
01322 box.setMinMax(min, max);
01323
01324
01325
01326
01327
01328 NLMISC::CAABBox tmpBox, startBox = box;
01329
01330 for (it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
01331 {
01332 if ((*it)->doesProduceBBox())
01333 {
01334 tmpBox = startBox;
01335 if ((*it)->completeBBox(tmpBox))
01336 {
01337 box = NLMISC::CAABBox::computeAABBoxUnion(tmpBox, box);
01338 }
01339 }
01340 }
01341
01342 return true;
01343 }
01344
01345
01347 void CPSLocated::setupDriverModelMatrix(void)
01348 {
01349 if (_SystemBasisEnabled)
01350 {
01351 getDriver()->setupModelMatrix(_Owner->getSysMat());
01352 }
01353 else
01354 {
01355 getDriver()->setupModelMatrix(CMatrix::Identity);
01356 }
01357 }
01358
01359
01360
01361
01362 void CPSLocated::queryCollisionInfo(void)
01363 {
01364 if (_CollisionInfoNbRef)
01365 {
01366 ++ _CollisionInfoNbRef;
01367 }
01368 else
01369 {
01370 _CollisionInfo = new TPSAttribCollisionInfo;
01371 _CollisionInfoNbRef = 1;
01372 _CollisionInfo->resize(_MaxSize);
01373
01374 for(uint k = 0; k < _Size; ++k)
01375 {
01376 _CollisionInfo->insert();
01377 }
01378 }
01379 }
01380
01381 void CPSLocated::releaseCollisionInfo(void)
01382 {
01383 nlassert(_CollisionInfoNbRef);
01384
01385 --_CollisionInfoNbRef;
01386 if (_CollisionInfoNbRef == 0)
01387 {
01388 delete _CollisionInfo;
01389 _CollisionInfo = NULL;
01390 }
01391 }
01392
01393
01394 void CPSLocated::resetCollisionInfo(void)
01395 {
01396 nlassert(_CollisionInfo);
01397
01398 TPSAttribCollisionInfo::iterator it = _CollisionInfo->begin(), endIt = _CollisionInfo->end();
01399
01400 for (; it != endIt; ++it)
01401 {
01402 it->reset();
01403 }
01404 }
01405
01406 void CPSLocated::registerIntegrableForce(CPSForce *f)
01407 {
01408 nlassert(std::find(_IntegrableForces.begin(), _IntegrableForces.end(), f) == _IntegrableForces.end());
01409 _IntegrableForces.push_back(f);
01410 if (_SystemBasisEnabled != f->getOwner()->isInSystemBasis())
01411 {
01412 ++_NumIntegrableForceWithDifferentBasis;
01413 releaseParametricInfos();
01414 }
01415 }
01416
01417
01418 void CPSLocated::unregisterIntegrableForce(CPSForce *f)
01419 {
01420 nlassert(f->getOwner());
01421 std::vector<CPSForce *>::iterator it = std::find(_IntegrableForces.begin(), _IntegrableForces.end(), f);
01422 nlassert(it != _IntegrableForces.end() );
01423 _IntegrableForces.erase(it);
01424 if (_SystemBasisEnabled != f->getOwner()->isInSystemBasis())
01425 {
01426 --_NumIntegrableForceWithDifferentBasis;
01427 }
01428 }
01429
01430 void CPSLocated::addNonIntegrableForceRef(void)
01431 {
01432 ++_NonIntegrableForceNbRefs;
01433 releaseParametricInfos();
01434 }
01435
01436 void CPSLocated::releaseNonIntegrableForceRef(void)
01437 {
01438 nlassert(_NonIntegrableForceNbRefs != 0);
01439 --_NonIntegrableForceNbRefs;
01440 }
01441
01442
01443 void CPSLocated::integrableForceBasisChanged(bool basis)
01444 {
01445 if (_SystemBasisEnabled != basis)
01446 {
01447 ++_NumIntegrableForceWithDifferentBasis;
01448 releaseParametricInfos();
01449 }
01450 else
01451 {
01452 --_NumIntegrableForceWithDifferentBasis;
01453 }
01454 }
01455
01456
01458 CPSLocatedBindable *CPSLocated::unbind(uint index)
01459 {
01460 nlassert(index < _LocatedBoundCont.size());
01461 CPSLocatedBindable *lb = _LocatedBoundCont[index];
01462 lb->setOwner(NULL);
01463 _LocatedBoundCont.erase(_LocatedBoundCont.begin() + index);
01464 return lb;
01465 }
01466
01468 bool CPSLocated::isBound(const CPSLocatedBindable *lb) const
01469 {
01470 TLocatedBoundCont::const_iterator it = std::find(_LocatedBoundCont.begin(), _LocatedBoundCont.end(), lb);
01471 return it != _LocatedBoundCont.end();
01472 }
01473
01475 uint CPSLocated::getIndexOf(const CPSLocatedBindable *lb) const
01476 {
01477 for(uint k = 0; k < _LocatedBoundCont.size(); ++k)
01478 {
01479 if (_LocatedBoundCont[k] == lb) return k;
01480 }
01481 nlassert(0);
01482 return 0;
01483 }
01484
01485
01486
01488
01490
01491
01493 CPSLocatedBindable::CPSLocatedBindable() : _LOD(PSLod1n2), _Owner(NULL), _ExternID(0), _Active(true)
01494 {
01495 _Owner = NULL;
01496 }
01497
01498 void CPSLocatedBindable::setOwner(CPSLocated *psl)
01499 {
01500 if (psl == NULL)
01501 {
01502 releaseAllRef();
01503 if (_Owner)
01504 {
01505
01506 for (uint k = 0; k < _Owner->getSize(); ++k)
01507 {
01508 deleteElement(0);
01509 }
01510 }
01511 }
01512 _Owner = psl;
01513 }
01514
01516 CPSLocatedBindable::~CPSLocatedBindable()
01517 {
01518 if (_ExternID)
01519 {
01520 if (_Owner && _Owner->getOwner())
01521 {
01522 _Owner->getOwner()->unregisterLocatedBindableExternID(this);
01523 }
01524 }
01525 }
01526
01528 const NLMISC::CMatrix &CPSLocatedBindable::getLocatedMat(void) const
01529 {
01530 nlassert(_Owner);
01531 if (_Owner->isInSystemBasis())
01532 {
01533 return _Owner->getOwner()->getSysMat();
01534 }
01535 else
01536 {
01537 return NLMISC::CMatrix::Identity;
01538 }
01539 }
01540
01541
01543 void CPSLocatedBindable::notifyTargetRemoved(CPSLocated *ptr)
01544 {
01545 ptr->unregisterDtorObserver(this);
01546 }
01547
01549 void CPSLocatedBindable::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
01550 {
01551 sint ver = f.serialVersion(4);
01552 f.serialPtr(_Owner);
01553 if (ver > 1) f.serialEnum(_LOD);
01554 if (ver > 2) f.serial(_Name);
01555 if (ver > 3)
01556 {
01557 if (f.isReading())
01558 {
01559 uint32 id;
01560 f.serial(id);
01561 setExternID(id);
01562 }
01563 else
01564 {
01565 f.serial(_ExternID);
01566 }
01567 }
01568
01569 }
01570
01572 void CPSLocatedBindable::displayIcon2d(const CVector tab[], uint nbSegs, float scale)
01573 {
01574 uint32 size = _Owner->getSize();
01575 if (!size) return;
01576 setupDriverModelMatrix();
01577
01578 const CVector I = computeI();
01579 const CVector K = computeK();
01580
01581 static std::vector<NLMISC::CLine> lines;
01582
01583 lines.clear();
01584
01585
01586 for (uint k = 0; k < size; ++k)
01587 {
01588
01589 const CVector p = _Owner->getPos()[k];
01590
01591
01592
01593 for (uint l = 0; l < nbSegs; ++l)
01594 {
01595 NLMISC::CLine li;
01596 li.V0 = p + scale * (tab[l << 1].x * I + tab[l << 1].y * K);
01597 li.V1 = p + scale * (tab[(l << 1) + 1].x * I + tab[(l << 1) + 1].y * K);
01598 lines.push_back(li);
01599 }
01600
01601 CMaterial mat;
01602
01603 mat.setBlendFunc(CMaterial::one, CMaterial::one);
01604 mat.setZWrite(false);
01605 mat.setLighting(false);
01606 mat.setBlend(true);
01607 mat.setZFunc(CMaterial::less);
01608
01609
01610
01611 CPSLocated *loc;
01612 uint32 index;
01613 CPSLocatedBindable *lb;
01614 _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
01615
01616 mat.setColor((lb == NULL || this == lb) && loc == _Owner && index == k ? CRGBA::Red : CRGBA(127, 127, 127));
01617
01618
01619 CDRU::drawLinesUnlit(lines, mat, *getDriver() );
01620 }
01621
01622 }
01623
01625 CFontManager *CPSLocatedBindable::getFontManager(void)
01626 {
01627 nlassert(_Owner);
01628 return _Owner->getFontManager();
01629 }
01630
01633 const CFontManager *CPSLocatedBindable::getFontManager(void) const
01634 {
01635 nlassert(_Owner);
01636 return _Owner->getFontManager();
01637 }
01638
01639
01641
01642 const NLMISC::CMatrix &CPSLocatedBindable::getSysMat(void) const
01643 {
01644 nlassert(_Owner);
01645 return _Owner->getOwner()->getSysMat();
01646 }
01647
01650 const NLMISC::CMatrix &CPSLocatedBindable::getInvertedSysMat(void) const
01651 {
01652 nlassert(_Owner);
01653 return _Owner->getOwner()->getInvertedSysMat();
01654
01655 }
01656
01658 const NLMISC::CMatrix &CPSLocatedBindable::getInvertedLocatedMat(void) const
01659 {
01660 nlassert(_Owner);
01661 if (_Owner->isInSystemBasis())
01662 {
01663 return _Owner->getOwner()->getInvertedSysMat();
01664 }
01665 else
01666 {
01667 return NLMISC::CMatrix::Identity;
01668 }
01669 }
01670
01673 const NLMISC::CMatrix &CPSLocatedBindable::getViewMat(void) const
01674 {
01675 nlassert(_Owner);
01676 return _Owner->getOwner()->getViewMat();
01677 }
01678
01679
01682 const NLMISC::CMatrix &CPSLocatedBindable::getInvertedViewMat(void) const
01683 {
01684 nlassert(_Owner);
01685 return _Owner->getOwner()->getInvertedViewMat();
01686 }
01687
01690 void CPSLocatedBindable::setupDriverModelMatrix(void)
01691 {
01692 nlassert(_Owner);
01693 _Owner->setupDriverModelMatrix();
01694 }
01695
01697 void CPSLocatedBindable::setExternID(uint32 id)
01698 {
01699 if (id == _ExternID) return;
01700 nlassert(_Owner && _Owner->getOwner());
01701
01702 _Owner->getOwner()->unregisterLocatedBindableExternID(this);
01703 if (id != 0)
01704 {
01705 _Owner->getOwner()->registerLocatedBindableExternID(id, this);
01706 _ExternID = id;
01707 }
01708 }
01709
01711 void CPSLocatedBindable::releaseAllRef()
01712 {
01713 }
01714
01715
01716
01717
01718
01720
01722
01724
01725 {
01726 (void)f.serialVersion(1);
01727 f.serialPtr(_Owner);
01728 f.serial(_Name);
01729 if (f.isReading())
01730 {
01731
01732 for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
01733 {
01734 delete (*it);
01735 }
01736 _Targets.clear();
01737 }
01738 f.serialContPolyPtr(_Targets);
01739 }
01740
01741
01743 void CPSTargetLocatedBindable::attachTarget(CPSLocated *ptr)
01744 {
01745
01746
01747 #ifdef NL_DEBUG
01748 if (_Owner)
01749 {
01750 nlassert(_Owner->getOwner() == ptr->getOwner());
01751 }
01752 #endif
01753
01754
01755 nlassert(std::find(_Targets.begin(), _Targets.end(), ptr) == _Targets.end());
01756 _Targets.push_back(ptr);
01757
01758
01759 ptr->registerDtorObserver(this);
01760 }
01761
01762
01764 void CPSTargetLocatedBindable::notifyTargetRemoved(CPSLocated *ptr)
01765 {
01766 TTargetCont::iterator it = std::find(_Targets.begin(), _Targets.end(), ptr);
01767 nlassert(it != _Targets.end());
01768 releaseTargetRsc(*it);
01769 _Targets.erase(it);
01770
01771 CPSLocatedBindable::notifyTargetRemoved(ptr);
01772 }
01773
01774
01775
01776
01777
01779 void CPSTargetLocatedBindable::finalize(void)
01780 {
01784 for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
01785 {
01786 releaseTargetRsc(*it);
01787 }
01788 }
01789
01791 CPSTargetLocatedBindable::~CPSTargetLocatedBindable()
01792 {
01793
01794 for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
01795 {
01796 (*it)->unregisterDtorObserver(this);
01797 }
01798 }
01799
01801 void CPSTargetLocatedBindable::releaseRefTo(const CParticleSystemProcess *other)
01802 {
01803 TTargetCont::iterator it = std::find(_Targets.begin(), _Targets.end(), other);
01804 if (it == _Targets.end()) return;
01805 releaseTargetRsc(*it);
01806 (*it)->unregisterDtorObserver(this);
01807 _Targets.erase(it);
01808 nlassert(std::find(_Targets.begin(), _Targets.end(), other) == _Targets.end());
01809 }
01810
01812 void CPSTargetLocatedBindable::releaseAllRef()
01813 {
01814 for (TTargetCont::iterator it = _Targets.begin(); it != _Targets.end(); ++it)
01815 {
01816 releaseTargetRsc(*it);
01817 (*it)->unregisterDtorObserver(this);
01818 }
01819 _Targets.clear();
01820 CPSLocatedBindable::releaseAllRef();
01821 }
01822
01823
01824
01825
01826 }