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,146 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_NORMALEMITTER
#define H_SPK_NORMALEMITTER
#include "Core/SPK_Emitter.h"
namespace SPK
{
/**
* @class NormalEmitter
* @brief An Emitter that emits particles following a Zone normals
*
* The Zone used to derive the direction of emission can either be the Emitter Zone
* or another Zone that can be set with setNormalZone(Zone*).<br>
* If the normal zone is NULL the emitter Zone is used.
*
* @since 1.02.00
*/
class SPK_PREFIX NormalEmitter : public Emitter
{
SPK_IMPLEMENT_REGISTERABLE(NormalEmitter)
public :
//////////////////
// Constructors //
//////////////////
/**
* @brief Constructor of NormalEmitter
* @param normalZone : the Zone used to compute normals (NULL to used the Emitter Zone)
* @param inverted : true to invert the normals, false otherwise
*/
NormalEmitter(Zone* normalZone = NULL,bool inverted = false);
/**
* @brief Creates and registers a new NormalEmitter
* @param normalZone : the Zone used to compute normals (NULL to used the Emitter Zone)
* @param inverted : true to invert the normals, false otherwise
* @return A new registered NormalEmitter
* @since 1.04.00
*/
static inline NormalEmitter* create(Zone* normalZone = NULL,bool inverted = false);
/////////////
// Setters //
/////////////
/**
* @brief Sets whether normals are inverted or not
* @param inverted true to use inverted normals, false not to
*/
inline void setInverted(bool inverted);
/**
* @brief the Zone used to compute normals
*
* Note that if the normal zone is NULL, the Emitter Zone is used.
*
* @param zone : the Zone used to compute normals (NULL to used the Emitter Zone)
*/
void setNormalZone(Zone* zone);
/////////////
// Getters //
/////////////
/**
* @brief Tells whether normals are inverted for this NormalEmitter
* @return true if normals are inverted, false if not
*/
inline bool isInverted() const;
/**
* @brief Gets the normal Zone of this NormalEmitter
* @return the normal Zone of this NormalEmitter
*/
inline Zone* getNormalZone() const;
///////////////
// Interface //
///////////////
virtual Registerable* findByName(const std::string& name);
protected :
virtual void registerChildren(bool registerAll);
virtual void copyChildren(const NormalEmitter& emitter,bool createBase);
virtual void destroyChildren(bool keepChildren);
private :
bool inverted;
Zone* normalZone;
virtual void generateVelocity(Particle& particle,float speed) const;
};
inline NormalEmitter* NormalEmitter::create(Zone* normalZone,bool inverted)
{
NormalEmitter* obj = new NormalEmitter(normalZone,inverted);
registerObject(obj);
return obj;
}
inline void NormalEmitter::setInverted(bool inverted)
{
this->inverted = inverted;
}
inline bool NormalEmitter::isInverted() const
{
return inverted;
}
inline Zone* NormalEmitter::getNormalZone() const
{
return normalZone;
}
}
#endif

View File

@ -0,0 +1,63 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_RANDOMEMITTER
#define H_SPK_RANDOMEMITTER
#include "Core/SPK_Emitter.h"
namespace SPK
{
/**
* @class RandomEmitter
* @brief An Emitter that emits in a random direction
* @since 1.02.00
*/
class SPK_PREFIX RandomEmitter : public Emitter
{
SPK_IMPLEMENT_REGISTERABLE(RandomEmitter)
public :
/**
* @brief Creates and registers a new RandomEmitter
* @return A new registered RandomEmitter
* @since 1.04.00
*/
static inline RandomEmitter* create();
private :
virtual void generateVelocity(Particle& particle,float speed) const;
};
inline RandomEmitter* RandomEmitter::create()
{
RandomEmitter* obj = new RandomEmitter;
registerObject(obj);
return obj;
}
}
#endif

View File

@ -0,0 +1,183 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_SPHERICEMITTER
#define H_SPK_SPHERICEMITTER
#include "Core/SPK_Emitter.h"
namespace SPK
{
/**
* @class SphericEmitter
* @brief An Emitter that emits particles in a portion of sphere
*
* This Emitter can emit particles in a spheric way.
* To do that 2 angles and a direction Vector3D can be parametered :
* <ul>
* <li>The direction Vector3D defines the direction of the emitter.</li>
* <li>The angles defines the area in between which wil be emitted the particles velocities.</li>
* </ul>
* Here are a few examples :
* <ul>
* <li><i>0 and 2 * PI</i> will define a complete sphere ie equivalent to a RandomEmitter</li>
* <li><i>0 and 0</i> will define a Emitter equivalent to a StraightEmitter</li>
* <li><i>PI and PI</i> will define a disk</li>
* <li><i>PI / 2 and PI / 2</i> will define a Cone of angle PI / 2</li>
* <li>...</li>
* </ul>
*/
class SPK_PREFIX SphericEmitter : public Emitter
{
SPK_IMPLEMENT_REGISTERABLE(SphericEmitter)
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief Constructor of SphericEmitter
* @param direction : the direction of the SphericEmitter
* @param angleA : the first angle in radians of the SphericEmitter
* @param angleB : the second angle in radians of the SphericEmitter
*/
SphericEmitter(const Vector3D& direction = Vector3D(0.0f,0.0f,-1.0f),float angleA = 0.0f,float angleB = 0.0f);
/**
* @brief Creates and registers a new SphericEmitter
* @param direction : the direction of the SphericEmitter
* @param angleA : the first angle in radians of the SphericEmitter
* @param angleB : the second angle in radians of the SphericEmitter
* @since 1.04.00
*/
static inline SphericEmitter* create(const Vector3D& direction = Vector3D(0.0f,0.0f,-1.0f),float angleA = 0.0f,float angleB = 0.0f);
/////////////
// Setters //
/////////////
/**
* @brief Sets the direction of this SphericEmitter
*
* Note that it is not necessary to provide a normalized Vector3D.
* This Vector3D only indicates a direction, its norm does not matter.
*
* @param direction : the direction of this SphericEmitter
*/
void setDirection(const Vector3D& direction);
/**
* @brief Sets the angles of this SphericEmitter
*
* Note that angles are clamped between 0 and 2 * PI
* AngleA does not have to be inferior to angleB, it has no importance as angles are sorted within the method.
*
* @param angleA : the first angle in radians of this SphericEmitter
* @param angleB : the second angle in radians of this SphericEmitter
*/
void setAngles(float angleA,float angleB);
/////////////
// Getters //
/////////////
/**
* @brief Gets the direction of this SphericEmitter
* @return the direction of this SphericEmitter
*/
inline const Vector3D& getDirection() const;
/**
* @brief Gets the direction of this SphericEmitter
* @return the direction of this SphericEmitter
*/
inline const Vector3D& getTransformedDirection() const;
/**
* @brief Gets the minimum angle of this SphericEmitter
* @return the minimum angle of this SphericEmitter
*/
inline float getAngleMin() const;
/**
* @brief Gets the maximum angle of this SphericEmitter
* @return the maximum angle of this SphericEmitter
*/
inline float getAngleMax() const;
protected :
virtual void innerUpdateTransform();
private :
static const float PI;
Vector3D direction;
Vector3D tDirection; // transformed direction
float angleMin;
float angleMax;
float cosAngleMin;
float cosAngleMax;
float matrix[9];
void computeMatrix();
virtual void generateVelocity(Particle& particle,float speed) const;
};
inline SphericEmitter* SphericEmitter::create(const Vector3D& direction,float angleA,float angleB)
{
SphericEmitter* obj = new SphericEmitter(direction,angleA,angleB);
registerObject(obj);
return obj;
}
inline const Vector3D& SphericEmitter::getDirection() const
{
return direction;
}
inline const Vector3D& SphericEmitter::getTransformedDirection() const
{
return tDirection;
}
inline float SphericEmitter::getAngleMin() const
{
return angleMin;
}
inline float SphericEmitter::getAngleMax() const
{
return angleMax;
}
}
#endif

