////////////////////////////////////////////////////////////////////////////////// // 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_PARTICLE #define H_SPK_PARTICLE #include "Core/SPK_DEF.h" #include "Core/SPK_Vector3D.h" #include "Core/SPK_Pool.h" #include "Core/SPK_Model.h" namespace SPK { /** * @class Particle * @brief A single particle (a point in space with a velocity and different parameters) * * A Particle is the primitive on which all the SPARK engine relies.
* Particles are designed to be handled in large amounts (called Group). * This is why the user cannot update or render directly a single Particle.
*
* Note that the Particle class is only a class that presents an interface to the user (since 1.02.00), particles data are stored in the groups. * This is why copying a Particle will not copy its data.
*/ class SPK_PREFIX Particle { friend inline bool isFurtherToCamera(const Particle&,const Particle&); friend void swapParticles(Particle& a,Particle& b); friend class Group; friend class Pool; public : /** * @brief Sets the current value for the given parameter * * Note that the method will have no effect if the parameter is not enabled in the Particle's Model. * In this case, the method returns false. * * @param type : the parameter to set * @param value : the value of the parameter * @return true if the parameter can be set, false otherwise (if the parameter is not enabled) */ bool setParamCurrentValue(ModelParam type,float value); /** * @brief Sets the final value for the given parameter * * The final value is the value the parameter will have at the end of the Particle's life.
* Note that the method will have no effect if the parameter is not mutable in the Particle's Model. * In this case, the method returns false and setParamCurrentValue(ModelParam,float) should be used. * * @param type : the parameter to set * @param value : the value of the parameter * @return true if the parameter can be set, false otherwise (if the parameter is not mutable) */ bool setParamFinalValue(ModelParam type,float value); /** * @brief Changes the current value for the given parameter * * The delta is added to the current value of the parameter.
* For more information see setParamCurrentValue(ModelParam,float). * * @param type : the parameter to set * @param delta : the delta * @return true if the parameter can be changed, false otherwise (if the parameter is not enabled) * @since 1.02.00 */ bool changeParamCurrentValue(ModelParam type,float delta); /** * @brief Changes the final value for the given parameter * * The delta is added to the final value of the parameter.
* For more information see setParamFinalValue(ModelParam,float). * * @param type : the parameter to set * @param delta : the delta * @return true if the parameter can be changed, false otherwise (if the parameter is not mutable) * @since 1.02.00 */ bool changeParamFinalValue(ModelParam type,float delta); /** * @brief Sets the life left of the Particle. * * When the Particle's life reaches 0, the Particle is inactivated. * * @param life : the amount of life left of the Particle */ inline void setLifeLeft(float life); ///////////// // Getters // ///////////// /** * @brief Gets the position of the Particle * @return the position of this Particle * @since 1.02.00 */ inline Vector3D& position(); /** * @brief Gets the velocity of the Particle * @return the velocity of this Particle * @since 1.02.00 */ inline Vector3D& velocity(); /** * @brief Gets the old position of the Particle * @return the old position of this Particle * @since 1.02.00 */ inline Vector3D& oldPosition(); /** * @brief Gets the position of the Particle * * This is the constant version of position() * * @return the position of this Particle * @since 1.02.00 */ inline const Vector3D& position() const; /** * @brief Gets the velocity of the Particle * * This is the constant version of velocity() * * @return the velocity of this Particle * @since 1.02.00 */ inline const Vector3D& velocity() const; /** * @brief Gets the old position of the Particle * * This is the constant version of oldPosition() * * @return the old position of this Particle * @since 1.02.00 */ inline const Vector3D& oldPosition() const; /** * @brief Gets the current value for the given parameter * * Note that if the the parameter is not enabled in the Particle's Model, the default value for the parameter is returned. * * @param type : the parameter to get the value * @return the current value of the parameter */ float getParamCurrentValue(ModelParam type) const; /** * @brief Gets the final value for the given parameter * * Note that if the the parameter is not enabled in the Particle's Model, the default value for the parameter is returned.
* If the parameter is enabled but not mutable, the current value is returned. * * @param type : the parameter to get the value * @return the current value of the parameter */ float getParamFinalValue(ModelParam type) const; /** * @brief Gets the Model of this Particle * @return A pointer on the Model of this Particle */ Model* getModel() const; /** * @brief Gets the group of this Particle * @return A pointer on the Group of this Particle * @since 1.02.00 */ inline Group* getGroup() const; /** * @brief Gets the index of this Particle in its Group * @return the index of thi Particle in its Group * @since 1.03.00 */ inline size_t getIndex() const; /** * @brief Gets the amount of life left of the Particle * * The life left of the Particle is the time left before the Particle dies.
* Note that in case of immortal particles, this value does not evolve. * * @return the amount of life left */ inline float getLifeLeft() const; /** * @brief Gets the age of the Particle * * The age of a Particle starts at zero when it is initialized and evolve at each update.
* Note that even immortal particles gets older. * * @return the age of the particle * @since 1.03.00 */ inline float getAge() const; /** * @brief Gets the distance of this Particle from the camera. * * Note that the correct distance is only returned if the Group of this Particles has its distance computation enabled. * * @return the distance of this Particle from the camera * @since 1.01.00 */ inline float getDistanceFromCamera() const; /** * @brief Gets the square distance of this Particle from the camera. * * Note that the correct distance is only returned if the Group of this Particles has its distance computation enabled.
* This method is faster than getDistanceFromCamera() and should be used instead when possible. * * @return the square distance of this Particle from the camera * @since 1.01.00 */ inline float getSqrDistanceFromCamera() const; /** * @brief Tells whether this Particle was initialized at its latest update or not * * A call to this method is equivalent to getAge() == 0.0f * * @return true if this Particle was initialized at its latest update, false if not * @since 1.03.00 */ inline bool isNewBorn() const; /** * @brief Tells whether this Particle is alive or not * * A call to this method is equivalent to getLifeLeft > 0.0f * * @return true if this Particle is alive, false if it is dead * @since 1.04.00 */ inline bool isAlive() const; /////////////// // Interface // /////////////// /** * @brief Initializes the Particle * * When a Particle is initialized, all its parameters are reinitialized as well as its life. */ void init(); /** * @brief Kills this Particle * * This method is equivalent to a call to setLifeLeft(float) with life being 0.
* * @since 1.01.00 */ inline void kill(); // As we know the color component are always enabled, we optimizes it a bit for access inline float getR() const { return currentParams[PARAM_RED]; } inline float getG() const { return currentParams[PARAM_GREEN]; } inline float getB() const { return currentParams[PARAM_BLUE]; } private : struct ParticleData { Vector3D oldPosition; Vector3D position; Vector3D velocity; float age; float life; float sqrDist; }; Group* group; size_t index; ParticleData* data; float* currentParams; float* extendedParams; Particle(Group* group,size_t index); bool update(float timeDelta); void computeSqrDist(); void interpolateParameters(); }; inline Group* Particle::getGroup() const { return group; } inline size_t Particle::getIndex() const { return index; } inline void Particle::setLifeLeft(float life) { data->life = life; } inline Vector3D& Particle::position() { return data->position; } inline Vector3D& Particle::velocity() { return data->velocity; } inline Vector3D& Particle::oldPosition() { return data->oldPosition; } inline const Vector3D& Particle::position() const { return data->position; } inline const Vector3D& Particle::velocity() const { return data->velocity; } inline const Vector3D& Particle::oldPosition() const { return data->oldPosition; } inline float Particle::getLifeLeft() const { return data->life; } inline float Particle::getAge() const { return data->age; } inline float Particle::getDistanceFromCamera() const { return std::sqrt(data->sqrDist); } inline float Particle::getSqrDistanceFromCamera() const { return data->sqrDist; } inline bool Particle::isNewBorn() const { return data->age == 0.0f; } inline bool Particle::isAlive() const { return data->life > 0.0f; } inline void Particle::kill() { data->life = 0.0f; } // specialization of the swap for particle template<> inline void Pool::swapElements(Particle& a,Particle& b) { swapParticles(a,b); } ////////////////////////////////// // Global functions definitions // ////////////////////////////////// inline bool isFurtherToCamera(const Particle& a, const Particle& b) { return a.getSqrDistanceFromCamera() > b.getSqrDistanceFromCamera(); } // Swaps particle data. Used internally. Do not use with particles that are not from the same group ! extern void swapParticles(Particle& a,Particle& b); } #endif