Click here to Skip to main content
Click here to Skip to main content
Go to top

Quagmire Particle Engine

, 23 Feb 2005
Rate this:
Please Sign up or sign in to vote.
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

Share

About the Author

Ken Mazaika

United States United States
No Biography provided

Comments and Discussions

 
Generalgood job Pinmemberalexander_2034812-Mar-07 5:24 
General[Message Removed] Pinmemberstonber5-Oct-08 7:06 
Questiondust particle in opengl Pinmemberkbariah15-Feb-07 16:38 
AnswerRe: dust particle in opengl PinmemberKen Mazaika15-Feb-07 17:14 
Questiondust particle (cont.) Pinmemberkbariah15-Feb-07 17:35 
AnswerRe: dust particle (cont.) PinmemberKen Mazaika15-Feb-07 20:49 
To start with this can be complicated stuff so you'll probably need to put some serious time into planning it. As far as the OpenGL API and stuff theres books for that, if thats where you're having problems I suggest you get the opengl red book, or check out nehe.gamedev.net. That site has a lot to offer someone interested in game programing.
 
Basically the code I provided here is pretty simple, in a nutshell heres what it does:
-represents an individual particle in a mathematical & OpenGL way
-manages a large set of particles
 
Your particles might need to be represented slightly differently than mine. I wrote this code before I knew a lot about the object oriented design techniques I do now. Soon I hope to have the time to reimplement this code to be cleaner and adhere to the OOD techniques I learned so inheriting from the particles is easier but it sounds like your running on a deadline and you can manually edit the Particle class if you need to.
 
My particle manager (the particleEngine) was designed to be extended so I feel this will do the trick for you just fine, if it is a fast enough solution.
 
So lets think about the data--the particles. Load a texture you like, probably a circular white one. Pick a color. What do the particles represent? Probably sand or dust or just fine things that are visible. We also have the car. Somehow the car and the particles need to interact with each other...we'll get to that later.
 
So initially the particles need to have a position, probably spread out on top of the pavement. Conceptually the Y coordinate of the dust initially will be the same, just above the Y coordinate of the pavement. The X and Z coordinates should be random so the particles are distributed.
 
Conceptually air-currents the car generates make the particles move around. Maybe there will be a gentle breeze that day too, not enough to lift the particles from the ground but once in flight will carry them one way. Either way it seems like currents are an important part of the problem, lets make a superclass for them, like an interface in java.
 
abstract class Current{
//a bunch of data we'll need for the calculation
void blowParticle(Particle p);
}

 
blowParticle will mutate the particle to the position the current takes it. Now when the particle advances we can just make all the currents act on the particle. From a realistic perspective all the currents would act on the particle at the same time, but if we do them one after another we'll get a pretty similar effect.
 
We will need a small amount of momentum in the downward direction so once a current moves a particle it will eventually fall back to the ground. We will also need to check it to make it so the particles don't fall through the pavement (unless it's really fresh pavement Poke tongue | ;-P ). When the particle advances we will need to check to make sure the data is right and fix it if it isn't. That shouldn't be too hard.
 
Now we're virtually done, all we need to do is figure out this current object. Lets start thinking about this gentle breeze. In physics we learned about static friction and how it makes particles resist initial motion along a surface with friction. Horizontal wind won't effect particles that are on the pavement, it will shoot right over them. So we'll need to test if the particle is on the pavement (which by assumption means its not moving if we have particles starting from rest) and do nothing to those particles. Particles above MIN_HEIGHT can get a couple units added to the X direction.
 
Now all we need to figure out is the currents generated by the car. I'm not sure of the physics of these currents so I might be off. You probably should check out videos of dusts under cars on youtube to see if my guess is right, but here is how I think these currents could work:
 
Currents travel around the car in certain paths. At a constant velocity I feel like the current should be the same at two different points in time. To make a completely accurate representation you would probably need to use a management system for the currents (because there are thousands going in different directions all around the car) but for simplicity's sake lets think of only two currents. The current in front of the car, and the current behind the car.
 
The current in front of the car: Because this is in front of the car we'll need to check the location of the particle. If the particle is in a location in front of the car the current will act on it. Otherwise it will simply return. If it is acting on it I feel like we'd want the particle to be lifted up and pulled towards the back of the car.
 
The current in the back of the car: Will need to only use particles in a certain region behind the car and it will spread the particles out, particles coming from the left side will go even more left; particles on the right side will go even more right. This shouldn't be difficult to implement.
 
Now the only hard part is figuring out where the objects should go. It seems pretty obvious that the currents will go inside the car representation. Either the car will need to be global, or INSIDE the particle engine. If you put it inside the particle engine class it will make it more like a scene engine, but i feel like it is a safer way to go.
 
I'd try to do this and display a simple cube or something, don't worry about the model until the end. If you get the particle effect but don't get the car to look realistic I'm sure you'll get a great mark. Seeing the batmobile cruising down the pavement would be awesome to see though...with a reflective hood...anyway.
 
Once you get it done you probably will want to break up these currents into subcurrents or find a more complicated realistic equation to describe them. If you break the project into chunks like this it seems pretty simple...
 
I haven't implemented this, so I'm not sure if this is the best way, or even a good way to do this, but it seems the most logical. If you have more specific questions I'd be happy to answer them, and I encourage you to email me your final project. Good luck!
QuestionRe: dust particle (cont.) 2 Pinmemberkbariah15-Feb-07 21:14 
GeneralMight have to DL glut PinmemberJWood27-Sep-06 9:28 
QuestionVoting on faith? PinmemberShog923-Feb-05 10:07 
AnswerRe: Voting on faith? PinmemberKen Mazaika23-Feb-05 17:28 
GeneralRe: Voting on faith? PinmemberShog923-Feb-05 18:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140916.1 | Last Updated 23 Feb 2005
Article Copyright 2005 by Ken Mazaika
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid