2012-05-29 13:31:11 +00:00
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
# include "std3d.h"
# include "nel/3d/particle_system_manager.h"
# include "nel/3d/particle_system_model.h"
# include "nel/3d/scene.h"
# include "nel/3d/skeleton_model.h"
namespace NL3D
{
CParticleSystemManager : : TManagerList * CParticleSystemManager : : ManagerList = NULL ;
CParticleSystemManager : : TManagerList & CParticleSystemManager : : getManagerList ( )
{
if ( ManagerList = = NULL )
{
ManagerList = new TManagerList ;
}
return * ManagerList ;
}
// release memory
void CParticleSystemManager : : release ( )
{
if ( ManagerList )
delete ManagerList ;
ManagerList = NULL ;
}
///=========================================================
CParticleSystemManager : : CParticleSystemManager ( ) : _NumModels ( 0 )
{
NL_PS_FUNC ( CParticleSystemManager_CParticleSystemManager )
_CurrListIterator = _ModelList . end ( ) ;
getManagerList ( ) . push_front ( this ) ;
_GlobalListHandle = getManagerList ( ) . begin ( ) ;
}
///=========================================================
CParticleSystemManager : : ~ CParticleSystemManager ( )
{
NL_PS_FUNC ( CParticleSystemManager_CParticleSystemManagerDtor )
// remove from global list
getManagerList ( ) . erase ( _GlobalListHandle ) ;
}
///=========================================================
void CParticleSystemManager : : refreshModels ( const std : : vector < NLMISC : : CPlane > & worldFrustumPyramid , const NLMISC : : CVector & viewerPos )
{
NL_PS_FUNC ( CParticleSystemManager_refreshModels )
# ifdef NL_DEBUG
nlassert ( _NumModels = = _ModelList . size ( ) ) ;
# endif
if ( _NumModels = = 0 ) return ;
const uint toProcess = std : : min ( _NumModels , ( uint ) NumProcessToRefresh ) ;
TModelList : : iterator nextIt ;
for ( uint k = 0 ; k < toProcess ; + + k )
{
if ( _CurrListIterator = = _ModelList . end ( ) )
{
_CurrListIterator = _ModelList . begin ( ) ;
nlassert ( _CurrListIterator ! = _ModelList . end ( ) ) ;
}
nextIt = _CurrListIterator ;
+ + nextIt ;
( * _CurrListIterator ) - > refreshRscDeletion ( worldFrustumPyramid , viewerPos ) ;
_CurrListIterator = nextIt ;
if ( _NumModels = = 0 ) break ;
}
# ifdef NL_DEBUG
nlassert ( _NumModels = = _ModelList . size ( ) ) ;
# endif
}
///=========================================================
CParticleSystemManager : : TModelHandle CParticleSystemManager : : addSystemModel ( CParticleSystemModel * model )
{
NL_PS_FUNC ( CParticleSystemManager_addSystemModel )
# ifdef NL_DEBUG
nlassert ( std : : find ( _ModelList . begin ( ) , _ModelList . end ( ) , model ) = = _ModelList . end ( ) ) ;
# endif
_ModelList . push_front ( model ) ;
+ + _NumModels ;
# ifdef NL_DEBUG
nlassert ( _NumModels = = _ModelList . size ( ) ) ;
# endif
TModelHandle handle ;
handle . Valid = true ;
handle . Iter = _ModelList . begin ( ) ;
return handle ;
}
///=========================================================
void CParticleSystemManager : : removeSystemModel ( TModelHandle & handle )
{
NL_PS_FUNC ( CParticleSystem_removeSystemModel )
nlassert ( handle . Valid ) ;
# ifdef NL_DEBUG
nlassert ( _NumModels = = _ModelList . size ( ) ) ;
# endif
nlassert ( _NumModels ! = 0 ) ;
if ( handle . Iter = = _CurrListIterator )
{
+ + _CurrListIterator ;
}
_ModelList . erase ( handle . Iter ) ;
- - _NumModels ;
handle . Valid = false ;
# ifdef NL_DEBUG
nlassert ( _NumModels = = _ModelList . size ( ) ) ;
# endif
}
///=========================================================
CParticleSystemManager : : TAlwaysAnimatedModelHandle CParticleSystemManager : : addPermanentlyAnimatedSystem ( CParticleSystemModel * ps )
{
NL_PS_FUNC ( CParticleSystemManager_addPermanentlyAnimatedSystem )
# ifdef NL_DEBUG
for ( TAlwaysAnimatedModelList : : iterator it = _PermanentlyAnimatedModelList . begin ( ) ; it ! = _PermanentlyAnimatedModelList . end ( ) ; + + it )
{
nlassert ( it - > Model ! = ps ) ;
}
# endif
CAlwaysAnimatedPS aaps ;
aaps . Model = ps ;
aaps . HasAncestorSkeleton = false ; // even if there's an ancestor skeleton yet, force the manager to recompute relative pos of the system when clipped
_PermanentlyAnimatedModelList . push_front ( aaps ) ;
TAlwaysAnimatedModelHandle handle ;
handle . Valid = true ;
handle . Iter = _PermanentlyAnimatedModelList . begin ( ) ;
return handle ;
}
///=========================================================
void CParticleSystemManager : : removePermanentlyAnimatedSystem ( CParticleSystemManager : : TAlwaysAnimatedModelHandle & handle )
{
NL_PS_FUNC ( CParticleSystemManager_removePermanentlyAnimatedSystem )
nlassert ( handle . Valid ) ;
_PermanentlyAnimatedModelList . erase ( handle . Iter ) ;
handle . Valid = false ;
}
///=========================================================
void CParticleSystemManager : : processAnimate ( TAnimationTime deltaT )
{
NL_PS_FUNC ( CParticleSystemManager_processAnimate )
for ( TAlwaysAnimatedModelList : : iterator it = _PermanentlyAnimatedModelList . begin ( ) ; it ! = _PermanentlyAnimatedModelList . end ( ) ; )
{
CParticleSystemModel & psm = * ( it - > Model ) ;
CParticleSystem * ps = psm . getPS ( ) ;
TAlwaysAnimatedModelList : : iterator nextIt = it ;
nextIt + + ;
if ( ps )
{
// test if already auto-animated
if ( ps - > getAnimType ( ) ! = CParticleSystem : : AnimAlways )
{
psm . invalidateAutoAnimatedHandle ( ) ;
it = _PermanentlyAnimatedModelList . erase ( it ) ;
continue ;
}
// special case for sticked fxs :
// When a fx is sticked as a son of a skeleton model, the skeleton matrix is not updated
// when the skeleton is not visible (clipped)
// This is a concern when fx generate trails because when the skeleton becomes visible again,
// a trail will appear between the previous visible pos and the new visible pos
// to solve this :
// When the ancestor skeleton is visible, we backup the relative position to the ancestor skeleton.
// - if it is not visible at start, we must evaluate the position of the stick point anyway
// When the father skeleton is clipped, we use the relative position
if ( psm . getAncestorSkeletonModel ( ) )
{
if ( psm . getAncestorSkeletonModel ( ) - > getVisibility ( ) ! = CHrcTrav : : Hide ) // matrix of ancestor is irrelevant if the system is hidden (because sticked to hidden parent for example)
{
if ( ! psm . isClipVisible ( ) ) // the system may not be visible because of clod
{
if ( ! it - > IsRelMatrix ) // relative matrix already computed ?
{
if ( ! it - > HasAncestorSkeleton )
{
psm . forceCompute ( ) ;
}
it - > OldAncestorMatOrRelPos = it - > OldAncestorMatOrRelPos . inverted ( ) * psm . getWorldMatrix ( ) ;
it - > IsRelMatrix = true ;
}
psm . setWorldMatrix ( psm . getAncestorSkeletonModel ( ) - > getWorldMatrix ( ) * it - > OldAncestorMatOrRelPos ) ;
}
else
{
// backup ancestor position matrix relative to the ancestor skeleton
it - > HasAncestorSkeleton = true ;
it - > OldAncestorMatOrRelPos = psm . getAncestorSkeletonModel ( ) - > getWorldMatrix ( ) ;
it - > IsRelMatrix = false ;
}
}
}
psm . doAnimate ( ) ;
if ( ! psm . getEditionMode ( ) )
{
// test deletion condition (no more particle, no more particle and emitters)
if ( ps - > isDestroyConditionVerified ( ) )
{
psm . releaseRscAndInvalidate ( ) ;
}
}
}
it = nextIt ;
}
}
///=========================================================
void CParticleSystemManager : : stopSound ( )
{
NL_PS_FUNC ( CParticleSystemManager_stopSound )
for ( TModelList : : iterator it = _ModelList . begin ( ) ; it ! = _ModelList . end ( ) ; + + it )
{
CParticleSystemModel & psm = * ( * it ) ;
CParticleSystem * ps = psm . getPS ( ) ;
if ( ps )
{
ps - > stopSound ( ) ;
}
}
}
///=========================================================
void CParticleSystemManager : : reactivateSound ( )
{
NL_PS_FUNC ( CParticleSystemManager_reactivateSound )
for ( TModelList : : iterator it = _ModelList . begin ( ) ; it ! = _ModelList . end ( ) ; + + it )
{
CParticleSystemModel & psm = * ( * it ) ;
CParticleSystem * ps = psm . getPS ( ) ;
if ( ps )
{
ps - > reactivateSound ( ) ;
}
}
}
///=========================================================
void CParticleSystemManager : : stopSoundForAllManagers ( )
{
NL_PS_FUNC ( CParticleSystemManager_stopSoundForAllManagers )
for ( TManagerList : : iterator it = getManagerList ( ) . begin ( ) ; it ! = getManagerList ( ) . end ( ) ; + + it )
{
nlassert ( * it ) ;
( * it ) - > stopSound ( ) ;
}
}
///=========================================================
void CParticleSystemManager : : reactivateSoundForAllManagers ( )
{
NL_PS_FUNC ( CParticleSystemManager_reactivateSoundForAllManagers )
for ( TManagerList : : iterator it = getManagerList ( ) . begin ( ) ; it ! = getManagerList ( ) . end ( ) ; + + it )
{
nlassert ( * it ) ;
( * it ) - > reactivateSound ( ) ;
}
}
} // NL3D