Particle Systems

A method of modeling "fuzzy" objects - e.g. fire, smoke, water

Introduced in 1983, in the Star Trek II "Genesis Effect"

Model complex objects not easily represented by ordinary surfaces - large masses of simple, dynamic particles are used.






Particles

Particles are usually treated as simple points with position, velocity, and color.

Individual particles are added to the system, move about, are affected by forces such as gravity, and eventually die out.






Particle Data

Example C data structure:

struct _particle
    {
     Vector3 position; 
     Vector3 tailPosition;
     Vector3 velocity;
     Vector3 color;
     float removeTime;
    };

struct _particle * particleArray;





Particle Class - Python

Example Python class:

class particle:
    def __init__(self, position=Vector([0,0,0])):
        self.position = position
        self.velocity = Vector([uniform(-3,3), 8, uniform(-3,3)])
        self.color = [uniform(.5,1), uniform(0,1), uniform(0,0.5)]
    def update(self, dt):
        self.position += self.velocity * dt
        self.velocity += gravity * dt

class particleSystem:
    def __init__(self):
        self.particles = []
    def addParticles(self, num):
        for i in range(0,num):
            self.particles.append(particle())
...





Particle Code

Particle system code has three major parts:






Rendering Particles

Particles can be drawn in different ways, for different visual effects.

The simplest way is using points or lines.


Example:






Cumulative Rendering

When drawing particles, we often want them to "add up" in some way to form a fuzzy effect, rather than looking like just a set of individual points or lines.

This can be done using blending. Disabling depth-buffer-writing in this case is useful, because we don't want the particles to obscure each other.






Cumulative Rendering

glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);
glDepthMask(GL_FALSE);
glBegin(GL_LINES);
for (int i=0; i < numParticles_; i++)
    {
    glColor3fv(particles_[i].color.vec);
    glVertex3fv(particles_[i].tailPosition.vec);
    glVertex3fv(particles_[i].position.vec);
    }
glEnd();
glDepthMask(GL_TRUE);
glBlendFunc(GL_ONE, GL_ZERO);
glDisable(GL_BLEND);

Example:






Forces

Particles can be affected by forces. This can be implemented in the same way as applying forces to ordinary solid objects.






Forces

dms::Vector3 gravityAccel = gravity_ * dt;
dms::Vector3 windAccel = wind_ * dt;
for (int i=0; i < numParticles_; i++)
    {
    particles_[i].velocity += gravityAccel;
    particles_[i].velocity += windAccel;
    particles_[i].tailPosition = particles_[i].position;
    particles_[i].position += particles_[i].velocity * dt;
    }

Examples:






Other Primitives

Particles don't have to be rendered as just points or lines.

A common alternative to points & lines for particles is simple textured polygons. For smoke or clouds, the texture would look like a single puff.

The particles will still be blended together, similar to the previous examples.






Other Primitives


Example:






A particle system can have hundreds (or thousands) of individual particles.
Operations on each particle can add up and make things slow.
For real-time use, minimize the number of particles, and avoid, simplify, or pre-calculate any expensive operations.

Expensive operations include: