I was all set to start talking about how to handle collision response. I thought I could just have these objects that you could move around, m
ake collide, and then watch their responses. Yeah, collision response, that will be great! Then I thought, "How am I going to get these objects flying around in the first place?" Well, I could give each object an initial velocity and they would collide. But, I would need world boundaries for those objects to bounce off of so they would stay in play. To direct the objects, I need to be able to apply force. Suddenly, instead of a nice collision demo, I had designed Asteroids. All I wanted was a little demonstration of a fairly simple concept and instead I ended up applying forces and acceleration to particles. I had stumbled on the big "D" word: Dynamics.
That’s alright. I will not be afraid. I always say, "Turn a problem into an opportunity." However, physics is a huge field full of fertile topics that can be distilled into nice column-sized pieces. So once more good friends, into the breach.
What’s So Dynamic About It?
When I was writing about inverse kinematics back in September, I was only really interested in kinematics: that is, the study of motion without regard to the forces that cause it. Dynamics, I said, concerns how forces are used to create motion, and I didn’t want to open up that can of worms. Well, the can is now open and the worms are climbing all over.
I’m going to have to recap a bit, but I suggest you go back and reread Chris Hecker’s column from the October/November 1996 Game Developer, "Physics, the Next Frontier." If you don’t have the magazine handy, that article as well as other physics related articles written by Chris Hecker are available on the Definition Six web site at http://www.d6.com/users/checker.
This month, I’m going to focus on particle dynamics. What is particularly important about particle dynamics is the relationship between force, f, the mass of a particle, m, and the acceleration of that particle, a. This can be stated in the familiar Newtonian notation as f = ma. You may recall that the acceleration of a particle is the derivative with respect to time of the velocity of that particle, v. Likewise, the velocity of the particle is the derivative with respect to time of the position of the particle, x. You can see how this relationship works in the following equation:
So, let me state the problem I’m trying to solve. Given a set of forces acting on a particle at time t, where will that particle be after a small amount of time has passed? It’s clear that with the value of the force and the mass of the particle, I can obtain the acceleration of the particle. If I integrate that acceleration with respect to t, I’ll end up with the new velocity of the particle. If I integrate again, I get the new position. Easy, right?
The structure for a particle is in Listing 1. It’s easier to store 1/m for the particle because this is what I need in the equations. The forces that act on the particle accumulate in the f term. With this information, I can integrate the dynamic system forward in time to establish a new position for the particle. This process involves solving ordinary differential equations. Fortunately, Chris’s column described a numerical method of solving these problems. Listing 2 contains code that uses the simplest numerical integrator, known as Euler’s method, to compute the new state of the system. The great thing about this integrator is that it’s simple to implement and understand. However, because it’s a simple approximation, it’s subject to numerical instability, as we will see later.
Listing 1. The particle type.
// TYPE FOR A PHYSICAL
PARTICLE IN THE SYSTEM
tVector pos; // Position of Particle
tVector v; // Velocity of Particle
tVector f; // Total Force Acting on Particle
float oneOverM; // 1 / Mass of Particle
Listing 2. My simple Euler intergrator.
// Function: Integrate
// Purpose: Calculate new Positions and Velocities given a deltatime
// Arguments: DeltaTime that has passed since last iteration
// Notes: This integrator uses Euler's method
void CPhysEnv::Integrate( float DeltaTime)
/// Local Variables //////////////////////////////////////////////////////////
source = m_CurrentSys; // CURRENT STATE OF PARTICLE
target = m_TargetSys; // WHERE I AM GOING TO STORE THE NEW STATE
for (loop = 0; loop < m_ParticleCnt; loop++)
// DETERMINE THE NEW VELOCITY FOR THE PARTICLE
target->v.x = source->v.x + (DeltaTime * source->f.x * source->oneOverM);
target->v.y = source->v.y + (DeltaTime * source->f.y * source->oneOverM);
target->v.z = source->v.z + (DeltaTime * source->f.z * source->oneOverM);
SET THE NEW POSITION
target->pos.x = source->pos.x + (DeltaTime * source->v.x);
target->pos.y = source->pos.y + (DeltaTime * source->v.y);
target->pos.z = source->pos.z + (DeltaTime * source->v.z);
You Can’t Force Me to Move, Can You?
I now have a method for dynamically moving particles around in a realistic fashion. However, to get anything interesting to happen, I need to get things moving. This requires the application of some brute force, or several forces. But what kinds of forces do I want to apply to my little particles?
Well, the obvious force that has been applied to objects in games since the beginning of computer simulations is gravity. Gravity is a constant force that is being applied to all particles. In order to realistically simulate gravity, force must be added into the particle’s force accumulator every system update. In general, this force is a vector pointing down along the y axis. However, there’s nothing to stop a simulator from having a gravity vector that points in a different direction. In fact, one of the very cool things about having a good physical simulation is that gravity can change and things will still "look" correct. This realistic look may not occur if you are trying to hand animate an object.