add sparkle explosions

This commit is contained in:
gmueller
2011-01-05 23:02:10 +01:00
parent b19f44ec32
commit a02ad6bd34
106 changed files with 19753 additions and 88 deletions

View File

@ -0,0 +1,165 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_COLLISION
#define H_SPK_COLLISION
#include "Core/SPK_Modifier.h"
#include "Core/SPK_Particle.h"
namespace SPK
{
/**
* @class Collision
* @brief A Modifier that perfoms particle against particle collisions in the Group
*
* The collision between particles uses the size of the particle to determine its radius.<br>
* The radius of a particle is computed as follows :
* <i>radius = size * scale * 0.5f</i><br>
* <br>
* Moreover the mass ratio of two particles colliding is used to get realistic collision.<br>
* <br>
* The collision can be set as being elastic or inelastic. This is determined thanks to the elasticity of this modifier :
* <ul>
* <li>An elasticity of 1.0f means the collision is fully elastic</li>
* <li>An elasticity of 0.0f means the collision is fully inelastic</li>
* <li>An elasticity superior to 1.0f means the collision creates energy. It is physically not possible but can however be set</li>
* <li>An elasticity inferior to 0.0f has no sens and cannot be set</li>
* <li>To simulate collisions the elasticity will generally be set between ]0.0f,1.0f[ depending on the material of the particle</li>
* </ul>
* Note that collision particle vs particles requires intensive processing.
* Moreover the algorithm has a complexity that badly scales which means processing times increase fastly as particles count increase.<br>
* Tries to limitate the number of particles to perform collision on. More than 1000 particles can require a lot of processing time even of recent hardware.<br>
* <br>
* The accuracy of the collisions is better with small update steps.
* Therefore try to keep the update time small by for instance multiplying the number of updates per frame.
*
* @since 1.04.00
*/
class SPK_PREFIX Collision : public Modifier
{
SPK_IMPLEMENT_REGISTERABLE(Collision)
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief Constructor of the Collision modifier
* @param scale : the scale of the particles
* @param elasticity : the elasticity of the collisions
*/
Collision(float scale = 1.0f,float elasticity = 1.0f);
/**
* @brief Creates and registers a new Collision
* @param scale : the scale of the particles
* @param elasticity : the elasticity of the collisions
* @since 1.04.00
*/
static inline Collision* create(float scale = 1.0f,float elasticity = 1.0f);
/////////////
// Setters //
/////////////
/**
* @brief Sets the scale of particles to compute their radius
*
* The radius of a particle is computed as follows :<br>
* <i>radius = size * scale * 0.5f</i><br>
*
* @param scale : the scale of the particles
*/
inline void setScale(float scale);
/**
* @brief Sets the elasticity of the collisions
*
* The elasticity of the collisions refers to the coefficient of restitution (also called bounciness).<br>
* See the class description for more information.
*
* @param elasticity : the elasticity of the collisions
*/
inline void setElasticity(float elasticity);
/////////////
// Getters //
/////////////
/**
* @brief Gets the elasticity of the collisions
* @return the elasticity of the collisions
*/
inline float getElasticity() const;
/**
* @brief Gets the scale applied on particle radius
* @return the scale
*/
inline float getScale() const;
private :
float elasticity;
float scale;
virtual void modify(Particle& particle,float deltaTime) const;
static inline void getMinMax(const Vector3D& v0,const Vector3D& v1,Vector3D& min,Vector3D& max);
static inline bool checkBoundingRect(const Vector3D& min1,const Vector3D& max1,const Vector3D& min2,const Vector3D& max2);
};
inline Collision* Collision::create(float scale,float elasticity)
{
Collision* obj = new Collision(scale,elasticity);
registerObject(obj);
return obj;
}
inline void Collision::setElasticity(float elasticity)
{
if (elasticity >= 0.0f)
this->elasticity = elasticity;
}
inline void Collision::setScale(float scale)
{
this->scale = scale;
}
inline float Collision::getElasticity() const
{
return elasticity;
}
inline float Collision::getScale() const
{
return scale;
}
}
#endif

View File

