particle_system_manager.cpp

Go to the documentation of this file.
00001 
00007 /* Copyright, 2000 - 2002 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 "3d/particle_system_manager.h"
00029 #include "3d/particle_system_model.h"
00030 #include "3d/scene.h"
00031 #include "3d/skeleton_model.h"
00032 
00033 
00034 namespace NL3D {
00035 
00036 
00037 CParticleSystemManager::TManagerList     &CParticleSystemManager::getManagerList()
00038 {       
00039         static TManagerList *manager = NULL;
00040         if (manager == NULL)
00041         {
00042                 manager = new TManagerList;             
00043         }
00044         return *manager;
00045 }
00046 
00047 
00048 
00049 
00051 CParticleSystemManager::CParticleSystemManager() : _NumModels(0)
00052 {
00053         _CurrListIterator = _ModelList.end();
00054         getManagerList().push_front(this);
00055         _GlobalListHandle = getManagerList().begin();   
00056 }
00057 
00059 CParticleSystemManager::~CParticleSystemManager()
00060 {
00061         // remove from global list
00062         getManagerList().erase(_GlobalListHandle);      
00063 }
00064 
00066 void    CParticleSystemManager::refreshModels(const std::vector<NLMISC::CPlane> &worldFrustumPyramid,  const NLMISC::CVector &viewerPos)
00067 {       
00068         #ifdef NL_DEBUG
00069                 nlassert(_NumModels == _ModelList.size());
00070         #endif
00071 
00072         if (_NumModels == 0) return;
00073         const uint toProcess = std::min(_NumModels, (uint) NumProcessToRefresh);        
00074         TModelList::iterator nextIt;
00075         for (uint k = 0; k < toProcess; ++k)
00076         {
00077                 if (_CurrListIterator == _ModelList.end())
00078                 {
00079                         _CurrListIterator = _ModelList.begin();
00080                 }
00081                 nextIt = _CurrListIterator;
00082                 ++ nextIt;
00083                 (*_CurrListIterator)->refreshRscDeletion(worldFrustumPyramid, viewerPos);
00084                 _CurrListIterator = nextIt;
00085                 if (_NumModels == 0) break;             
00086         }
00087 
00088         #ifdef NL_DEBUG
00089                 nlassert(_NumModels == _ModelList.size());
00090         #endif
00091 }
00092 
00094 CParticleSystemManager::TModelHandle CParticleSystemManager::addSystemModel(CParticleSystemModel *model)
00095 {
00096         #ifdef NL_DEBUG
00097                 nlassert(std::find(_ModelList.begin(), _ModelList.end(), model) == _ModelList.end()); 
00098         #endif
00099         _ModelList.push_front(model);
00100         ++_NumModels;
00101 
00102         #ifdef NL_DEBUG
00103                 nlassert(_NumModels == _ModelList.size());
00104         #endif
00105 
00106         TModelHandle handle;
00107         handle.Valid = true;
00108         handle.Iter = _ModelList.begin();
00109         return handle;
00110 }
00111 
00112 
00114 void            CParticleSystemManager::removeSystemModel(TModelHandle &handle)
00115 {       
00116         nlassert(handle.Valid);
00117         #ifdef NL_DEBUG
00118                 nlassert(_NumModels == _ModelList.size());
00119         #endif
00120         nlassert(_NumModels != 0);      
00121         if (handle.Iter == _CurrListIterator)
00122         {
00123                 ++_CurrListIterator;            
00124         }
00125 
00126         _ModelList.erase(handle.Iter);
00127         --_NumModels;
00128         handle.Valid = false;
00129         #ifdef NL_DEBUG
00130                 nlassert(_NumModels == _ModelList.size());
00131         #endif
00132 }
00133 
00134 
00136 CParticleSystemManager::TAlwaysAnimatedModelHandle      CParticleSystemManager::addPermanentlyAnimatedSystem(CParticleSystemModel *ps)
00137 {
00138         #ifdef NL_DEBUG
00139                 for(TAlwaysAnimatedModelList::iterator it = _PermanentlyAnimatedModelList.begin(); it != _PermanentlyAnimatedModelList.end(); ++it)
00140                 {  
00141                         nlassert(it->Model != ps);
00142                 }               
00143         #endif
00144         CAlwaysAnimatedPS aaps;
00145         aaps.Model = ps;
00146         aaps.HasAncestorSkeleton = false; // even if there's an ancestor skeleton yet, force the manager to recompute relative pos of the system when clipped           
00147         _PermanentlyAnimatedModelList.push_front(aaps);
00148 
00149 
00150         TAlwaysAnimatedModelHandle handle;
00151         handle.Valid = true;
00152         handle.Iter = _PermanentlyAnimatedModelList.begin();
00153         return handle;  
00154 }
00155 
00157 void                    CParticleSystemManager::removePermanentlyAnimatedSystem(CParticleSystemManager::TAlwaysAnimatedModelHandle &handle)
00158 {
00159         nlassert(handle.Valid);
00160         _PermanentlyAnimatedModelList.erase(handle.Iter);       
00161         handle.Valid = false;
00162 }
00163 
00165 void    CParticleSystemManager::processAnimate(TAnimationTime deltaT)
00166 {
00167         for (TAlwaysAnimatedModelList::iterator it = _PermanentlyAnimatedModelList.begin(); it != _PermanentlyAnimatedModelList.end();)
00168         {
00169                 CParticleSystemModel &psm = *(it->Model);
00170                 CParticleSystem          *ps  = psm.getPS();
00171                 TAlwaysAnimatedModelList::iterator nextIt = it;
00172                 nextIt++;
00173                 if (ps)
00174                 {
00175                         // test if already auto-animated
00176                         if (ps->getAnimType() != CParticleSystem::AnimAlways)
00177                         {
00178                                 psm.invalidateAutoAnimatedHandle();
00179                                 it = _PermanentlyAnimatedModelList.erase(it);
00180                                 continue;
00181                         }
00182                         // special case for sticked fxs :
00183                         // When a fx is sticked as a son of a skeleton model, the skeleton matrix is not updated 
00184                         // when the skeleton is not visible (clipped)
00185                         // This is a concern when fx generate trails because when the skeleton becomes visible again,
00186                         // a trail will appear between the previous visible pos and the new visible pos
00187                         // to solve this :
00188                         // When the ancestor skeleton is visible, we backup the relative position to the ancestor skeleton.
00189                         //                      - if it is not visible at start, we must evaluate the position of the stick point anyway
00190                         // When the father skeleton is clipped, we use the relative position                                    
00191                         if (psm.getAncestorSkeletonModel())
00192                         {               
00193                                 if(psm.getAncestorSkeletonModel()->getVisibility() != CHrcTrav::Hide) // matrix of ancestor is irrelevant if the system is hidden (because sticked to hidden parent for example)
00194                                 {                               
00195                                         if (!psm.isClipVisible()) // the system may not be visible because of clod
00196                                         {                                                                                       
00197                                                 if (!it->IsRelMatrix) // relative matrix already computed ?
00198                                                 {
00199                                                         if (!it->HasAncestorSkeleton)
00200                                                         {
00201                                                                 psm.forceCompute();
00202                                                         }
00203                                                         it->OldAncestorMatOrRelPos = it->OldAncestorMatOrRelPos.inverted() * psm.getWorldMatrix();
00204                                                         it->IsRelMatrix = true;
00205                                                 }                                       
00206                                                 psm.setWorldMatrix(psm.getAncestorSkeletonModel()->getWorldMatrix() * it->OldAncestorMatOrRelPos);                                      
00207                                         }
00208                                         else
00209                                         {
00210                                                 // backup ancestor position matrix relative to the ancestor skeleton
00211                                                 it->HasAncestorSkeleton = true;
00212                                                 it->OldAncestorMatOrRelPos = psm.getAncestorSkeletonModel()->getWorldMatrix();
00213                                                 it->IsRelMatrix = false;                                        
00214                                         }
00215                                 }
00216                         }                       
00217                         psm.doAnimate();
00218                         if (!psm.getEditionMode())
00219                         {                       
00220                                 // test deletion condition (no more particle, no more particle and emitters)
00221                                 if (ps->isDestroyConditionVerified())
00222                                 {                               
00223                                         psm.releaseRscAndInvalidate();
00224                                 }                               
00225                         }
00226 
00227                 }
00228                 it = nextIt;
00229         }
00230 }
00231 
00233 void CParticleSystemManager::stopSound()
00234 {
00235         for(TModelList::iterator it = _ModelList.begin(); it != _ModelList.end(); ++it)
00236         {
00237                 CParticleSystemModel &psm = *(*it);
00238                 CParticleSystem          *ps  = psm.getPS();
00239                 if (ps)
00240                 {
00241                         ps->stopSound();
00242                 }
00243         }
00244 }
00245 
00247 void CParticleSystemManager::reactivateSound()
00248 {
00249         for(TModelList::iterator it = _ModelList.begin(); it != _ModelList.end(); ++it)
00250         {
00251                 CParticleSystemModel &psm = *(*it);
00252                 CParticleSystem          *ps  = psm.getPS();
00253                 if (ps)
00254                 {
00255                         ps->reactivateSound();
00256                 }
00257         }
00258 }
00259 
00261 void CParticleSystemManager::stopSoundForAllManagers()
00262 {
00263         for(TManagerList::iterator it = getManagerList().begin(); it != getManagerList().end(); ++it)
00264         {
00265                 nlassert(*it);
00266                 (*it)->stopSound();
00267         }
00268 }
00269 
00271 void CParticleSystemManager::reactivateSoundForAllManagers()
00272 {
00273         for(TManagerList::iterator it = getManagerList().begin(); it != getManagerList().end(); ++it)
00274         {
00275                 nlassert(*it);
00276                 (*it)->reactivateSound();
00277         }
00278 }
00279 
00280 
00281 
00282 } // NL3D
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 

Generated on Tue Mar 16 06:30:53 2004 for NeL by doxygen 1.3.6