Merge branch 'main/rendor-staging' into fixes
[ryzomcore.git] / nel / src / 3d / particle_system_manager.cpp
blob5778b289814e8d51d5d3a1ef91de3f920f3043bd
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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.
8 //
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/>.
17 #include "std3d.h"
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"
24 #ifdef DEBUG_NEW
25 #define new DEBUG_NEW
26 #endif
28 namespace NL3D
31 CParticleSystemManager::TManagerList *CParticleSystemManager::ManagerList = NULL;
33 CParticleSystemManager::TManagerList &CParticleSystemManager::getManagerList()
35 if (ManagerList == NULL)
37 ManagerList = new TManagerList;
39 return *ManagerList;
43 // release memory
44 void CParticleSystemManager::release()
46 if( ManagerList )
47 delete ManagerList;
48 ManagerList = NULL;
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)
72 #ifdef NL_DEBUG
73 nlassert(_NumModels == _ModelList.size());
74 #endif
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;
87 ++ nextIt;
88 (*_CurrListIterator)->refreshRscDeletion(worldFrustumPyramid, viewerPos);
89 _CurrListIterator = nextIt;
90 if (_NumModels == 0) break;
93 #ifdef NL_DEBUG
94 nlassert(_NumModels == _ModelList.size());
95 #endif
98 ///=========================================================
99 CParticleSystemManager::TModelHandle CParticleSystemManager::addSystemModel(CParticleSystemModel *model)
101 NL_PS_FUNC(CParticleSystemManager_addSystemModel)
102 #ifdef NL_DEBUG
103 nlassert(std::find(_ModelList.begin(), _ModelList.end(), model) == _ModelList.end());
104 #endif
105 _ModelList.push_front(model);
106 ++_NumModels;
108 #ifdef NL_DEBUG
109 nlassert(_NumModels == _ModelList.size());
110 #endif
112 TModelHandle handle;
113 handle.Valid = true;
114 handle.Iter = _ModelList.begin();
115 return handle;
119 ///=========================================================
120 void CParticleSystemManager::removeSystemModel(TModelHandle &handle)
122 NL_PS_FUNC(CParticleSystem_removeSystemModel)
123 nlassert(handle.Valid);
124 #ifdef NL_DEBUG
125 nlassert(_NumModels == _ModelList.size());
126 #endif
127 nlassert(_NumModels != 0);
128 if (handle.Iter == _CurrListIterator)
130 ++_CurrListIterator;
133 _ModelList.erase(handle.Iter);
134 --_NumModels;
135 handle.Valid = false;
136 #ifdef NL_DEBUG
137 nlassert(_NumModels == _ModelList.size());
138 #endif
142 ///=========================================================
143 CParticleSystemManager::TAlwaysAnimatedModelHandle CParticleSystemManager::addPermanentlyAnimatedSystem(CParticleSystemModel *ps)
145 NL_PS_FUNC(CParticleSystemManager_addPermanentlyAnimatedSystem)
146 #ifdef NL_DEBUG
147 for(TAlwaysAnimatedModelList::iterator it = _PermanentlyAnimatedModelList.begin(); it != _PermanentlyAnimatedModelList.end(); ++it)
149 nlassert(it->Model != ps);
151 #endif
152 CAlwaysAnimatedPS aaps;
153 aaps.Model = ps;
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;
159 handle.Valid = true;
160 handle.Iter = _PermanentlyAnimatedModelList.begin();
161 return handle;
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;
182 nextIt++;
183 if (ps)
185 // test if already auto-animated
186 if (ps->getAnimType() != CParticleSystem::AnimAlways)
188 psm.invalidateAutoAnimatedHandle();
189 it = _PermanentlyAnimatedModelList.erase(it);
190 continue;
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
197 // to solve this :
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)
211 psm.forceCompute();
213 it->OldAncestorMatOrRelPos = it->OldAncestorMatOrRelPos.inverted() * psm.getWorldMatrix();
214 it->IsRelMatrix = true;
216 psm.setWorldMatrix(psm.getAncestorSkeletonModel()->getWorldMatrix() * it->OldAncestorMatOrRelPos);
218 else
220 // backup ancestor position matrix relative to the ancestor skeleton
221 it->HasAncestorSkeleton = true;
222 it->OldAncestorMatOrRelPos = psm.getAncestorSkeletonModel()->getWorldMatrix();
223 it->IsRelMatrix = false;
227 psm.doAnimate();
228 if (!psm.getEditionMode())
230 // test deletion condition (no more particle, no more particle and emitters)
231 if (ps->isDestroyConditionVerified())
233 psm.releaseRscAndInvalidate();
238 it = nextIt;
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();
250 if (ps)
252 ps->stopSound();
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();
265 if (ps)
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)
278 nlassert(*it);
279 (*it)->stopSound();
283 ///=========================================================
284 void CParticleSystemManager::reactivateSoundForAllManagers()
286 NL_PS_FUNC(CParticleSystemManager_reactivateSoundForAllManagers)
287 for(TManagerList::iterator it = getManagerList().begin(); it != getManagerList().end(); ++it)
289 nlassert(*it);
290 (*it)->reactivateSound();
294 } // NL3D