@ -0,0 +1,76 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_DESTROYER
#define H_SPK_DESTROYER
#include "Core/SPK_Modifier.h"
namespace SPK
{
/**
* @class Destroyer
* @brief A Modifier that destroy particles
*/
class SPK_PREFIX Destroyer : public Modifier
{
SPK_IMPLEMENT_REGISTERABLE(Destroyer)
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief Constructor of Destroyer
* @param zone : the Zone of the Destroyer
* @param trigger : the trigger of the Destroyer
*/
Destroyer(Zone* zone = NULL,ModifierTrigger trigger = INSIDE_ZONE);
/**
* @brief Creates and registers a new Destroyer
* @param zone : the Zone of the Destroyer
* @param trigger : the trigger of the Destroyer
* @return A new registered Destroyer
* @since 1.04.00
*/
static inline Destroyer* create(Zone* zone = NULL,ModifierTrigger trigger = INSIDE_ZONE);
private :
virtual void modify(Particle& particle,float deltaTime) const;
virtual void modifyWrongSide(Particle& particle,bool inside) const;
};
inline Destroyer* Destroyer::create(Zone* zone,ModifierTrigger trigger)
{
Destroyer* obj = new Destroyer(zone,trigger);
registerObject(obj);
return obj;
}
}
#endif

View File

@ -0,0 +1,209 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_LINEARFORCE
#define H_SPK_LINEARFORCE
#include "Core/SPK_Modifier.h"
#include "Core/SPK_Model.h"
namespace SPK
{
/**
* @enum ForceFactor
* @brief An enum defining the way a factor is applied to a force
* @since 1.03.00
*/
enum ForceFactor
{
FACTOR_NONE, /**< No factor is applied */
FACTOR_LINEAR, /**< A linear factor is applied */
FACTOR_SQUARE, /**< A square factor is applied */
};
/**
* @class LinearForce
* @brief A Modifier applying a linear force on particles
*
* The force is identical from any points of the universe (only if the modifier is triggered).<br>
* In that way, particles under the influence of a LinearForce can theorically reach an infinite speed if not
* under the influence of a friction.<br>
* <br>
* The force can be multiplied or not by a particle parameter either linearly or squared.
* <br>
* Note that this Modifier can be used to set a global gravity that can be updated for all groups at a time.<br>
* To do so, the LinearForce has to be used with the param : <i>PARAM_MASS</i> and the FactorType <i>FACTOR_LINEAR</i>.
*
* @since 1.03.00
*/
class SPK_PREFIX LinearForce : public Modifier
{
SPK_IMPLEMENT_REGISTERABLE(LinearForce)
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief Default constructor for LinearForce
* @param zone : the Zone of the LinearForce or NULL if no Zone
* @param trigger : the trigger of the LinearForce
* @param force : the force of the LinearForce
* @param type : the type of multiplier for the factor
* @param param : the parameter used as the factor (if type != FACTOR_NONE)
*/
LinearForce(Zone* zone = NULL,
ModifierTrigger trigger = INSIDE_ZONE,
const Vector3D& force = Vector3D(),
ForceFactor type = FACTOR_NONE,
ModelParam param = PARAM_SIZE);
/**
* @brief Creates and registers a new LinearForce
* @param zone : the Zone of the LinearForce or NULL if no Zone
* @param trigger : the trigger of the LinearForce
* @param force : the force of the LinearForce
* @param type : the type of multiplier for the factor
* @param param : the parameter used as the factor (if type != FACTOR_NONE)
* @return A new registered LinearForce
* @since 1.04.00
*/
static inline LinearForce* create(Zone* zone = NULL,
ModifierTrigger trigger = INSIDE_ZONE,
const Vector3D& force = Vector3D(),
ForceFactor type = FACTOR_NONE,
ModelParam param = PARAM_SIZE);
/////////////
// Setters //
/////////////
/**
* @brief Sets the force vector
* @param force : the force vector
* @since 1.03.02
*/
inline void setForce(const Vector3D& force);
/**
* @brief Sets the factor type to apply to the force
* @param type : the type of multiplier for the factor
* @param param : the parameter of the Particle to use as the factor
*/
inline void setFactor(ForceFactor type,ModelParam param = PARAM_SIZE);
/////////////
// Getters //
/////////////
/**
* @brief Gets the force vector
* @return the force vector
* @since 1.03.02
*/
inline const Vector3D& getForce() const;
/**
* @brief Gets the transformed force vector
* @return the transformed force vector
* @since 1.03.02
*/
inline const Vector3D& getTransformedForce() const;
/**
* @brief Gets the factor multiplier of this LinearForce
* @return the factor multiplier of this LinearForce
*/
inline ForceFactor getFactorType() const;
/**
* @brief Gets the factor parameter of this LinearForce
* @return the factor parameter of this LinearForce
*/
inline ModelParam getFactorParam() const;
protected :
virtual inline void innerUpdateTransform();
private :
Vector3D force;
Vector3D tForce;
ForceFactor factorType;
ModelParam factorParam;
virtual void modify(Particle& particle,float deltaTime) const;
};
inline LinearForce* LinearForce::create(Zone* zone,ModifierTrigger trigger,const Vector3D& force,ForceFactor type,ModelParam param)
{
LinearForce* obj = new LinearForce(zone,trigger,force,type,param);
registerObject(obj);
return obj;
}
inline void LinearForce::setForce(const Vector3D& force)
{
this->force = tForce = force;
notifyForUpdate();
}
inline void LinearForce::setFactor(ForceFactor type,ModelParam param)
{
factorType = type;
factorParam = param;
}
inline const Vector3D& LinearForce::getForce() const
{
return force;
}
inline const Vector3D& LinearForce::getTransformedForce() const
{
return tForce;
}
inline ForceFactor LinearForce::getFactorType() const
{
return factorType;
}
inline ModelParam LinearForce::getFactorParam() const
{
return factorParam;
}
inline void LinearForce::innerUpdateTransform()
{
Modifier::innerUpdateTransform();
transformDir(tForce,force);
}
}
#endif