View File

@ -0,0 +1,69 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_STATICEMITTER
#define H_SPK_STATICEMITTER
#include "Core/SPK_Emitter.h"
namespace SPK
{
/**
* @class StaticEmitter
* @brief An Emitter that emits particles with no initial velocity
* @since 1.05.00
*/
class StaticEmitter : public Emitter
{
SPK_IMPLEMENT_REGISTERABLE(StaticEmitter)
public :
/**
* @brief Creates and registers a new StaticEmitter
* @return A new registered StaticEmitter
*/
static inline StaticEmitter* create();
private :
virtual inline void generateVelocity(Particle& particle,float speed) const;
};
inline StaticEmitter* StaticEmitter::create()
{
StaticEmitter* obj = new StaticEmitter;
registerObject(obj);
return obj;
}
inline void StaticEmitter::generateVelocity(Particle& particle,float speed) const
{
particle.velocity().set(0.0f,0.0f,0.0f); // no initial velocity
}
}
#endif

View File

@ -0,0 +1,126 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_STRAIGHEMITTER
#define H_SPK_STRAIGHEMITTER
#include "Core/SPK_Emitter.h"
#include "Core/SPK_Particle.h"
namespace SPK
{
/**
* @class StraightEmitter
* @brief An Emitter that emits in a given direction
*/
class SPK_PREFIX StraightEmitter : public Emitter
{
SPK_IMPLEMENT_REGISTERABLE(StraightEmitter)
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief The constructor of StraightEmitter
* @param direction : the direction of the StraighEmitter
*/
StraightEmitter(const Vector3D& direction = Vector3D(0.0f,0.0f,-1.0f));
/**
* @brief Creates and registers a new StraightEmitter
* @param direction : the direction of the StraighEmitter
* @since 1.04.00
*/
static inline StraightEmitter* create(const Vector3D& direction = Vector3D(0.0f,0.0f,-1.0f));
/////////////
// Setters //
/////////////
/**
* @brief Sets the direction of this StraightEmitter
*
* Note that it is not necessary to provide a normalized Vector3D.
* This Vector3D only indicates a direction, its norm does not matter.
*
* @param direction : the direction of this StraightEmitter
*/
void setDirection(const Vector3D& direction);
/////////////
// Getters //
/////////////
/**
* @brief Gets the direction of this StraightEmitter
* @return the direction of this StraightEmitter
*/
inline const Vector3D& getDirection() const;
/**
* @brief Gets the transformed direction of this StraightEmitter
* @return the transformed direction of this StraightEmitter
*/
inline const Vector3D& getTransformedDirection() const;
protected :
virtual void innerUpdateTransform();
private :
Vector3D direction;
Vector3D tDirection;
virtual inline void generateVelocity(Particle& particle,float speed) const;
};
inline StraightEmitter* StraightEmitter::create(const Vector3D& direction)
{
StraightEmitter* obj = new StraightEmitter(direction);
registerObject(obj);
return obj;
}
inline const Vector3D& StraightEmitter::getDirection() const
{
return direction;
}
inline const Vector3D& StraightEmitter::getTransformedDirection() const
{
return tDirection;
}
inline void StraightEmitter::generateVelocity(Particle& particle,float speed) const
{
particle.velocity() = tDirection;
particle.velocity() *= speed;
}
}
#endif

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

View File

@ -0,0 +1,125 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_LINERENDERERINTERFACE
#define H_SPK_LINERENDERERINTERFACE
#include "Core/SPK_DEF.h"
namespace SPK
{
/**
* @brief Base Interface for rendering particles with lines
* @since 1.04.00
*/
class LineRendererInterface
{
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief Constructor of LineRendererInterface
* @param length : the length multiplier of this LineRendererInterface
* @param width : the width of this GLLineRenderer
*/
inline LineRendererInterface(float length = 1.0f,float width = 1.0f);
////////////////
// Destructor //
////////////////
/** @brief Destructor of LineRendererInterface */
virtual inline ~LineRendererInterface() {}
/////////////
// Setters //
/////////////
/**
* @brief Sets the length multiplier of this LineRendererInterface
*
* The length multiplier is the value which will be multiplied by the Particle velocity to get the line length in the universe.<br>
* A positive length means the line will be drawn in advance to the Particle, as opposed to a negative length.
*
* @param length : the length multiplier of this GLLineRenderer
*/
inline void setLength(float length);
/**
* @brief Sets the width of this LineRendererInterface
* @param width : the width of this LineRendererInterface
*/
virtual inline void setWidth(float width);
/////////////
// Getters //
/////////////
/**
* @brief Gets the length multiplier of this LineRendererInterface
* @return the length multiplier of this LineRendererInterface
*/
inline float getLength() const;
/**
* @brief Gets the width of this LineRendererInterface
* @return the width of this LineRendererInterface
*/
inline float getWidth() const;
protected :
float length;
float width;
};
inline LineRendererInterface::LineRendererInterface(float length,float width) :
length(length),
width(width)
{}
inline void LineRendererInterface::setLength(float length)
{
this->length = length;
}
inline void LineRendererInterface::setWidth(float width)
{
this->width = width;
}
inline float LineRendererInterface::getLength() const
{
return length;
}
inline float LineRendererInterface::getWidth() const
{
return width;
}
}
#endif

View File

