DevMaster.net  
Home | Forums | 3D Engines Database | Wiki | Articles/Tutorials | Game Dev Jobs | IRC Chat Network | Contact Us

Graphics Theory & Implementation > General


Particle Systems      
20/03/2004

Introduction

Particle systems are a technique for modelling things that can't really be modelled with other approaches. Things such as explosions fall into this category. And this file will be concerned with modelling explosions using particle systems

The Basics

A particle system is a collection of independant entities, known as particles, which are animated using a set of rules, with the intention of modelling some effect. The specific way in which particles are displayed, moved, and interact is generally specific to the particle application that they are being used for.

A Particle is in general a single point in space. This point is assigned some attributes or characteristics, and animated over time. Common characteristics for a particle are:

  • Position
  • Speed
  • Energy
  • Direction
As the animation progresses, these characteristics are used, modified, and updated. For example, at time = 0, a particle may have a very high velocity, and a lot of energy. As time progresses, this velocity and energy will decrease, and its path will change.

The general algorithm for a particle will be:

Set up particle

While Animation In Progress
    If Particle Not Dead Then
        Add Particle Direction * Speed To Particle Position
        Add Particle Acceleration To Particle Speed
        Modify Particles Speed
        Modify Particles Energy

        If Particles Energy < Threshold Then
            Mark Particle As Dead
        End If

	If Particle Hits Object Then
	    Modify Particles Position, Direction, Speed and Energy
	End If

	Display Particle
    End If
End While
When it comes to displaying a particle, we can choose many approaches. We can set a particle to be a single pixel. We can scale a particle according to its distance from the viewer. We can make a particle illuminate its environment. We can even place a sprite in the particles position, or a 3D model. My personal favourite is to add the colour of each particle to the screen, clipping it into the legal range, then blur the screen afterwards. This gives the effect of many close particles illuminating a region, and it also smoothes out the pixellated effect of the screen. The blur will also give a primitive trail to the particles.

Explosions

Explosions are one of the easier, and most impressive things to model using particle systems. To do an explosion, we generally set all particles to have some common point of origin, either a single, finite point, or randomly distributed within some sphere. We set them all to have directions and velocities which will shoot them away from the point of explosion. We also set them all to have high energy. We then set the system running...

In general, there are two kinds of explosions we can model. These are airborne explosions, and explosions at some point of impact. The two different kinds behave very differently. In general, an airborne explosions particle directions will be distributed in a sphere, centred at the point of explosion. An explosion based on a point of explosion will have a particles distributed in a hemi-spherical direction, where the sphere is cut by the plane where the explosion occurred, such as a ground, wall, or model plane. The particles will travel generally in the direction of the planes normal, but randomly spread out.

Airborne Explosions

For an airborne explosion, we set the point of origin to be the point of explosion, perhaps randomly distributed within a sphere. We set all directions to be randomly distributed about a sphere. We then normalize the directions, and find some random number, which will be our speed. This poorly-drawn diagram should help clarify this:

To set up the particle, the following pseudo-code will create the particle, in 2D space. I use 2D for simplicity of explanation: 3D is just a case of adding an extra dimension:

randomvec.x = random(distribution) - distribution / 2
randomvec.y = random(distribution) - distribution / 2
Normalize(randomvec)
dist = random(distribution)

particle.x = explosion-x + randomvec.x * dist
particle.y = explosion-y + randomvec.y * dist

dir.x = random(width) - width / 2
dir.y = random(height) - height / 2
Normalize(dir)
dist = random(size)

particle.dir.x = dir.x
particle.dir.y = dir.y;
particle.speed = dist + 1
particle.energy = 1.0
This is an adaptation of the code that I use. Here, distribution is some value used to spread the origins out about the centre of the explosion. Width and Height are used to vary the shape of the explosion. If width == height, then a spherical explosion is generated. Else, the explosion is elliptical. Elliptical explosions generally look better, in my opinion, because they look more natural, random, and less artificial.

Impact Explosions

I'll limit the discussion of these kinds to a simple ground-based type, because arbitrary types tend to complicate matters. In general, these kinds of explosions work the same as air-based, except for the fact that we are confined to one half-space of a plane. In this case, this half-space will be space above the ground. Things don't explode underground in solid soil. Our code will generally be the same as the first type, except that dir.y will be confined to one direction, the positive direction. So all particles will be forced to go upwards, though the amount will vary. So our code will look nearly the same:

randomvec.x = random(distribution) - distribution / 2
randomvec.y = random(distribution)
Normalize(randomvec)
dist = random(distribution)

particle.x = explosion-x + randomvec.x * dist
particle.y = explosion-y + randomvec.y * dist

dir.x = random(width) - width / 2
dir.y = random(height)
Normalize(dir)
dist = random(size)

particle.dir.x = dir.x
particle.dir.y = dir.y;
particle.speed = dist + 1
particle.energy = 1.0
Simply note that we don't subtract height / 2 or distribution / 2 from the Y components of the vectors.

Running The System

Once you have set up your system, you need to run it through. First, I'll discuss the movement of the particle system, then the rendering of it.

Movement

Generally, a basic movement system is all we need. We need to account for the following effects:

  • Movement due to particles own individual force
  • Movement due to gravity
  • Movement due to collision with objects
We ignore movement due to particles impacting with each other, to keep the speed up, and simplify the code. In any case, it wouldn't add much to the simulation.

Movement due the particles own force is easy to simulate. We just add the particles direction, multiplied by the particles speed, to the particles position. You can also decrease the speed at each frame. You have to be careful about that though, because if you reduce it too quickly, the particle will stop dead, then fall to the floor. The code is simple enough:

Particle.x = Particle.x + Particle.Speed * Particle.Direction.x
Particle.y = Particle.y + Particle.Speed * Particle.Direction.y

Movement due to gravity is a piece of cake. You simply have to make the particle accelerate towards the floor. If I remember rightly, the speed of gravity is about 31 feet per second squared. And remember, that's acceleration, not a constant speed. That's easy enough to test. Just drop some stuff. Objects don't float, they speed up. Though the increase in speed is hard to notice because in general objects fall to earth quickly, it is present.

Movement due to collision with objects is easy to simulate too. If a particle impacts an object, such as the floor, you have to reflect its direction about the normal of the object it hit, and reduce its speed. To recap, the formula for reflecting a vector is: R = 2.0 * (N * L) * N - L, where N is the normal, and L is the negative particle direction. In cases such as walls, or the ground, then only one component will be non-zero, such as Y for the floors. In this case, you can get away with just negating the Y direction. Also, be sure to decrease the particle energy. It makes sense that some energy will be absorbed into the ground. If you use blurring, you will also notice that you get this strange kind of flame whoosh up into the sky when a lot of closely spaced particles bounce off the ground. That looks very nice.

Rendering the Particle System

We'll only need two routines here: One to draw the particle, and one to blur the screen. The routine to paint a particle is simple enough. Just take the colour of the background, add the particles colour, clip to the valid range (e.g. 0..255), and put the pixel back to the screen. This will make areas of the screen light up, according to how many particles cover that pixel.

The blur routine is simple enough too. Just take a pixels 4 surrounding neighbours, average them, and subtract some damping constant. Because of the subtraction, the value may go below zero. No problem, just clip to zero. And that's it! Just create the particles, the enter a loop, moving, painting and blurring, and you've got an explosion. Set off a new explosion when the current one dies out, and that's it. So simple.




Discuss this article in the forums
Print article

© 2003-2004 DevMaster.net. All Rights Reserved. Terms of Use & Privacy Policy Want to write for us? Click here