View File

@ -0,0 +1,287 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_MODIFIERGROUP
#define H_SPK_MODIFIERGROUP
#include "Core/SPK_Modifier.h"
#include "Core/SPK_Particle.h"
#include "Core/SPK_Zone.h"
namespace SPK
{
/**
* @class ModifierGroup
* @brief A Group of Modifiers
*
* This modifier can be used in 2 ways :
* <ul>
* <li>Partition group : to partition the universe and make a global light test before testing inner modifiers more precisely.</li>
* <li>Global group : To activate several modifiers with a single trigger.</li>
* </ul>
* By default a ModifierGroup is used as a partition group. the user can change it by calling useGlobalGroup(bool,bool) or usePartitionGroup(bool).
*
* @since 1.02.00
*/
class SPK_PREFIX ModifierGroup : public Modifier
{
SPK_IMPLEMENT_REGISTERABLE(ModifierGroup)
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief Constructor of ModifierGroup
* @param zone : the Zone of this ModifierGroup
* @param trigger : the trigger of the ModifierGroup
*/
ModifierGroup(Zone* zone = NULL,ModifierTrigger trigger = INSIDE_ZONE);
/**
* @brief Creates and registers a new ModifierGroup
* @param zone : the Zone of this ModifierGroup
* @param trigger : the trigger of the ModifierGroup
* @return A new registered ModifierGroup
* @since 1.04.00
*/
static inline ModifierGroup* create(Zone* zone = NULL,ModifierTrigger trigger = INSIDE_ZONE);
/////////////
// Setters //
/////////////
/**
* @brief Uses this ModifierGroup as a global group
*
* A global group allows to use only one trigger for many modifiers. It works as follow :<ul>
* <li>If the trigger of the partition group is activated, then the all children modifiers are activated no matter their Zone.</li>
* <li>The same happens for the wrong side.</li>
* </ul>
* Note that if a child Modifier needs intersection or normal computation (the Modifier Obstacle for instance), the variables have to be set.
*
* @param useIntersection : true to enable intersection computation in this ModifierGroup
* @param useNormal : true to enable normal computation in this ModifierGroup
*/
inline void useGlobalGroup(bool useIntersection = false,bool useNormal = false);
/**
* @brief Uses this ModifierGroup as a partition group
*
* A partition group allows to partition the space in order to have faster tests. It works as follow :<ul>
* <li>If the trigger of the partition group is activated, then modifiers within are tested to check if they are triggered.</li>
* <li>If yes, the Modifier is activated, if no, nothing happens.</li>
* <li>If handleWrongSize if set, the isWrongSide() method of the partition group calls the isWrongSide() of its children if it has to.</li>
* </ul>
*
* @param handleWrongSide : true to enable intersection computation in this ModifierGroup
*/
inline void usePartitionGroup(bool handleWrongSide = false);
/////////////
// Getters //
/////////////
/**
* @brief Gets the number of modifiers in this ModifierGroup
* @return the number of modifiers in this ModifierGroup
*/
inline size_t getNb() const;
/**
* @brief Gets the vector containing all the children modifiers
* @return the vector containing all the children modifiers
*/
inline const std::vector<Modifier*>& getModifiers() const;
/**
* @brief Tells whether this ModifierGroup is a global group
*
* For more information about global groups, see useGlobalGroup(bool,bool).
*
* @return true if this ModifierGroup is a global group, false if not
*/
inline bool isGlobalGroup() const;
/**
* @brief Tells whether this ModifierGroup is a partition group
*
* For more information about partition groups, see usePartitionGroup(bool).
*
* @return true if this ModifierGroup is a partition group, false if not
*/
inline bool isPartitionGroup() const;
/**
* @brief Tells whether this partition group handles wrong side
*
* If this ModifierGroup is a global group, the return value is not used.<br>
* For more information about partition groups, see usePartitionGroup(bool).<br>
* <br>
* Note that the wrong side can only be used with the following triggers :<ul>
* <li>ModifierTrigger::INSIDE_ZONE</li>
* <li>ModifierTrigger::OUTSIDE_ZONE</li>
* <li>ModifierTrigger::ENTER_ZONE</li>
* <li>ModifierTrigger::EXIT_ZONE</li>
* </ul>
*
* @return true if this ModifierGroup handles wrong size, false if not
*/
inline bool handlesWrongSide() const;
/**
* @brief Tells whether this global group computes the intersection
*
* If this ModifierGroup is a partition group, the return value is not used.<br>
* For more information about global groups, see useGlobalGroup(bool,bool).<br>
* <br>
* Note that the intersection can only be used with the following triggers :<ul>
* <li>ModifierTrigger::INTERSECT_ZONE</li>
* <li>ModifierTrigger::ENTER_ZONE</li>
* <li>ModifierTrigger::EXIT_ZONE</li>
* </ul>
*
* @return true if this ModifierGroup computes the intersection, false if not
*/
inline bool usesIntersection() const;
/**
* @brief Tells whether this global group computes the normal
*
* If this ModifierGroup is a partition group, the return value is not used.<br>
* For more information about global groups, see useGlobalGroup(bool,bool).<br>
* <br>
* Note that the normal can only be used with the following triggers :<ul>
* <li>ModifierTrigger::INTERSECT_ZONE</li>
* <li>ModifierTrigger::ENTER_ZONE</li>
* <li>ModifierTrigger::EXIT_ZONE</li>
* </ul>
*
* @return true if this ModifierGroup computes the normal, false if not
*/
inline bool usesNormal() const;
///////////////
// Interface //
///////////////
/**
* @brief Adds a Modifier to this ModifierGroup
* @param modifier : the Modifier to add to this ModifierGroup
*/
void addModifier(Modifier* modifier);
/**
* @brief Removes a Modifier from this ModifierGroup
* @param modifier : the Modifier to remove from this ModifierGroup
* @return true if the Modifier has been found and removed, false if not
*/
bool removeModifier(const Modifier* modifier);
/**
* @brief Removes all Modifier children from this ModifierGroup
*/
inline void clear();
virtual void createBuffers(const Group& group);
virtual void destroyBuffers(const Group& group);
virtual Registerable* findByName(const std::string& name);
protected :
virtual void registerChildren(bool registerAll);
virtual void copyChildren(const ModifierGroup& modifier,bool createBase);
virtual void destroyChildren(bool keepChildren);
virtual bool checkBuffers(const Group& group);
private :
std::vector<Modifier*> modifiers;
bool globalZone;
bool handleWrongSide;
virtual void modify(Particle& particle,float deltaTime) const;
virtual void modifyWrongSide(Particle& particle,bool inside) const;
};
inline ModifierGroup* ModifierGroup::create(Zone* zone,ModifierTrigger trigger)
{
ModifierGroup* obj = new ModifierGroup(zone,trigger);
registerObject(obj);
return obj;
}
inline void ModifierGroup::useGlobalGroup(bool useIntersection,bool useNormal)
{
globalZone = true;
needsIntersection = useIntersection;
needsNormal = useNormal;
}
inline void ModifierGroup::usePartitionGroup(bool handleWrongSide)
{
globalZone = false;
this->handleWrongSide = handleWrongSide;
}
inline size_t ModifierGroup::getNb() const
{
return modifiers.size();
}
inline const std::vector<Modifier*>& ModifierGroup::getModifiers() const
{
return modifiers;
}
inline bool ModifierGroup::isGlobalGroup() const
{
return globalZone;
}
inline bool ModifierGroup::isPartitionGroup() const
{
return !globalZone;
}
inline bool ModifierGroup::handlesWrongSide() const
{
return handleWrongSide;
}
inline bool ModifierGroup::usesIntersection() const
{
return needsIntersection;
}
inline bool ModifierGroup::usesNormal() const
{
return needsNormal;
}
}
#endif

