/**

  * ParticleEngine class by Justin Klein, 2003

  * Major Overhaul in 2004

  *

  * This class implements a particle engine in OpenGL that supports gravity, local attractors, varying particle

  * lifetimes, velocities, emission angles, point sources, line sources, and real-time level of detail adjustments.

  * Each of these features can be set with a call to one of the functions that are documented below.

  **/

 

class ParticleEngine

{

public:

      ParticleEngine();

      ~ParticleEngine();

 

 

/**

  * Initializes the particle engine.  Params:

  *

  * -texture:                 Pointer to a texture that will be applied to each particle emitted by this engine.

  * -numOfParticles:          The MAXIMUM number of particles that can be emitted at one time by this emitter

  *                           (the number that's currently emitting can be altered in realtime with a different function call)

  *

  * There are a large number of other parameters needed by this engine that get initialized to default values.

  * These can be changed by calling any of the other functions listed below.

  **/

      int Init(int texture,int numOfParticles );

 

/**

  * Updates the particles' velocity, brightness, position, and possibly activating/deactivating particles.

  * If this is not called during every frame (along with Render()), the engine will appear to freeze.

  * frameTime must contain the time (in seconds) taken to render the last frame; this is used for time-based movement

  * of the particles.

  **/

      void Update(float frameTime);

 

/**

  * Renders each particle; this must be called once for every frame, or nothing will be drawn.  Also, for the

  * particles to update their positions, Update() must be called for every frame.

  *

  * Nothing will be drawn if the particle engine has not been initialized with a call to Init().

  *

  * NOTE: For particles to visibly fade (i.e. smoke or fire), blending must be enabled; if blending is

  *       not enabled, the lifetime of each particle will be the same, but they will not fade to death

  *       (i.e. rocks or water drops).   BlendFunc must be glBlendFunc(GL_SRC_ALPHA, GL_ONE);

  *

  * NOTE: For particles to be textured, texturing MUST be enabled before drawParticles() is called.

  *

  * NOTE: For particle backgrounds to disasppear (particles to not be square), AlphaTesting MUST be

  *       enabled, with its func set as glAlphaFunc(GL_GREATER, 0); (initParticleEngine automatically does this,

  *       however if you change it anywhere, it must be changed back before rendering particles).

  *

  * Returns the number of particles that were actually drawn.

  **/

      int Render();

 

/**

  * Cleans up our particle engine by deallocating the memory used to store the particles.

  **/

      void Cleanup();

 

/**

  * Sets the texture to be used for each particle emitted by this engine. This must have already been loaded by OpenGL.

  **/

      int setTexture(unsigned int tex);

 

/**

  * Sets the edge-length of each particle; return 0 for invalid value. Default is 1.0.

  **/

      int setParticleSize(float size);

 

/**

  * May be used to reduce or increase the number of particles currently being rendered, for purposes

  * of level-of-detail; valid values are between 0 and the numOfParticles that was specified when the

  * engine was initialized (this is the maximum number of particles it's capable of rendering without

  * re-initializing it).

  *

  * Returns 1 for success, 0 for error.

  **/

      int setNumOfParticles(int howMany);

 

 

 

/**

  * Returns the number of particles that currently EXIST.  This may be more or less than the

  * number that was specified by setNumOfParticle (for instance, if the desired number was

  * recently changed, this number will be higher until enough particles die out)

  **/

      int getNumOfParticles();

 

 

/**

  * Sets the particle-emitter's color to (colorR, colorG, colorB);

  * every particle that's emitted AFTER the color-change will be

  * emitted in the new color.  Returns 1 for success, 0 for bad range. Default is white.

  **/

      int setColor(float colorR, float colorG, float colorB);

 

 

 

/**

  * Changes the location from which particles originate. Default is (0,0,0).

  * Note that just calling glTranslatef before rendering the engine moves the ENTIRE engine, including

  * any particles that have already been emitted, where this only changes the location that new particles

  * will be emitted (the SOURCE of the emitter).

  **/

      int setPos(float x, float y, float z);

 

/**

  * Changes area over which particles originate.  (0,0,0) is default, and creates a point source.

  * (1,0,0), for example, creates a line source of length 1 along the X-axis.

  **/

      int setPosVar(float x, float y, float z);

     

/**

  * Specifies the angle of emission.  Note that this is NOT the same as calling glRotate, which will rotate

  * the entire engine and any particles that have been emitted so far; this changes the direction in which new

  * particles are emitted.  The specifed angles are AROUND the x-axis and AROUND the y-axis.  Angles are in degrees.

  **/

      void setAngle(float x, float y);

 

/**

  * Sets the amount that angles are allowed to vary in degrees.  0 causes a perfect line-stream of particles;

  * 45 degrees looks like a "spout", etc.

  **/

      void setAngleVar(float x, float y);

 

 

 

 

/**

  * Sets the base percentage of the particle's life that decreases for each frame rendered.  For instance,

  * a particle with fadeSpeed = .5 will die after 2 frames (fades 50% per frame).  Fade speed of 0 is not

  * allowed, and will be rounded to a very small number. Default is 0.05.

  **/

      int setFade(float fadeSpeed);

 

/**

  * Sets the amount by which the fadeSpeed is allowed to vary.  This causes the particles to die at

  * a variety of different times, so the emitter is "smooth" (if fadeVar is zero, it will emit "bursts"

  * where every particle dies and is re-emitted at the same times.)  Default is 0.05.

  **/

      int setFadeVar(float fadeVar);

 

/**

  * Specifies the speed with which particles are launched (0->1; greater values are allowed). Default is 0.15.

  **/

      int setVelocity(float velocity);

 

/**

  * Specifies the maximum allowed variation in velocity (0->1; greater values allowed), so that the particles

  * can move at more randomized speeds. Default is 0.05.

  **/

      int setVelocityVar(float var);

 

 

 

/**

  * Sets the gravity in the x, y, and z directions.  Values can be from -1 to 1, where

  * 0 is no gravity and 1 is the strongest gravity, -1 is reverse-gravity. Default is 0, 0, 0.

  **/

      int setGravity(float x, float y, float z);

 

/**

  * Sets the strength of an attractor (aka a "point" source for gravity, instead of directional). 

  * Negative strengths repel particles. Magnitudes normally range between -1 and 1, but can be greater.

  * Default is 0 (turned off).

  **/

      void setAttractorStr(float attractorStrength);

 

/**

  * Sets the position of an attractor.  Note that local attractors are off by default (strength = 0).

  **/

      void setAttractorPos(float x, float y, float z);