@ -0,0 +1,216 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_ORIENTED2DRENDERERINTERFACE
#define H_SPK_ORIENTED2DRENDERERINTERFACE
#include "Core/SPK_Vector3D.h"
#include "Core/SPK_Group.h"
namespace SPK
{
/**
* @brief Defines the orientation of a particle oriented in 2D
* @since 1.04.00
*/
enum Orientation2D
{
ORIENTATION2D_UP, /**< Oriented towards the camera plane */
ORIENTATION2D_DIRECTION, /**< Oriented towards the direction of the particle */
ORIENTATION2D_POINT, /**< Oriented towards a point in the universe */
ORIENTATION2D_AXIS /**< The orientation vector is defined by an axis */
};
/**
* @brief Base Interface for rendering particles that can be oriented in a 2D world
* @since 1.04.00
*/
class Oriented2DRendererInterface
{
public :
///////////////
// Parameter //
///////////////
/**
* @brief The orientation vector
*
* It is used in 2 orientation modes :
* <ul>
* <li>ORIENTATION2D_AXIS : The orientation vector is used as the axis</li>
* <li>ORIENTATION2D_POINT : The orientation vector is the point particle look to</li>
* </ul>
* In other modes the orientation vector is not used
*/
Vector3D orientationVector;
//////////////////
// Constructors //
//////////////////
/** @brief Constructor of Oriented2DRendererInterface */
inline Oriented2DRendererInterface();
////////////////
// Destructor //
////////////////
/** @brief Destructor of Oriented2DRendererInterface */
virtual inline ~Oriented2DRendererInterface() {}
/////////////
// Setters //
/////////////
/**
* @brief Sets the way quads are oriented in the universe
* @param orientation : the orientation of the quad
*/
inline void setOrientation(Orientation2D orientation);
/////////////
// Getters //
/////////////
/**
* @brief Gets the orientation of the quads
* @return the orientation of the quads
*/
inline Orientation2D getOrientation() const;
protected :
Orientation2D orientation;
inline bool hasGlobalOrientation();
inline void computeGlobalOrientation2D();
inline void computeSingleOrientation2D(const Particle& particle);
inline void scaleQuadVectors(const Particle& particle,float scaleX,float scaleY) const;
inline void rotateAndScaleQuadVectors(const Particle& particle,float scaleX,float scaleY) const;
inline const Vector3D& quadUp() const;
inline const Vector3D& quadSide() const;
private :
// Used to store the orientation of quads before scaling
mutable Vector3D up;
mutable Vector3D side;
// This is where are stored quad orientation info after computation
mutable Vector3D sideQuad;
mutable Vector3D upQuad;
};
inline Oriented2DRendererInterface::Oriented2DRendererInterface() :
orientation(ORIENTATION2D_UP)
{
orientationVector.set(0.0f,-1.0f);
}
inline void Oriented2DRendererInterface::setOrientation(Orientation2D orientation)
{
this->orientation = orientation;
}
inline Orientation2D Oriented2DRendererInterface::getOrientation() const
{
return orientation;
}
inline const Vector3D& Oriented2DRendererInterface::quadUp() const
{
return upQuad;
}
inline const Vector3D& Oriented2DRendererInterface::quadSide() const
{
return sideQuad;
}
inline bool Oriented2DRendererInterface::hasGlobalOrientation()
{
return ((orientation == ORIENTATION2D_UP)||(ORIENTATION2D_AXIS));
}
inline void Oriented2DRendererInterface::computeGlobalOrientation2D()
{
if (orientation == ORIENTATION2D_UP)
up.set(0.0f,-0.5f);
else if (orientation == ORIENTATION2D_AXIS)
{
up.set(orientationVector.x,orientationVector.y);
up.normalize();
up *= 0.5f;
}
}
inline void Oriented2DRendererInterface::computeSingleOrientation2D(const Particle& particle)
{
if (orientation == ORIENTATION2D_DIRECTION)
up = particle.velocity();
else if (orientation == ORIENTATION2D_POINT)
{
up = orientationVector;
up -= particle.position();
}
up.z = 0.0f;
up.normalize();
up *= 0.5f;
}
inline void Oriented2DRendererInterface::scaleQuadVectors(const Particle& particle,float scaleX,float scaleY) const
{
float size = particle.getParamCurrentValue(PARAM_SIZE);
upQuad.set(up.x,up.y);
upQuad *= size * scaleY;
sideQuad.set(-up.y,up.x);
sideQuad *= size * scaleX;
}
inline void Oriented2DRendererInterface::rotateAndScaleQuadVectors(const Particle& particle,float scaleX,float scaleY) const
{
float size = particle.getParamCurrentValue(PARAM_SIZE);
float angleTexture = particle.getParamCurrentValue(PARAM_ANGLE);
float cosA = cos(angleTexture);
float sinA = sin(angleTexture);
upQuad.x = cosA * up.x + sinA * up.y;
upQuad.y = -sinA * up.x + cosA * up.y;
upQuad.z = 0.0f;
sideQuad.set(-upQuad.y,upQuad.x);
sideQuad *= size * scaleX;
upQuad *= size * scaleY;
}
}
#endif

View File