View File

@ -0,0 +1,148 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_OBSTACLE
#define H_SPK_OBSTACLE
#include "Core/SPK_Modifier.h"
#include "Core/SPK_Particle.h"
#include "Core/SPK_Zone.h"
namespace SPK
{
/**
* @class Obstacle
* @brief A Modifier that acts as an obstacle on particles
*/
class SPK_PREFIX Obstacle : public Modifier
{
SPK_IMPLEMENT_REGISTERABLE(Obstacle)
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief Constructor of Obstacle
* @param zone : the Zone of the Obstacle
* @param trigger : the trigger of the Destructor
* @param bouncingRatio : the bouncingRatio of the Obstacle
* @param friction : the friction of the Obstacle
*/
Obstacle(Zone* zone = NULL,ModifierTrigger trigger = INTERSECT_ZONE,float bouncingRatio = 1.0f,float friction = 1.0f);
/**
* @brief Creates and registers a new Obstacle
* @param zone : the Zone of the Obstacle
* @param trigger : the trigger of the Destructor
* @param bouncingRatio : the bouncingRatio of the Obstacle
* @param friction : the friction of the Obstacle
* @return A new registered Obstacle
* @since 1.04.00
*/
static inline Obstacle* create(Zone* zone = NULL,ModifierTrigger trigger = INTERSECT_ZONE,float bouncingRatio = 1.0f,float friction = 1.0f);
/////////////
// Setters //
/////////////
/**
* @brief Sets the bouncing ratio of this Obstacle
*
* The bouncing ratio is the multiplier applied to the normal component of the rebound.
*
* @param bouncingRatio : the bouncing ratio of this Obstacle
*/
inline void setBouncingRatio(float bouncingRatio);
/**
* @brief Sets the friction of this Obstacle
*
* The bouncing ratio is the multiplier applied to the tangent component of the rebound.
*
* @param friction : the friction of this Obstacle
*/
inline void setFriction(float friction);
/////////////
// Getters //
/////////////
/**
* @brief Gets the bouncing ratio of this Obstacle
* @return the bouncing ratio of this Obstacle
*/
inline float getBouncingRatio() const;
/**
* @brief Gets the friction of this Obstacle
* @return the friction of this Obstacle
*/
inline float getFriction() const;
private :
float bouncingRatio;
float friction;
virtual void modify(Particle& particle,float deltaTime) const;
virtual inline void modifyWrongSide(Particle& particle,bool inside) const;
};
inline Obstacle* Obstacle::create(Zone* zone,ModifierTrigger trigger,float bouncingRatio,float friction)
{
Obstacle* obj = new Obstacle(zone,trigger,bouncingRatio,friction);
registerObject(obj);
return obj;
}
inline void Obstacle::setBouncingRatio(float bouncingRatio)
{
this->bouncingRatio = bouncingRatio < 0.0f ? 0.0f : bouncingRatio;
}
inline void Obstacle::setFriction(float friction)
{
this->friction = friction;
}
inline float Obstacle::getBouncingRatio() const
{
return bouncingRatio;
}
inline float Obstacle::getFriction() const
{
return friction;
}
inline void Obstacle::modifyWrongSide(Particle& particle,bool inside) const
{
if (isFullZone())
getZone()->moveAtBorder(particle.position(),inside);
}
}
#endif

