// NeL - MMORPG Framework // 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 . #ifndef NL_PS_PARTICLE_BASIC_H #define NL_PS_PARTICLE_BASIC_H #include "nel/misc/types_nl.h" #include "nel/misc/vector_2f.h" #include "nel/misc/stream.h" #include "nel/3d/ps_located.h" #include "nel/3d/ps_plane_basis.h" #include "nel/3d/material.h" #include "nel/3d/ps_attrib_maker.h" namespace NL3D { //////////////////////////////// // class forward declarations // //////////////////////////////// class CTextureGrouped; /** * This is the base class for all particles. * A deriver must provide a drawing method for his particle. * Not sharable accross systems. * \author Nicolas Vizerie * \author Nevrax France * \date 2001 */ class CPSParticle : public CPSLocatedBindable { public: /// Constructor CPSParticle(); /// return this bindable type uint32 getType(void) const { return PSParticle; } /// return priority virtual uint32 getPriority(void) const { return 1000; } /// return true if this located bindable derived class holds alive particles virtual bool hasParticles(void) const { nlassert(_Owner); return _Owner->getSize() != 0; } /** * process one pass for the particles. The default behaviour shows the particles */ virtual void step(TPSProcessPass pass) { if ( (pass == PSBlendRender && hasTransparentFaces()) || (pass == PSSolidRender && hasOpaqueFaces()) ) { draw(pass == PSSolidRender); } else if (pass == PSToolRender) // edition mode only { showTool(); } } /// return true if there are transparent faces in the object virtual bool hasTransparentFaces(void) = 0; /// return true if there are Opaque faces in the object virtual bool hasOpaqueFaces(void) = 0; /** Returns true if there are lightable faces in the object */ virtual bool hasLightableFaces() = 0; /** Returns true if the object can use global lighting color. (example : 'lookat' particle do not have * normals, so they use global lighting color instead */ bool usesGlobalColorLighting() { return _UsesGlobalColorLighting; } // active / deactive global color lighting void enableGlobalColorLighting(bool enabled) { _UsesGlobalColorLighting = enabled; } // is global color lighting supported ? virtual bool supportGlobalColorLighting() const = 0; /// derivers draw the particles here virtual void draw(bool opaque) {} /// draw the particles for edition mode. The default behaviour just draw a wireframe model virtual void showTool(); /// return the max number of faces needed for display. This is needed for LOD balancing virtual uint32 getNumWantedTris() const = 0; /// serialisation. Derivers must override this, and call their parent version virtual void serial(NLMISC::IStream &f) throw(NLMISC::EStream) { /// version 3 : global color lighting /// version 2 : auto-lod saved sint ver = f.serialVersion(3); CPSLocatedBindable::serial(f); if (ver >= 3) { f.serial(_UsesGlobalColorLighting); } if (ver >= 2) { f.serial(_DisableAutoLOD); } } /// Force the Auto-LOD to be disbaled. When set to false, the default behaviour set in the system is used void disableAutoLOD(bool disable = true) { _DisableAutoLOD = disable; } /// Test whether Auto-LOD is disabled. bool isAutoLODDisabled() const { return _DisableAutoLOD; } // Change z-bias of material. this must be redefined for all renderable particles virtual void setZBias(float value) = 0; virtual float getZBias() const = 0; protected: /** Shortcut to notify that the max number of faces has changed * This must be called when a geometric property of the particle has been modified * This needn't to be called during CPSParticle::resize overrides */ /* void notifyOwnerMaxNumFacesChanged(void) const { if (_Owner) { _Owner->notifyMaxNumFacesChanged(); } }*/ /** Generate a new element for this bindable. They are generated according to the properties of the class */ virtual void newElement(const CPSEmitterInfo &info) = 0; /** Delete an element given its index * Attributes of the located that hold this bindable are still accessible for the index given * index out of range -> nl_assert */ virtual void deleteElement(uint32 index) = 0; /** Resize the bindable attributes containers. Size is the max number of element to be contained. DERIVERS MUST CALL THEIR PARENT VERSION * should not be called directly. Call CPSLocated::resize instead */ virtual void resize(uint32 size) = 0; /** System may have hand-tuned LOD, or auto LOD. * This compute the number of particles that must really be displayed, and the src step * that allow to go through the whole collection. The step in the source is in a fixed point 16:16 format */ void computeSrcStep(uint32 &step, uint &numToProcess); private: /// Disable Auto-LOD flag bool _DisableAutoLOD; bool _UsesGlobalColorLighting; }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// this class adds tunable color to a particle. Can be added using public multiple inheritance class CPSColoredParticle { public: /** Set an attribute maker that produce a color * It must have been allocated by new * It will be deleted by this object */ void setColorScheme(CPSAttribMaker *col); /// get the color scheme (NULL if none) CPSAttribMaker *getColorScheme(void) { return _ColorScheme; } /// get the color scheme (NULL if none) const version const CPSAttribMaker *getColorScheme(void) const { return _ColorScheme; } /// Set a constant color for the particles. remove any previous scheme void setColor(NLMISC::CRGBA col); /// Get the color NLMISC::CRGBA getColor(void) const { return _Color; } /// ctor : default are white particles (constant color) CPSColoredParticle(); /// dtor virtual ~CPSColoredParticle(); /// serialization. void serialColorScheme(NLMISC::IStream &f) throw(NLMISC::EStream); protected: /// deriver must return their owner there virtual CPSLocated *getColorOwner(void) = 0; CRGBA _Color; CPSAttribMaker *_ColorScheme; /// Update the material and the vb and the like so that they match the color scheme virtual void updateMatAndVbForColor(void) = 0; void newColorElement(const CPSEmitterInfo &info) { if (_ColorScheme && _ColorScheme->hasMemory()) _ColorScheme->newElement(info); } void deleteColorElement(uint32 index) { if (_ColorScheme && _ColorScheme->hasMemory()) _ColorScheme->deleteElement(index); } void resizeColor(uint32 size) { nlassert(size < (1 << 16)); if (_ColorScheme && _ColorScheme->hasMemory()) _ColorScheme->resize(size, getColorOwner()->getSize()); } }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// this class adds tunable size to a particle. Can be added using public multiple inheritance class CPSSizedParticle { public: /** Set an attribute maker that produce a size * It must have been allocated by new * It will be deleted by this object */ void setSizeScheme(CPSAttribMaker *size); /// get the size scheme (NULL if none) CPSAttribMaker *getSizeScheme(void) { return _SizeScheme; } /// get the size scheme (NULL if none) const version const CPSAttribMaker *getSizeScheme(void) const { return _SizeScheme; } /// Set a constant size for the particles void setSize(float size); /// get the constant size float getSize(void) const { return _ParticleSize; } /// ctor : default are 0.1f sized particles CPSSizedParticle(); /// dtor virtual ~CPSSizedParticle(); /// serialization. We choose a different name because of multiple-inheritance void serialSizeScheme(NLMISC::IStream &f) throw(NLMISC::EStream); protected: /// deriver must return their owner there virtual CPSLocated *getSizeOwner(void) = 0; float _ParticleSize; CPSAttribMaker *_SizeScheme; void newSizeElement(const CPSEmitterInfo &info) { if (_SizeScheme && _SizeScheme->hasMemory()) _SizeScheme->newElement(info); } void deleteSizeElement(uint32 index) { if (_SizeScheme && _SizeScheme->hasMemory()) _SizeScheme->deleteElement(index); } void resizeSize(uint32 size) { nlassert(size < (1 << 16)); if (_SizeScheme && _SizeScheme->hasMemory()) _SizeScheme->resize(size, getSizeOwner()->getSize()); } }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// this class adds tunable 2D rotation to a particle, it can be used by public multiple inheritance class CPSRotated2DParticle { public: /** Set an attribute maker that produce a float * It must have been allocated by new * It will be deleted by this object * Output angles must range from 0.0f to 256.0f */ void setAngle2DScheme(CPSAttribMaker *scheme); /// get the angle 2D scheme (NULL if none) CPSAttribMaker *getAngle2DScheme(void) { return _Angle2DScheme; } /// get the angle 2D scheme (NULL if none) const version const CPSAttribMaker *getAngle2DScheme(void) const { return _Angle2DScheme; } /** Set a constant angle for the particle. Angles range from 0.0f to 256.0f (2 pi) * This discrad any previous scheme * \see setAngle2DScheme() */ void setAngle2D(float angle); /// get the constant float getAngle2D(void) const { return _Angle2D; } /// ctor : default are unrotated particles (angle = 0.0f) CPSRotated2DParticle(); /// dtor virtual ~CPSRotated2DParticle(); /// serialization. We choose a different name because of multiple-inheritance void serialAngle2DScheme(NLMISC::IStream &f) throw(NLMISC::EStream); /** this return a float table used to speed up rotations of face look at and the like * for each angle, there are 4 float : 2 couple of float : a1, b1, a2, b2 * a1 * I + b1 * K = up left corner, a2 * I + b2 * K = up right corner, * This table must have been initialized with initRotTable */ static inline const float *getRotTable(void) { nlassert(_InitializedRotTab); // must have called initRotTable at the start of the apply return _RotTable; } /// init the rotation table static void initRotTable(void); protected: /// deriver must return their owner there virtual CPSLocated *getAngle2DOwner(void) = 0; float _Angle2D; CPSAttribMaker *_Angle2DScheme; static float _RotTable[4 * 256]; //#ifdef NL_DEBUG /// it is true if the table has been initialized, for debug purposes static bool _InitializedRotTab; //#endif void newAngle2DElement(const CPSEmitterInfo &info) { if (_Angle2DScheme && _Angle2DScheme->hasMemory()) _Angle2DScheme->newElement(info); } void deleteAngle2DElement(uint32 index) { if (_Angle2DScheme && _Angle2DScheme->hasMemory()) _Angle2DScheme->deleteElement(index); } void resizeAngle2D(uint32 size) { nlassert(size < (1 << 16)); if (_Angle2DScheme && _Angle2DScheme->hasMemory()) _Angle2DScheme->resize(size, getAngle2DOwner()->getSize()); } }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// this class is an interface for particles that have unanimated textures struct CPSTexturedParticleNoAnim { virtual ~CPSTexturedParticleNoAnim() {} /// set the texture for this particle virtual void setTexture(CSmartPtr tex) = 0; /// get the texture used for this particle virtual ITexture *getTexture(void) = 0; virtual const ITexture *getTexture(void) const = 0; }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** this class adds a texture to a particle. The texture can be animated or not. it can be used by public multiple inheritance. * The frame animation are all stored in the same texture for optimisation so it's not suited for large anim... */ class CPSTexturedParticle { public: /** Set an attribute maker that produce a sint32 * It must have been allocated by new * It will be deleted by this object * a texture group must have been set before this, an assertion occurs otherwise * The integer is used as an index in a grouped texture. It tells which frame to use */ void setTextureIndexScheme(CPSAttribMaker *animOrder); /// get the texture scheme (null if none) CPSAttribMaker *getTextureIndexScheme(void) { return _TextureIndexScheme; } /// get the texture scheme (null if none) const version const CPSAttribMaker *getTextureIndexScheme(void) const { return _TextureIndexScheme; } /// set a constant index for the current texture. not very useful, but available... void setTextureIndex(sint32 index); /// get the animated texture index. MeaningFul only if a texture group was set sint32 getTextureIndex(void) const { return _TextureIndex; } /// set the texture group being used. It toggles animation on virtual void setTextureGroup(NLMISC::CSmartPtr texGroup); /// get the texture group used. it discard any previous single texture. (if null, there's no texture animation) CTextureGrouped *getTextureGroup(void) { return _TexGroup; } /// get the texture group used if there's a texture scheme, const version. (if null, there's no texture animation) const CTextureGrouped *getTextureGroup(void) const { return _TexGroup; } /** Set a constant texture for the particle * This discard any previous scheme * \see setTextureScheme() */ virtual void setTexture(CSmartPtr tex); /// get the constant texture ITexture *getTexture(void) { return _Tex; } // get the texture (const version) const ITexture *getTexture(void) const { return _Tex; } /// ctor : default have no texture. You must set it, otherwise you'll get an assertion when it's drawn CPSTexturedParticle(); /// dtor virtual ~CPSTexturedParticle(); /// serialization. We choose a different name because of multiple-inheritance void serialTextureScheme(NLMISC::IStream &f) throw(NLMISC::EStream); void enumTexs(std::vector > &dest); protected: /// deriver must return their owner there virtual CPSLocated *getTextureIndexOwner(void) = 0; // a single texture CSmartPtr _Tex; // a grouped texture CSmartPtr _TexGroup; CPSAttribMaker *_TextureIndexScheme; // a texture index. Most of the time, a scheme of index will be used instead of that sint32 _TextureIndex; /// Update the material so that it match the texture scheme virtual void updateMatAndVbForTexture(void) = 0; void newTextureIndexElement(const CPSEmitterInfo &info) { if (_TextureIndexScheme && _TextureIndexScheme->hasMemory()) _TextureIndexScheme->newElement(info); } void deleteTextureIndexElement(uint32 index) { if (_TextureIndexScheme && _TextureIndexScheme->hasMemory()) _TextureIndexScheme->deleteElement(index); } void resizeTextureIndex(uint32 size) { nlassert(size < (1 << 16)); if (_TextureIndexScheme && _TextureIndexScheme->hasMemory()) _TextureIndexScheme->resize(size, getTextureIndexOwner()->getSize() ); } }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** This class add multitexturing support to particles. It doesn't support texture animation however. * It adds a second texture that is combined with the main texture by using a given operation. * An alternate mode must be provided, for gfx boards that doesn't support the op. * For now, 2 stages only are supported. */ class CPSMultiTexturedParticle { public: /// ctor CPSMultiTexturedParticle(); virtual ~CPSMultiTexturedParticle() {} /// we only use a useful set of operations enum TOperator { Add = 0, Modulate, Decal, EnvBumpMap, Last = 0xff }; /// when set to false, this discard the textures that have been set void enableMultiTexture(bool enabled = true); bool isMultiTextureEnabled() const { return (_MultiTexState & (uint8) MultiTextureEnabled) != 0; } /// Set the main texture for multitexturing. Convert the texture to / from a bumpmap if needed (so you just provide its heightmap) void setTexture2(ITexture *tex); /// Get the main texture for multitexturing const ITexture *getTexture2() const { return _Texture2; } ITexture *getTexture2() { return _Texture2; } /** Set the operation for the main texture. When EnvBumpMap is used, setTexture2 must be called with a bump map, * and the primary texture must be convertible to rgba. Convert the texture to / from a bumpmap if needed */ void setMainTexOp(TOperator op); TOperator getMainTexOp() const { return _MainOp; } // Enable the use of an alternate texture for multitexturing. When disabled, this discard the textures that may have been set. void enableAlternateTex(bool enabled = true); bool isAlternateTexEnabled() const { return (_MultiTexState & (uint8) AlternateTextureEnabled) != 0; } /// Set the alternate texture for multitexturing. It is used when the main operator is not supported by the gfx board. // Convert the texture to / from a bumpmap if needed. (so you just provide its heightmap) void setTexture2Alternate(ITexture *tex); /// Get the alternate texture for multitexturing. const ITexture *getTexture2Alternate() const { return _AlternateTexture2; } ITexture *getTexture2Alternate() { return _AlternateTexture2; } /// Set the operation for the alternate texture. Convert the texture to / from a bumpmap if needed. void setAlternateTexOp(TOperator op); TOperator getAlternateTexOp() const { return _AlternateOp; } /** set the scroll speed for tex 1 & 2 when the main op is used * \param stage can be set to 0 or one */ void setScrollSpeed(uint stage, const NLMISC::CVector2f &sp) { nlassert(stage < 2); _TexScroll[stage] = sp; } const NLMISC::CVector2f &getScrollSpeed(uint stage) const { nlassert(stage < 2); return _TexScroll[stage]; } /** set the scroll speed for tex 1 & 2 when the alternate op is used * \param stage can be set to 0 or one */ void setAlternateScrollSpeed(uint stage, const NLMISC::CVector2f &sp) { nlassert(stage < 2); _TexScrollAlternate[stage] = sp; } const NLMISC::CVector2f &getAlternateScrollSpeed(uint stage) const { nlassert(stage < 2); return _TexScrollAlternate[stage]; } /// serial this object void serialMultiTex(NLMISC::IStream &f) throw(NLMISC::EStream); /** setup a material from this object and a primary texture * drv is used to check the device caps. * Must be called before display when multitextureing is used * vb is needed because uv routing may be changed because of embm */ void setupMaterial(ITexture *primary, IDriver *drv, CMaterial &mat, CVertexBuffer &vb); /** this act as if the system had the most basic caps supported (no EMBM for example...) * Should be used only in edition mode for test */ static void forceBasicCaps(bool force = true) { _ForceBasicCaps = force; } /// test whether basic caps are forced static bool areBasicCapsForced() { return _ForceBasicCaps; } /// Use the particle age rather than the global time to compute textures coordinates. void setUseLocalDate(bool use); bool getUseLocalDate() { return (_MultiTexState & ScrollUseLocalDate) != 0; } /// Use the particle age rather than the global time to compute textures coordinates. (when alternate texture is used) void setUseLocalDateAlt(bool use); bool getUseLocalDateAlt() { return (_MultiTexState & ScrollUseLocalDateAlternate) != 0; } /// Set a bump factor (when embm is used) void setBumpFactor(float bumpFactor) { _BumpFactor = bumpFactor; touch(); } float getBumpFactor() const { return _BumpFactor; } void enumTexs(std::vector > &dest, IDriver &drv); protected: void setupMultiTexEnv(TOperator op, ITexture *tex1, ITexture *tex2, CMaterial &mat, IDriver &drv); TOperator _MainOp, _AlternateOp; NLMISC::CSmartPtr _Texture2; NLMISC::CSmartPtr _AlternateTexture2; /// texture scrolling NLMISC::CVector2f _TexScroll[2]; /// alternate texture scrollMultiTextureEnabled NLMISC::CVector2f _TexScrollAlternate[2]; enum TMultiTexState { TouchFlag = 0x01, MultiTextureEnabled = 0x02, AlternateTextureEnabled = 0x04, AlternateTextureUsed = 0x08, EnvBumpMapUsed = 0x10, BasicCapsForced = 0x20, ScrollUseLocalDate = 0x40, ScrollUseLocalDateAlternate = 0x80 }; uint8 _MultiTexState; /// test whether the alternate texture is used bool isAlternateTextureUsed(IDriver &driver) const; bool isEnvBumpMapUsed() const { return (_MultiTexState & EnvBumpMapUsed) != 0; } // update wrap mode for all textures virtual void updateTexWrapMode(IDriver &drv) = 0; void touch() { _MultiTexState |= (uint8) TouchFlag; } void unTouch() { _MultiTexState &= ~ (uint8) TouchFlag; } bool isTouched() const { return (_MultiTexState & TouchFlag) != 0; } bool areBasicCapsForcedLocal() const { return (_MultiTexState & BasicCapsForced) != 0; } void forceBasicCapsLocal(bool force) { if (force) _MultiTexState |= BasicCapsForced; else _MultiTexState &= ~BasicCapsForced; } float _BumpFactor; static bool _ForceBasicCaps; }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** this class adds tunable 3D rotation to a PLANE particle, it can be used by public multiple inheritance * It must just produce 2 vectors that give the x and y vector of the local basis. */ class CPSRotated3DPlaneParticle { public: /** Set an attribute maker that produce a basis * It must have been allocated by new * It will be deleted by this object */ void setPlaneBasisScheme(CPSAttribMaker *basisMaker); /** Set a constant basis for all particles * \see setPlaneBasisSchemeScheme() */ /// get the plane basis scheme, (NULL if none) CPSAttribMaker *getPlaneBasisScheme(void) { return _PlaneBasisScheme; } /// get the plane basis scheme, (NULL if none) const version const CPSAttribMaker *getPlaneBasisScheme(void) const { return _PlaneBasisScheme; } void setPlaneBasis(const CPlaneBasis &basis); /// get the constant basis CPlaneBasis getPlaneBasis(void) const { return _PlaneBasis; } /// ctor : default have constant basis that map to the I & J vector (e.g identity) CPSRotated3DPlaneParticle(); /// dtor virtual ~CPSRotated3DPlaneParticle(); /// serialization. We choose a different name because of multiple-inheritance void serialPlaneBasisScheme(NLMISC::IStream &f) throw(NLMISC::EStream); protected: /// if this is false, constant size will be used instead of a scheme /// deriver must return their owner there virtual CPSLocated *getPlaneBasisOwner(void) = 0; CPSAttribMaker *_PlaneBasisScheme; CPlaneBasis _PlaneBasis; // constant basis.. void newPlaneBasisElement(const CPSEmitterInfo &info) { if (_PlaneBasisScheme && _PlaneBasisScheme->hasMemory()) _PlaneBasisScheme->newElement(info); } void deletePlaneBasisElement(uint32 index) { if (_PlaneBasisScheme && _PlaneBasisScheme->hasMemory()) _PlaneBasisScheme->deleteElement(index); } void resizePlaneBasis(uint32 size) { nlassert(size < (1 << 16)); if (_PlaneBasisScheme && _PlaneBasisScheme->hasMemory()) _PlaneBasisScheme->resize(size, getPlaneBasisOwner()->getSize()); } }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** This add a hint to rotated particle : only a few one are rotated, and the other are duplcated * */ struct CPSHintParticleRotateTheSame { virtual ~CPSHintParticleRotateTheSame() {} /** Tells that all particles are turning in the same manner, and only have a rotationnal bias * This is faster then other method. Any previous set scheme for 3d rotation is kept. * \param: the number of rotation configuration we have. The more high it is, the slower it'll be * If this is too low, a lot of particles will have the same orientation * If it is 0, then the hint is disabled * \param minAngularVelocity : the maximum angular velocity for particle rotation * \param maxAngularVelocity : the maximum angular velocity for particle rotation * \see CPSRotated3dPlaneParticle */ virtual void hintRotateTheSame(uint32 nbConfiguration , float minAngularVelocity = NLMISC::Pi , float maxAngularVelocity = NLMISC::Pi ) = 0; /** disable the hint 'hintRotateTheSame' * The previous set scheme for roation is used * \see hintRotateTheSame(), CPSRotated3dPlaneParticle */ virtual void disableHintRotateTheSame(void) = 0; /** check whether a call to hintRotateTheSame was performed * \return 0 if the hint is disabled, the number of configurations else * \see hintRotateTheSame(), CPSRotated3dPlaneParticle */ virtual uint32 checkHintRotateTheSame(float &minAngularVelocity, float &maxAngularVelocity) const = 0; }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// base struct for particle that have a tail struct CPSTailParticle { virtual ~CPSTailParticle() {} /** (de)activate color fading * when its done, colors fades to black along the tail */ virtual void setColorFading(bool onOff = true) = 0; /// test whether color fading is activated virtual bool getColorFading(void) const = 0; /// there may be a maximum with some particles virtual void setTailNbSeg(uint32 nbSeg) = 0; // get the number of segments in the tail virtual uint32 getTailNbSeg(void) const = 0; }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /// base struct for particles that can have a shape (e.g mesh...) struct CPSShapeParticle { virtual ~CPSShapeParticle() {} /// set a new shape virtual void setShape(const std::string &shape) = 0; /// get the shape used for those particles virtual std::string getShape(void) const = 0; }; ////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** this contains material of a particle, this doesn't initiliaze anything, this just give the abylity to * change the blending mode */ class CPSMaterial { public: /// ctor : the default is additive blending CPSMaterial(); /// this enum summarize the useful modes for blending to the framebuffer enum TBlendingMode { add, modulate, alphaBlend, alphaTest }; /// serialization (not named 'serial' because it will be used via multiple-inheritance) void serialMaterial(NLMISC::IStream &f) throw(NLMISC::EStream); /// set the blending mode. The default is ass void setBlendingMode(CPSMaterial::TBlendingMode mode); /// return the blending mode currently used CPSMaterial::TBlendingMode getBlendingMode(void) const; /** Force the material to have one texture that is modulated by diffuse, and a constant color * and its diffuse color. This is not compatible with multitextureing, however. * \param force true to force constant color modulation */ void forceModulateConstantColor(bool force, const NLMISC::CRGBA &col = NLMISC::CRGBA::White); /** This setup n stage of a material with at least texture. * - If a texture was present for a given stage it still is * - If a texture wasn't present, it create a dummy white texture there * - Above numStages, textures are disabled. * It can be used to do extra math with stages that have no textures (required by the driver) */ void forceTexturedMaterialStages(uint numStages); // enable / disable z-test (default is enabled) void enableZTest(bool enabled); // test if z test is enabled bool isZTestEnabled() const; // set z-bias void setZBias(float value) { _Mat.setZBias(value); } float getZBias() const { return _Mat.getZBias(); } protected: CMaterial _Mat; }; //========================================================================== /// setup a stage as modulate, by specifying the source and destination inline void SetupModulatedStage(CMaterial &m, uint stage, CMaterial::TTexSource src1, CMaterial::TTexSource src2) { m.texEnvOpRGB(stage, CMaterial::Modulate); m.texEnvOpAlpha(stage, CMaterial::Modulate); m.texEnvArg0RGB(stage, src1, CMaterial::SrcColor); m.texEnvArg1RGB(stage, src2, CMaterial::SrcColor); m.texEnvArg0Alpha(stage, src1, CMaterial::SrcAlpha); m.texEnvArg1Alpha(stage, src2, CMaterial::SrcAlpha); } } // NL3D #endif // NL_PS_PARTICLE_BASIC_H /* End of ps_particle_basic.h */