Particle Systems

CS 481/681 2007 Lecture, Dr. Lawlor

Mechanics

So.  Sir Issac Newton.  Specifically, mechanics:

    F = m * A
    A = dV/dt
    V = dP/dt

Physics for Particle Systems

The simplest place to apply Newton's laws is on "particles"--little dots or points floating in space.  Each particle has at least a position (P), but also optionally a color, a velocity (V), a size, etc.  The easiest way to draw particles is something silly like:
	glBegin(GL_POINTS);
for (unsigned int i=0;i<particles.size();i++) {
glColor4fv(particles[i].color);
glVertex3fv(particles[i].P);
}
glEnd();
So fill up the array of particles.  Draw them every frame.  This is easy, but they're just floating in space.

Now you just need to move the particles--just change their positions.  This is actually quite easy, and comes straight from the definitions above:
  1. Pick a "timestep"--a small interval of time to simulate.  In the differentials above, this is "dt".
  2. V = change in P / change in time.  Change in time==dt.  So solving for P, dt*V==change in P.  Thus we just run
        P+=dt*V;
    This alone will give you particles travelling in straight lines (Newton's First Law).
  3. Compute the net force on the particle (see below).  Now F=m*A, so A=F/m  (or for gravity, A=constant).
  4. A = change in V / change in time.  So solve for V, dt*A==change in V.  Thus we run
        V+=dt*A;
    This will allow the particles to respond to arbitrary forces, yet still have inertia.  It looks darn good, and it's easy!
Note: we are faking it here somewhat.  For a nonzero timestep, the velocity will change over the timestep, so our resulting P's are not exact, especially if V changes quickly.  If accuracy is important, you can use the second-order formula "P+=dt*V + 0.5*(dt*dt)*A;" or even something fancy like a Verlet integrator.

One place where virtually all normal integrations fail is for short-duration sharp impacts.  The problem is that the force changes extremely rapidly, changing the velocity in a jump.  Of course, we can fake this pretty easily for coordinate-aligned reflection planes:
	if (P.x<0) {P.x=0; V.x=-elasticity*V.x;}
Or for an arbitrary plane with outward-facing normal N and on-plane point O:
	float dist=dot(P,N)-dot(O,N);
if (dist<0) {
P-=dist*N; /* move P to the plane surface */
V=elasticity*reflect(V,N);
}
Elasticity controls how elastic the collision is--how much velocity is retained after the bounce.  elasticity==0.0 means particles do not bounce, like blobs of clay (or organs).  elasticity==1.0 means particles rebound with exactly as much velocity as they started with.

But usually computing the net force is easy--just sum up all the forces.  Forces can be as interesting as you like:
Once your particles fall offscreen (or just get wedged in one place for too long), it's a good idea to stop drawing them.  You can actually reincarnate the particle at some source (a "fountain" of particles), or

Easy ways to Screw Up Physics

People spend their entire lives watching these laws in action, and they're amazingly good at detecting violations of them--and many games and animations "just don't look right" because the designers thought they could cut corners, or "just fake it".
 
For example:
Luckily, the real laws of physics are strikingly easy to get right if you aren't trying to "make this cool thing happen" (that is, script the outcome of the motion).  If you just follow Newton's laws and let the coolness emerge, it's really easy.

Cool ways to Render Points