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 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.
Example C data structure:
struct _particle { Vector3 position; Vector3 tailPosition; Vector3 velocity; Vector3 color; float removeTime; }; struct _particle * particleArray;
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 system code has three major parts:
Particles can be drawn in different ways, for different visual effects.
The simplest way is using points or lines.
Example:
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.
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:
Particles can be affected by forces. This can be implemented in the same way as applying forces to ordinary solid objects.
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:
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.
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: