gremlin/libs/spark/include/Core/SPK_Group.h
2011-01-05 23:02:10 +01:00

1062 lines
36 KiB
C++

//////////////////////////////////////////////////////////////////////////////////
// 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_GROUP
#define H_SPK_GROUP
#include "Core/SPK_DEF.h"
#include "Core/SPK_Registerable.h"
#include "Core/SPK_Transformable.h"
#include "Core/SPK_Vector3D.h"
#include "Core/SPK_Pool.h"
#include "Core/SPK_Particle.h"
namespace SPK
{
class Renderer;
class Emitter;
class Modifier;
class Zone;
class Model;
class Buffer;
class BufferCreator;
/**
* @class Group
* @brief A group of many particles
*
* A Group is the structure the user will interact with the most to build up a full Particle System.<br>
* More than only storing many particles, a Group also defines and entire environment for Particle generation and Evolution.<br>
* <br>
* This class is the spine of the SPARK engine.
*/
class SPK_PREFIX Group : public Registerable, public Transformable
{
friend class Renderer;
friend class Particle;
friend void swapParticles(Particle& a,Particle& b);
SPK_IMPLEMENT_REGISTERABLE(Group)
public :
//////////////////
// Constructors //
//////////////////
/**
* @brief Constructor for a Group
*
* A Group is constructed with a Model (if NULL, the default Model will be used to generate particles).
* This Model will be used to handle Particle's generation and evolution within the Group.<br>
* <br>
* A Group also needs a maximum capacity which is the maximum number of particles the Group can handle. This is necessary to reserve some memory space.
* Note that the capacity can be changed by calling reallocate(unsigned int).
* By default, the capacity is set to Pool::DEFAULT_CAPACITY.
*
* @param model : the Model of this Group
* @param capacity : The maximum number of particles of this Group
*/
Group(Model* model = NULL,size_t capacity = Pool<Particle>::DEFAULT_CAPACITY);
/**
* @brief Copy Constructor of Group
* @param group : the Group to construct the new Group from
*/
Group(const Group& group);
/**
* @brief Creates and registers a new Group
* @param model : the Model of this Group
* @param capacity : The maximum number of particles of this Group
* @return A new registered Group
* @since 1.04.00
*/
static inline Group* create(Model* model = NULL,size_t capacity = Pool<Particle>::DEFAULT_CAPACITY);
////////////////
// Destructor //
////////////////
/** @brief The destructor of Group */
~Group();
/////////////
// Setters //
/////////////
/**
* @brief change the Model of this Group
*
* If the model parameter is set to NULL, the default model will be used. No changes are done if the model parameter is equal
* to the Model of this Group. Changing the Model of this Group will empty it.
*
* @param model : the Model of this Group
*/
void setModel(Model* model);
/**
* @brief Sets the Renderer of this Group
*
* If the Renderer is set to NULL, the particles of the Group will not be renderered with a call to render().<br>
* <br>
* Note that if the bufferManagement is on (see enableBuffersManagement(bool)), setting the Renderer will first
* destroys the buffers needed for the previous Renderer held by this Group and create buffers needed for the new Renderer.
*
* @param renderer : the Renderer of this Group
*/
void setRenderer(Renderer* renderer);
/**
* @brief Sets the friction of this Group
*
* The friction defines the way particles are accelerated or decelerated in their environment.<br>
* <ul>
* <li>If the friction is 0.0f, particles in the Group are neither accelerated nor decelerated (it is the default setting).</li>
* <li>If the friction is positive, particles will be decelerated function of their speed.</li>
* <li>If the friction is negative, particles will be accelerated function of their speed.</li>
* </ul>
* The friction is applied on each Particle as followed :<br>
* <i>velocity *= 1 - min(1,friction * deltaTime / weight)</i><br>
* <br>
* Note that the lighter the Particle, the more effect has the friction on it.
*
* @param friction the friction of the Group
*/
inline void setFriction(float friction);
/**
* @brief Sets the gravity of this Group
*
* The gravity is a vector which defines an attractive force that will be applied to each Particle in the Group during the update.<br>
* By default the gravity is the null vector (i.e. a Vector3D equal to (0,0,0)) which means no gravity is applied.<br>
* <br>
* The gravity is applied on each Particle as followed :<br>
* <i>velocity += gravity * deltaTime</i><br>
*
* @param gravity : the Vector3D that will be used as the gravity for this Group
*/
inline void setGravity(const Vector3D& gravity);
/**
* @brief Assigns a callback for the custom update
*
* The user has the possibility to assign a callback function for update that will be called for each Particle right after the standard update.<br>
* The signature of the function must be of the form :<br>
* <i>bool customUpdate(Particle&,unsigned int)</i><br>
* with :
* <ul>
* <li>Particle& being the Particle which is currently updated</li>
* <li>float being the time step</li>
* <li> the return bool being true if the Particle has to die at the end of the update, false otherwise</li>
* </ul>
*
* @param fupdate : A pointer to the callback function that will perform custom update for this Group
*/
inline void setCustomUpdate(bool (*fupdate)(Particle&,float));
/**
* @brief Assigns a callback for custom birth
*
* This method allows to assign a callback function that will be called each time a Particle borns.<br>
* The signature of the function must be of the form :<br>
* <i>void customUpdate(Particle&)</i><br>
* with Particle& being the Particle which is just born.
*
* @param fbirth : A pointer to the callback function that will perform custom birth for this Group
*/
inline void setCustomBirth(void (*fbirth)(Particle&));
/**
* @brief Assigns a callback for custom death
*
* This method allows to assign a callback function that will be called each time a Particle dies.<br>
* The signature of the function must be of the form :<br>
* <i>void customUpdate(Particle&)</i><br>
* with Particle& being the Particle which has just died.
*
* @param fdeath : A pointer to the callback function that will perform custom death for this Group
*/
inline void setCustomDeath(void (*fdeath)(Particle&));
/**
* @brief Enables or disables the sorting of particles
*
* The sorting is performed from particles further to the camera to particles closer to the camera.<br>
* Sorting particles allows to well draw particles with alpha.<br>
* <br>
* If the sorting is enabled/disabled, the distance computation is enabled/disabled as well.<br>
* <br>
* Note that sorting a Group is a computationnaly expensive operation that should be avoided when possible.
*
* @param sort : true to enable the sorting of particles, false otherwise
*/
inline void enableSorting(bool sort);
/**
* @brief Enables or disables the computation of the distance of a Particle from the camera
*
* The distance computation happens at each call to update(unsigned int).<br>
* The distance of a Particle from the camera can be gotten with a call to Particle::getDistanceFromCamera() or Particle::getSqrDistanceFromCamera()<br>
* <br>
* Note that the distance is defined by the difference vector between the Particle and the the camera set with System::setCameraPosition(Vector3D&).<br>
* <br>
* If the distance computation is disabled, then the sorting of particles is disabled as well.
*
* @param distanceComputation : true to enable the computation of the camera distance, false not to
* @since 1.01.00
*/
inline void enableDistanceComputation(bool distanceComputation);
/**
* @brief Enables or disables the computation of the axis aligned bouding box of the Group
*
* if the computing of the AABB is enabled, after each call to update(unsigned int), 2 Vector3D are updated with the coordinates information of the AABB.
* Those Vector3D can be gotten with getAABBMin() and getAABBMax() which give respectively the minimum and maximum coordinates of the bounding box in each axis.<br>
* <br>
* Knowing the AABB of a Group of particles can be useful in some case like frustum culling for instance.<br>
* <br>
* Note that the bounding box does not use the size information of the particles which means when computing the bounding box, particles are considered to be points in the space.
*
* @param AABB : true to enable the computing of the AABB of the Group, false to disable it
*/
inline void enableAABBComputing(bool AABB);
/**
* @brief Enables or not Renderer buffers management in a statix way
*
* If the buffer management is enabled, then a call to setRenderer(Renderer*) will destroy the existing buffers of the previous Renderer
* held by this Group, and create the needed buffer for the new Renderer.<br>
* <br>
* By default, the renderer buffers management is enabled.
*
* @param manage : true to enable buffers management, false to disable it
* @since 1.03.00
*/
static void enableBuffersManagement(bool manage);
/////////////
// Getters //
/////////////
/**
* @brief Gets the Pool of particles of the Group
*
* Note that the Pool returned is constant as the user is not allowed to modify the internal structure of particles.
*
* @return the Pool of the Group
*/
inline const Pool<Particle>& getParticles() const;
/**
* @brief Gets a single Particle in the Group by its index
*
* Note that a given Particle in a Group is not ensured to keep the same index all over its life.
* Particle index can be changed when inactivating particles.
*
* @param index : the position in the Group's Pool of the Particle to get
* @return : the Particle at index
*/
inline Particle& getParticle(size_t index);
/**
* @brief Gets a single Particle in the Group by its index
*
* This is the constant version of getParticle(size_t).
*
* @param index : the index of the Particle to get
* @return the Particle at index
* @since 1.02.00
*/
inline const Particle& getParticle(size_t index) const;
/**
* @brief Gets the number of particles in the Group
* @return the number of particles in the Group
*/
inline size_t getNbParticles() const;
/**
* @brief Gets the emitters of the Group
* @return the vector of emitters of the Group
*/
inline const std::vector<Emitter*>& getEmitters() const;
/**
* @brief Gets an Emitter of the Group by its index
* @param index : the position in the vector of emitters of the Emitter to get
* @return : the Emitter at index
*/
inline Emitter* getEmitter(size_t index) const;
/**
* @brief Gets the number of emitters in this Group
* @return the number of emitters in this Group
*/
inline size_t getNbEmitters() const;
/**
* @brief Gets the modifiers of the Group
* @return the vector of modifiers of the Group
*/
inline const std::vector<Modifier*>& getModifiers() const;
/**
* @brief Gets an Modifier of the Group by its index
* @param index : the position in the vector of modifiers of the Modifier to get
* @return : the Modifier at index
*/
inline Modifier* getModifier(size_t index) const;
/**
* @brief Gets the number of modifiers in this Group
* @return the number of modifiers in this Group
*/
inline size_t getNbModifiers() const;
/**
* @brief Gets the Model of this Group
* @return the Model of this Group
*/
inline Model* getModel() const;
/**
* @brief Gets the Renderer of this Group
* @return the Renderer of this Group
*/
inline Renderer* getRenderer() const;
/**
* @brief Gets the friction coefficient of this Group
*
* For a description of the friction see setFriction(float).
*
* @return the friction coefficient of this Group
*/
inline float getFriction() const;
/**
* @brief Gets the gravity Vector3D of this Group
*
* For a description of the gravity see setGravity(Vector3D&).
*
* @return the gravity Vector3D of this Group
*/
inline const Vector3D& getGravity() const;
/**
* @brief Tells whether the sorting of particles from back to front is enabled
*
* For a description of the sorting of particles, see enableSorting(bool).
*
* @return true if the sorting is enabled, false otherwise
*/
inline bool isSortingEnabled() const;
/**
* @brief Tells whether the distance computation between particles and camera is enabled
* @return true is the distance computation is enabled, false if not
* @since 1.01.00
*/
inline bool isDistanceComputationEnabled() const;
/**
* @brief Tells whether the computation of the axis aligned bouding box is enabled
*
* For a description of the computation of the AABB, see enableAABBComputing(bool).
*
* @return true if the computation of the AABB is enabled, false if it is disabled
*/
inline bool isAABBComputingEnabled() const;
/**
* @brief Gets a Vector3D holding the minimum coordinates of the AABB of the Group.
*
* Note that this method is only useful when the AABB computation is enabled (see enableAABBComputing(bool)).
*
* @return a Vector3D holding the minimum coordinates of the AABB of the Group
*/
inline const Vector3D& getAABBMin() const;
/**
* @brief Gets a Vector3D holding the maximum coordinates of the AABB of the Group.
*
* Note that this method is only useful when the AABB computation is enabled (see enableAABBComputing(bool)).
*
* @return a Vector3D holding the maximum coordinates of the AABB of the Group
*/
inline const Vector3D& getAABBMax() const;
/**
* @brief Gets the start address of the given param
*
* This method is used by a Renderer to define the start position of an array to pass to the GPU.<br>
* You will not generally need it unless you re designing your own Renderer.<br>
* <br>
* Note that if the parameter is not enabled, the return value will point to an enabled parameter starting address.
*
* @param param : the parameter whose start address is gotten
* @since 1.03.00
*/
const void* getParamAddress(ModelParam param) const;
/**
* @brief Gets the start address of the position
*
* This method is used by a Renderer to define the start position of an array to pass to the GPU.<br>
* You will not generally need it unless you re designing your own Renderer.
*
* @since 1.03.00
*/
inline const void* getPositionAddress() const;
/**
* @brief Gets the stride for parameters
*
* This method is used by a Renderer to know the stride of an array to pass to the GPU.<br>
* You will not generally need it unless you re designing your own Renderer.
*
* @since 1.03.00
*/
size_t getParamStride() const;
/**
* @brief Gets the stride for positions
*
* This method is used by a Renderer to know the stride of an array to pass to the GPU.<br>
* You will not generally need it unless you re designing your own Renderer.
*
* @since 1.03.00
*/
inline size_t getPositionStride() const;
/**
* @brief Tells whether renderers buffer management is enabled or not
*
* see enableBuffersManagement(bool) for more information.
*
* @return true if renderers buffer management is enabled, false if it is disable
* @since 1.03.00
*/
static bool isBuffersManagementEnabled();
///////////////
// Interface //
///////////////
/**
* @brief Adds some Particles to this Group
*
* This method and all the methods of type addParticles will add a given number of Particles at the given position with the given velocity.<br>
* Note that even if a Zone and an Emitter is passed, the position and the velocity will be the same for all Particles.<br>
* <br>
* In case a Zone is passed, Zone::generatePosition(Particle,bool) is used to generate the position.<br>
* In case an Emitter is passed, Emitter::generateVelocity(Particle) with a mass of 1 is used to generate the velocity.
* The velocity will then be updated with the Particle's mass when the Particle will be generated.<br>
* In case a delta time is passed instead of a fixed number, the number will be computed thanks to the flow of the Emitter passed.<br>
* <br>
* Particles will be added to the Group at the next call to update(unsigned int) or flushAddedParticles().<br>
* This is why any Emitter and Zone used to generate particles must be valid at the next call of either update(unsigned int) or flushAddedParticles().<br>
* <br>
* On some methods addParticles, the full variable is present. This variable defines where to generate positions in a Zone :
* <ul>
* <li>true to generate position somewhere within the whole Zone.</li>
* <li>false to generate position somewhere on the Zone border.</li>
* </ul>
*
* @param nb : the number of Particles to add
* @param position : the position where the Particles will be added
* @param velocity : the velocity of the Particles
*/
inline void addParticles(unsigned int nb,const Vector3D& position,const Vector3D& velocity);
/**
* @brief Adds some Particles to this Group
*
* See addParticles(unsigned int,const Vector3D&,const Vector3D&) for a complete description.
*
* @param nb : the number of Particles to add
* @param zone : the Zone that will be used to generate the position
* @param emitter : the Emitter that will be used to generate the velocity
* @param full : true to generate a position within the whole Zonz, false only at its borders
*/
void addParticles(unsigned int nb,const Zone* zone,Emitter* emitter,bool full = true);
/**
* @brief Adds some Particles to this Group
*
* See addParticles(unsigned int,const Vector3D&,const Vector3D&) for a complete description.
*
* @param nb : the number of Particles to add
* @param zone : the Zone that will be used to generate the position
* @param velocity : the velocity of the Particles
* @param full : true to generate a position within the whole Zonz, false only at its borders
*/
inline void addParticles(unsigned int nb,const Zone* zone,const Vector3D& velocity,bool full = true);
/**
* @brief Adds some Particles to this Group
*
* See addParticles(unsigned int,const Vector3D&,const Vector3D&) for a complete description.
*
* @param nb : the number of Particles to add
* @param position : the position where the Particles will be added
* @param emitter : the Emitter that will be used to generate the velocity
*/
inline void addParticles(unsigned int nb,const Vector3D& position,Emitter* emitter);
/**
* @brief Adds some Particles to this Group
*
* See addParticles(unsigned int,const Vector3D&,const Vector3D&) for a complete description.
*
* @param nb : the number of Particles to add
* @param emitter : the Emitter that will be used to generate the velocity and whose Zone will be used to generate the position
*/
void addParticles(unsigned int nb,Emitter* emitter);
/**
* @brief Adds some Particles to this Group
*
* See addParticles(unsigned int,const Vector3D&,const Vector3D&) for a complete description.
*
* @param zone : the Zone that will be used to generate the position
* @param emitter : the Emitter that will be used to generate the velocity
* @param deltaTime : the step time that will be used to determine how many particles to generate
* @param full : true to generate a position within the whole Zonz, false only at its borders
*/
void addParticles(const Zone* zone,Emitter* emitter,float deltaTime,bool full = true);
/**
* @brief Adds some Particles to this Group
*
* See addParticles(unsigned int,const Vector3D&,const Vector3D&) for a complete description.
*
* @param position : the position where the Particles will be added
* @param emitter : the Emitter that will be used to generate the velocity
* @param deltaTime : the step time that will be used to determine how many particles to generate
*/
void addParticles(const Vector3D& position,Emitter* emitter,float deltaTime);
/**
* @brief Adds some Particles to this Group
*
* See addParticles(unsigned int,const Vector3D&,const Vector3D&) for a complete description.
*
* @param emitter : the Emitter that will be used to generate the velocity and whose Zone will be used to generate the position
* @param deltaTime : the step time that will be used to determine how many particles to generate
*/
void addParticles(Emitter* emitter,float deltaTime);
/**
* @brief Adds some Particles to this Group
*
* This method is slightly different to other addParticles methods as Particles are generated not at a point but on a line defined by start and end.<br>
* The step is the distance between each Particle on the line and the offset is the starting distance to compute the first Particle's position.<br>
* The offset is useful to generate equidistant particles on several lines. the returned offset has to be used as the passed offset for the next line.<br>
* <br>
* This method is useful to generate equidistant particles on lines no matter the framerate.<br>
* <br>
* See addParticles(unsigned int,const Vector3D&,const Vector3D&) for some complementary information.
*
* @param start : the position of the start of the line
* @param end : the position of the end of the line
* @param emitter : the Emitter that will be used to generate the velocity
* @param step : the distance between each generated Particle
* @param offset : the starting distance of the beginning of the line
* @return the new offset at the end of the line
*/
float addParticles(const Vector3D& start,const Vector3D& end,Emitter* emitter,float step,float offset = 0.0f);
/**
* @brief Adds some Particles to this Group
*
* See addParticles(const Vector3D&,const Vector3D&,const Emitter*,float,float) for a complete description.
*
* @param start : the position of the start of the line
* @param end : the position of the end of the line
* @param velocity : the velocity of the Particles
* @param step : the distance between each generated Particle
* @param offset : the starting distance of the beginning of the line
* @return the new offset at the end of the line
*/
float addParticles(const Vector3D& start,const Vector3D& end,const Vector3D& velocity,float step,float offset = 0.0f);
/**
* @brief Removes a Particle from this Group
*
* Note that the Particle object is not destroyed but only inactivated in the Pool.
*
* @param index : the position of the Particle in this Group
*/
inline void removeParticle(size_t index);
/**
* @brief Adds an Emitter in this Group
*
* Note that if the emitter is already in the group, it will not be inserted again.
*
* @param emitter : the Emitter to add
*/
void addEmitter(Emitter* emitter);
/**
* @brief Removes an Emitter from this Group
* @param emitter : the Emitter to remove
*/
void removeEmitter(Emitter* emitter);
/**
* @brief Adds an Modifier in this Group
* @param modifier : the Modifier to add
*/
void addModifier(Modifier* modifier);
/**
* @brief Removes an Modifier from this Group
* @param modifier : the Modifier to remove
*/
void removeModifier(Modifier* modifier);
/**
* @brief Updates this Group by a step time
*
* The update process performs those operations :
* <ul>
* <li>Updates the mutable parameters of each Particle.</li>
* <li>Updates the velocity of each Particle function of the friction and the gravity of the Group.</li>
* <li>Applies each Modifier of the Group to each Particle.</li>
* <li>Removes all dead particles</li>
* <li>Adds particles generated by the emitters of the Group.</li>
* <li>Adds particles added manually by the user (with calls to addParticles).</li>
* </ul>
* Those operations are optimized to limit the swaps and shifts of particles in the Pool to its minimum.<br>
* This method tells whether the Group still has some Particles, or if some Particles will still be generated by the Emitters at the next updates by returning a boolean.
*
* @param deltaTime : the time step used to update the Group
* @return true if the Group has still some current or future Particles to update, false otherwise
*/
bool update(float deltaTime);
/**
* @brief Renders this Group
*
* Note that if no Renderer is attached to the Group, nothing will happen.
*/
void render();
/**
* @brief Empties this Group
*
* Not that this method does not release resource of this Group.
* Particles are only inactivated, not destroyed.
*/
void empty();
/**
* @brief Adds all manually added particles to the Group
*
* This method adds all particles added with the addParticles methods immediatly to the Group without waiting the next call to update(unsigned int).
* The Particles are added in FIFO order until there is no more or the capacity limit of the Group is reached.
*/
void flushAddedParticles();
/**
* @brief Sorts the particles within this Group
*
* The particles are sorted only if the sorting of this Group is enabled. See enableSorting(bool).<br>
* Note that update(unsigned int) also sorts the particles.<br>
* This method is therefore only useful when the camera position changes several times between 2 updates.<br>
* <br>
* This method also makes a call to computeDistances().
*
* @since 1.01.00
*/
void sortParticles();
/**
* @brief Computes the distance between each Particle within this Group and the camera
*
* The distances are computed only if the computation of distances of this Group is enabled. See enableDistanceComputation(bool).<br>
* Note that update(unsigned int) also computes the distances between particles and camera.<br>
* This method is therefore only useful when the camera position changes several times between 2 updates.
*
* @since 1.01.00
*/
void computeDistances();
/**
* @brief Computes the bounding box of this Group
*
* The bounding box is computed only if the computation of the bounding box of this Group is enabled. See enableAABBComputing(bool).<br>
* Note that update(unsigned int) also computes the bounding box.<br>
* This method is therefore only useful when the bounding boxe has to be recomputed between 2 updates.
*
* @since 1.01.00
*/
void computeAABB();
/**
* @brief Increases the maximum number of particles this Group can hold
*
* Note that decreasing the capacity will have no effect.<br>
* A reallocation of the group capacity will destroy all its current buffers.
*
* @param capacity The maximum number of particles of this Group
* @since 1.02.00
*/
void reallocate(size_t capacity);
/**
* @brief Creates a new additional buffer attached to the Group.
*
* Additional buffers are used to attach data to a particles. They are mainly used by renderers to store data to transfer to the GPU
* but can be used by the user in any other way.<br>
* <br>
* A buffer is defined by a ID which is a std::string.<br>
* A buffer also has a flag, which can give information about the way it is configured.<br>
* <br>
* Note that ID starting with <i>SPK_</i> are reserved by the engine.
* Note also that creating a buffer with an already existing ID will destroy the previous buffer.
* <br>
* A buffer needs a BufferCreator to allow the group to create it.
*
* @param ID : the ID of the additinal buffer
* @param creator : the buffer creator object
* @param flag : the flag of the buffer
* @param swapData : true to swap data when particle are swapped, false not to (faster but dont keep right order)
* @since 1.03.00
*/
Buffer* createBuffer(const std::string& ID,const BufferCreator& creator,unsigned int flag = 0,bool swapData = true) const;
/**
* @brief Destroys the buffer with the given ID
*
* If no buffer with this ID exists, nothing happens.<br>
* Note that destroying a buffer must never freeze the engine. Checks must be performed.
*
* @param ID : the ID of the buffer to destroyed
* @since 1.03.00
*/
void destroyBuffer(const std::string& ID) const;
/**
* @brief Destroys all the buffers held by this Group
* @since 1.03.00
*/
void destroyAllBuffers() const;
/**
* @brief Gets the buffer with the given ID and checks its flag
*
* The flag is used as a check. the passed flag must be the same as the stored flag.<br>
* If not or if no buffer with the given ID exists, NULL is returned.<br>
* <br>
* The method returns a pointer on the buffer.
*
* @param ID : the ID of the buffer to get
* @param flag : the flag used for the flag check
* @return a pointer to the buffer, or NULL if not found or with an incorrect flag
* @since 1.03.00
*/
Buffer* getBuffer(const std::string& ID,unsigned int flag) const;
/**
* @brief Gets the buffer with the given ID
*
* NULL is returned if the buffer does not exist
*
* @param ID : the ID of the buffer
* @return a pointer to the buffer, or NULL if not found
* @since 1.03.02
*/
Buffer* getBuffer(const std::string& ID) const;
virtual Registerable* findByName(const std::string& name);
protected :
virtual void registerChildren(bool registerAll);
virtual void copyChildren(const Group& group,bool createBase);
virtual void destroyChildren(bool keepChildren);
virtual void propagateUpdateTransform();
private :
struct CreationData
{
unsigned int nb;
Vector3D position;
Vector3D velocity;
const Zone* zone;
Emitter* emitter;
bool full;
};
struct EmitterData
{
Emitter* emitter;
unsigned int nbParticles;
};
// statics
static bool bufferManagement;
static Model& getDefaultModel();
// registerables
Model* model;
Renderer* renderer;
std::vector<Emitter*> emitters;
std::vector<Modifier*> modifiers;
mutable std::vector<EmitterData> activeEmitters;
mutable std::vector<Modifier*> activeModifiers; // Vector of active modifiers to optimise the parsing when updating
// physics parameters
float friction;
Vector3D gravity;
// particles data
Pool<Particle> pool;
Particle::ParticleData* particleData;
float* particleCurrentParams; // Stores the current parameters values of the particles
float* particleExtendedParams; // Stores the extended parameters values of the particles (final values and interpolated data)
// sorting
bool sortingEnabled;
bool distanceComputationEnabled;
// creation data
std::deque<CreationData> creationBuffer;
unsigned int nbBufferedParticles;
// callbacks
bool (*fupdate)(Particle&,float);
void (*fbirth)(Particle&);
void (*fdeath)(Particle&);
// bounding box
bool boundingBoxEnabled;
Vector3D AABBMin;
Vector3D AABBMax;
// additional buffers
mutable std::map<std::string,Buffer*> additionalBuffers;
mutable std::set<Buffer*> swappableBuffers;
void pushParticle(std::vector<EmitterData>::iterator& emitterIt,unsigned int& nbManualBorn);
void launchParticle(Particle& p,std::vector<EmitterData>::iterator& emitterIt,unsigned int& nbManualBorn);
void addParticles(unsigned int nb,const Vector3D& position,const Vector3D& velocity,const Zone* zone,Emitter* emitter,bool full = false);
void popNextManualAdding(unsigned int& nbManualBorn);
void updateAABB(const Particle& particle);
void sortParticles(int start,int end);
};
inline Group* Group::create(Model* model,size_t capacity)
{
Group* obj = new Group(model,capacity);
registerObject(obj);
return obj;
}
inline void Group::setFriction(float friction)
{
this->friction = friction;
}
inline void Group::setGravity(const Vector3D& gravity)
{
this->gravity = gravity;
}
inline void Group::setCustomUpdate(bool (*fupdate)(Particle&,float))
{
this->fupdate = fupdate;
}
inline void Group::setCustomBirth(void (*fbirth)(Particle&))
{
this->fbirth = fbirth;
}
inline void Group::setCustomDeath(void (*fdeath)(Particle&))
{
this->fdeath = fdeath;
}
inline void Group::enableSorting(bool sort)
{
sortingEnabled = sort;
distanceComputationEnabled = sort;
}
inline void Group::enableDistanceComputation(bool distanceComputation)
{
distanceComputationEnabled = distanceComputation;
if (!distanceComputation) enableSorting(false);
}
inline void Group::enableAABBComputing(bool AABB)
{
boundingBoxEnabled = AABB;
}
inline const Pool<Particle>& Group::getParticles() const
{
return pool;
}
inline Particle& Group::getParticle(size_t index)
{
return pool[index];
}
inline const Particle& Group::getParticle(size_t index) const
{
return pool[index];
}
inline size_t Group::getNbParticles() const
{
return pool.getNbActive();
}
inline const std::vector<Emitter*>& Group::getEmitters() const
{
return emitters;
}
inline Emitter* Group::getEmitter(size_t index) const
{
return emitters[index];
}
inline size_t Group::getNbEmitters() const
{
return emitters.size();
}
inline const std::vector<Modifier*>& Group::getModifiers() const
{
return modifiers;
}
inline Modifier* Group::getModifier(size_t index) const
{
return modifiers[index];
}
inline size_t Group::getNbModifiers() const
{
return modifiers.size();
}
inline Model* Group::getModel() const
{
return model;
}
inline Renderer* Group::getRenderer() const
{
return renderer;
}
inline float Group::getFriction() const
{
return friction;
}
inline const Vector3D& Group::getGravity() const
{
return gravity;
}
inline bool Group::isSortingEnabled() const
{
return sortingEnabled;
}
inline bool Group::isDistanceComputationEnabled() const
{
return distanceComputationEnabled;
}
inline bool Group::isAABBComputingEnabled() const
{
return boundingBoxEnabled;
}
inline const Vector3D& Group::getAABBMin() const
{
return AABBMin;
}
inline const Vector3D& Group::getAABBMax() const
{
return AABBMax;
}
inline void Group::addParticles(unsigned int nb,const Vector3D& position,const Vector3D& velocity)
{
addParticles(nb,position,velocity,NULL,NULL);
}
inline void Group::addParticles(unsigned int nb,const Zone* zone,Emitter* emitter,bool full)
{
addParticles(nb,Vector3D(),Vector3D(),zone,emitter,full);
}
inline void Group::addParticles(unsigned int nb,const Zone* zone,const Vector3D& velocity,bool full)
{
addParticles(nb,Vector3D(),velocity,zone,NULL,full);
}
inline void Group::addParticles(unsigned int nb,const Vector3D& position,Emitter* emitter)
{
addParticles(nb,position,Vector3D(),NULL,emitter);
}
inline void Group::removeParticle(size_t index)
{
pool.makeInactive(index);
}
inline const void* Group::getPositionAddress() const
{
return &(particleData[0].position);
}
inline size_t Group::getPositionStride() const
{
return sizeof(Particle::ParticleData);
}
}
#endif