////////////////////////////////////////////////////////////////////////////////// // SPARK particle engine // // Copyright (C) 2008-2009 - Julien Fryer - julienfryer@gmail.com // // // // This software is provided 'as-is', without any express or implied // // warranty. In no event will the authors be held liable for any damages // // arising from the use of this software. // // // // Permission is granted to anyone to use this software for any purpose, // // including commercial applications, and to alter it and redistribute it // // freely, subject to the following restrictions: // // // // 1. The origin of this software must not be misrepresented; you must not // // claim that you wrote the original software. If you use this software // // in a product, an acknowledgment in the product documentation would be // // appreciated but is not required. // // 2. Altered source versions must be plainly marked as such, and must not be // // misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source distribution. // ////////////////////////////////////////////////////////////////////////////////// #ifndef H_SPK_MODEL #define H_SPK_MODEL #include "Core/SPK_DEF.h" #include "Core/SPK_Registerable.h" #include "Core/SPK_Interpolator.h" namespace SPK { /** * @enum ModelParamFlag * @brief Constants used to set bits in Model flags * * These constant values are simply 1 << ModelParam constants */ enum ModelParamFlag { FLAG_NONE = 0, /**< the flag bit for no parameter */ FLAG_RED = 1 << PARAM_RED, /**< the flag bit for PARAM_RED */ FLAG_GREEN = 1 << PARAM_GREEN, /**< the flag bit for PARAM_GREEN */ FLAG_BLUE = 1 << PARAM_BLUE, /**< the flag bit for PARAM_BLUE */ FLAG_ALPHA = 1 << PARAM_ALPHA, /**< the flag bit for PARAM_ALPHA */ FLAG_SIZE = 1 << PARAM_SIZE, /**< the flag bit for PARAM_SIZE */ FLAG_MASS = 1 << PARAM_MASS, /**< the flag bit for PARAM_MASS */ FLAG_ANGLE = 1 << PARAM_ANGLE, /**< the flag bit for PARAM_ANGLE */ FLAG_TEXTURE_INDEX = 1 << PARAM_TEXTURE_INDEX, /**< the flag bit for PARAM_TEXTURE_INDEX */ FLAG_ROTATION_SPEED = 1 << PARAM_ROTATION_SPEED, /**< the flag bit for PARAM_ROTATION_SPEED */ FLAG_CUSTOM_0 = 1 << PARAM_CUSTOM_0, /**< the flag bit for PARAM_CUSTOM_0 */ FLAG_CUSTOM_1 = 1 << PARAM_CUSTOM_1, /**< the flag bit for PARAM_CUSTOM_1 */ FLAG_CUSTOM_2 = 1 << PARAM_CUSTOM_2, /**< the flag bit for PARAM_CUSTOM_2 */ }; /** * @class Model * @brief A model of particles for particles' generation and evolution * * This class defines a behavior for particles generation and evolution over time.
* A Particle is generated under a Model that cannot be changed during its life time. * A Particle Model can however be changed but it will reinitialize the Particle parameters and life.
*
* A Model defines which parameters to use/update for a Particle. To do that an Model holds 4 flags that are : * * The flags are processed when building up a model so that they are consistent : * * The life time of a particle and immortality is also defined by the Model.
*
* The default values for the parameters are the following : * */ class SPK_PREFIX Model : public Registerable { friend class Particle; SPK_IMPLEMENT_REGISTERABLE(Model) public : ////////////////// // Constructors // ////////////////// /** * @brief The constructor for Model * * The user have to pass the Model flags that cannot be changed afterwards.
* To set up flags enumerators from ModelParamFlag can be used in a OR way.
* For instance, Model(FLAG_RED | FLAG_GREEN | FLAG_BLUE | FLAG_ALPHA,FLAG_NONE,FLAG_NONE,FLAG_NONE) * constructs a Model that will generate Particles with a defined color that will not change over time.
*
* Since 1.03.00, PARAM_RED, PARAM_GREEN and PARAM_BLUE are enabled by default. * This is needed to pass the values to the GPU in an optimized way.
* Note that even the enable flag passed by the user does not containt those params, they will be enabled anyway. * * @param enableFlag : the enable flag * @param mutableFlag : the mutable flag * @param randomFlag : the random flag * @param interpolatedFlag : the interpolated flag */ Model(int enableFlag = FLAG_RED | FLAG_GREEN | FLAG_BLUE,int mutableFlag = FLAG_NONE,int randomFlag = FLAG_NONE,int interpolatedFlag = FLAG_NONE); /** * @brief The copy constructor for Model * @param model : The Model to construct the new Model from */ Model(const Model& model); /** * @brief Creates and registers a new Model * @param enableFlag : the enable flag * @param mutableFlag : the mutable flag * @param randomFlag : the random flag * @param interpolatedFlag : the interpolated flag * @return A new registered Model * @since 1.04.00 */ static inline Model* create(int enableFlag = FLAG_RED | FLAG_GREEN | FLAG_BLUE,int mutableFlag = FLAG_NONE,int randomFlag = FLAG_NONE,int interpolatedFlag = FLAG_NONE); //////////////// // Destructor // //////////////// /** @brief The destructor for Model */ ~Model(); ///////////// // Setters // ///////////// /** * @brief Sets the life time * * All particles generated under this Model will be given a life time randomly generated within [lifeTimeMin,lifeTimeMax[.
* To generate particles with a non random life time, simply use setLifeTime(a,a). * * @param lifeTimeMin : the minimum life time * @param lifeTimeMax : the maximum life time */ inline void setLifeTime(float lifeTimeMin,float lifeTimeMax); /** * @brief Defines whether to generate immortal particles or not * * Immortal particles will still be given a life time. However the age of immortal particles will not increase so that they cannot die. * An immortal Particle whose Model immortality is unset will grow older again.
* The immortality is therefore dynamic and can be granted or removed by impacting all particles generated under this Model. * * @param immortal : whether the Model will generate immortal particles or not */ inline void setImmortal(bool immortal); /** * @brief Sets a given parameter with 4 values * * This method will only set parameters that are enabled, mutable and random.
* If not nothing will happen and the method will return false. * * @param type : the parameter to set * @param startMin : the minimum value at the Particle birth * @param startMax : the maximum value at the Particle birth * @param endMin : the minimum value at the Particle death * @param endMax : the maximum value at the Particle death * @return true if the parameter can be set (right flags), false otherwise */ bool setParam(ModelParam type,float startMin,float startMax,float endMin,float endMax); /** * @brief Sets a given parameter with 2 values * * This method will only set parameters that are enabled and either mutable or random.
* If not nothing will happen and the method will return false.
*
* In case of a mutable parameter : value0 defines the birth value and value0 defines the death value.
* In case of a random parameter : value0 defines the minimum value and value1 defines the maximum value.
* * @param type : the parameter to set * @param value0 : the first value (the meaning depends on the flag) * @param value1 : the second value (the meaning depends on the flag) * @return true if the parameter can be set (right flags), false otherwise */ bool setParam(ModelParam type,float value0,float value1); /** * @brief Sets a given parameter with 1 value * * This method will only set parameters that are enabled and neither mutable or random.
* If not nothing will happen and the method will return false.
*
* Note that to set the value of an interpolated parameter cannot be set with this function, * you must used the interpolator object associated to the parameter to control its value. * * @param type : the parameter to set * @param value : the value of the parameter * @return true if the parameter can be set (right flags), false otherwise */ bool setParam(ModelParam type,float value); ///////////// // Getters // ///////////// /** * @brief Gets the minimum life time * @return the minimum life time */ inline float getLifeTimeMin() const; /** * @brief Gets the maximum life time * @return the minimum life time */ inline float getLifeTimeMax() const; /** * @brief Returns whether immortility is set or not * @return whether immortility is set or not */ inline bool isImmortal() const; /** * @brief Checks whether a parameter is enabled or not * @param type : the parameter * @return 0 is the parameter is not enabled, a flag with the parameter bit set otherwise */ inline int isEnabled(ModelParam type) const; /** * @brief Checks whether a parameter is mutable or not * @param type : the parameter * @return 0 is the parameter is not mutable, a flag with the parameter bit set otherwise */ inline int isMutable(ModelParam type) const; /** * @brief Checks whether a parameter is random or not * @param type : the parameter * @return 0 is the parameter is not random, a flag with the parameter bit set otherwise */ inline int isRandom(ModelParam type) const; /** * @brief Checks whether a parameter is interpolated or not * @param type : the parameter * @return 0 is the parameter is not interpolated, a flag with the parameter bit set otherwise * @since 1.05.00 */ inline int isInterpolated(ModelParam type) const; /** * @brief Gets a parameter value * * If index is superior or equal to the number of values for the parameter, the default value of the parameter is returned.
* Otherwise the value returned depending on the index is : * * * Note that in case of an interpolated parameter, the default value is always returned.
* The user has to use the interpolator object associated to the parameter to get its values. * * @param type : the parameter * @param index : the index of the value to get * @return the value */ float getParamValue(ModelParam type,size_t index) const; /** * @brief Gets the number of values for a parameter * * The number of values depends on the Model flags : * * @param type : the parameter * @return the number of values stored in the Model for the parameter */ unsigned int getNbValues(ModelParam type) const; /** * @brief Gets the number of enabled parameters * @return the number of enabled parameters in the model * @since 1.05.00 */ inline size_t getNbEnabled() const; /** * @brief Gets the number of mutable parameters * @return the number of mutable parameters in the model * @since 1.05.00 */ inline size_t getNbMutable() const; /** * @brief Gets the number of random parameters * @return the number of random parameters in the model * @since 1.05.00 */ inline size_t getNRandom() const; /** * @brief Gets the interpolator for the given parameter * @param param : the parameter whose intepolator must be retrieved * @return a pointer to the interpolator of the given parameter or NULL if the parameter is not interpolated * @since 1.05.00 */ inline Interpolator* getInterpolator(ModelParam param); /** * @brief Gets the number of interpolated parameters * @return the number of interpolated parameters in the model * @since 1.05.00 */ inline size_t getNbInterpolated() const; /** * @brief Gets the number of float values in the particle current array * * The particle current array holds the current values of enabled parameters for a particle.
* This is used internally and should not be needed by the user. * * @return the number of float values in the particle current array * @since 1.02.00 */ inline size_t getSizeOfParticleCurrentArray() const; /** * @brief Gets the number of float values in the particle extended array * * The particle extended array holds the extended values needed for parameters interpolation for a particle.
* This is used internally and should not be needed by the user. * * @return the number of float values in the particle extended array * @since 1.03.00 */ inline size_t getSizeOfParticleExtendedArray() const; /** * @brief Gets the number of float values in the model array * * This is used internally and should not be needed by the user. * * @return the number of float values in the model array * @since 1.02.00 */ inline size_t getSizeOfModelArray() const; /** * @brief Gets the offset of the given parameter in the current array * * This methods is used internally by the engine * * @param param : the parameter * @return the offset of the given parameter in the current array * @since 1.03.00 */ inline size_t getParameterOffset(ModelParam param) const; /** * @brief Gets the default value of the parameter * @param param : the parameter to get the default value from * @return the default value of the parameter * @since 1.05.00 */ static float getDefaultValue(ModelParam param); private : // total number of parameters static const size_t NB_PARAMS = 12; // default values for the parameters static const float DEFAULT_VALUES[NB_PARAMS]; // arrays storing the values of parameters for the model following that form : // enable : 1 value -> value // mutable : 2 values -> start value | end value // random : 2 values -> min value | max value // mutable and random : 4 values -> start min value | start max value | end min value | end max value // interpolated : 0 value float* params; size_t paramsSize; // array storing the parameters that are enabled size_t nbEnableParams; int* enableParams; // array storing the parameters that are mutable size_t nbMutableParams; int* mutableParams; // array storing the parameters that are interpolated size_t nbInterpolatedParams; int* interpolatedParams; // nb of random parameters size_t nbRandomParams; // array of interpolators Interpolator* interpolators[NB_PARAMS]; // the flags of the model int enableFlag; int mutableFlag; int randomFlag; int interpolatedFlag; int particleEnableIndices[NB_PARAMS]; // array storing the index of a parameter in the enableParams array int particleMutableIndices[NB_PARAMS]; // array storing the index of a parameter in the mutableParams array int indices[NB_PARAMS]; // array storing the index of a parameter in the model param array float lifeTimeMin; float lifeTimeMax; bool immortal; void initParamArrays(const Model& model); }; inline Model* Model::create(int enableFlag,int mutableFlag,int randomFlag,int interpolatedFlag) { Model* obj = new Model(enableFlag,mutableFlag,randomFlag,interpolatedFlag); registerObject(obj); return obj; } inline void Model::setLifeTime(float lifeTimeMin,float lifeTimeMax) { this->lifeTimeMin = lifeTimeMin; this->lifeTimeMax = lifeTimeMax; } inline void Model::setImmortal(bool immortal) { this->immortal = immortal; } inline float Model::getLifeTimeMin() const { return lifeTimeMin; } inline float Model::getLifeTimeMax() const { return lifeTimeMax; } inline bool Model::isImmortal() const { return immortal; } inline int Model::isEnabled(ModelParam type) const { return enableFlag & (1 << type); } inline int Model::isMutable(ModelParam type) const { return mutableFlag & (1 << type); } inline int Model::isRandom(ModelParam type) const { return randomFlag & (1 << type); } inline int Model::isInterpolated(ModelParam type) const { return interpolatedFlag & (1 << type); } inline size_t Model::getNbEnabled() const { return nbEnableParams; } inline size_t Model::getNbMutable() const { return nbMutableParams; } inline size_t Model::getNRandom() const { return nbRandomParams; } inline Interpolator* Model::getInterpolator(ModelParam param) { return interpolators[param]; } inline size_t Model::getNbInterpolated() const { return nbInterpolatedParams; } inline size_t Model::getSizeOfParticleCurrentArray() const { return nbEnableParams; } inline size_t Model::getSizeOfParticleExtendedArray() const { return nbMutableParams + (nbInterpolatedParams << 1) + nbInterpolatedParams; // nbMutable + nbInterpolated * 3 } inline size_t Model::getSizeOfModelArray() const { return paramsSize; } inline size_t Model::getParameterOffset(ModelParam param) const { return particleEnableIndices[param]; } } #endif