View File

@ -0,0 +1,199 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_POINTMASS
#define H_SPK_POINTMASS
#include "Core/SPK_Modifier.h"
namespace SPK
{
/**
* @class PointMass
* @brief A Modifier defining a point with a mass that attracts or repulses particles
*
* A PointMass triggered on a Particle will affect its velocity as followed :<br>
* <i>dist = pointMassPosition - particlePosition<br>
* particleVelocity += dist * mass * step / max(minDistance,|dist|)</i>
*/
class SPK_PREFIX PointMass : public Modifier
{
SPK_IMPLEMENT_REGISTERABLE(PointMass)
public :
////////////////
// Construtor //
////////////////
/**
* @brief Constructor of PointMass
* @param zone : the Zone of the PointMass
* @param trigger : the trigger of the PointMass
* @param mass : the mass of the PointMass
* @param minDistance : the minimum distance of the PointMass
*/
PointMass(Zone* zone = NULL,ModifierTrigger trigger = INSIDE_ZONE,float mass = 1.0f,float minDistance = 0.05f);
/**
* @brief Creates and registers a new PointMass
* @param zone : the Zone of the PointMass
* @param trigger : the trigger of the PointMass
* @param mass : the mass of the PointMass
* @param minDistance : the minimum distance of the PointMass
* @return A new registered PointMass
* @since 1.04.00
*/
static inline PointMass* create(Zone* zone = NULL,ModifierTrigger trigger = INSIDE_ZONE,float mass = 1.0f,float minDistance = 0.05f);
/////////////
// Setters //
/////////////
/**
* @brief Sets the delta position from the position of the zone (or origin if no zone set)
* @param pos : the delta position
* @since 1.03.02
*/
inline void setPosition(const Vector3D& pos);
/**
* @brief Sets the mass of this PointMass
*
* The mass defines the strenght of the attraction. The more the mass, the stronger the attraction.<br>
* A position mass will result into an attraction while a negative mass will result into a repulsion.
* Moreover a mass equal to 0 make the PointMass have no effect.
*
* @param mass : the mass of this PointMass
*/
inline void setMass(float mass);
/**
* @brief Sets the minimum distance of this PointMass
*
* The minimum distance of the PointMass is the minimum distance that can be considered to compute the force implied by the PointMass.
* If a distance between a Particle and a PointMass is inferior to the minimum distance of the PointMass, the distance is clamped to the minimum distance.<br>
* This avoids forces that approaching the infinity with Particle getting very close to the PointMass.
*
* @param minDistance : the minimum distance of this PointMass
*/
inline void setMinDistance(float minDistance);
/////////////
// Getters //
/////////////
/**
* @brief Gets the delta position
* @return the delta position
* @since 1.03.02
*/
inline const Vector3D& getPosition() const;
/**
* @brief Gets the transformed delta position
* @return the transformed delta position
* @since 1.03.02
*/
inline const Vector3D& getTransformedPosition() const;
/**
* @brief Gets the mass of this PointMass
* @return the mass of this PointMass
*/
inline float getMass() const;
/**
* @brief Gets the minimum distance of this PointMass
* @return the minimum distance of this PointMass
*/
inline float getMinDistance() const;
protected :
virtual inline void innerUpdateTransform();
private :
Vector3D position;
Vector3D tPosition;
float mass;
float minDistance;
float sqrMinDistance;
virtual void modify(Particle& particle,float deltaTime) const;
};
inline PointMass* PointMass::create(Zone* zone,ModifierTrigger trigger,float mass,float minDistance)
{
PointMass* obj = new PointMass(zone,trigger,mass,minDistance);
registerObject(obj);
return obj;
}
inline void PointMass::setPosition(const Vector3D& pos)
{
position = tPosition = pos;
notifyForUpdate();
}
inline void PointMass::setMass(float mass)
{
this->mass = mass;
}
inline void PointMass::setMinDistance(float minDistance)
{
this->minDistance = minDistance;
sqrMinDistance = minDistance * minDistance;
}
inline const Vector3D& PointMass::getPosition() const
{
return position;
}
inline const Vector3D& PointMass::getTransformedPosition() const
{
return tPosition;
}
inline float PointMass::getMass() const
{
return mass;
}
inline float PointMass::getMinDistance() const
{
return minDistance;
}
inline void PointMass::innerUpdateTransform()
{
Modifier::innerUpdateTransform();
transformDir(tPosition,position); // the delta position is actually a direction not a position
}
}
#endif