@ -0,0 +1,387 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_ORIENTED3DRENDERERINTERFACE
#define H_SPK_ORIENTED3DRENDERERINTERFACE
#include "Core/SPK_Vector3D.h"
#include "Core/SPK_Group.h"
// Packs the orientations parameters into one int for orientation presets
#define PACK_ORIENTATION(lock,look,up) ((lock << 0x10)|(look << 0x8)|(up))
namespace SPK
{
/**
* @brief Defines the orientation of the vector Look of an oriented 3D particle
*
* Enumerators marked as (fast) are the ones that only needs to be computed once for
* a set of particles instead of being computed for each particles.
*
* @since 1.04.00
*/
enum LookOrientation
{
LOOK_CAMERA_PLANE, /**< Look towards the camera plane (fast) */
LOOK_CAMERA_POINT, /**< Look towards the camera point (better effect but more expensive) */
LOOK_AXIS, /**< The look vector is defined by an axis (fast) */
LOOK_POINT, /**< Look towards a point in the universe */
};
/**
* @brief Defines the orientation of the vector Up of an oriented 3D particle
*
* Enumerators marked as (fast) are the ones that only needs to be computed once for
* a set of particles instead of being computed for each particles.
*
* @since 1.04.00
*/
enum UpOrientation
{
UP_CAMERA, /**< The up vector is defined by the up vector of the camera (fast) */
UP_DIRECTION, /**< The up vector is oriented towards the direction of the particle */
UP_AXIS, /**< The up vector is is defined by an axis (fast) */
UP_POINT, /**< The up vector is oriented towards a point */
};
/**
* @brief Defines which axis is locked and will not change when computing a cross product.
*
* Note that the side vector cannot be locked as it is always derived from the look and up vectors.
*
* @since 1.04.00
*/
enum LockedAxis
{
LOCK_LOOK, /**< The look vector is locked */
LOCK_UP, /**< The up vector is locked */
};
/**
* @brief Orientation presets to easily set up common orientations
* @since 1.04.00
*/
enum OrientationPreset
{
CAMERA_PLANE_ALIGNED = PACK_ORIENTATION(LOCK_LOOK,LOOK_CAMERA_PLANE,UP_CAMERA), /**< Particles are oriented towards the camera plane (the most common) */
CAMERA_POINT_ALIGNED = PACK_ORIENTATION(LOCK_LOOK,LOOK_CAMERA_POINT,UP_CAMERA), /**< Particles are oriented towards the camera point (better effect but more expensive) */
DIRECTION_ALIGNED = PACK_ORIENTATION(LOCK_UP,LOOK_CAMERA_PLANE,UP_DIRECTION), /**< Particles are oriented function of their direction and try to look to the camera */
AROUND_AXIS = PACK_ORIENTATION(LOCK_UP,LOOK_CAMERA_POINT,LOOK_AXIS), /**< Particles can only rotate around an axis and try to look to the camera */
TOWARDS_POINT = PACK_ORIENTATION(LOCK_LOOK,LOOK_POINT,UP_CAMERA), /**< Particles are oriented towards a point in the universe */
FIXED_ORIENTATION = PACK_ORIENTATION(LOCK_LOOK,LOOK_AXIS,UP_AXIS), /**< Particles have a fixed orientation in the universe */
};
/**
* @brief Base Interface for rendering particles that can be oriented in a 3D world
* @since 1.04.00
*/
class SPK_PREFIX Oriented3DRendererInterface
{
public :
///////////////
// Parameter //
///////////////
/**
* @brief The look vector
*
* It is used in 2 LookOrientation modes :
* <ul>
* <li>LOOK_AXIS : The look vector is used as the axis</li>
* <li>LOOK_POINT : The look vector is the point quads look to</li>
* </ul>
* In other modes the look vector is not used
*/
Vector3D lookVector;
/**
* @brief The up vector
*
* It is used in 2 UpOrientation modes :
* <ul>
* <li>UP_AXIS : The up axis is used as the axis</li>
* <li>UP_POINT : The up axis is the point quads will be oriented towards</li>
* </ul>
* In other modes the up vector is not used
*/
Vector3D upVector;
//////////////////
// Constructors //
//////////////////
/** @brief Constructor of Oriented3DRendererInterface */
Oriented3DRendererInterface();
////////////////
// Destructor //
////////////////
/** @brief Destructor of Oriented3DRendererInterface */
virtual inline ~Oriented3DRendererInterface() {}
/////////////
// Setters //
/////////////
/**
* @brief Sets the way quads are oriented in the universe
*
* This method allows to accuratly configure the orientation of quads.<br>
* Another method with only one parameters that take presets exist.<br>
* See setOrientation(OrientationPreset)
*
* @param lookOrientation : The way the look vector of the quad is set
* @param upOrientation : The way the up vector of the quad is set
* @param lockedAxis : tells which axis prevails over the other
*/
void setOrientation(LookOrientation lookOrientation,UpOrientation upOrientation,LockedAxis lockedAxis);
/**
* @brief Sets the way quads are oriented in the universe
*
* This method takes some presets to orientate the quads.<br>
* Another method that has more options to configure orientation exists<br>
* See setOrientation(LookOrientation,UpOrientation,LockedAxis)
*
* @param orientation : the orientation preset of the quad
*/
void setOrientation(OrientationPreset orientation);
/////////////
// Getters //
/////////////
/**
* @brief Gets the look orientation of the quads
* @return the look orientation of the quads
*/
inline LookOrientation getLookOrientation() const;
/**
* @brief Gets the up orientation of the quads
* @return the up orientation of the quads
*/
inline UpOrientation getUpOrientation() const;
/**
* @brief Gets the locked axis (the one prevailing over the others)
* @return the locked axis
*/
inline LockedAxis getLockedAxis() const;
protected :
// Orientation
LookOrientation lookOrientation;
UpOrientation upOrientation;
LockedAxis lockedAxis;
inline bool precomputeOrientation3D(const Group& group,const Vector3D& look,const Vector3D& up,const Vector3D& pos);
inline void computeGlobalOrientation3D();
inline void computeSingleOrientation3D(const Particle& particle);
inline void scaleQuadVectors(const Particle& particle,float scaleX,float scaleY) const;
inline void rotateAndScaleQuadVectors(const Particle& particle,float scaleX,float scaleY) const;
inline const Vector3D& quadUp() const;
inline const Vector3D& quadSide() const;
private :
// Used to store modelview information
mutable Vector3D mVLook;
mutable Vector3D mVUp;
mutable Vector3D mVPos;
// Used to store precomputed orientation
mutable Vector3D globalLook;
mutable Vector3D globalUp;
// Used to store the orientation of quads before scaling
mutable Vector3D up;
mutable Vector3D side;
mutable Vector3D look;
// Is using rotation
mutable int quadRotated;
// This is where are stored quad orientation info after computation
mutable Vector3D sideQuad;
mutable Vector3D upQuad;
};
inline LookOrientation Oriented3DRendererInterface::getLookOrientation() const
{
return lookOrientation;
}
inline UpOrientation Oriented3DRendererInterface::getUpOrientation() const
{
return upOrientation;
}
inline LockedAxis Oriented3DRendererInterface::getLockedAxis() const
{
return lockedAxis;
}
inline const Vector3D& Oriented3DRendererInterface::quadUp() const
{
return upQuad;
}
inline const Vector3D& Oriented3DRendererInterface::quadSide() const
{
return sideQuad;
}
inline bool Oriented3DRendererInterface::precomputeOrientation3D(const Group& group,const Vector3D& modelViewLook,const Vector3D& modelViewUp,const Vector3D& modelViewPos)
{
mVLook = modelViewLook;
mVUp = modelViewUp;
mVPos = modelViewPos;
bool globalOrientation = true;
if (lookOrientation == LOOK_CAMERA_PLANE)
globalLook = -mVLook;
else if (lookOrientation == LOOK_AXIS)
globalLook = lookVector;
else
globalOrientation = false;
if (upOrientation == UP_CAMERA)
globalUp = mVUp;
else if (upOrientation == UP_AXIS)
globalUp = upVector;
else globalOrientation = false;
quadRotated = group.getModel()->isEnabled(PARAM_ANGLE);
return globalOrientation;
}
inline void Oriented3DRendererInterface::computeGlobalOrientation3D()
{
look = globalLook;
up = globalUp;
crossProduct(up,look,side);
if (lockedAxis == LOCK_LOOK)
crossProduct(look,side,up);
else if (quadRotated)
{
crossProduct(side,up,look);
look.normalize();
}
up.normalize();
up *= 0.5f;
side.normalize();
side *= 0.5f;
}
inline void Oriented3DRendererInterface::computeSingleOrientation3D(const Particle& particle)
{
if (lookOrientation == LOOK_CAMERA_POINT)
{
look = mVPos;
look -= particle.position();
}
else if (lookOrientation == LOOK_POINT)
{
look = lookVector;
look -= particle.position();
}
else
look = globalLook;
if (upOrientation == UP_DIRECTION)
up = particle.velocity();
else if (upOrientation == UP_POINT)
{
up = upVector;
up -= particle.position();
}
else
up = globalUp;
crossProduct(up,look,side);
if (lockedAxis == LOCK_LOOK)
crossProduct(look,side,up);
else if (quadRotated)
{
crossProduct(side,up,look);
look.normalize();
}
side.normalize();
side *= 0.5f;
up.normalize();
up *= 0.5f;
}
inline void Oriented3DRendererInterface::scaleQuadVectors(const Particle& particle,float scaleX,float scaleY) const
{
float size = particle.getParamCurrentValue(PARAM_SIZE);
sideQuad = side;
sideQuad *= size * scaleX;
upQuad = up;
upQuad *= size * scaleY;
}
inline void Oriented3DRendererInterface::rotateAndScaleQuadVectors(const Particle& particle,float scaleX,float scaleY) const
{
float size = particle.getParamCurrentValue(PARAM_SIZE);
float angleTexture = particle.getParamCurrentValue(PARAM_ANGLE);
float cosA = cos(angleTexture);
float sinA = sin(angleTexture);
upQuad.x = (look.x * look.x + (1.0f - look.x * look.x) * cosA) * up.x
+ (look.x * look.y * (1.0f - cosA) - look.z * sinA) * up.y
+ (look.x * look.z * (1.0f - cosA) + look.y * sinA) * up.z;
upQuad.y = (look.x * look.y * (1.0f - cosA) + look.z * sinA) * up.x
+ (look.y * look.y + (1.0f - look.y * look.y) * cosA) * up.y
+ (look.y * look.z * (1.0f - cosA) - look.x * sinA) * up.z;
upQuad.z = (look.x * look.z * (1.0f - cosA) - look.y * sinA) * up.x
+ (look.y * look.z * (1.0f - cosA) + look.x * sinA) * up.y
+ (look.z * look.z + (1.0f - look.z * look.z) * cosA) * up.z;
crossProduct(upQuad,look,sideQuad);
sideQuad *= size * scaleX;
upQuad *= size * scaleY;
}
}
#endif

