1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "nel/3d/particle_system_manager.h"
20 #include "nel/3d/particle_system_model.h"
21 #include "nel/3d/scene.h"
22 #include "nel/3d/skeleton_model.h"
31 CParticleSystemManager::TManagerList
*CParticleSystemManager::ManagerList
= NULL
;
33 CParticleSystemManager::TManagerList
&CParticleSystemManager::getManagerList()
35 if (ManagerList
== NULL
)
37 ManagerList
= new TManagerList
;
44 void CParticleSystemManager::release()
51 ///=========================================================
52 CParticleSystemManager::CParticleSystemManager() : _NumModels(0)
54 NL_PS_FUNC(CParticleSystemManager_CParticleSystemManager
)
55 _CurrListIterator
= _ModelList
.end();
56 getManagerList().push_front(this);
57 _GlobalListHandle
= getManagerList().begin();
60 ///=========================================================
61 CParticleSystemManager::~CParticleSystemManager()
63 NL_PS_FUNC(CParticleSystemManager_CParticleSystemManagerDtor
)
64 // remove from global list
65 getManagerList().erase(_GlobalListHandle
);
68 ///=========================================================
69 void CParticleSystemManager::refreshModels(const std::vector
<NLMISC::CPlane
> &worldFrustumPyramid
, const NLMISC::CVector
&viewerPos
)
71 NL_PS_FUNC(CParticleSystemManager_refreshModels
)
73 nlassert(_NumModels
== _ModelList
.size());
76 if (_NumModels
== 0) return;
77 const uint toProcess
= std::min(_NumModels
, (uint
) NumProcessToRefresh
);
78 TModelList::iterator nextIt
;
79 for (uint k
= 0; k
< toProcess
; ++k
)
81 if (_CurrListIterator
== _ModelList
.end())
83 _CurrListIterator
= _ModelList
.begin();
84 nlassert(_CurrListIterator
!=_ModelList
.end());
86 nextIt
= _CurrListIterator
;
88 (*_CurrListIterator
)->refreshRscDeletion(worldFrustumPyramid
, viewerPos
);
89 _CurrListIterator
= nextIt
;
90 if (_NumModels
== 0) break;
94 nlassert(_NumModels
== _ModelList
.size());
98 ///=========================================================
99 CParticleSystemManager::TModelHandle
CParticleSystemManager::addSystemModel(CParticleSystemModel
*model
)
101 NL_PS_FUNC(CParticleSystemManager_addSystemModel
)
103 nlassert(std::find(_ModelList
.begin(), _ModelList
.end(), model
) == _ModelList
.end());
105 _ModelList
.push_front(model
);
109 nlassert(_NumModels
== _ModelList
.size());
114 handle
.Iter
= _ModelList
.begin();
119 ///=========================================================
120 void CParticleSystemManager::removeSystemModel(TModelHandle
&handle
)
122 NL_PS_FUNC(CParticleSystem_removeSystemModel
)
123 nlassert(handle
.Valid
);
125 nlassert(_NumModels
== _ModelList
.size());
127 nlassert(_NumModels
!= 0);
128 if (handle
.Iter
== _CurrListIterator
)
133 _ModelList
.erase(handle
.Iter
);
135 handle
.Valid
= false;
137 nlassert(_NumModels
== _ModelList
.size());
142 ///=========================================================
143 CParticleSystemManager::TAlwaysAnimatedModelHandle
CParticleSystemManager::addPermanentlyAnimatedSystem(CParticleSystemModel
*ps
)
145 NL_PS_FUNC(CParticleSystemManager_addPermanentlyAnimatedSystem
)
147 for(TAlwaysAnimatedModelList::iterator it
= _PermanentlyAnimatedModelList
.begin(); it
!= _PermanentlyAnimatedModelList
.end(); ++it
)
149 nlassert(it
->Model
!= ps
);
152 CAlwaysAnimatedPS aaps
;
154 aaps
.HasAncestorSkeleton
= false; // even if there's an ancestor skeleton yet, force the manager to recompute relative pos of the system when clipped
155 _PermanentlyAnimatedModelList
.push_front(aaps
);
158 TAlwaysAnimatedModelHandle handle
;
160 handle
.Iter
= _PermanentlyAnimatedModelList
.begin();
164 ///=========================================================
165 void CParticleSystemManager::removePermanentlyAnimatedSystem(CParticleSystemManager::TAlwaysAnimatedModelHandle
&handle
)
167 NL_PS_FUNC(CParticleSystemManager_removePermanentlyAnimatedSystem
)
168 nlassert(handle
.Valid
);
169 _PermanentlyAnimatedModelList
.erase(handle
.Iter
);
170 handle
.Valid
= false;
173 ///=========================================================
174 void CParticleSystemManager::processAnimate(TAnimationTime deltaT
)
176 NL_PS_FUNC(CParticleSystemManager_processAnimate
)
177 for (TAlwaysAnimatedModelList::iterator it
= _PermanentlyAnimatedModelList
.begin(); it
!= _PermanentlyAnimatedModelList
.end();)
179 CParticleSystemModel
&psm
= *(it
->Model
);
180 CParticleSystem
*ps
= psm
.getPS();
181 TAlwaysAnimatedModelList::iterator nextIt
= it
;
185 // test if already auto-animated
186 if (ps
->getAnimType() != CParticleSystem::AnimAlways
)
188 psm
.invalidateAutoAnimatedHandle();
189 it
= _PermanentlyAnimatedModelList
.erase(it
);
192 // special case for sticked fxs :
193 // When a fx is sticked as a son of a skeleton model, the skeleton matrix is not updated
194 // when the skeleton is not visible (clipped)
195 // This is a concern when fx generate trails because when the skeleton becomes visible again,
196 // a trail will appear between the previous visible pos and the new visible pos
198 // When the ancestor skeleton is visible, we backup the relative position to the ancestor skeleton.
199 // - if it is not visible at start, we must evaluate the position of the stick point anyway
200 // When the father skeleton is clipped, we use the relative position
201 if (psm
.getAncestorSkeletonModel())
203 if(psm
.getAncestorSkeletonModel()->getVisibility() != CHrcTrav::Hide
) // matrix of ancestor is irrelevant if the system is hidden (because sticked to hidden parent for example)
205 if (!psm
.isClipVisible()) // the system may not be visible because of clod
207 if (!it
->IsRelMatrix
) // relative matrix already computed ?
209 if (!it
->HasAncestorSkeleton
)
213 it
->OldAncestorMatOrRelPos
= it
->OldAncestorMatOrRelPos
.inverted() * psm
.getWorldMatrix();
214 it
->IsRelMatrix
= true;
216 psm
.setWorldMatrix(psm
.getAncestorSkeletonModel()->getWorldMatrix() * it
->OldAncestorMatOrRelPos
);
220 // backup ancestor position matrix relative to the ancestor skeleton
221 it
->HasAncestorSkeleton
= true;
222 it
->OldAncestorMatOrRelPos
= psm
.getAncestorSkeletonModel()->getWorldMatrix();
223 it
->IsRelMatrix
= false;
228 if (!psm
.getEditionMode())
230 // test deletion condition (no more particle, no more particle and emitters)
231 if (ps
->isDestroyConditionVerified())
233 psm
.releaseRscAndInvalidate();
242 ///=========================================================
243 void CParticleSystemManager::stopSound()
245 NL_PS_FUNC(CParticleSystemManager_stopSound
)
246 for(TModelList::iterator it
= _ModelList
.begin(); it
!= _ModelList
.end(); ++it
)
248 CParticleSystemModel
&psm
= *(*it
);
249 CParticleSystem
*ps
= psm
.getPS();
257 ///=========================================================
258 void CParticleSystemManager::reactivateSound()
260 NL_PS_FUNC(CParticleSystemManager_reactivateSound
)
261 for(TModelList::iterator it
= _ModelList
.begin(); it
!= _ModelList
.end(); ++it
)
263 CParticleSystemModel
&psm
= *(*it
);
264 CParticleSystem
*ps
= psm
.getPS();
267 ps
->reactivateSound();
272 ///=========================================================
273 void CParticleSystemManager::stopSoundForAllManagers()
275 NL_PS_FUNC(CParticleSystemManager_stopSoundForAllManagers
)
276 for(TManagerList::iterator it
= getManagerList().begin(); it
!= getManagerList().end(); ++it
)
283 ///=========================================================
284 void CParticleSystemManager::reactivateSoundForAllManagers()
286 NL_PS_FUNC(CParticleSystemManager_reactivateSoundForAllManagers
)
287 for(TManagerList::iterator it
= getManagerList().begin(); it
!= getManagerList().end(); ++it
)
290 (*it
)->reactivateSound();