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__emitter_8cpp-source.html | 1527 +++++++++++++++++++++++++ 1 file changed, 1527 insertions(+) create mode 100644 docs/doxygen/nel/ps__emitter_8cpp-source.html (limited to 'docs/doxygen/nel/ps__emitter_8cpp-source.html') diff --git a/docs/doxygen/nel/ps__emitter_8cpp-source.html b/docs/doxygen/nel/ps__emitter_8cpp-source.html new file mode 100644 index 00000000..7921829c --- /dev/null +++ b/docs/doxygen/nel/ps__emitter_8cpp-source.html @@ -0,0 +1,1527 @@ + + + + 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_emitter.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 #include <stdlib.h>
+00029 #include "3d/ps_emitter.h"
+00030 #include "3d/material.h"
+00031 #include "nel/misc/line.h"
+00032 #include "3d/dru.h"
+00033 #include "3d/particle_system.h"
+00034 
+00035 namespace NL3D {
+00036 
+00037 
+00038 
+00039 // number of emitter to be processed at once
+00040 const uint emitterBuffSize = 512;
+00041 
+00043 // CPSEmitter implementation //
+00045 CPSEmitter::CPSEmitter() : _EmittedType(NULL),
+00046                                                    _SpeedInheritanceFactor(0.f),
+00047                                                    _EmissionType(regular),
+00048                                                    _Period(0.02f),
+00049                                                    _PeriodScheme(NULL), 
+00050                                                    _GenNb(1), 
+00051                                                    _GenNbScheme(NULL), 
+00052                                                    _EmitDelay(0),
+00053                                                    _MaxEmissionCount(0),
+00054                                                    _SpeedBasisEmission(false),
+00055                                                    _EmitDirBasis(true),
+00056                                                    _ConsistentEmission(true)
+00057 {
+00058 }
+00059 
+00060 
+00062 CPSEmitter::~CPSEmitter()
+00063 {
+00064         delete _PeriodScheme;
+00065         delete _GenNbScheme;
+00066         // if a located is emitted, unregister us as an observer
+00067         if (_EmittedType)
+00068         {
+00069                 _EmittedType->unregisterDtorObserver(this);
+00070         }
+00071 }
+00072 
+00074 void CPSEmitter::releaseRefTo(const CParticleSystemProcess *other)
+00075 {
+00076         if (_EmittedType == other)
+00077         {
+00078                 setEmittedType(NULL);
+00079         }
+00080 }
+00081 
+00082 void CPSEmitter::releaseAllRef()
+00083 {
+00084         setEmittedType(NULL);
+00085 }
+00086 
+00087 
+00089 inline void CPSEmitter::processEmit(uint32 index, sint nbToGenerate)
+00090 {       
+00091         static NLMISC::CVector speed, pos;
+00092         
+00093         if (!_SpeedBasisEmission)
+00094         {
+00095                 if (_SpeedInheritanceFactor == 0.f)
+00096                 {               
+00097                         if (_EmitDirBasis)
+00098                         {
+00099                                 while (nbToGenerate > 0)
+00100                                 {
+00101                                         nbToGenerate --;
+00102                                         emit(_Owner->getPos()[index], index, pos, speed);
+00103                                         _EmittedType->newElement(pos, speed, this->_Owner, index);
+00104                                 }
+00105                         }
+00106                         else
+00107                         {
+00108                                 while (nbToGenerate > 0)
+00109                                 {
+00110                                         nbToGenerate --;
+00111                                         emit(_Owner->getPos()[index], index, pos, speed);
+00112                                         _EmittedType->newElement(pos, speed, this->_Owner, index, false);
+00113                                 }
+00114                         }
+00115                 }
+00116                 else
+00117                 {
+00118                         while (nbToGenerate --)
+00119                         {
+00120                                 emit(_Owner->getPos()[index], index, pos, speed);
+00121                                 _EmittedType->newElement(pos, speed + _SpeedInheritanceFactor * _Owner->getSpeed()[index], this->_Owner);
+00122                         }
+00123                 }
+00124         }
+00125         else
+00126         {
+00127                 NLMISC::CMatrix m;
+00128                 CPSUtil::buildSchmidtBasis(_Owner->getSpeed()[index], m);
+00129                 if (_SpeedInheritanceFactor == 0.f)
+00130                 {               
+00131                         while (nbToGenerate > 0)
+00132                         {
+00133                                 nbToGenerate --;
+00134                                 emit(_Owner->getPos()[index], index, pos, speed);
+00135                                 _EmittedType->newElement(pos, m * speed, this->_Owner, index);
+00136                         }
+00137                 }
+00138                 else
+00139                 {
+00140                         while (nbToGenerate --)
+00141                         {
+00142                                 emit(_Owner->getPos()[index], index, pos, speed);
+00143                                 _EmittedType->newElement(pos, m * speed + _SpeedInheritanceFactor * _Owner->getSpeed()[index], this->_Owner, index);
+00144                         }
+00145                 }
+00146         }
+00147 }
+00148 
+00152 static inline void CompensateEmission(CPSLocated *emittedType, uint emittedIndex, TAnimationTime deltaT, TAnimationTime ellapsedTime, float realEllapsedTimeRatio)
+00153 {       
+00154         // now, update emitted element life time        
+00155         if (emittedType->getLastForever())
+00156         {               
+00157                 emittedType->getTime()[emittedIndex] += realEllapsedTimeRatio * deltaT;
+00158 
+00159                 if (emittedType->isParametricMotionEnabled())
+00160                 {
+00161                         emittedType->getParametricInfos()[emittedIndex].Date -= realEllapsedTimeRatio * deltaT;
+00162                 }
+00163                 else
+00164                 {
+00165                         if (!emittedType->hasCollisionInfos())
+00166                         {
+00167                                 // no collision case
+00168                                 emittedType->getPos()[emittedIndex] += deltaT * emittedType->getSpeed()[emittedIndex];
+00169                         }
+00170                         else // if there are collisions, we delay the step to the next iteration to ensure correct collisions
+00171                         {
+00172                                 emittedType->getCollisionInfo()[emittedIndex].TimeSliceRatio = deltaT / ellapsedTime;                           
+00173                         }
+00174                 }
+00175         }
+00176         else
+00177         {               
+00178                 TAnimationTime &destTime = emittedType->getTime()[emittedIndex];
+00179                 if (emittedType->getLifeScheme() != NULL)
+00180                 {
+00181                         destTime = realEllapsedTimeRatio * deltaT * emittedType->getTimeIncrement()[emittedIndex];
+00182                 }
+00183                 else
+00184                 {                               
+00185                         if (emittedType->getInitialLife() != 0.f)
+00186                         {
+00187                                 destTime = realEllapsedTimeRatio * deltaT / emittedType->getInitialLife();
+00188                         }
+00189                 }
+00190                 if (destTime >= 1.f)
+00191                 {                                       
+00192                         emittedType->deleteElement(emittedIndex);                       
+00193                 }
+00194                 else
+00195                 {       
+00196                         if (emittedType->isParametricMotionEnabled())
+00197                         {
+00198                                 emittedType->getParametricInfos()[emittedIndex].Date -= realEllapsedTimeRatio * deltaT;
+00199                         }
+00200                         else
+00201                         {
+00202                                 if (!emittedType->hasCollisionInfos())
+00203                                 {
+00204                                         // no collision case
+00205                                         emittedType->getPos()[emittedIndex] += deltaT * emittedType->getSpeed()[emittedIndex];
+00206                                 }
+00207                                 else // if there are collisions, we delay the step to the next iteration to ensure correct collisions
+00208                                 {
+00209                                         emittedType->getCollisionInfo()[emittedIndex].TimeSliceRatio = deltaT / ellapsedTime;                           
+00210                                 }
+00211                         }
+00212                 }
+00213         }
+00214 }
+00215 
+00217 inline void CPSEmitter::processEmitConsistent(const NLMISC::CVector &emitterPos,
+00218                                                                                           uint32 index,
+00219                                                                                           sint nbToGenerate,
+00220                                                                                           TAnimationTime deltaT,
+00221                                                                                           TAnimationTime ellapsedTime,
+00222                                                                                           float realEllapsedTimeRatio
+00223                                                                                          )
+00224 {               
+00225         static NLMISC::CVector speed, pos; 
+00226         sint emittedIndex;
+00227         if (!_SpeedBasisEmission)
+00228         {
+00229                 if (_SpeedInheritanceFactor == 0.f)
+00230                 {               
+00231                         if (_EmitDirBasis)
+00232                         {
+00233                                 while (nbToGenerate > 0)
+00234                                 {
+00235                                         nbToGenerate --;
+00236                                         emit(emitterPos, index, pos, speed);
+00237                                         emittedIndex = _EmittedType->newElement(pos, speed, this->_Owner, index, true, deltaT);
+00238                                         if (emittedIndex != - 1) CompensateEmission(_EmittedType, emittedIndex, deltaT, ellapsedTime, realEllapsedTimeRatio);
+00239                                         else break;
+00240                                 }
+00241                         }
+00242                         else
+00243                         {
+00244                                 while (nbToGenerate > 0)
+00245                                 {
+00246                                         nbToGenerate --;
+00247                                         emit(emitterPos, index, pos, speed);
+00248                                         emittedIndex = _EmittedType->newElement(pos, speed, this->_Owner, index, false, deltaT);
+00249                                         if (emittedIndex != - 1) CompensateEmission(_EmittedType, emittedIndex, deltaT, ellapsedTime, realEllapsedTimeRatio);
+00250                                         else break;
+00251                                 }
+00252                         }
+00253                 }
+00254                 else
+00255                 {
+00256                         while (nbToGenerate --)
+00257                         {
+00258                                 emit(emitterPos, index, pos, speed);
+00259                                 emittedIndex = _EmittedType->newElement(pos, speed + _SpeedInheritanceFactor * _Owner->getSpeed()[index], this->_Owner, index, true, deltaT);
+00260                                 if (emittedIndex != - 1) CompensateEmission(_EmittedType, emittedIndex, deltaT, ellapsedTime, realEllapsedTimeRatio);
+00261                                         else break;
+00262                         }
+00263                 }
+00264         }
+00265         else
+00266         {
+00267                 NLMISC::CMatrix m;
+00268                 CPSUtil::buildSchmidtBasis(_Owner->getSpeed()[index], m);
+00269                 if (_SpeedInheritanceFactor == 0.f)
+00270                 {               
+00271                         while (nbToGenerate > 0)
+00272                         {
+00273                                 nbToGenerate --;
+00274                                 emit(emitterPos, index, pos, speed);
+00275                                 emittedIndex = _EmittedType->newElement(pos, m * speed, this->_Owner, index, true, deltaT);
+00276                                 if (emittedIndex != - 1) CompensateEmission(_EmittedType, emittedIndex, deltaT, ellapsedTime, realEllapsedTimeRatio);
+00277                                         else break;
+00278                         }
+00279                 }
+00280                 else
+00281                 {
+00282                         while (nbToGenerate --)
+00283                         {
+00284                                 emit(emitterPos, index, pos, speed);
+00285                                 emittedIndex = _EmittedType->newElement(pos, m * speed + _SpeedInheritanceFactor * _Owner->getSpeed()[index], this->_Owner, index, true, deltaT);
+00286                                 if (emittedIndex != - 1) CompensateEmission(_EmittedType, emittedIndex, deltaT, ellapsedTime, realEllapsedTimeRatio);
+00287                                         else break;
+00288                         }
+00289                 }
+00290         }
+00291 }
+00292 
+00293 
+00295 void    CPSEmitter::setEmissionType(TEmissionType freqType)
+00296 { 
+00297         _EmissionType = freqType; 
+00298 }
+00299 
+00301 void CPSEmitter::setEmittedType(CPSLocated *et) 
+00302 {
+00303         if (_EmittedType)
+00304         {
+00305                 _EmittedType->unregisterDtorObserver(this);
+00306         }
+00307         if (et)
+00308         {
+00309                 et->registerDtorObserver(this);
+00310         }       
+00311 
+00312         _EmittedType = et;
+00313 }
+00314 
+00316 void CPSEmitter::notifyTargetRemoved(CPSLocated *ptr)
+00317 {
+00318         nlassert(ptr == _EmittedType && _EmittedType);
+00319         setEmittedType(NULL);   
+00320 }
+00321 
+00323 void CPSEmitter::setPeriod(float period)
+00324 {
+00325         if (_PeriodScheme)
+00326         {
+00327                 delete _PeriodScheme;
+00328                 _PeriodScheme = NULL;
+00329         }
+00330         _Period = period;
+00331 }
+00332 
+00334 void CPSEmitter::setPeriodScheme(CPSAttribMaker<float> *scheme)
+00335 {       
+00336         delete _PeriodScheme;   
+00337         _PeriodScheme = scheme;
+00338         if (_Owner && scheme->hasMemory()) scheme->resize(_Owner->getMaxSize(), _Owner->getSize());
+00339 }
+00340 
+00342 void CPSEmitter::setGenNb(uint32 genNb)
+00343 {
+00344         if (_GenNbScheme)
+00345         {
+00346                 delete _GenNbScheme;
+00347                 _GenNbScheme = NULL;
+00348         }
+00349         _GenNb = genNb; 
+00350 }
+00351 
+00353 void CPSEmitter::setGenNbScheme(CPSAttribMaker<uint32> *scheme)
+00354 {
+00355         delete _GenNbScheme;    
+00356         _GenNbScheme = scheme;
+00357         if (_Owner && scheme->hasMemory()) scheme->resize(_Owner->getMaxSize(), _Owner->getSize());
+00358 }
+00359 
+00361 void CPSEmitter::showTool(void) 
+00362 {
+00363         uint32 size = _Owner->getSize();
+00364         if (!size) return;              
+00365         setupDriverModelMatrix();       
+00366 
+00367         const CVector I = computeI();
+00368         const CVector K = computeK();
+00369 
+00370         // ugly slow code, but not for runtime
+00371         for (uint  k = 0; k < size; ++k)
+00372         {
+00373                 // center of the current particle
+00374                 const CVector p = _Owner->getPos()[k];
+00375                 const float sSize =0.1f;        
+00376                 std::vector<NLMISC::CLine> lines;
+00377                 NLMISC::CLine l;
+00378                 l.V0 = p - sSize * I; l.V1 =  p + sSize * I; lines.push_back(l);
+00379                 l.V0 = p - sSize * K; l.V1 =  p + sSize * K; lines.push_back(l);
+00380                 l.V0 = p - sSize * (I + K); l.V1 = p + sSize * (I + K); lines.push_back(l);
+00381                 l.V0 = p - sSize * (I - K); l.V1 = p + sSize * (I - K); lines.push_back(l);
+00382                                                                                                                                                 
+00383                 CMaterial mat;
+00384                 mat.setBlendFunc(CMaterial::one, CMaterial::one);
+00385                 mat.setZWrite(false);
+00386                 mat.setLighting(false);
+00387                 mat.setBlend(true);
+00388                 mat.setZFunc(CMaterial::less);
+00389                 
+00390         
+00391                 CPSLocated *loc;                
+00392                 uint32 index;
+00393                 CPSLocatedBindable *lb;
+00394                 _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
+00395 
+00396                 mat.setColor((lb == NULL || this == lb) && loc == _Owner && index == k  ? CRGBA::Red : CRGBA(127, 127, 127));
+00397                 
+00398 
+00399                 CDRU::drawLinesUnlit(lines, mat, *getDriver() );
+00400         }
+00401 }
+00402 
+00404 void CPSEmitter::singleEmit(uint32 index, uint quantity)
+00405 {
+00406         nlassert(_Owner);
+00407         const uint32 nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner,0) : _GenNb;                
+00408         processEmit(index, quantity * nbToGenerate);
+00409 }
+00410 
+00411 
+00413 void CPSEmitter::processRegularEmission(TAnimationTime ellapsedTime)
+00414 {
+00415         nlassert(_Owner);
+00416         const uint size = _Owner->getSize();
+00417         uint leftToDo = size, toProcess;
+00418         float emitPeriod[emitterBuffSize]; 
+00419         float *currEmitPeriod;
+00420         uint currEmitPeriodPtrInc = _PeriodScheme ? 1 : 0;                      
+00421         sint32 nbToGenerate;
+00422 
+00423         TPSAttribTime::iterator phaseIt = _Phase.begin(), endPhaseIt; 
+00424         TPSAttribUInt8::iterator numEmitIt = _NumEmission.begin(); 
+00425 
+00426         // we don't use an iterator here
+00427         // because it could be invalidated if size change (a located could generate itself)     
+00428         do
+00429         {
+00430                 toProcess = leftToDo < emitterBuffSize ? leftToDo : emitterBuffSize;
+00431 
+00432 
+00433                 if (_PeriodScheme)
+00434                 {
+00435                         currEmitPeriod = (float *) (_PeriodScheme->make(_Owner, size - leftToDo, emitPeriod, sizeof(float), toProcess, true));                          
+00436                 }
+00437                 else
+00438                 {
+00439                         currEmitPeriod = &_Period;
+00440                 }
+00441 
+00442                 endPhaseIt = phaseIt + toProcess;
+00443 
+00444                 if (_MaxEmissionCount == 0) // no emission count limit
+00445                 {
+00447                         if (_EmitDelay == 0.f) // no emission delay
+00448                         {
+00449                                 do                      
+00450                                 {
+00451                                         *phaseIt += ellapsedTime;
+00452                                         if ( *phaseIt >= *currEmitPeriod) // phase is greater than period -> must emit
+00453                                         {                                       
+00454                                                 if (*currEmitPeriod != 0)
+00455                                                 {
+00456                                                         *phaseIt -= ::floorf(*phaseIt / *currEmitPeriod) * *currEmitPeriod;
+00457                                                 }
+00458                                                 const uint32 k = phaseIt - (_Phase.begin());
+00459                                                 nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, k) : _GenNb;                                    
+00460                                                 processEmit(k, nbToGenerate);                                                                           
+00461                                         }       
+00462                                         
+00463                                         ++phaseIt;
+00464                                         currEmitPeriod += currEmitPeriodPtrInc;
+00465                                 }
+00466                                 while (phaseIt != endPhaseIt);
+00467                         }
+00468                         else // thhere's an emission delay
+00469                         {
+00470                                 do                      
+00471                                 {
+00472                                         *phaseIt += ellapsedTime;
+00473                                         if ( *phaseIt >= *currEmitPeriod + _EmitDelay) // phase is greater than period -> must emit
+00474                                         {
+00475                                                 if (*currEmitPeriod != 0)
+00476                                                 {
+00477                                                         *phaseIt -= ::floorf((*phaseIt - _EmitDelay)  / *currEmitPeriod) * *currEmitPeriod;
+00478                                                 }
+00479                                                 const uint32 k = phaseIt - (_Phase.begin());
+00480                                                 nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, k) : _GenNb;                                    
+00481                                                 processEmit(k, nbToGenerate);                                                                           
+00482                                         }       
+00483                                         
+00484                                         ++phaseIt;
+00485                                         currEmitPeriod += currEmitPeriodPtrInc;
+00486                                 }
+00487                                 while (phaseIt != endPhaseIt);
+00488                         }
+00489                 }
+00490                 else // there's an emission count limit
+00491                 {
+00493                         if (_EmitDelay == 0.f) // no emission delay
+00494                         {
+00495                                 do                      
+00496                                 {
+00497                                         if (*numEmitIt < _MaxEmissionCount)
+00498                                         {
+00499                                                 *phaseIt += ellapsedTime;
+00500                                                 if ( *phaseIt >= *currEmitPeriod) // phase is greater than period -> must emit
+00501                                                 {
+00502                                                         if (*currEmitPeriod != 0)
+00503                                                         {
+00504                                                                 *phaseIt -= ::floorf(*phaseIt / *currEmitPeriod) * *currEmitPeriod;
+00505                                                         }
+00506                                                         const uint32 k = phaseIt - (_Phase.begin());
+00507                                                         nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, k) : _GenNb;                                    
+00508                                                         processEmit(k, nbToGenerate);
+00509                                                         ++*numEmitIt;
+00510                                                 }       
+00511                                         }       
+00512                                         ++phaseIt;
+00513                                         currEmitPeriod += currEmitPeriodPtrInc;                                                 
+00514                                         ++ numEmitIt;
+00515                                 }
+00516                                 while (phaseIt != endPhaseIt);
+00517                         }
+00518                         else // there's an emission delay
+00519                         {
+00520                                 do                      
+00521                                 {
+00522                                         if (*numEmitIt < _MaxEmissionCount)
+00523                                         {
+00524                                                 *phaseIt += ellapsedTime;
+00525                                                 if ( *phaseIt >= *currEmitPeriod + _EmitDelay) // phase is greater than period -> must emit
+00526                                                 {
+00527                                                         if (*currEmitPeriod != 0)
+00528                                                         {
+00529                                                                 *phaseIt -= ::floorf((*phaseIt - _EmitDelay) / *currEmitPeriod) * *currEmitPeriod;
+00530                                                         }
+00531                                                         const uint32 k = phaseIt - (_Phase.begin());
+00532                                                         nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, k) : _GenNb;                                    
+00533                                                         processEmit(k, nbToGenerate);
+00534                                                         ++*numEmitIt;
+00535                                                 }
+00536                                         }                                                       
+00537                                         ++phaseIt;
+00538                                         currEmitPeriod += currEmitPeriodPtrInc;
+00539                                         ++numEmitIt;
+00540                                 }
+00541                                 while (phaseIt != endPhaseIt);
+00542                         }
+00543                 }
+00544 
+00545                 leftToDo -= toProcess;
+00546         }
+00547         while (leftToDo);
+00548 }
+00549 
+00551 //  depending on wether its motion is parametric or incremental. This is used to create emittees at the right position
+00552 
+00553 static inline uint GenEmitterPositions(CPSLocated *emitter,
+00554                                                                            CPSLocated *emittee,
+00555                                                                            uint emitterIndex,
+00556                                                                            uint numStep,
+00557                                                                            TAnimationTime deltaT, /* fraction of time needed to reach the first emission */
+00558                                                                            TAnimationTime step,
+00559                                                                            std::vector<NLMISC::CVector> &dest
+00560                                                                           )
+00561 {
+00562         const uint toProcess = std::max(1U, std::min(numStep, (uint) emittee->getMaxSize()));   
+00563         dest.resize(toProcess);
+00564         
+00565         
+00566         if (!emitter->isParametricMotionEnabled()) // standard case : take current pos and integrate
+00567         {
+00568                 if (toProcess == 1) // only one emission -> takes current pos
+00569                 {
+00570                         dest[0] = emitter->getPos()[emitterIndex] - deltaT * emitter->getSpeed()[emitterIndex];
+00571                 }
+00572                 else
+00573                 {
+00574                         std::vector<NLMISC::CVector>::iterator outIt = dest.end();
+00575                         std::vector<NLMISC::CVector>::iterator endIt = dest.begin();
+00576                         NLMISC::CVector pos = emitter->getPos()[emitterIndex] - deltaT * emitter->getSpeed()[emitterIndex];
+00577                         NLMISC::CVector speed = step * emitter->getSpeed()[emitterIndex];
+00578                         do
+00579                         {
+00580                                 -- outIt;
+00581                                 *outIt = pos;
+00582                                 pos -= speed;                           
+00583                         }
+00584                         while (outIt != endIt);
+00585                 }
+00586         }
+00587         else // compute parametric trajectory
+00588         {
+00589                 emitter->integrateSingle(emitter->getOwner()->getSystemDate() - deltaT - step * toProcess,
+00590                                                                  step,
+00591                                                                  toProcess,                                                                      
+00592                                                                  emitterIndex,
+00593                                                                  &dest[0]
+00594                                                                 );                              
+00595         }
+00596         
+00597         return toProcess;
+00598 }
+00599 
+00601 void CPSEmitter::processRegularEmissionConsistent(TAnimationTime ellapsedTime, float realEllapsedTimeRatio)
+00602 {
+00604 
+00605         static std::vector<NLMISC::CVector> emitterPositions; 
+00606         // Positions for the emitter. They are computed by using a parametric trajectory or by using integration
+00607 
+00608         const uint size = _Owner->getSize();
+00609         uint leftToDo = size, toProcess;
+00610         float emitPeriod[emitterBuffSize]; 
+00611         float *currEmitPeriod;
+00612         uint currEmitPeriodPtrInc = _PeriodScheme ? 1 : 0;                      
+00613         sint32 nbToGenerate;
+00614 
+00615 
+00616         TPSAttribTime::iterator phaseIt = _Phase.begin(), endPhaseIt; 
+00617         TPSAttribUInt8::iterator numEmitIt = _NumEmission.begin(); 
+00618 
+00619         // we don't use an iterator here
+00620         // because it could be invalidated if size change (a located could generate itself)     
+00621         do
+00622         {
+00623                 toProcess = leftToDo < emitterBuffSize ? leftToDo : emitterBuffSize;
+00624 
+00625 
+00626                 if (_PeriodScheme)
+00627                 {
+00628                         currEmitPeriod = (float *) (_PeriodScheme->make(_Owner, size - leftToDo, emitPeriod, sizeof(float), toProcess, true));                          
+00629                 }
+00630                 else
+00631                 {
+00632                         currEmitPeriod = &_Period;
+00633                 }
+00634 
+00635                 endPhaseIt = phaseIt + toProcess;
+00636 
+00637                 if (_MaxEmissionCount == 0) // no emission count limit
+00638                 {
+00640                         if (_EmitDelay == 0.f) // no emission delay
+00641                         {
+00642                                 do                      
+00643                                 {
+00644                                         *phaseIt += ellapsedTime;
+00645                                         if ( *phaseIt >= *currEmitPeriod) // phase is greater than period -> must emit
+00646                                         {                                                                       
+00647                                                 if (*currEmitPeriod != 0)
+00648                                                 {               
+00651                                                         *phaseIt = std::min(*phaseIt, *currEmitPeriod + ellapsedTime);
+00652                                                         //
+00654                                                         uint numEmissions = (uint) ::floorf(*phaseIt / *currEmitPeriod);
+00655                                                         *phaseIt -= *currEmitPeriod * numEmissions;
+00656                                                         float deltaT = std::max(0.f, *phaseIt);
+00657                                                         //nlassert(deltaT >= 0.f);
+00658                                                         uint emitterIndex = phaseIt - _Phase.begin();
+00659 
+00661                                                         numEmissions = GenEmitterPositions(_Owner,
+00662                                                                                                                                 _EmittedType,
+00663                                                                                                                                 emitterIndex,
+00664                                                                                                                                 numEmissions,
+00665                                                                                                                                 deltaT,
+00666                                                                                                                                 *currEmitPeriod,
+00667                                                                                                                                 emitterPositions
+00668                                                                                                                            );
+00669 
+00671                                                         nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, emitterIndex) : _GenNb;
+00672                                                         uint k = numEmissions;                                                  
+00673                                                         do
+00674                                                         {       
+00675                                                                 --k;
+00676                                                                 processEmitConsistent(emitterPositions[k],
+00677                                                                                                           emitterIndex,
+00678                                                                                                           nbToGenerate,
+00679                                                                                                           deltaT,
+00680                                                                                                           ellapsedTime,
+00681                                                                                                           realEllapsedTimeRatio);
+00682                                                                 deltaT += *currEmitPeriod;                                                              
+00683                                                         }
+00684                                                         while (k);                                                                                                                                      
+00685                                                 }
+00686                                                 else
+00687                                                 {
+00688                                                         const uint32 emitterIndex = phaseIt - (_Phase.begin());
+00689                                                         nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, emitterIndex) : _GenNb;
+00690                                                         processEmit(emitterIndex, nbToGenerate);
+00691                                                 }
+00692                                         }       
+00693                                         
+00694                                         ++phaseIt;                                      
+00695                                         currEmitPeriod += currEmitPeriodPtrInc;
+00696                                 }
+00697                                 while (phaseIt != endPhaseIt);
+00698                         }
+00699                         else // thhere's an emission delay
+00700                         {
+00701                                 do                      
+00702                                 {
+00703                                         *phaseIt += ellapsedTime;
+00704                                         if ( *phaseIt >= *currEmitPeriod + _EmitDelay) // phase is greater than period -> must emit
+00705                                         {                                               
+00706                                                 if (*currEmitPeriod != 0)
+00707                                                 {               
+00710                                                         *phaseIt = std::min(*phaseIt, *currEmitPeriod + ellapsedTime + _EmitDelay);
+00711                                                         //
+00712                                                         uint numEmissions = (uint) ::floorf((*phaseIt - _EmitDelay) / *currEmitPeriod);
+00713                                                         *phaseIt -= *currEmitPeriod * numEmissions;
+00714                                                         float deltaT = std::max(*phaseIt - _EmitDelay, 0.f);
+00715                                                         //nlassert(deltaT >= 0.f);
+00716 
+00717                                                         uint emitterIndex = phaseIt - _Phase.begin();
+00719                                                         numEmissions = GenEmitterPositions(_Owner,
+00720                                                                                         _EmittedType,
+00721                                                                                                 emitterIndex,
+00722                                                                                 numEmissions,
+00723                                                                                                 deltaT,
+00724                                                                                             *currEmitPeriod,
+00725                                                                                             emitterPositions
+00726                                                                                            );
+00728                                                         nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, emitterIndex) : _GenNb;                                                 
+00729                                                         uint k = numEmissions;                                                  
+00730                                                         do
+00731                                                         {       
+00732                                                                 --k;
+00733                                                                 processEmitConsistent(emitterPositions[k],
+00734                                                                                                           emitterIndex,
+00735                                                                                                           nbToGenerate,
+00736                                                                                                           deltaT,
+00737                                                                                                           ellapsedTime,
+00738                                                                                                           realEllapsedTimeRatio);
+00739                                                                 deltaT += *currEmitPeriod;                                                              
+00740                                                         }
+00741                                                         while (k);                                                                                                      
+00742                                                 }
+00743                                                 else
+00744                                                 {               
+00745                                                         const uint32 emitterIndex = phaseIt - (_Phase.begin());
+00746                                                         nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, emitterIndex) : _GenNb;
+00747                                                         processEmit(emitterIndex, nbToGenerate);                                                        
+00748                                                 }                                                                       
+00749                                         }       
+00750                                         
+00751                                         ++phaseIt;                                      
+00752                                         currEmitPeriod += currEmitPeriodPtrInc;
+00753                                 }
+00754                                 while (phaseIt != endPhaseIt);
+00755                         }
+00756                 }
+00757                 else // there's an emission count limit
+00758                 {
+00760                         if (_EmitDelay == 0.f) // no emission delay
+00761                         {
+00762                                 do                      
+00763                                 {
+00764                                         if (*numEmitIt < _MaxEmissionCount)
+00765                                         {
+00766                                                 *phaseIt += ellapsedTime;
+00767                                                 if ( *phaseIt >= *currEmitPeriod) // phase is greater than period -> must emit
+00768                                                 {
+00769                                                         if (*currEmitPeriod != 0)
+00770                                                         {
+00773                                                                 *phaseIt = std::min(*phaseIt, *currEmitPeriod + ellapsedTime);
+00774                                                                 //
+00775                                                                 uint numEmissions = (uint) ::floorf(*phaseIt / *currEmitPeriod);
+00776                                                                 *numEmitIt +=  numEmissions;                                                            
+00777                                                                 *phaseIt -= *currEmitPeriod * numEmissions;
+00778                                                                 float deltaT = std::max(*phaseIt, 0.f);
+00779                                                                 //nlassert(deltaT >= 0.f);
+00780                                                                 uint emitterIndex = phaseIt - _Phase.begin();
+00781                                                                 if (*numEmitIt > _MaxEmissionCount) // make sure we don't go over the emission limit
+00782                                                                 {
+00783                                                                         numEmissions -= *numEmitIt - _MaxEmissionCount;
+00784                                                                         *numEmitIt = _MaxEmissionCount;
+00785                                                                 }
+00787                                                                 numEmissions = GenEmitterPositions(_Owner,
+00788                                                                                                         _EmittedType,
+00789                                                                                                         emitterIndex,
+00790                                                                                                         numEmissions,
+00791                                                                                                         deltaT,
+00792                                                                                                         *currEmitPeriod,
+00793                                                                                                         emitterPositions
+00794                                                                                                    );
+00795                                                                 uint k = numEmissions;                                                          
+00797                                                                 nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, emitterIndex) : _GenNb;                                                         
+00798                                                                 do
+00799                                                                 {
+00800                                                                         --k;
+00801                                                                         processEmitConsistent(emitterPositions[k],
+00802                                                                                                                   emitterIndex,
+00803                                                                                                                   nbToGenerate,
+00804                                                                                                                   deltaT,
+00805                                                                                                                   ellapsedTime,
+00806                                                                                                                   realEllapsedTimeRatio);
+00807                                                                         deltaT += *currEmitPeriod;                                                                      
+00808                                                                 }
+00809                                                                 while (k);                                                                                                              
+00810                                                         }
+00811                                                         else
+00812                                                         {
+00813                                                                 const uint32 emitterIndex = phaseIt - _Phase.begin();
+00814                                                                 nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, emitterIndex) : _GenNb;
+00815                                                                 processEmit(emitterIndex, nbToGenerate);                                                                
+00816                                                                 ++*numEmitIt;
+00817                                                         }
+00818                                                 }       
+00819                                         }       
+00820                                         ++phaseIt;                                      
+00821                                         currEmitPeriod += currEmitPeriodPtrInc;                                                 
+00822                                         ++ numEmitIt;
+00823                                 }
+00824                                 while (phaseIt != endPhaseIt);
+00825                         }
+00826                         else // there's an emission delay
+00827                         {
+00828                                 do                      
+00829                                 {
+00830                                         if (*numEmitIt < _MaxEmissionCount)
+00831                                         {
+00832                                                 *phaseIt += ellapsedTime;
+00833                                                 if ( *phaseIt >= *currEmitPeriod + _EmitDelay) // phase is greater than period -> must emit
+00834                                                 {                                                       
+00835                                                         if (*currEmitPeriod != 0)
+00836                                                         {               
+00839                                                                 *phaseIt = std::min(*phaseIt, *currEmitPeriod + ellapsedTime + _EmitDelay);
+00840                                                                 //
+00841                                                                 uint numEmissions = (uint) ::floorf((*phaseIt - _EmitDelay) / *currEmitPeriod);
+00842                                                                 *numEmitIt +=  numEmissions;                                                            
+00843                                                                 *phaseIt -= *currEmitPeriod * numEmissions;
+00844                                                                 float deltaT = std::max(*phaseIt - _EmitDelay, 0.f);
+00845                                                                 //nlassert(deltaT >= 0.f);
+00846                                                                 uint emitterIndex = phaseIt - _Phase.begin();
+00847                                                                 if (*numEmitIt > _MaxEmissionCount) // make sure we don't go over the emission limit
+00848                                                                 {
+00849                                                                         numEmissions -= *numEmitIt - _MaxEmissionCount;
+00850                                                                         *numEmitIt = _MaxEmissionCount;
+00851                                                                 }
+00853                                                                 numEmissions = GenEmitterPositions(_Owner,
+00854                                                                                                                                         _EmittedType,
+00855                                                                                                                                         emitterIndex,
+00856                                                                                                                                         numEmissions,
+00857                                                                                                                                         deltaT,
+00858                                                                                                                                         *currEmitPeriod,
+00859                                                                                                                                         emitterPositions
+00860                                                                                                                                    );
+00861                                                                 uint k = numEmissions;                                                          
+00863                                                                 nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, emitterIndex) : _GenNb;                                                         
+00864                                                                 do
+00865                                                                 {       
+00866                                                                         --k;
+00867                                                                         processEmitConsistent(emitterPositions[k],
+00868                                                                                                                   emitterIndex,
+00869                                                                                                                   nbToGenerate,
+00870                                                                                                                   deltaT,
+00871                                                                                                                   ellapsedTime,
+00872                                                                                                                   realEllapsedTimeRatio);
+00873                                                                         deltaT += *currEmitPeriod;                                                                      
+00874                                                                 }
+00875                                                                 while (k);                                                              
+00876                                                         }
+00877                                                         else
+00878                                                         {
+00879                                                                 const uint32 emitterIndex = phaseIt - (_Phase.begin());
+00880                                                                 nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, emitterIndex) : _GenNb;
+00881                                                                 processEmit(emitterIndex, nbToGenerate);                                                                
+00882                                                                 ++*numEmitIt;
+00883                                                         }
+00884                                                 }
+00885                                         }                                                       
+00886                                         ++phaseIt;                                      
+00887                                         currEmitPeriod += currEmitPeriodPtrInc;
+00888                                         ++numEmitIt;
+00889                                 }
+00890                                 while (phaseIt != endPhaseIt);
+00891                         }
+00892                 }
+00893 
+00894                 leftToDo -= toProcess;
+00895         }
+00896         while (leftToDo);
+00897 }
+00898 
+00900 void CPSEmitter::step(TPSProcessPass pass, TAnimationTime ellapsedTime, TAnimationTime realEllapsedTime)
+00901 {       
+00902         if (pass == PSToolRender)
+00903         {
+00904                 showTool();
+00905                 return;
+00906         }
+00907         if (pass != PSEmit || !_EmittedType) return;
+00908         const uint32 size = _Owner->getSize();
+00909         if (!size) return;
+00910 
+00911         if (ellapsedTime == 0.f) return; // do nothing when paused
+00912 
+00913         // our behaviour depend of the frequency
+00914         switch (_EmissionType)
+00915         {
+00916                 case CPSEmitter::once :
+00917                 {
+00918                         TPSAttribTime::iterator timeIt = _Phase.begin()
+00919                                                                                   , timeEndIt = _Phase.end();
+00920 
+00921                         while (timeIt != timeEndIt)
+00922                         {
+00923                                 if (*timeIt == 0.f)
+00924                                 {
+00925                                         const uint32 nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, timeIt - _Phase.begin()) : _GenNb;         
+00926                                         processEmit(timeIt - _Phase.begin(), nbToGenerate);             
+00927                                         *timeIt = 1.f;
+00928                                 }
+00929                                 ++timeIt;
+00930                         }                       
+00931                 }
+00932                 break;
+00933                 case (CPSEmitter::regular):
+00934                 {
+00935                         if (!_ConsistentEmission)
+00936                         {
+00937                                 processRegularEmission(ellapsedTime);
+00938                         }
+00939                         else
+00940                         {
+00941                                 processRegularEmissionConsistent(ellapsedTime, realEllapsedTime / ellapsedTime);
+00942                         }
+00943                 }
+00944                 break;  
+00945                 default: break;
+00946         }
+00947 }
+00948 
+00950 void CPSEmitter::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
+00951 {       
+00952         nlassert(_Phase.getSize() != _Phase.getMaxSize());      
+00953 
+00954         _Phase.insert(0.f);
+00955         if (_MaxEmissionCount != 0)
+00956         {
+00957                 _NumEmission.insert(0); 
+00958         }
+00959         if (_PeriodScheme && _PeriodScheme->hasMemory()) _PeriodScheme->newElement(emitterLocated, emitterIndex);
+00960         if (_GenNbScheme && _GenNbScheme->hasMemory()) _GenNbScheme->newElement(emitterLocated, emitterIndex);
+00961 
+00962 }
+00963 
+00965 void CPSEmitter::deleteElement(uint32 index)
+00966 {       
+00967 
+00968         if (_EmissionType == CPSEmitter::onDeath && _EmittedType)
+00969         {
+00970                 const uint32 nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, index) : _GenNb;           
+00971                 processEmit(index, nbToGenerate);               
+00972         }               
+00973 
+00974         if (_PeriodScheme && _PeriodScheme->hasMemory()) _PeriodScheme->deleteElement(index);
+00975         if (_GenNbScheme && _GenNbScheme->hasMemory()) _GenNbScheme->deleteElement(index);
+00976         _Phase.remove(index);
+00977         if (_MaxEmissionCount != 0)
+00978         {
+00979                 _NumEmission.remove(index);
+00980         }
+00981 }
+00982 
+00984 void CPSEmitter::resize(uint32 size)
+00985 {
+00986         nlassert(size < (1 << 16));
+00987         if (_PeriodScheme && _PeriodScheme->hasMemory()) _PeriodScheme->resize(size, _Owner->getSize());
+00988         if (_GenNbScheme && _GenNbScheme->hasMemory()) _GenNbScheme->resize(size, _Owner->getSize());
+00989         _Phase.resize(size);
+00990         if (_MaxEmissionCount != 0)
+00991         {
+00992                 _NumEmission.resize(size);
+00993         }
+00994 }
+00995 
+00997 void CPSEmitter::bounceOccured(uint32 index)
+00998 {
+00999         // TODO : avoid duplication with deleteElement
+01000         if (_EmissionType == CPSEmitter::onBounce)
+01001         {
+01002                 const uint32 nbToGenerate = _GenNbScheme ? _GenNbScheme->get(_Owner, index) : _GenNb;           
+01003                 processEmit(index, nbToGenerate);
+01004         }               
+01005 }
+01006 
+01008 void CPSEmitter::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+01009 {
+01010 
+01012         sint ver = f.serialVersion(4);  
+01013         CPSLocatedBindable::serial(f);
+01014         
+01015         f.serialPolyPtr(_EmittedType);
+01016         f.serial(_Phase);
+01017         f.serial(_SpeedInheritanceFactor);
+01018         f.serial(_SpeedBasisEmission);
+01019         
+01020         f.serialEnum(_EmissionType);
+01021 
+01022         // this is for use with serial
+01023         bool trueB = true, falseB = false;
+01024 
+01025         if (!f.isReading())
+01026         {
+01027                 switch (_EmissionType)
+01028                 {
+01029                         case CPSEmitter::regular:                       
+01030                                 if (_PeriodScheme)
+01031                                 {
+01032                                         f.serial(trueB);
+01033                                         f.serialPolyPtr(_PeriodScheme);
+01034                                 }
+01035                                 else
+01036                                 {
+01037                                          f.serial(falseB);
+01038                                          f.serial(_Period);
+01039                                 }
+01040                                 if (ver >= 3)
+01041                                 {
+01042                                         f.serial(_EmitDelay, _MaxEmissionCount);                                                                                                        
+01043                                 }
+01044                         break;
+01045                         default:
+01046                         break;
+01047                 }
+01048                 if (_GenNbScheme)
+01049                 {
+01050                         f.serial(trueB);
+01051                         f.serialPolyPtr(_GenNbScheme);
+01052                 }
+01053                 else
+01054                 {
+01055                          f.serial(falseB);
+01056                          f.serial(_GenNb);
+01057                 }
+01058         }
+01059         else
+01060         {
+01061                 bool useScheme;
+01062                 switch (_EmissionType)
+01063                 {
+01064                         case CPSEmitter::regular:
+01065                         {                               
+01066                                 f.serial(useScheme);
+01067                                 if (useScheme)
+01068                                 {
+01069                                         delete _PeriodScheme;                                   
+01070                                         f.serialPolyPtr(_PeriodScheme);
+01071                                 }
+01072                                 else
+01073                                 {                                        
+01074                                          f.serial(_Period);
+01075                                 }
+01076                                 if (ver >= 3)
+01077                                 {
+01078                                         f.serial(_EmitDelay, _MaxEmissionCount);
+01079                                         updateMaxCountVect();
+01080                                 }                               
+01081                         }
+01082                         break;
+01083                         default:
+01084                         break;
+01085                 }
+01086 
+01087                 f.serial(useScheme); 
+01088                 if (useScheme)
+01089                 {
+01090                         delete _GenNbScheme;
+01091                         f.serialPolyPtr(_GenNbScheme);
+01092                 }
+01093                 else
+01094                 {                               
+01095                          f.serial(_GenNb);
+01096                 }
+01097         }
+01098         if (ver > 1)
+01099         {
+01100                 f.serial(_EmitDirBasis);
+01101         }
+01102         if (ver >= 4)
+01103         {
+01104                 f.serial(_ConsistentEmission);
+01105         }
+01106 }
+01107 
+01109 void    CPSEmitter::updateMaxCountVect()
+01110 {
+01111         if (!_MaxEmissionCount)
+01112         {
+01113                 _NumEmission.resize(0);
+01114         }
+01115         else
+01116         {
+01117                 nlassert(_Owner);
+01118                 _NumEmission.resize(_Owner->getMaxSize());
+01119                 while (_NumEmission.getSize() != 0) 
+01120                 {               
+01121                         _NumEmission.remove(0);
+01122                 }
+01123                 while (_NumEmission.getSize() != _Owner->getSize())
+01124                 {
+01125                         _NumEmission.insert(0);
+01126                 }               
+01127         }
+01128 }
+01129 
+01131 void    CPSEmitter::setMaxEmissionCount(uint8 count)
+01132 {
+01133         if (count == _MaxEmissionCount) return;
+01134         _MaxEmissionCount = count;
+01135         updateMaxCountVect();   
+01136 }
+01137 
+01138 
+01139 
+01141 // implementation of CPSModulatedEmitter  //
+01143 
+01144 void CPSModulatedEmitter::serialEmitteeSpeedScheme(NLMISC::IStream &f) throw(NLMISC::EStream)
+01145 {
+01146         bool useScheme;                 
+01147         if (!f.isReading())
+01148         {
+01149                 useScheme = useEmitteeSpeedScheme();
+01150         }
+01151         f.serial(useScheme);
+01152         if (useScheme)
+01153         {
+01154                 f.serialPolyPtr(_EmitteeSpeedScheme);
+01155         }
+01156         else
+01157         {
+01158                 f.serial(_EmitteeSpeed);
+01159         }
+01160 }
+01161 
+01162 
+01163 
+01165 // implementation of CPSEmitterOmni               //
+01167 
+01169 void CPSEmitterOmni::emit(const NLMISC::CVector &srcPos, uint32 index, CVector &pos, CVector &speed)
+01170 {
+01171         // TODO : verifier que ca marche si une particule s'emet elle-mem
+01172         nlassert(_EmittedType); 
+01173         
+01174         CVector v( ((rand() % 1000) - 500) / 500.0f
+01175                                    , ((rand() % 1000) - 500) / 500.0f
+01176                                    , ((rand() % 1000) - 500) / 500.0f);
+01177         v.normalize();
+01178         v *= _EmitteeSpeedScheme ? _EmitteeSpeedScheme->get(_Owner, index) : _EmitteeSpeed;             
+01179 
+01180         pos = srcPos;
+01181         speed = v;      
+01182 }
+01183 
+01185 void CPSEmitterOmni::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+01186 {
+01187         f.serialVersion(1);     
+01188         CPSEmitter::serial(f);
+01189         CPSModulatedEmitter::serialEmitteeSpeedScheme(f);
+01190 }
+01191 
+01193 void CPSEmitterOmni::newElement(CPSLocated *emitter, uint32 emitterIndex)
+01194 {
+01195         CPSEmitter::newElement(emitter, emitterIndex);
+01196         newEmitteeSpeedElement(emitter, emitterIndex);
+01197 }
+01198 
+01200 void CPSEmitterOmni::deleteElement(uint32 index)
+01201 {       
+01202         CPSEmitter::deleteElement(index);
+01203         deleteEmitteeSpeedElement(index);
+01204 }
+01205 
+01207 void CPSEmitterOmni::resize(uint32 capacity)
+01208 {
+01209         nlassert(capacity < (1 << 16));
+01210         CPSEmitter::resize(capacity);
+01211         resizeEmitteeSpeed(capacity);
+01212 }
+01213 
+01215 void CPSEmitterDirectionnal::emit(const NLMISC::CVector &srcPos, uint32 index, CVector &pos, CVector &speed)
+01216 {
+01217         // TODO : verifier que ca marche si une particule s'emet elle-mem
+01218         nlassert(_EmittedType); 
+01219         
+01220 
+01221         speed = (_EmitteeSpeedScheme ? _EmitteeSpeedScheme->get(_Owner, index) : _EmitteeSpeed) * _Dir;         
+01222         pos = srcPos;   
+01223 }
+01224 
+01226 void CPSEmitterDirectionnal::newElement(CPSLocated *emitter, uint32 emitterIndex)
+01227 {
+01228         CPSEmitter::newElement(emitter, emitterIndex);
+01229         newEmitteeSpeedElement(emitter, emitterIndex);
+01230 }
+01231 
+01233 void CPSEmitterDirectionnal::deleteElement(uint32 index)
+01234 {       
+01235         CPSEmitter::deleteElement(index);
+01236         deleteEmitteeSpeedElement(index);
+01237 }
+01238 
+01240 void CPSEmitterDirectionnal::resize(uint32 capacity)
+01241 {
+01242         nlassert(capacity < (1 << 16));
+01243         CPSEmitter::resize(capacity);
+01244         resizeEmitteeSpeed(capacity);
+01245 }
+01246 
+01248 void CPSEmitterDirectionnal::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+01249 {
+01250         f.serialVersion(1);     
+01251         CPSEmitter::serial(f);
+01252         CPSModulatedEmitter::serialEmitteeSpeedScheme(f);
+01253         f.serial(_Dir);
+01254 }
+01255 
+01257 // implementation of CPSEmitterRectangle  //
+01259 
+01261 void CPSEmitterRectangle::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+01262 {
+01263         f.serialVersion(1);     
+01264         CPSEmitter::serial(f);
+01265         CPSModulatedEmitter::serialEmitteeSpeedScheme(f);
+01266         f.serial(_Basis);       
+01267         f.serial(_Width);
+01268         f.serial(_Height);
+01269         f.serial(_Dir);
+01270 
+01271 }
+01272 
+01274 void CPSEmitterRectangle::emit(const NLMISC::CVector &srcPos, uint32 index, CVector &pos, CVector &speed)
+01275 {
+01276         CVector N = _Basis[index].X ^ _Basis[index].Y;
+01277         pos = srcPos + ((rand() % 32000) * (1.f / 16000) - 1.f) *  _Width[index] *  _Basis[index].X 
+01278                                  + ((rand() % 32000) * (1.f / 16000) - 1.f) *  _Height[index] * _Basis[index].Y;
+01279         speed = (_EmitteeSpeedScheme ? _EmitteeSpeedScheme->get(_Owner, index) : _EmitteeSpeed) 
+01280                                         * (_Dir.x * _Basis[index].X+ _Dir.y * _Basis[index].Y + _Dir.z *  N);
+01281 }
+01282 
+01284 void CPSEmitterRectangle::setMatrix(uint32 index, const CMatrix &m)
+01285 {
+01286         _Owner->getPos()[index] = m.getPos();
+01287 
+01288         
+01289          _Basis[index].X = m.getI();
+01290          _Basis[index].Y = m.getJ();
+01291 }
+01292 
+01294 CMatrix CPSEmitterRectangle::getMatrix(uint32 index) const
+01295 {
+01296         CMatrix m;
+01297         m.setPos(_Owner->getPos()[index]);
+01298         m.setRot(_Basis[index].X, _Basis[index].Y, _Basis[index].X ^ _Basis[index].Y, true);
+01299         return m;
+01300 }
+01301 
+01303 void CPSEmitterRectangle::setScale(uint32 index, float scale)
+01304 {
+01305         _Width[index] = scale;
+01306         _Height[index] = scale;
+01307 }
+01308 
+01310 void CPSEmitterRectangle::setScale(uint32 index, const CVector &s)
+01311 {
+01312         _Width[index] = s.x;
+01313         _Height[index] = s.y;
+01314 }
+01315 
+01317 CVector CPSEmitterRectangle::getScale(uint32 index) const
+01318 {       
+01319         return CVector(_Width[index], _Height[index], 1.f); 
+01320 }
+01321 
+01323                 void CPSEmitterRectangle::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
+01324 {
+01325         CPSEmitter::newElement(emitterLocated, emitterIndex);
+01326         newEmitteeSpeedElement(emitterLocated, emitterIndex);
+01327         _Basis.insert(CPlaneBasis(CVector::K));
+01328         _Width.insert(1.f);
+01329         _Height.insert(1.f);
+01330 }
+01331 
+01333 void CPSEmitterRectangle::deleteElement(uint32 index)
+01334 {
+01335         CPSEmitter::deleteElement(index);
+01336         deleteEmitteeSpeedElement(index);
+01337         _Basis.remove(index);
+01338         _Width.remove(index);
+01339         _Height.remove(index);
+01340 }
+01341 
+01343 void CPSEmitterRectangle::resize(uint32 size)
+01344 {
+01345         nlassert(size < (1 << 16));
+01346         CPSEmitter::resize(size);
+01347         resizeEmitteeSpeed(size);
+01348         _Basis.resize(size);
+01349         _Width.resize(size);
+01350         _Height.resize(size);
+01351 }
+01352 
+01354 void CPSEmitterRectangle::showTool(void)
+01355 {
+01356         nlassert(_Owner);
+01357         const uint size = _Owner->getSize();
+01358         if (!size) return;
+01359         setupDriverModelMatrix();       
+01360         CMatrix mat;
+01361         
+01362         CPSLocated *loc;
+01363         uint32 index;
+01364         CPSLocatedBindable *lb;
+01365         _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
+01366 
+01367         for (uint k = 0; k < size; ++k) 
+01368         {       
+01369                 const CVector &I = _Basis[k].X;
+01370                 const CVector &J = _Basis[k].Y;
+01371                 mat.setRot(I, J , I ^J);
+01372                 mat.setPos(_Owner->getPos()[k]);
+01373                 CPSUtil::displayBasis(getDriver() ,getLocatedMat(), mat, 1.f, *getFontGenerator(), *getFontManager());                          
+01374                 setupDriverModelMatrix();       
+01375 
+01376                 const CRGBA col = ((lb == NULL || this == lb) && loc == _Owner && index == k  ? CRGBA::Red : CRGBA(127, 127, 127));
+01377         
+01378 
+01379 
+01380                 const CVector &pos = _Owner->getPos()[k];
+01381                 CPSUtil::display3DQuad(*getDriver(), pos + I * _Width[k] + J * _Height[k]
+01382                                                                                    , pos + I * _Width[k] - J * _Height[k]
+01383                                                                                    , pos - I * _Width[k] - J * _Height[k]
+01384                                                                                    , pos - I * _Width[k] + J * _Height[k], col);
+01385         }
+01386 }
+01387 
+01388 
+01389 
+01391 // CPSEmitterconic implementation //
+01393 
+01395 void CPSEmitterConic::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+01396 {
+01397         f.serialVersion(1);     
+01398         CPSEmitterDirectionnal::serial(f);
+01399         f.serial(_Radius);      
+01400 }
+01401         
+01403 void CPSEmitterConic::setDir(const CVector &v)
+01404 {
+01405         CPSEmitterDirectionnal::setDir(v);
+01406         
+01407 }
+01408 
+01410 void CPSEmitterConic::emit(const NLMISC::CVector &srcPos, uint32 index, CVector &pos, CVector &speed)
+01411 {
+01412         // TODO : optimize that
+01413         nlassert(_EmittedType); 
+01414         
+01415         // we choose a custom direction like with omnidirectionnal emitter
+01416         // then we force the direction vect to have the unit size
+01417 
+01418         static const double divRand = (2.0 / RAND_MAX);
+01419 
+01420         CVector dir((float) (rand() * divRand - 1)
+01421                                 , (float) (rand() * divRand - 1)
+01422                                 , (float) (rand() * divRand - 1) );
+01423 
+01424         const float n =dir.norm();
+01425 
+01426         dir *= _Radius / n;
+01427 
+01428         dir -= (_Dir * dir) * _Dir;
+01429         dir += _Dir;
+01430         dir.normalize();
+01431         
+01432         
+01433         speed = (_EmitteeSpeedScheme ? _EmitteeSpeedScheme->get(_Owner, index) : _EmitteeSpeed) 
+01434                     * dir;
+01435         pos = srcPos;   
+01436 }
+01437 
+01439 // CPSSphericalEmitter implementation //
+01441 
+01443 void CPSSphericalEmitter::emit(const NLMISC::CVector &srcPos, uint32 index, CVector &pos, CVector &speed)
+01444 {
+01445         static const double divRand = (2.0 / RAND_MAX);
+01446         CVector dir((float) (rand() * divRand - 1), (float) (rand() * divRand - 1) , (float) (rand() * divRand - 1) );
+01447         dir.normalize();
+01448         pos = srcPos + _Radius[index] * dir;
+01449         speed = (_EmitteeSpeedScheme ? _EmitteeSpeedScheme->get(_Owner, index) : _EmitteeSpeed)  * dir; 
+01450 }
+01451 
+01452 
+01454 void CPSSphericalEmitter::showTool(void)
+01455 {
+01456         CPSLocated *loc;
+01457         uint32 index;
+01458         CPSLocatedBindable *lb;
+01459         _Owner->getOwner()->getCurrentEditedElement(loc, index, lb);
+01460 
+01461 
+01462         TPSAttribFloat::const_iterator radiusIt = _Radius.begin();
+01463         TPSAttribVector::const_iterator posIt = _Owner->getPos().begin(), endPosIt = _Owner->getPos().end();
+01464         setupDriverModelMatrix();       
+01465         for (uint k = 0; posIt != endPosIt; ++posIt, ++radiusIt, ++k) 
+01466         {       
+01467                 const CRGBA col = ((lb == NULL || this == lb) && loc == _Owner && index == k  ? CRGBA::Red : CRGBA(127, 127, 127));             
+01468                 CPSUtil::displaySphere(*getDriver(), *radiusIt, *posIt, 5, col);
+01469         }
+01470 }
+01471 
+01472 
+01474 void CPSSphericalEmitter::setMatrix(uint32 index, const CMatrix &m)
+01475 {
+01476         nlassert(index < _Radius.getSize());            
+01477         // compute new pos
+01478         _Owner->getPos()[index] = m.getPos();
+01479         
+01480 }
+01481 
+01483 CMatrix CPSSphericalEmitter::getMatrix(uint32 index) const
+01484 {
+01485         nlassert(index < _Radius.getSize());
+01486         CMatrix m;
+01487         m.identity();
+01488         m.translate(_Owner->getPos()[index]);   
+01489         return m; 
+01490 }
+01491                 
+01493 void CPSSphericalEmitter::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+01494 {
+01495         f.serialVersion(1);     
+01496         CPSEmitter::serial(f);
+01497         CPSModulatedEmitter::serialEmitteeSpeedScheme(f);
+01498         f.serial(_Radius);
+01499 }
+01500                 
+01502 void CPSSphericalEmitter::newElement(CPSLocated *emitterLocated, uint32 emitterIndex)
+01503 {
+01504         CPSEmitter::newElement(emitterLocated, emitterIndex);
+01505         newEmitteeSpeedElement(emitterLocated, emitterIndex);   
+01506         _Radius.insert(1.f);
+01507 }
+01508 
+01510 void CPSSphericalEmitter::deleteElement(uint32 index)
+01511 {
+01512         CPSEmitter::deleteElement(index);
+01513         deleteEmitteeSpeedElement(index);       
+01514         _Radius.remove(index);
+01515 }
+01516 
+01518 void CPSSphericalEmitter::resize(uint32 size)
+01519 {
+01520         nlassert(size < (1 << 16));
+01521         CPSEmitter::resize(size);
+01522         resizeEmitteeSpeed(size);       
+01523         _Radius.resize(size);
+01524 }
+01525 
+01527 // CPSRadialEmitter implementation //
+01529 
+01531 void CPSRadialEmitter::serial(NLMISC::IStream &f) throw(NLMISC::EStream)
+01532 {
+01533         f.serialVersion(1);
+01534         CPSEmitterDirectionnal::serial(f);
+01535 }
+01536 
+01538 void CPSRadialEmitter::emit(const NLMISC::CVector &srcPos, uint32 index, NLMISC::CVector &pos, NLMISC::CVector &speed)
+01539 {
+01540         // TODO : verifier que ca marche si une particule s'emet elle-mem
+01541         nlassert(_EmittedType); 
+01542 
+01543         static const double divRand = (2.0 / RAND_MAX);
+01544         CVector dir((float) (rand() * divRand - 1)
+01545                                 , (float) (rand() * divRand - 1)
+01546                                 , (float) (rand() * divRand - 1) );
+01547         dir -= (dir * _Dir) * _Dir; //keep tangential direction
+01548         dir.normalize();
+01549         
+01550         speed = (_EmitteeSpeedScheme ? _EmitteeSpeedScheme->get(_Owner, index) : _EmitteeSpeed) * dir;          
+01551         pos = srcPos;
+01552 }
+01553 
+01554 
+01555 
+01556 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1