View File

@ -0,0 +1,84 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_ROTATOR
#define H_SPK_ROTATOR
#include "Core/SPK_Modifier.h"
namespace SPK
{
/**
* @class Rotator
* @brief A Modifier allowing to rotate particle with their rotation speed
*
* Instead of controlling directly the particle angle, this modifier allows to control the particle rotation speed.<br>
* The rotator derives the particle angle from the particle rotation speed.<br>
* <br>
* For this modifier to work, the PARAM_ANGLE must be enabled (and can be random in addition but not mutable or interpolated)
* and the PARAM_ROTATION_SPEED must be at least enabled in the model of the group of particles that are modified.
*
* @since 1.05.00
*/
class Rotator : public Modifier
{
SPK_IMPLEMENT_REGISTERABLE(Rotator)
public :
/////////////////
// Constructor //
/////////////////
/** @brief Constructor of Rotator */
inline Rotator();
/**
* @brief Creates and registers a new Rotator
* @return A new registered Rotator
*/
static inline Rotator* create();
private :
virtual inline void modify(Particle& particle,float deltaTime) const;
};
inline Rotator::Rotator() : Modifier(ALWAYS | INSIDE_ZONE | OUTSIDE_ZONE) {}
inline Rotator* Rotator::create()
{
Rotator* obj = new Rotator;
registerObject(obj);
return obj;
}
inline void Rotator::modify(Particle& particle,float deltaTime) const
{
float angle = particle.getParamCurrentValue(PARAM_ANGLE) + deltaTime * particle.getParamCurrentValue(PARAM_ROTATION_SPEED);
particle.setParamCurrentValue(PARAM_ANGLE,angle);
}
}
#endif

