From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- docs/doxygen/nel/ps__located_8cpp-source.html | 1818 +++++++++++++++++++++++++ 1 file changed, 1818 insertions(+) create mode 100644 docs/doxygen/nel/ps__located_8cpp-source.html (limited to 'docs/doxygen/nel/ps__located_8cpp-source.html') diff --git a/docs/doxygen/nel/ps__located_8cpp-source.html b/docs/doxygen/nel/ps__located_8cpp-source.html new file mode 100644 index 00000000..53605158 --- /dev/null +++ b/docs/doxygen/nel/ps__located_8cpp-source.html @@ -0,0 +1,1818 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

ps_located.cpp

Go to the documentation of this file.
00001 
+00007 /* Copyright, 2001 Nevrax Ltd.
+00008  *
+00009  * This file is part of NEVRAX NEL.
+00010  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00011  * it under the terms of the GNU General Public License as published by
+00012  * the Free Software Foundation; either version 2, or (at your option)
+00013  * any later version.
+00014 
+00015  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00016  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00018  * General Public License for more details.
+00019 
+00020  * You should have received a copy of the GNU General Public License
+00021  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00022  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00023  * MA 02111-1307, USA.
+00024  */
+00025 
+00026 #include "std3d.h"
+00027 
+00028 
+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         // located bindables
+00085         {       
+00086                 for(TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
+00087                 {
+00088                         (*it)->releaseRefTo(other);
+00089                 }
+00090         }
+00091         // dtor observers
+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          // located bindables
+00110         {       
+00111                 for(TLocatedBoundCont::iterator it = _LocatedBoundCont.begin(); it != _LocatedBoundCont.end(); ++it)
+00112                 {
+00113                         (*it)->releaseAllRef();
+00114                 }
+00115         }
+00116 
+00117         // we must do a copy, because the subsequent call can modify this vector
+00118         TDtorObserversVect copyVect(_DtorObserversVect.begin(), _DtorObserversVect.end());
+00119         // call all the dtor observers
+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); //If this is not = 0, then someone didnt call releaseCollisionInfo
+00127                                                                                  // If this happen, you can register with the registerDTorObserver
+00128                                                                                  // (observer pattern)
+00129                                                                                  // and override notifyTargetRemove to call releaseCollisionInfo
+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 /*= sizeof(NLMISC::CVector)*/)
+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 // no forces applied, just deduce position from date, initial pos and speed
+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         //step(PSEmit, ellapsedTime, realEllapsedTime); 
+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         // copy back infos from current position and speeds
+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 /*= true*/)
+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         // we examine wether we have particle attached to us, and ask for the max number of faces they may want
+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; // for benchmark purpose      
+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()); // scheme with memory is invalid there !!
+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()); // scheme with memory is invalid there !!
+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); // conversion must be made between entity of the same system
+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                 // we must express the I vector in the system basis, so we need to multiply it by the inverted matrix of the system
+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                 // we must express the J vector in the system basis, so we need to multiply it by the inverted matrix of the system
+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                 // we must express the K vector in the system basis, so we need to multiply it by the inverted matrix of the system
+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() ); // you haven't called setDriver on the system
+00477         return _Owner->getDriver();
+00478 }
+00479 
+00481 
+00482 CPSLocated::~CPSLocated()
+00483 {
+00484         // we must do a copy, because the subsequent call can modify this vector
+00485         TDtorObserversVect copyVect(_DtorObserversVect.begin(), _DtorObserversVect.end());
+00486         // call all the dtor observers
+00487         for (TDtorObserversVect::iterator it = copyVect.begin(); it != copyVect.end(); ++it)
+00488         {
+00489                 (*it)->notifyTargetRemoved(this);
+00490         }
+00491 
+00492         nlassert(_CollisionInfoNbRef == 0); //If this is not = 0, then someone didnt call releaseCollisionInfo
+00493                                                                                  // If this happen, you can register with the registerDTorObserver
+00494                                                                                  // (observer pattern)
+00495                                                                                  // and override notifyTargetRemove to call releaseCollisionInfo
+00496         nlassert(_IntegrableForces.size() == 0);
+00497         nlassert(_NonIntegrableForceNbRefs == 0);
+00498         nlassert(!_CollisionInfo);
+00499 
+00500         // delete all bindable
+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) // the "<" operator sort them correctly
+00523         {
+00524                 ++it;
+00525         }
+00526 
+00527         _LocatedBoundCont.insert(it, lb);
+00528         lb->setOwner(this);
+00529         lb->resize(_MaxSize);
+00530 
+00531         // any located bindable that is bound to us should have no element in it for now !!
+00532         // we resize it anyway...
+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         // check wether the observer wasn't registered twice
+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         // check that it was registered
+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 /* = 0.f */)
+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         // get the convertion matrix  from the emitter basis to the emittee basis
+00601         // if the emitter is null, we assume that the coordinate are given in the chosen basis for this particle type
+00602 
+00603         
+00604         
+00605         if (_MaxSize == _Size) return -1;
+00606 
+00607         // During creation, we interpolate the position of the system (by using the ellapsed time) if particle are created in world basis and if the emitter is in local basis.
+00608         // Example a fireball FX let particles in world basis, but the fireball is moving. If we dont interpolate position between 2 frames, emission will appear to be "sporadic".
+00609         // For now, we manage the local to world case. The world to local is possible, but not very useful
+00610         const CMatrix &convMat = emitter ? CPSLocated::getConversionMatrix(this, emitter) 
+00611                                                                          :  CMatrix::Identity;
+00612         if (!_SystemBasisEnabled && emitter && emitter->_SystemBasisEnabled)
+00613         {
+00614                 // Interpolate linearly position of the system based on the ellapsed time.
+00615                 // The system keep track the ellapsed time passed in the call to step(), so it can compute the right position for us
+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); // all attributs must contains the same number of elements
+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         // test wether parametric motion is used, and generate the infos that are needed then
+00639         if (_ParametricMotion)
+00640         {
+00641                 _PInfo.insert( CParametricInfo(_Pos[creationIndex], _Speed[creationIndex], _Owner->getSystemDate() ) );
+00642         }
+00643 
+00644 
+00646         // generate datas for all bound objects  //
+00648         _UpdateLock = true;     
+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;        // if this is modified, you must also modify the getNewElementIndex in this class
+00659                                 // because that method give the index of the element being created for overrider of the newElement method
+00660                                 // of the CPSLocatedClass (which is called just above)
+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         // delete all bindable before : they may need our coordinate
+00695         // to perform a destruction task
+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         // remove common located's attributes
+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; // we're dealing with unsigned quantities
+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         // resize attributes for all bound objects
+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                 // when writing the stack, we must make a copy because we can't access elements by their index
+00899                 // so the stack must be destroyed
+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                 // now rebuild the stack while serializing it;
+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                 // evaluate our max number of faces
+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 // integrate speed of particles. Makes eventually use of SSE instructions when present
+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                    )   // must must be sure that memory alignment is identical     
+00967                 {
+00968 
+00969                         // compute first datas in order to align to 16 byte boudary
+00970 
+00971                         uint alignCount =  ((uint) src1 >> 2) & 3; // number of float to process
+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                                 // sse part of computation
+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                         // proceed with left float
+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                 // standard version     
+01030                 
+01031         /*      for (float *src1End = src1 + count; src1 != src1End; ++src1, ++src2)
+01032                 {                               
+01033                         *src1 += ellapsedTime * *src2;                  
+01034                 } */
+01035 
+01036 
+01037                 // standard version     
+01038                 uint countDiv8 = count>>3;
+01039                 count &= 7; // takes count % 8
+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                 // check wether we must perform LOD degradation
+01077                 if (_LODDegradation)
+01078                 {
+01079                         if (ellapsedTime > 0)
+01080                         {
+01081                                 nlassert(_Owner);
+01082                                 // compute the number of particles to show
+01083                                 const uint maxToHave = (uint) (_MaxSize * _Owner->getOneMinusCurrentLODRatio());
+01084                                 if (_Size > maxToHave) // too much instances ?
+01085                                 {
+01086                                         // choose a random element to start at, and a random step
+01087                                         // this will avoid a pulse effect when the system is far away
+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                 // check if we must skip frames
+01105                 if (!_NbFramesToSkip || !( (uint32) _Owner->getDate() % (_NbFramesToSkip + 1)))
+01106                 {
+01107                         
+01108 
+01109                         // update the located creation requests that may have been posted
+01110                         updateNewElementRequestStack();
+01111 
+01112 
+01113                         // there are 2 integration steps : with and without collisions
+01114 
+01115                         if (!_CollisionInfo) // no collisionner are used
+01116                         {
+01117                                 if (_Size != 0) // avoid referencing _Pos[0] if there's no size, causes STL vectors to assert...
+01118                                         IntegrateSpeed(_Size * 3, &_Pos[0].x, &_Speed[0].x, ellapsedTime);
+01119                         }
+01120                         else
+01121                         {
+01122                                 // integration with collisions
+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                                                 // notify each located bindable that a bounce occured ...
+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                                 // reset collision info for the next time => done during the traversal
+01162                                 
+01163                         }               
+01164                 }
+01165                 else
+01166                 {
+01167                         return; // we skip the frame...
+01168                 }
+01169         }
+01170 
+01171         if (pass != PSMotion)
+01172         {
+01173                 // apply the pass to all bound objects
+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()) // has this object the right LOD ?
+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                 // the time attribute gives the life in seconds
+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; // something to compute ?
+01293 
+01294 
+01295         TLocatedBoundCont::const_iterator it;
+01296         TPSAttribVector::const_iterator it2;
+01297 
+01298         // check whether any object bound to us need a bbox
+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         // we've considered that located had no extent in space
+01325         // now, we must call each objects that are bound to the located in order
+01326         // to complete the bbox if they have no null extent
+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); // check whether queryCollisionInfo was called
+01384                                                                         // so the number of refs must not = 0                                                                   
+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()); // force registered twice
+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()); // f must be attached to a located
+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 // CPSLocatedBindable implementation //
+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                         // empty this located bindable. Need to be empty if it must be rebound to another located.
+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         // ugly slow code, but not for runtime
+01586         for (uint  k = 0; k < size; ++k)
+01587         {
+01588                 // center of the current particle
+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 // Shortcut to get the matrix of the system     
+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()); // to call this method, this locatedBindable must be inserted in a system!! 
+01701                                                                                         // (e.g not standalone)
+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 // CPSTargetLocatedBindable implementation //
+01722 
+01724 void CPSTargetLocatedBindable::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+01725 {
+01726         (void)f.serialVersion(1);       
+01727         f.serialPtr(_Owner);
+01728         f.serial(_Name);
+01729         if (f.isReading())
+01730         {
+01731                 // delete previous attached bindables...
+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         // a target can't be shared between different particle systems
+01747         #ifdef NL_DEBUG
+01748         if (_Owner)
+01749         {
+01750                 nlassert(_Owner->getOwner() == ptr->getOwner());
+01751         }
+01752         #endif
+01753 
+01754         // see wether this target has not been registered before 
+01755         nlassert(std::find(_Targets.begin(), _Targets.end(), ptr) == _Targets.end());
+01756         _Targets.push_back(ptr);
+01757 
+01758         // we register us to be notified when the target disappear
+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 // dtor
+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         // we unregister to all the targets
+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 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1