View File

@ -0,0 +1,137 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_POINTRENDERERINTERFACE
#define H_SPK_POINTRENDERERINTERFACE
#include "Core/SPK_DEF.h"
namespace SPK
{
/**
* @enum PointType
* @brief Constants defining the type of points to render
*/
enum PointType
{
POINT_SQUARE, /**< Points are renderered as squares */
POINT_CIRCLE, /**< Points are renderered as circles */
POINT_SPRITE, /**< Points are renderered as point sprites (textured points) */
};
/**
* @brief Base Interface for rendering particles with points
* @since 1.04.00
*/
class PointRendererInterface
{
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief Constructor of PointRendererInterface
* @param type : the initial type of this PointRendererInterface (must be supported by default by the platform)
* @param size : the width of this PointRendererInterface
*/
inline PointRendererInterface(PointType type = POINT_SQUARE,float size = 1.0f);
////////////////
// Destructor //
////////////////
/** @brief Destructor of PointRendererInterface */
virtual inline ~PointRendererInterface() {}
/////////////
// Setters //
/////////////
/**
* @brief Sets the type of points to use in this PointRendererInterface
*
* If the type is not supported by the platform, false is returned and the type per default is set.
*
* @param type : the type of points to use in this PointRendererInterface
* @return true if the type can be set, false otherwise
*/
virtual inline bool setType(PointType type);
/**
* @brief Sets the size of the points in this PointRendererInterface
* @param size : the size of the points in this PointRendererInterface
*/
virtual inline void setSize(float size);
/////////////
// Getters //
/////////////
/**
* @brief Gets the type of points in this PointRendererInterface
* @return the type of points in this PointRendererInterface
*/
inline PointType getType() const;
/**
* @brief Gets the size of points in this PointRendererInterface
* @return the size of points in this PointRendererInterface
*/
inline float getSize() const;
protected :
PointType type;
float size;
};
inline PointRendererInterface::PointRendererInterface(PointType type,float size) :
type(type),
size(size)
{}
inline bool PointRendererInterface::setType(PointType type)
{
this->type = type;
return true;
}
inline void PointRendererInterface::setSize(float size)
{
this->size = size;
}
inline PointType PointRendererInterface::getType() const
{
return type;
}
inline float PointRendererInterface::getSize() const
{
return size;
}
}
#endif

View File

@ -0,0 +1,265 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_QUADRENDERERINTERFACE
#define H_SPK_QUADRENDERERINTERFACE
#include "Core/SPK_DEF.h"
#include "Core/SPK_Particle.h"
namespace SPK
{
/**
* @enum TexturingMode
* @brief Constants defining the way to apply texture over the particles
* @since 1.02.00
*/
enum TexturingMode
{
TEXTURE_NONE, /**< Constant telling no texturing is used */
TEXTURE_2D, /**< Constant telling a 2D texture is used */
TEXTURE_3D, /**< Constant telling a 3D texture is used */
};
/**
* @brief Base Interface for rendering particles with quads
* @since 1.04.00
*/
class SPK_PREFIX QuadRendererInterface
{
public :
//////////////////
// Constructors //
//////////////////
/**
* @brief Constructor of QuadRendererInterface
* @param scaleX the scale of the width of the quad
* @param scaleY the scale of the height of the quad
*/
QuadRendererInterface(float scaleX = 1.0f,float scaleY = 1.0f);
////////////////
// Destructor //
////////////////
/** @brief Destructor of QuadRendererInterface */
virtual inline ~QuadRendererInterface() {}
/////////////
// Setters //
/////////////
/**
* @brief Sets the texturing mode for this GLQuadRenderer
*
* The texturing mode defines whether or not to apply a texture
* and if so which type of texture to apply (2D,3D or atlas).<br>
* <br>
* Note that the validity of the texturing mode depends on the rendering API below.<br>
* The method returns true if the rendering mode can be set, false if it cannot
*
* @param mode : the texturing mode of this GLQuadRenderer
* @return true if the rendering mode can be set, false if it cannot
*/
virtual inline bool setTexturingMode(TexturingMode mode);
/**
* @brief Sets the cut of the texture
*
* This is available only if SPK::PARAM_TEXTURE_INDEX is enabled and texturing mode is TEXTURE_2D.<br>
* <br>
* Particles can be rendered only with a part of the texture depending on their texture index value.<br>
* The cut can only be constant.<br>
* The user defines in how many parts the texture must be divided in X and Y.<br>
* The first index is located at the top left cut, the it goes from left to right and from top to bottom.<br>
* <br>
* For instance a cut with nbX = 3 and nbY = 2 will be as followed :
* <br><i>
* -------------<br>
* | 0 | 1 | 2 |<br>
* -------------<br>
* | 3 | 4 | 5 |<br>
* -------------</i><br>
* <br>
* By default nbX and nbY are equal to 1.<br>
*
* @param nbX : the number of cuts in the X axis
* @param nbY : the number of cuts in the Y axis
*/
void setAtlasDimensions(size_t nbX,size_t nbY);
/**
* @brief Sets the size ratio of this GLQuadRenderer
*
* These values defines how quads are scaled.
* The height and width of a quad in the universe is defined as followed :
* <ul>
* <li><i>width = size * ratioX</i>
* <li><i>height = size * ratioY</i>
* </ul>
*
* @param scaleX : the scale of the width of the quad
* @param scaleY : the scale of the height of the quad
*/
inline void setScale(float scaleX,float scaleY);
/////////////
// Getters //
/////////////
/**
* @brief Gets the texturing mode of this GLQuadRenderer
* @return the texturing mode of this GLQuadRenderer
*/
inline TexturingMode getTexturingMode() const;
/**
* @brief Gets the atlas dimension on the X axis
*
* See setAtlasDimensions(size_t,size_t) for more information
*
* @return the atlas dimension on the X axis
*/
inline size_t getAtlasDimensionX() const;
/**
* @brief Gets the atlas dimension on the Y axis
*
* See setAtlasDimensions(size_t,size_t) for more information
*
* @return the atlas dimension on the Y axis
*/
inline size_t getAtlasDimensionY() const;
/**
* @brief Gets the scale of the width of this GLQuadRenderer
* @return the scale of the width of this GLQuadRenderer
*/
inline float getScaleX() const;
/**
* @brief Gets the scale of the height of this GLQuadRenderer
* @return the scale of the height of this GLQuadRenderer
*/
inline float getScaleY() const;
protected :
TexturingMode texturingMode;
float scaleX;
float scaleY;
// texture atlas info
size_t textureAtlasNbX;
size_t textureAtlasNbY;
float textureAtlasW;
float textureAtlasH;
inline void computeAtlasCoordinates(const Particle& particle) const;
inline float textureAtlasU0() const;
inline float textureAtlasU1() const;
inline float textureAtlasV0() const;
inline float textureAtlasV1() const;
private :
// this is where textureAtlas are stored after computation
mutable float atlasU0;
mutable float atlasU1;
mutable float atlasV0;
mutable float atlasV1;
};
inline bool QuadRendererInterface::setTexturingMode(TexturingMode mode)
{
texturingMode = mode;
return true;
}
inline void QuadRendererInterface::setScale(float scaleX,float scaleY)
{
this->scaleX = scaleX;
this->scaleY = scaleY;
}
inline TexturingMode QuadRendererInterface::getTexturingMode() const
{
return texturingMode;
}
inline size_t QuadRendererInterface::getAtlasDimensionX() const
{
return textureAtlasNbX;
}
inline size_t QuadRendererInterface::getAtlasDimensionY() const
{
return textureAtlasNbY;
}
inline float QuadRendererInterface::getScaleX() const
{
return scaleX;
}
inline float QuadRendererInterface::getScaleY() const
{
return scaleY;
}
inline float QuadRendererInterface::textureAtlasU0() const
{
return atlasU0;
}
inline float QuadRendererInterface::textureAtlasU1() const
{
return atlasU1;
}
inline float QuadRendererInterface::textureAtlasV0() const
{
return atlasV0;
}
inline float QuadRendererInterface::textureAtlasV1() const
{
return atlasV1;
}
inline void QuadRendererInterface::computeAtlasCoordinates(const Particle& particle) const
{
int textureIndex = static_cast<int>(particle.getParamCurrentValue(PARAM_TEXTURE_INDEX));
atlasU0 = atlasU1 = static_cast<float>(textureIndex % textureAtlasNbX) / textureAtlasNbX;
atlasV0 = atlasV1 = static_cast<float>(textureIndex / textureAtlasNbY) / textureAtlasNbY;
atlasU1 += textureAtlasW;
atlasV1 += textureAtlasH;
}
}
#endif

