mirror of
https://port.numenaute.org/aleajactaest/khanat-opennel-code.git
synced 2024-12-23 17:38:44 +00:00
501 lines
16 KiB
C++
501 lines
16 KiB
C++
// 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/>.
|
|
|
|
#ifndef NL_PARTICLE_SYSTEM_MODEL_H
|
|
#define NL_PARTICLE_SYSTEM_MODEL_H
|
|
|
|
#include "nel/misc/types_nl.h"
|
|
#include "nel/misc/plane.h"
|
|
#include "nel/misc/contiguous_block_allocator.h"
|
|
#include "nel/3d/transform_shape.h"
|
|
#include "nel/3d/particle_system.h"
|
|
#include "nel/3d/particle_system_manager.h"
|
|
#include "nel/3d/clip_trav.h"
|
|
#include "nel/3d/anim_detail_trav.h"
|
|
#include "nel/3d/load_balancing_trav.h"
|
|
#include "nel/3d/scene.h"
|
|
|
|
// tmp
|
|
#include "nel/misc/hierarchical_timer.h"
|
|
|
|
#include <vector>
|
|
|
|
namespace NL3D {
|
|
|
|
/////////////////////////////////////////////////////////
|
|
// THE FOLLOWING CLASS IS FOR INSERTION OF A PARTICLE //
|
|
// SYSTEM IN A MOT MODEL //
|
|
// SEE also CParticleSystemshape, CParticleSystem //
|
|
/////////////////////////////////////////////////////////
|
|
|
|
class CParticleSystem;
|
|
class CScene;
|
|
class CParticleSystemShape;
|
|
|
|
|
|
/** A particle system model : it is built using a CParticleSystemShape.
|
|
* You should forgot to call the animate() method of the CScene it is part of
|
|
* if you want motion to be performed
|
|
*/
|
|
|
|
class CParticleSystemModel : public CTransformShape
|
|
{
|
|
public:
|
|
///\name Object
|
|
//@{
|
|
/// ctor
|
|
CParticleSystemModel();
|
|
/// dtor
|
|
~CParticleSystemModel();
|
|
|
|
/// register the basic models
|
|
static void registerBasic();
|
|
//@}
|
|
|
|
///\name Embedded particle system
|
|
//@{
|
|
|
|
/** Get the particle system contained in this transform shape. (NB: This is shared by a smart ptr)
|
|
* \return pointer to the system, or NULL if no system is currently hold by this model.
|
|
* this may happen when the system is not visible and that it has been deleted
|
|
*/
|
|
CParticleSystem *getPS(void)
|
|
{
|
|
return _ParticleSystem;
|
|
}
|
|
|
|
/** Get the particle system (NB : This is shared by a smart ptr) contained in this transform shape.
|
|
* This may be null if the model is not visible.
|
|
*/
|
|
const CParticleSystem *getPS(void) const
|
|
{
|
|
return _ParticleSystem;
|
|
}
|
|
|
|
/** Set the particle system for this transform shape after it has been instanciated (from a memory stream, or by sharing)
|
|
* see CParticleSystemShape
|
|
*/
|
|
void setParticleSystem(CParticleSystem *ps)
|
|
{
|
|
nlassert(!_ParticleSystem);
|
|
_ParticleSystem = ps;
|
|
updateOpacityInfos();
|
|
}
|
|
//@}
|
|
|
|
///\name Life managment
|
|
//@{
|
|
/**
|
|
* test whether the system has become invalid. The condition for a system to be invalid
|
|
* are encoded in the system itself (no more particles for example). When a system has become invalid, you may want to remove it most of the time
|
|
*/
|
|
bool isInvalid(void) const { return _Invalidated; }
|
|
|
|
/// interface for object that observe this model. They will be notified when it becomes invalid
|
|
struct IPSModelObserver
|
|
{
|
|
virtual ~IPSModelObserver() {}
|
|
/// called when a system has been invalidated
|
|
virtual void invalidPS(CParticleSystemModel *psm) = 0;
|
|
};
|
|
|
|
/// register an observer that will be notified when this model becomes invalid
|
|
void registerPSModelObserver(IPSModelObserver *obs);
|
|
|
|
/** remove an observer
|
|
* \see registerPSModelObserver
|
|
*/
|
|
void removePSModelObserver(IPSModelObserver *obs);
|
|
/// test whether obs observe this model
|
|
bool isPSModelObserver(IPSModelObserver *obs);
|
|
//@}
|
|
|
|
|
|
//\name Time managment
|
|
//@{
|
|
|
|
/** when called with true, this force the model to querry himself the ellapsed time to the scene.
|
|
* This is the default. Otherwise, setEllapsedTime must be called
|
|
*/
|
|
void enableAutoGetEllapsedTime(bool enable = true)
|
|
{
|
|
_AutoGetEllapsedTime = enable;
|
|
}
|
|
/** This apply a ratio on the ellapsed time. This can be used to slow down a system
|
|
* This must be in the >= 0.
|
|
* 1 means the system run at normal speed
|
|
*/
|
|
void setEllapsedTimeRatio(float value)
|
|
{
|
|
nlassert(value >= 0);
|
|
_EllapsedTimeRatio = value;
|
|
}
|
|
//
|
|
float getEllapsedTimeRatio() const { return _EllapsedTimeRatio; }
|
|
/// tells whether the model will querry himself for the ellapsed time
|
|
bool isAutoGetEllapsedTimeEnabled(void) const
|
|
{
|
|
return _AutoGetEllapsedTime;
|
|
}
|
|
/// set the ellapsed time (in second) used for animation.
|
|
void setEllapsedTime(TAnimationTime ellapsedTime)
|
|
{
|
|
_EllapsedTime = ellapsedTime;
|
|
}
|
|
/// get the ellapsed time used for animation
|
|
TAnimationTime getEllapsedTime(void) const
|
|
{
|
|
return _EllapsedTime;
|
|
}
|
|
//@}
|
|
|
|
///\name Edition related methods
|
|
//@{
|
|
/// activate the display of tool (for edition purpose)
|
|
void enableDisplayTools(bool enable = true);
|
|
|
|
// check whether the display of tools is enabled
|
|
bool isToolDisplayEnabled(void) const
|
|
{
|
|
return _ToolDisplayEnabled;
|
|
}
|
|
/** force the edition mode : this will prevent the system from being removed when it is out of range.
|
|
* When the model is first allocated, the system resource are not allocated until it becomes visible.
|
|
* This also forces the resources to be allocated.
|
|
* when there are no more particles in it etc. (this also mean that you can safely keep a pointer on it)
|
|
* This flag is not saved.
|
|
*/
|
|
void setEditionMode(bool enable = true) ;
|
|
/// test if edition mode is activated
|
|
bool getEditionMode(void) const
|
|
{
|
|
return _EditionMode;
|
|
}
|
|
/// edition purpose : touch the system to tell that the transparency state of the system has changed (added/removed opaque/tansparent faces )
|
|
void touchTransparencyState(void)
|
|
{
|
|
_TransparencyStateTouched = true;
|
|
}
|
|
/// edition purpose : touch the system to tell that the lightable state of the system has changed (added/removed lightable faces )
|
|
void touchLightableState(void)
|
|
{
|
|
_LightableStateTouched = true;
|
|
}
|
|
//@}
|
|
|
|
///\name User params / animation
|
|
//@{
|
|
/// for now, we have 4 animatables value in a system
|
|
enum TAnimValues
|
|
{
|
|
OwnerBit= CTransformShape::AnimValueLast,
|
|
PSParam0,
|
|
PSParam1,
|
|
PSParam2,
|
|
PSParam3,
|
|
PSTrigger, // trigger the instanciation of the system
|
|
AnimValueLast,
|
|
};
|
|
virtual IAnimatedValue *getValue (uint valueId);
|
|
virtual const char *getValueName (uint valueId) const;
|
|
static const char *getPSParamName (uint valueId);
|
|
virtual ITrack *getDefaultTrack (uint valueId);
|
|
virtual void registerToChannelMixer(CChannelMixer *chanMixer,
|
|
const std::string &prefix = "");
|
|
// Bypass a global user param.
|
|
void bypassGlobalUserParamValue(uint userParamIndex, bool byPass = true);
|
|
bool isGlobalUserParamValueBypassed(uint userParamIndex) const;
|
|
//@}
|
|
|
|
/** This update the infos about opacity (e.g are there solid faces and / or transparent faces in the system).
|
|
* This must be called when the system is instanciated, or when attributes have changed, such as the blending mode
|
|
*/
|
|
void updateOpacityInfos(void);
|
|
// Update the lighted/not lighted flag of the system
|
|
void updateLightingInfos(void);
|
|
|
|
virtual void getAABBox(NLMISC::CAABBox &bbox) const;
|
|
/// inherited from CTransformShape. Returns the number of triangles wanted depeneding on the distance
|
|
virtual float getNumTriangles (float distance);
|
|
/// create an instance of this class
|
|
static CTransform *creator()
|
|
{
|
|
return new CParticleSystemModel;
|
|
}
|
|
|
|
|
|
/// \name CTransform traverse specialisation
|
|
// @{
|
|
/** Very special clip for Particle System (because of the complexity of not rendered, but still detail-animated...)
|
|
*/
|
|
virtual void traverseClip();
|
|
// no-op clip() because all done in special traverse()
|
|
virtual bool clip();
|
|
/**
|
|
* - call CTransformShape::traverseAnimDetail()
|
|
* - Detail animation for a particle system. It perform motion of the particles
|
|
* (so, motion occurs only when the system has not be clipped)
|
|
*/
|
|
virtual void traverseAnimDetail();
|
|
virtual void traverseRender();
|
|
// @}
|
|
|
|
// activate / deactivate all emitters
|
|
void activateEmitters(bool active);
|
|
// test if there are active emitters in the system
|
|
bool hasActiveEmitters() const;
|
|
|
|
// user color
|
|
void setUserColor(NLMISC::CRGBA userColor);
|
|
NLMISC::CRGBA getUserColor() const { return _UserColor; }
|
|
|
|
/** Set user matrix of the system.
|
|
*
|
|
* Particle can be located in various coordinate system :
|
|
* - in world (identity matrix)
|
|
* - local to the particle system (matrix of the particle system)
|
|
* - local to the coord. sys. defined by the user matrix
|
|
*
|
|
*/
|
|
void setUserMatrix(const NLMISC::CMatrix &userMatrix) { _UserMatrix = userMatrix; }
|
|
// Set the user matrix, with instant update of the CParticleSystem pointed by that model (if instanciated)
|
|
void forceSetUserMatrix(const NLMISC::CMatrix &userMatrix);
|
|
const NLMISC::CMatrix &getUserMatrix() const { return _UserMatrix; }
|
|
|
|
void forceInstanciate();
|
|
|
|
// Set z-bias. Value is in world coordinates. Value remains even if ps isn't present (rsc not allocated)
|
|
void setZBias(float value);
|
|
|
|
// sound on / off
|
|
void stopSound();
|
|
void reactivateSound();
|
|
|
|
// from CTransform
|
|
virtual void update();
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
private:
|
|
friend class CParticleSystemShape;
|
|
friend class CParticleSystemManager;
|
|
|
|
|
|
/// Called when the resource (attached system) for this system must be reallocated
|
|
void reallocRsc();
|
|
/// Called by the particle system manager to release this model resources (if it is too far for example)
|
|
void refreshRscDeletion(const std::vector<CPlane> &worldFrustumPyramid, const NLMISC::CVector &viewerPos);
|
|
// Release the resources (attached system) of this model, but doesn't make it invalid.
|
|
void releaseRsc();
|
|
// Mark this system model as invalid, delete the attached system, and calls his observers
|
|
void releaseRscAndInvalidate();
|
|
/// Return true if the system is in the given world pyramid
|
|
bool checkAgainstPyramid(const std::vector<CPlane> &worldFrustumPyramid) const;
|
|
// Release PS and backup system params
|
|
void releasePSPointer();
|
|
|
|
void invalidateAutoAnimatedHandle();
|
|
|
|
|
|
// insert the model in the Clip/AnimDetail/LoadBalacing visible list.
|
|
void insertInVisibleList()
|
|
{
|
|
// if not already not inserted
|
|
if (!_InsertedInVisibleList)
|
|
{
|
|
_Visible = true;
|
|
_InsertedInVisibleList = true;
|
|
// add to clip/load Trav.
|
|
getOwnerScene()->getClipTrav().addVisibleModel(this);
|
|
getOwnerScene()->getLoadBalancingTrav().addVisibleModel(this);
|
|
|
|
// Add only if no ancestor skeleton model
|
|
if( _AncestorSkeletonModel==NULL )
|
|
{
|
|
// need to test isLightable(), because most of PS are not lightable
|
|
// NB: don't insert if has an _AncestorSkeletonModel, because in this case,
|
|
// result is driven by the _LightContribution of the _AncestorSkeletonModel.
|
|
if( isLightable() )
|
|
getOwnerScene()->getLightTrav().addLightedModel(this);
|
|
// no need to test isAnimDetailable()... for PS, always add them
|
|
// NB: don't insert if has an _AncestorSkeletonModel, because in this case, this ancestor will
|
|
// animDetail through the hierarchy...
|
|
getOwnerScene()->getAnimDetailTrav().addVisibleModel(this);
|
|
}
|
|
}
|
|
}
|
|
bool checkDestroyCondition(CParticleSystem *ps);
|
|
// perform actual animation of the particles
|
|
void doAnimate();
|
|
|
|
private:
|
|
CParticleSystemManager::TModelHandle _ModelHandle; /** a handle to say when the resources
|
|
* of the model (_ParticleSystem) are deleted
|
|
*/
|
|
CParticleSystemManager::TAlwaysAnimatedModelHandle _AnimatedModelHandle; // handle for permanenlty animated models
|
|
NLMISC::CSmartPtr<CParticleSystem> _ParticleSystem;
|
|
CScene *_Scene;
|
|
TAnimationTime _EllapsedTime;
|
|
float _EllapsedTimeRatio;
|
|
|
|
// old animation mode for the system
|
|
CParticleSystem::TAnimType _AnimType;
|
|
|
|
bool _AutoGetEllapsedTime : 1;
|
|
bool _ToolDisplayEnabled : 1;
|
|
bool _TransparencyStateTouched : 1;
|
|
bool _LightableStateTouched : 1;
|
|
bool _EditionMode : 1;
|
|
bool _Invalidated : 1; /// if false, system should be recreated
|
|
bool _InsertedInVisibleList : 1;
|
|
bool _InClusterAndVisible : 1;
|
|
bool _EmitterActive : 1;
|
|
bool _SoundActive : 1;
|
|
|
|
std::vector<IPSModelObserver *> _Observers;
|
|
CAnimatedValueBool _TriggerAnimatedValue;
|
|
/// user params of the system
|
|
CAnimatedValueFloat _UserParam[MaxPSUserParam];
|
|
uint8 _BypassGlobalUserParam; // mask to bypass a global user param. This state is not serialized
|
|
NLMISC::CRGBA _UserColor;
|
|
NLMISC::CMatrix _UserMatrix;
|
|
float _ZBias;
|
|
CHrcTrav::TVisibility _LastVisibility;
|
|
|
|
#ifdef PS_FAST_ALLOC
|
|
// for fast allocation of ps resources
|
|
NLMISC::CContiguousBlockAllocator _Allocator;
|
|
#endif
|
|
};
|
|
|
|
|
|
// tmp
|
|
class CMiniTimer
|
|
{
|
|
public:
|
|
NLMISC::CSimpleClock SC;
|
|
uint64 &Target;
|
|
uint64 StartDate;
|
|
CMiniTimer(uint64 &target) : Target(target)
|
|
{
|
|
SC.start();
|
|
}
|
|
~CMiniTimer()
|
|
{
|
|
SC.stop();
|
|
Target += SC.getNumTicks();
|
|
}
|
|
};
|
|
|
|
#define MINI_TIMER(name)
|
|
|
|
/*
|
|
#define MINI_TIMER(name) CMiniTimer mt(name);
|
|
|
|
|
|
extern uint64 PSStatsRegisterPSModelObserver;
|
|
extern uint64 PSStatsRemovePSModelObserver;
|
|
extern uint64 PSStatsUpdateOpacityInfos;
|
|
extern uint64 PSStatsUpdateLightingInfos;
|
|
extern uint64 PSStatsGetAABBox;
|
|
extern uint64 PSStatsReallocRsc;
|
|
extern uint64 PSStatsReleasePSPointer;
|
|
extern uint64 PSStatsRefreshRscDeletion;
|
|
extern uint64 PSStatsReleaseRsc;
|
|
extern uint64 PSStatsReleaseRscAndInvalidate;
|
|
extern uint64 PSStatsGetNumTriangles;
|
|
extern uint64 PSStatsCheckAgainstPyramid;
|
|
extern uint64 PSStatsTraverseAnimDetail;
|
|
extern uint64 PSStatsTraverseAnimDetailPart1;
|
|
extern uint64 PSStatsTraverseAnimDetailPart2;
|
|
extern uint64 PSStatsTraverseAnimDetailPart3;
|
|
extern uint64 PSStatsTraverseAnimDetailPart4;
|
|
extern uint64 PSStatsDoAnimate;
|
|
extern uint64 PSStatsDoAnimatePart1;
|
|
extern uint64 PSStatsDoAnimatePart2;
|
|
extern uint64 PSStatsDoAnimatePart3;
|
|
extern uint64 PSStatsTraverseRender;
|
|
extern uint64 PSStatsTraverseClip;
|
|
extern uint64 PSStatsClipSystemInstanciated;
|
|
extern uint64 PSStatsClipSystemNotInstanciated;
|
|
extern uint64 PSStatsClipSystemCheckAgainstPyramid;
|
|
extern uint64 PSStatsInsertInVisibleList;
|
|
extern uint64 PSStatsCheckDestroyCondition;
|
|
extern uint64 PSStatsForceInstanciate;
|
|
extern uint64 PSAnim1;
|
|
extern uint64 PSAnim2;
|
|
extern uint64 PSAnim3;
|
|
extern uint64 PSAnim4;
|
|
extern uint64 PSAnim5;
|
|
extern uint64 PSAnim6;
|
|
extern uint64 PSAnim7;
|
|
extern uint64 PSAnim8;
|
|
extern uint64 PSAnim9;
|
|
extern uint64 PSAnim10;
|
|
extern uint64 PSAnim11;
|
|
extern uint PSStatsNumDoAnimateCalls;;
|
|
extern float PSMaxET;
|
|
extern uint PSMaxNBPass;
|
|
extern uint64 PSStatsZonePlane;
|
|
extern uint64 PSStatsZoneSphere;
|
|
extern uint64 PSStatsZoneDisc;
|
|
extern uint64 PSStatsZoneRectangle;
|
|
extern uint64 PSStatsZoneCylinder;
|
|
extern uint64 PSMotion1;
|
|
extern uint64 PSMotion2;
|
|
extern uint64 PSMotion3;
|
|
extern uint64 PSMotion4;
|
|
extern uint64 PSStatCollision;
|
|
extern uint64 PSStatEmit;
|
|
extern uint64 PSStatRender;
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
} // NL3D
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // NL_PARTICLE_SYSTEM_MODEL_H
|
|
|
|
/* End of particle_system_model.h */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|