View File

@ -0,0 +1,338 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_VORTEX
#define H_SPK_VORTEX
#include "Core/SPK_Modifier.h"
namespace SPK
{
/**
* @brief A modifier defining a vortex in the universe
*
* A vortex is a spinning flow around a center. Its center (its eye) is defined as a line in the universe.<br>
* In addition to its center line, a vortex is defined by 2 speeds :
* <ul>
* <li>the rotation speed which defines the speed of rotation around the vortex eye.</li>
* <li>the attraction speed which defined the speeds at which a particle is attracted by the eye (or repeled).</li>
* </ul>
* The rotation speed can be defined either in units per second or in radians per seconds. In the first case,
* the closer to the eye particles are, the faster they will spin around. In the second case, the speed is constant.<br>
* <br>
* The attraction speed can be either constant or linear (function of the distance to the eye). In the second case,
* the farther particles are from the eye, the faster the are attracted (or repeled). First case can be assimilated
* to a Archimedes' spiral while second is more a logarithmic spiral (Bernoulli's).
* <br>
* The vertex eye radius can be defined. The user has also the possibility to tell the vortex to destroy particles
* that enter its eye automatically.<br>
* <br>
* Note that this modifier does not update particle's velocity. Therefore particles modified by a vortex does not have any inertia.<br>
* This is because defining an accurate vortex in a discrete environment cannot be performed by using the derivatives of the position and velocity.
*
* @since 1.05.00
*/
class SPK_PREFIX Vortex : public Modifier
{
SPK_IMPLEMENT_REGISTERABLE(Vortex)
public :
//////////////////
// Constructors //
//////////////////
/**
* @brief Constructor of vortex
* @param position : the position of the eye
* @param direction : the direction of the eye
* @param rotationSpeed : the speed of rotation
* @param attractionSpeed : the speed of attraction
*/
Vortex(const Vector3D& position = Vector3D(),const Vector3D& direction = Vector3D(0.0f,1.0f,0.0f),float rotationSpeed = 1.0f,float attractionSpeed = 0.0f);
/**
* @brief Creates and registers a new Vortex
* @param position : the position of the eye
* @param direction : the direction of the eye
* @param rotationSpeed : the speed of rotation
* @param attractionSpeed : the speed of attraction
* @return a new registered vortex
*/
static inline Vortex* create(const Vector3D& position = Vector3D(),const Vector3D& direction = Vector3D(0.0f,1.0f,0.0f),float rotationSpeed = 1.0f,float attractionSpeed = 0.0f);
/////////////
// Setters //
/////////////
/**
* @brief Sets the position of the eye of the vortex
*
* The eye of the vortex is an infinite line defined by a position and a direction.
*
* @param position : the position of the eye of the vortex
*/
inline void setPosition(const Vector3D& position);
/**
* @brief Sets the direction of the eye of the vortex
*
* The eye of the vortex is an infinite line defined by a position and a direction.<br>
* Note that the direction is normalized internally.
*
* @param direction : the direction of the eye of the vortex
*/
inline void setDirection(const Vector3D& direction);
/**
* @brief Sets the rotation speed of the vortex
*
* The rotation speed can either be in units per second or in radians per second (angular).<br>
* In the case the rotation speed is angular, all particles are rotated around the eye at the same speed.<br>
* In the other case, the more particles are close to the eye, the faster they rotate.<br>
* <br>
* The sens of rotation is defined by the sens of the speed (and depends also on whether we are in a right or left handed system).<br>
* A speed of 0 means no rotation.
*
* @param rotationSpeed : the speed of rotation (either in units per unit of time or in radians per unit of time dependent on the second parameter)
* @param angular : true to have the rotation in radians per unit of time, false to have it in unit per unit of time.
*/
inline void setRotationSpeed(float rotationSpeed,bool angular);
/**
* @brief Sets the attraction speed of the vortex
*
* The attraction speed is the speed that move particles towards the eye of the vortex.<br>
* It can either be constant or linear (function of the distance of the particle from the eye).<br>
* <br>
* A constant attraction speed is defined in units per unit of time,
* a linear attraction speed is also defined in units per unit of time and the value is the speed at a distance of 1.0f from the eye.<br>
* <br>
* A negative speed means particles are repelled by the eye.<br>
* A speed of 0.0f means particles are neither attracted nor repelled by the eye of the vortex.
*
* @param attractionSpeed : the attraction speed of the vortex in units per unit of time
* @param linear : true to set the speed function of the distance from the eye, false to set it constant
*/
inline void setAttractionSpeed(float attractionSpeed,bool linear);
/**
* @brief Sets the eye radius
*
* Note that an negative radius is inverted internally
*
* @param eyeRadius : the eye radius
*/
inline void setEyeRadius(float eyeRadius);
/**
* @brief Tells whether particles is the eye must be killed or not
* @param kill : true to kill particles in the eye, false not to
*/
inline void enableParticleKilling(bool kill);
/////////////
// Getters //
/////////////
/**
* @brief Gets the position of the eye
* @return the position of the eye
*/
inline const Vector3D& getPosition() const;
/**
* @brief Gets the direction of the eye
* @return the direction of the eye (normalized)
*/
inline const Vector3D& getDirection() const;
/**
* @brief Gets the transformed position of the eye
* @return the transformed position of the eye
*/
inline const Vector3D& getTransformedPosition() const;
/**
* @brief Gets the transformed direction of the eye
* @return the transformed direction of the eye (normalized)
*/
inline const Vector3D& getTransformedDirection() const;
/**
* @brief Gets the rotation speed
* @return the rotation speed
*/
inline float getRotationSpeed() const;
/**
* @brief Gets the attraction speed
* @return the attraction speed
*/
inline float getAttractionSpeed() const;
/**
* @brief Tells whether rotation speed is angular
* @return true if rotation speed is angular, false if not
*/
inline bool isRotationSpeedAngular() const;
/**
* @brief Tells whether attraction speed is function of the distance from the eye
* @return true if attraction speed is linear, false if it is constant
*/
inline bool isAttractionSpeedLinear() const;
/**
* @brief Returns the eye radius
* @return the eye radius
*/
inline float getEyeRadius() const;
/**
* @brief Tells whether particles are killed when in the eye
* @return true if particles are killed in the eye, false if not
*/
inline bool isParticleKillingEnabled() const;
protected :
virtual void innerUpdateTransform();
private :
Vector3D position;
Vector3D direction;
Vector3D tPosition;
Vector3D tDirection;
float rotationSpeed;
float attractionSpeed;
bool angularSpeedEnabled;
bool linearSpeedEnabled;
float eyeRadius;
bool killingParticleEnabled;
virtual void modify(Particle& particle,float deltaTime) const;
};
inline Vortex* Vortex::create(const Vector3D& position,const Vector3D& direction,float rotationSpeed,float attractionSpeed)
{
Vortex* obj = new Vortex(position,direction,rotationSpeed,attractionSpeed);
registerObject(obj);
return obj;
}
inline void Vortex::setPosition(const Vector3D& position)
{
this->position = position;
tPosition = this->position;
notifyForUpdate();
}
inline void Vortex::setDirection(const Vector3D& direction)
{
this->direction = direction;
this->direction.normalize();
tDirection = this->direction;
notifyForUpdate();
}
inline void Vortex::setRotationSpeed(float rotationSpeed,bool angular)
{
this->rotationSpeed = rotationSpeed;
angularSpeedEnabled = angular;
}
inline void Vortex::setAttractionSpeed(float attractionSpeed,bool linear)
{
this->attractionSpeed = attractionSpeed;
linearSpeedEnabled = linear;
}
inline void Vortex::setEyeRadius(float eyeRadius)
{
if (eyeRadius < 0.0f) eyeRadius = -eyeRadius;
this->eyeRadius = eyeRadius;
}
inline void Vortex::enableParticleKilling(bool kill)
{
killingParticleEnabled = kill;
}
inline const Vector3D& Vortex::getPosition() const
{
return position;
}
inline const Vector3D& Vortex::getDirection() const
{
return direction;
}
inline const Vector3D& Vortex::getTransformedPosition() const
{
return tPosition;
}
inline const Vector3D& Vortex::getTransformedDirection() const
{
return tDirection;
}
inline float Vortex::getRotationSpeed() const
{
return rotationSpeed;
}
inline float Vortex::getAttractionSpeed() const
{
return attractionSpeed;
}
inline bool Vortex::isRotationSpeedAngular() const
{
return angularSpeedEnabled;
}
inline bool Vortex::isAttractionSpeedLinear() const
{
return linearSpeedEnabled;
}
inline float Vortex::getEyeRadius() const
{
return eyeRadius;
}
inline bool Vortex::isParticleKillingEnabled() const
{
return killingParticleEnabled;
}
}
#endif