View File

@ -0,0 +1,154 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_AABOX
#define H_SPK_AABOX
#include "Core/SPK_Zone.h"
namespace SPK
{
/**
* @class AABox
* @brief A Zone defining an axis-aligned Box
*
* An AABox is defined by its center and a dimension in each axis.
*/
class SPK_PREFIX AABox : public Zone
{
SPK_IMPLEMENT_REGISTERABLE(AABox)
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief Constructor of AABox
* @param position : the position of the AABox
* @param dimension : the dimension of the AABox
*/
AABox(const Vector3D& position = Vector3D(0.0f,0.0f,0.0f),const Vector3D& dimension = Vector3D(0.0f,0.0f,0.0f));
/**
* @brief Creates and registers a new AABox
* @param position : the position of the AABox
* @param dimension : the dimension of the AABox
* @since 1.04.00
*/
static inline AABox* create(const Vector3D& position = Vector3D(0.0f,0.0f,0.0f),const Vector3D& dimension = Vector3D(0.0f,0.0f,0.0f));
////////////
// Setter //
////////////
/**
* @brief Sets the dimensions of this AABox
*
* The negative dimensions are clamped to 0.<br>
* An AABox with 0 as its 3 dimensions is equivalent to a Point
*
* @param dimension : the dimensions of this AABox
*/
void setDimension(const Vector3D& dimension);
////////////
// Getter //
////////////
/**
* @brief Gets the dimensions of this AABox
* @return the dimensions of this AABox
*/
inline const Vector3D& getDimension() const;
///////////////
// Interface //
///////////////
virtual void generatePosition(Particle& particle,bool full) const;
virtual bool contains(const Vector3D& v) const;
virtual bool intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const;
virtual void moveAtBorder(Vector3D& v,bool inside) const;
virtual Vector3D computeNormal(const Vector3D& point) const;
private :
Vector3D dimension;
inline bool slabIntersects(float p0,float p1,float bMin,float bMax,float& tEnter,float& tExit,int& firstAxis,int axis) const;
};
inline AABox* AABox::create(const Vector3D& position,const Vector3D& dimension)
{
AABox* obj = new AABox(position,dimension);
registerObject(obj);
return obj;
}
inline const Vector3D& AABox::getDimension() const
{
return dimension;
}
inline bool AABox::slabIntersects(float p0,float p1,float bMin,float bMax,float& tEnter,float& tExit,int& firstAxis,int axis) const
{
float dir = p1 - p0;
if (dir == 0.0f)
{
if ((p0 < bMin)||(p0 > bMax))
return false;
return true;
}
float t0 = (bMin - p0) / dir;
float t1 = (bMax - p0) / dir;
if (t0 > t1)
{
std::swap(t0,t1);
axis += 3;
}
if ((t1 < tEnter)||(t0 > tExit))
return false;
if (t0 > tEnter)
{
tEnter = t0;
firstAxis = (firstAxis & 0xF0) | (axis & 0x0F);
}
if (t1 < tExit)
{
tExit = t1;
firstAxis = (firstAxis & 0x0F) | ((axis << 4) & 0xF0);
}
return true;
}
}
#endif

View File

@ -0,0 +1,176 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_LINE
#define H_SPK_LINE
#include "Core/SPK_Zone.h"
namespace SPK
{
/**
* @class Line
* @brief A Zone defining a line in the universe
*
* As any Zone, a Line is defined by a position. The Line in itself is defined by two bounds.<br>
* Moving the position results in moving the 2 bounds in the universe by the same vector.<br>
* <br>
* To conform with the Zone class (the position is defined as the center of the Zone), the position is always set to
* be the center of the line. Therefore, if a bound is modified, the position will be modified as well.
*
* @since 1.01.00
*/
class SPK_PREFIX Line : public Zone
{
SPK_IMPLEMENT_REGISTERABLE(Line)
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief Constructor of Line
* @param p0 : the first bound of this Line
* @param p1 : the second bound of this Line
*/
Line(const Vector3D& p0 = Vector3D(0.0f,0.0f,0.0f),const Vector3D& p1 = Vector3D(0.0f,0.0f,0.0f));
/**
* @brief Creates and registers a new Line
* @param p0 : the first bound of this Line
* @param p1 : the second bound of this Line
* @since 1.04.00
*/
static inline Line* create(const Vector3D& p0 = Vector3D(0.0f,0.0f,0.0f),const Vector3D& p1 = Vector3D(0.0f,0.0f,0.0f));
/////////////
// Setters //
/////////////
void setPosition(const Vector3D& v);
/**
* @brief Sets the bounds of this Line
* @param p0 : the first bound of this Line
* @param p1 : the second bound of this Line
*/
void setBounds(const Vector3D& p0,const Vector3D& p1);
/////////////
// Getters //
/////////////
/**
* @brief Gets the bound of index of this Line
* @param index : the index of the bound (0 or 1)
* @return the first bound of index of this Line
* @since 1.03.00
*/
inline const Vector3D& getBound(size_t index) const;
/**
* @brief Gets the transformed bound of index of this Line
* @param index : the index of the bound (0 or 1)
* @return the transformed bound of index of this Line
* @since 1.03.00
*/
inline const Vector3D& getTransformedBound(size_t index) const;
///////////////
// Interface //
///////////////
/**
* @brief Pushes a new bound to this Line
*
* This method replaces the first bound by the second bound and the second bound by the new bound.<br>
* It allows to follow the trajectory of a moving object over time with a single Line.
*
* @param bound : the new bound of this Line
*/
void pushBound(const Vector3D& bound);
virtual void generatePosition(Particle& particle,bool full) const;
virtual inline bool contains(const Vector3D& v) const;
virtual inline bool intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const;
virtual inline void moveAtBorder(Vector3D& v,bool inside) const;
virtual Vector3D computeNormal(const Vector3D& point) const;
protected :
virtual void innerUpdateTransform();
private :
Vector3D bounds[2];
Vector3D tBounds[2];
Vector3D tDist;
inline void computeDist();
inline void computePosition();
};
inline Line* Line::create(const Vector3D& p0,const Vector3D& p1)
{
Line* obj = new Line(p0,p1);
registerObject(obj);
return obj;
}
inline const Vector3D& Line::getBound(size_t index) const
{
return bounds[index];
}
inline const Vector3D& Line::getTransformedBound(size_t index) const
{
return tBounds[index];
}
inline bool Line::contains(const Vector3D& v) const
{
return false;
}
inline bool Line::intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const
{
return false;
}
inline void Line::moveAtBorder(Vector3D& v,bool inside) const {}
inline void Line::computeDist()
{
tDist = tBounds[1] - tBounds[0];
}
inline void Line::computePosition()
{
Zone::setPosition((bounds[0] + bounds[1]) * 0.5f);
}
}
#endif

View File

@ -0,0 +1,163 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_PLANE
#define H_SPK_PLANE
#include "Core/SPK_Zone.h"
#include "Core/SPK_Particle.h"
namespace SPK
{
/**
* @class Plane
* @brief A Zone defining a plane in the universe
*
* A Plane is defined by 2 parameters :
* <ul>
* <li>A Position is the universe</li>
* <li>A Normal</li>
* </ul>
* The defined Plane is the Plane having the normal and passing by the position.<br>
* The direction of the normal defines the sens of the plane. The normal goes from inside the Plane to outside.<br>
* <br>
* Note that the normal does not have to be normalized as it is normalized internally when set.
*/
class SPK_PREFIX Plane : public Zone
{
SPK_IMPLEMENT_REGISTERABLE(Plane)
public :
//////////////////
// Constructors //
//////////////////
/**
* @brief Constructor of Plane
* @param position : the position of the Plane
* @param normal : the normal of the Plane
*/
Plane(const Vector3D& position = Vector3D(0.0f,0.0f,0.0f),const Vector3D& normal = Vector3D(0.0f,1.0f,0.0f));
/**
* @brief Creates and registers a new Plane
* @param position : the position of the Plane
* @param normal : the normal of the Plane
* @return a new registered plane
* @since 1.04.00
*/
static inline Plane* create(const Vector3D& position = Vector3D(0.0f,0.0f,0.0f),const Vector3D& normal = Vector3D(0.0f,1.0f,0.0f));
/////////////
// Setters //
/////////////
/**
* @brief Sets the normal of this Plane
*
* Note that the normal is normalized internally.
*
* @param normal : the normal of this Plane
*/
inline void setNormal(const Vector3D& normal);
/////////////
// Getters //
/////////////
/**
* @brief Gets the normal of this Plane
* @return the normal of this Plane
*/
inline const Vector3D& getNormal() const;
/**
* @brief Gets the transformed normal of this Plane
* @return the transformed normal of this Plane
* @since 1.05.00
*/
inline const Vector3D& getTransformedNormal() const;
///////////////
// Interface //
///////////////
virtual inline void generatePosition(Particle& particle,bool full) const;
virtual inline bool contains(const Vector3D& v) const;
virtual bool intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const;
virtual void moveAtBorder(Vector3D& v,bool inside) const;
virtual inline Vector3D computeNormal(const Vector3D& point) const;
protected :
virtual void innerUpdateTransform();
private :
Vector3D normal;
Vector3D tNormal;
};
inline Plane* Plane::create(const Vector3D& position,const Vector3D& normal)
{
Plane* obj = new Plane(position,normal);
registerObject(obj);
return obj;
}
inline void Plane::setNormal(const Vector3D& normal)
{
this->normal = normal;
this->normal.normalize();
tNormal = this->normal;
notifyForUpdate();
}
inline const Vector3D& Plane::getNormal() const
{
return normal;
}
inline const Vector3D& Plane::getTransformedNormal() const
{
return tNormal;
}
inline void Plane::generatePosition(Particle& particle,bool full) const
{
particle.position() = getTransformedPosition();
}
inline bool Plane::contains(const Vector3D& v) const
{
return dotProduct(normal,v - getTransformedPosition()) <= 0.0f;
}
inline Vector3D Plane::computeNormal(const Vector3D& point) const
{
return tNormal;
}
}
#endif

View File

@ -0,0 +1,93 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_POINT
#define H_SPK_POINT
#include "Core/SPK_Zone.h"
#include "Core/SPK_Particle.h"
namespace SPK
{
/**
* @class Point
* @brief A Zone defining a point in the universe
*/
class SPK_PREFIX Point : public Zone
{
SPK_IMPLEMENT_REGISTERABLE(Point)
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief Constructor of Point
* @param position : the position of the Point
*/
Point(const Vector3D& position = Vector3D(0.0f,0.0f,0.0f));
/**
* @brief Creates and registers a new Point
* @param position : the position of the Point
* @return A new registered Point
* @since 1.04.00
*/
static inline Point* create(const Vector3D& position = Vector3D(0.0f,0.0f,0.0f));
// Interface
virtual inline void generatePosition(Particle& particle,bool full) const;
virtual inline bool contains(const Vector3D& v) const;
virtual inline bool intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const;
virtual inline void moveAtBorder(Vector3D& v,bool inside) const;
virtual Vector3D computeNormal(const Vector3D& point) const;
};
inline Point* Point::create(const Vector3D& position)
{
Point* obj = new Point(position);
registerObject(obj);
return obj;
}
inline void Point::generatePosition(Particle& particle,bool full) const
{
particle.position() = getTransformedPosition();
}
inline bool Point::contains(const Vector3D& v) const
{
return false;
}
inline bool Point::intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const
{
return false;
}
inline void Point::moveAtBorder(Vector3D& v,bool inside) const {}
}
#endif

