Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Quagmire Particle Engine

0.00/5 (No votes)
23 Feb 2005 1  
An object oriented OpenGL particle engine, for the simple creation of advanced particle effects.

Sample Image - ParticleEngine.jpg

The Big Picture

OpenGL is a powerful graphical library, which can be used to render some amazing effects. Despite the great power of the library, it can be a great hassle to create particle effects. The included particle engine is intended to greatly simplify the creation of such effects. The code offered here is far from perfect, but it is a merely a start to this endeavor. Any suggestions, ideas, or modifications of this code are welcome.

Particle Effects

The concept of particle effects is very simple. Particle effects can be used to simulate fire, fireworks, water fountains, snow, rain, explosions and many other things. The effects are created by creating a definite number of particles. Depending on the need for performance and realistic appearance, the number of particles can range from 50 to thousands. Each particle has its own location, size, velocity, color, life and image. The particle engine controls the particles and makes them react according to the rules of the particle itself.

As the particles fade away, the particle engine is alerted that the particle is dead. Once all the particles die, the effect will stop, or if as the engine is alerted that the particles are dead, it can reinitialize it and it can be displayed again. You may wish to look at the fire demo of this particle engine. It uses glut[^] to simplify the Windows programming aspect of the demonstration, and the actual particle engine does not rely on it in any way.

An Overview of the Particle

The particle is encapsulated in QdParticle and is used by the QdParticleEngine. The particle engine is used to manipulate the particles and their variables. The variables that the particles have control their behavior, and after the particles are initialized, they should not be changed manually. Below is a list of QdParticleEngine's member functions to manipulate the data stored in the particles.

Table 1.1 QdParticleEngine's member functions.

Function Effect
setCurrentColor(nParticle,fRed,fGreen,fBlue,fAlpha) Sets the color to change to prior to the particle is drawn. The color of the particle will be determined through this and the colors of the bitmap.
setFadeColor(nParticle,fRed,fGreen,fBlue,fAlpha) Each time the particle is updated the current color becomes its previous value plus the value of the color given.
setDirection(nParticle,fX,fY,fZ) Each time the particle is update its coordinates become their previous value plus the value of the value given.
setGravity(nParticle,fX,fY,fZ) The force of gravity is similar to the direction, except as the age of the particle increases its effect does too. If the direction is set with positive Y values, and gravity is set with small negative Y values the particle will rise, slow down, and then fall.
setLR(nParticle,fX,fY,fZ) Sets initial position of the lower right corner.
setUL(nParticle,fX,fY,fZ) Sets initial position of the upper left corner.
setAge(nParticle,fAge) Sets age for computation of the effect of gravity. When particle is initialized it should be set to 0.
setGravityFactor(nParticle, fGravityFactor) The gravity factor can make gravitational forces stronger or weaker.
setLife(nParticle,fLife) Sets how alive the particle is. When the life value is 0 the particle is "dead".
setFadeLife(nParticle,fFadeLife) Sets what value should be added to the life each time the particle is updated. Should be negative values.

The particles are created in an array of particles on the heap with the function init(nParticles). The parameter is the number of particles to exist in the array. When the engine is deconstructed it deletes these particles off the heap. The init function can only be called once. The greater the number of particles the engine controls the slower the effect will go at its maximum speed.

Creating Your Own Engine

Create a class to encapsulate the effect, inheriting from QdParticleEngine. Add any variables that your engine would use and use its constructor to initialize these variables as needed. The virtual functions resetParticles() and particleDead should be used to set the variables of the individual particles.

The resetParticles() function is called initially, and can be called more times to bring the particles to the position they were initially. Because random number generation is used to give values to the variables in this, the default random number generator needs to be seeded:

srand(time(NULL));

Now it is required to fill the particle variables with information about how to react as time goes by. In the demo included, the initialization that each particle will undergo will be the same as when each particle fades into nothing and is re-initialized with data. I could copy and paste a lot of code, but besides being bad practice, it is more work for me to do. The solution is to call the particleDead() function for each particle.

    int nCount=0;
    while(nCount != m_nParticles)
    {
        particleDead(nCount);
        nCount++;
    }

The variable m_nParticles is set by the function init(nParticles) and needs not to be manually altered with. This function can easily initialize the particles in a way that is completely unrelated to the particleDead(nParticle) function, the fire engine though, is more logically connected with it.

The particleDead() function is called whenever the particle's m_fLife variable is less than 0. This variable changes consistently over time by initializing it with the setLife() and setLifeFade() variables. Also when a particle is re-initialized it is important to set the frame and age to 0. The setFrame() and setAge function should be used accordingly. If these functions are not called, unusual effects will occur with the gravity variables.

In the fire engine, a non-default constructor was used to set the initial color of the particles. Constructors and variables within the particle engine can be used for things like this, or for other reasons that fit.

Particle Bitmap Path

By default the bitmap used for each of the particles is called particle.bmp, but the path can be changed. Before the particle engine calls the init() function, call the function setImgPath(). If the path given to the engine is incorrect, if the image isn't a valid bitmap, or if for some other reason the engine cannot use the bitmap, upon initialization the executable could display a not so helpful error message:

Error Message: Bitmap not Valid

Particles That Can Overlap

To make most particle effects work, and allow the particles to overlap each other without erasing the picture created earlier, the engine needs to make part of the particle transparent. The transparent part of the particle is denoted on the bitmap of the particle by the color black. To make the color black transparent on the particles, the following code should be added prior to the displaying of the particles.

    glDisable(GL_DEPTH_TEST);                    
    glEnable(GL_BLEND);                                    
    glBlendFunc(GL_SRC_ALPHA,GL_ONE);

Setting Limits For the Particle

When particles leave the viewing window, they can be reinitialized by setting limits for the particle. The function setLimit(fLimitL, fLimitR, fLimitT, fLimitB) sets just such boundaries. It can be called any time during the engine's life. Disabling the boundaries can easily be done.

setLimit(0);

The texture engine included, which the inner workings of the particle engine requires, was also created by me and can be freely distributed with the particle engine in any project you choose to use it in. The texture engine works with this example, yet may not work in a variety of other situations. Make sure you include texture.cpp and texture.h or errors will occur in the compiling.

Feel free to leave any questions or comments, and if you create any engines of your own off of this I would be interested to see it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here