View File

@ -0,0 +1,198 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_RING
#define H_SPK_RING
#include "Core/SPK_Zone.h"
namespace SPK
{
/**
* @brief A ZOne defining a flat ring in the universe
*
* A ring is defined by :
* <ul>
* <li>The position of its center</li>
* <li>The normal of the plane on which it lies</li>
* <li>A minimum and maximum radius</li>
* </ul>
* Note that by having the minimum radius equal to 0, the ring becomes a disk in the universe.<br>
* Note that the normal does not have to be normalized as it is normalized internally when set.
*
* @since 1.05.00
*/
class SPK_PREFIX Ring : public Zone
{
SPK_IMPLEMENT_REGISTERABLE(Ring)
public :
//////////////////
// Constructors //
//////////////////
/**
* @brief Constructor of ring
* @param position : the position of the ring
* @param normal : the normal of the plane on which lies the ring
* @param minRadius : the minimum radius of the ring
* @param maxRadius : the maximum radius of the ring
*/
Ring(const Vector3D& position = Vector3D(0.0f,0.0f,0.0f),const Vector3D& normal = Vector3D(0.0f,1.0f,0.0f),float minRadius = 0.0f,float maxRadius = 1.0f);
/**
* @brief Creates and registers a new Ring
* @param position : the position of the ring
* @param normal : the normal of the plane on which lies the ring
* @param minRadius : the minimum radius of the ring
* @param maxRadius : the maximum radius of the ring
* @return a new registered ring
*/
static inline Ring* create(const Vector3D& position = Vector3D(0.0f,0.0f,0.0f),const Vector3D& normal = Vector3D(0.0f,1.0f,0.0f),float minRadius = 0.0f,float maxRadius = 1.0f);
/////////////
// Setters //
/////////////
/**
* @brief Sets the normal of the plane on which lies this ring
*
* Note that the normal is normalized internally
*
* @param normal : the normal of the plane on which lies the ring
*/
inline void setNormal(const Vector3D& normal);
/**
* @brief Sets the min and max radius of this ring
*
* A radius cannot be negative.<br>
* Note that negative radius are inverted internally
*
* @param minRadius : the minimum radius of this ring
* @param maxRadius : the maximum radius of this ring
*/
void setRadius(float minRadius,float maxRadius);
/////////////
// Getters //
/////////////
/**
* @brief Gets the normal of this ring
* @return the normal of this ring
*/
inline const Vector3D& getNormal() const;
/**
* @brief Gets the transformed normal of this ring
* @return the transformed normal of this ring
*/
inline const Vector3D& getTransformedNormal() const;
/**
* @brief Gets the minimum radius of this ring
* @return the minimum radius of this ring
*/
inline float getMinRadius() const;
/**
* @brief Gets the maximum radius of this ring
* @return the maximum radius of this ring
*/
inline float getMaxRadius() const;
///////////////
// Interface //
///////////////
virtual void generatePosition(Particle& particle,bool full) const;
virtual inline bool contains(const Vector3D& v) const;
virtual bool intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const;
virtual void moveAtBorder(Vector3D& v,bool inside) const;
virtual inline Vector3D computeNormal(const Vector3D& point) const;
protected :
virtual void innerUpdateTransform();
private :
Vector3D normal;
Vector3D tNormal;
float minRadius;
float maxRadius;
// Square of the radius (for optimization purpose)
float sqrMinRadius;
float sqrMaxRadius;
};
inline Ring* Ring::create(const Vector3D& position,const Vector3D& normal,float minRadius,float maxRadius)
{
Ring* obj = new Ring(position,normal,minRadius,maxRadius);
registerObject(obj);
return obj;
}
inline void Ring::setNormal(const Vector3D& normal)
{
this->normal = normal;
this->normal.normalize();
tNormal = this->normal;
notifyForUpdate();
}
inline const Vector3D& Ring::getNormal() const
{
return normal;
}
inline const Vector3D& Ring::getTransformedNormal() const
{
return tNormal;
}
inline float Ring::getMinRadius() const
{
return minRadius;
}
inline float Ring::getMaxRadius() const
{
return maxRadius;
}
inline bool Ring::contains(const Vector3D& v) const
{
return false;
}
inline Vector3D Ring::computeNormal(const Vector3D& point) const
{
return tNormal;
}
}
#endif

View File

@ -0,0 +1,117 @@
//////////////////////////////////////////////////////////////////////////////////
// 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_SPHERE
#define H_SPK_SPHERE
#include "Core/SPK_Zone.h"
namespace SPK
{
/**
* @class Sphere
* @brief A Zone defining a sphere in the universe
*/
class SPK_PREFIX Sphere : public Zone
{
SPK_IMPLEMENT_REGISTERABLE(Sphere)
public :
/////////////////
// Constructor //
/////////////////
/**
* @brief Constructor of Sphere
* @param position : position of the center of the Sphere
* @param radius : radius of the Sphere
*/
Sphere(const Vector3D& position = Vector3D(0.0f,0.0f,0.0f),float radius = 0.0f);
/**
* @brief Creates and registers a new Sphere
* @param position : position of the center of the Sphere
* @param radius : radius of the Sphere
* @return A new registered Sphere
* @since 1.04.00
*/
static inline Sphere* create(const Vector3D& position = Vector3D(0.0f,0.0f,0.0f),float radius = 0.0f);
////////////
// Setter //
////////////
/**
* @brief Sets the radius of this Sphere
*
* A negative radius will be clamped to 0.0f and the Sphere will therefore acts as a Point.
*
* @param radius : the radius of this Sphere
*/
inline void setRadius(float radius);
////////////
// Getter //
////////////
/**
* @brief Gets the radius of this Sphere
* @return the radius of this Sphere
*/
inline float getRadius() const;
///////////////
// Interface //
///////////////
virtual void generatePosition(Particle& particle,bool full) const;
virtual bool contains(const Vector3D& v) const;
virtual bool intersects(const Vector3D& v0,const Vector3D& v1,Vector3D* intersection,Vector3D* normal) const;
virtual void moveAtBorder(Vector3D& v,bool inside) const;
virtual Vector3D computeNormal(const Vector3D& point) const;
private :
float radius;
};
inline Sphere* Sphere::create(const Vector3D& position,float radius)
{
Sphere* obj = new Sphere(position,radius);
registerObject(obj);
return obj;
}
inline void Sphere::setRadius(float radius)
{
this->radius = radius >= 0.0f ? radius : 0.0f;
}
inline float Sphere::getRadius() const
{
return radius;
}
}
#endif