CS448A Final Project - Rigid Body Simulation
Not so fun without the video, huh?
Objective
My goal for this project was to create a solid framework for simulations of rigid body dynamics,
based on the ideas and algorithms of the paper
Nonconvex Rigid Bodies with Stacking by Eran Guendelman, Robert Bridson, and Ronald Fedkiw.
My first idea was to get some boxes bouncing around, but after reading up on the algorithms
necessary for collision detection between boxes using oriented bounding boxes and plane separation
techniques, I decided I'd rather focus on the physics than the collision detection. So, boxes
turned to spheres. I decided that my goal would be to have absolutely general frictional
impulses acting on collisions between spheres and generating physically plausible animations from my results. I developed using C++ with OpenGL for the rendering.
The burning question - Why?
A lot of people asked me why on earth I would want to build a rigid body simulator that could do stuff you could probably hack up in less than 100 lines of code. The main reason is: it's all about the framework. Sure, I can write 10 lines of code that will bounce two spheres together realistically, but will that same code work if I change the initial conditions, or add more spheres, or change the angle of the floor? Probably not. And thus I embarked on a quest to make as general a simulator as possible so it would be easy to extend in the future, yet still provide physically plausible results.
Details
- Primitives
So far my simulator has four primitives, but only two are currently allowed to be in collisions. These two are spheres, and immovable planes. Both are modeled implicitly, and spheres are displayed with glutSolidSphere while immovable planes are displayed with GL_QUADs. In sticking with the theme of being as general as possible, the immovable planes can be in any orientation, so they are useful not just as a ground plane but also as walls. All primitives are subclassed off a RigidBody base class which holds all of the common variables for rigid bodies. The two primitives not currently enabled for collisions are cubes and general boxes.
- Collision detection
Since my rigid bodies are very basic at the moment, I decided to model all collisions between then implicitly, because the formulas are fairly simple. For optimization, I use axis-aligned bounding boxes around all rigid bodies in order to only do collision checking for objects whose bounding boxes overlap.
- Collision modeling
Collisions are modeled using the impulse method. That is, impulses are computed after a collision is detected, and these impulses instantaneously change the velocities of the objects involved. I decided to follow a similar approach to (1) and process all collisions together rather than processing them sequentially. For small enough time steps, the results are still good, and this avoids having to rewind the ODE solver to find the exact times of collion.
- ODE methods
I used simple forward Euler integration for my simulator. Although it is only first-order accurate,
it was good enough for plausible results on a lot of the demos, even with time steps as large as
1/30th of a second for the real-time simulations. For the animations, I use a time step of 1/300th
of a second, but only output frames every 1/30th of a second, so there are ten intermediate frames
computed for each actual frame of the animation.
- The main algorithm
I also modeled the main algorithm for updating the scene after the novel approach in
(1).
The order of events is: collision detection and modeling, advance velocties, contact resolution,
and advance the positions. I used three rounds of collision processing and one round of contact
resolution per update.
- Output
I used the screendump code from SimGear to write PPMs for each frame of the animation, and then I converted the PPMs to BMPs and made AVIs and MPGs from the BMPs with freeware.
Results
So does it work? Bring on the physics!
- Scene 1 - The Bouncing Ball
How can you have a physics simulation without a bouncing ball? You can't. That's why the first stepping stone was getting a bouncing ball without any hackiness whatsoever. Below is a video of the famous bouncing ball. Thrilling, yes, but remember - it's all general impulses. And yes, you're right - it takes about 10 lines of OpenGL code to make a similar scene. Behold....
Bouncing ball (avi)
Bouncing ball (mpg)
- Scene 2 - Sphere collisions
The next step was to get spheres colliding realistically. Below is an animation of two spheres
colliding and bouncing off each other. It was actually generated after friction was added to the
system, but the results are identical, so pretend this was when the simulator was still frictionless.
Colliding spheres (avi)
Colliding spheres (mpg)
- Scene 3 - Collision propagation
Before I added friction to my system, I wanted to see if I could get collisions to propagate through a series of billiard balls. Man, it's so gratifying to see that work based purely on the physics. Keep in mind that since there's no friction, these balls are actually sliding rather than rolling.
Pool balls (avi)
Pool balls (mpg)
- Scene 4 and 5 - Fun with friction
After many frustrating hours trying to figure out why my spheres would not simply roll across the table but
would instead bounce off to infinity, fly through the floor, or roll one direction while sliding the
opposite direction, I finally got working friction in my system, and magically, the balls started to roll.
The first fun thing to do was simulate what happens with tennis balls undergoing topspin and backspin.
Notice how the ball gets additional forward bounce as expected after hitting with topspin, and bounces
back the other direction after hitting the ground with backspin.
Top spin (avi)
Top spin (mpg)
Back spin (avi)
Back spin (mpg)
- Scene 6 - A whole bunch of balls bouncing around
The thing I like about this scene is how most of the balls start with no angular velocity, but the midair collisions impart spin on the balls. Cool.
Cool stuff (avi)
Cool stuff (mpg)
What this project is
This project is thus far a simple simulator for rigid body dynamics, although it is a solid framework
for future extensions with other types of primitives, nonconvex objects, and more complicated collisions and
stacking problems. As it stands, it runs real-time simulations (on my ancient PII 350 with 32MB GeForce2 running
Windows XP Pro) for simple scenes and environments that
give pretty realistic results.
What this project isn't
This project is not a simulator nearly as powerful as the physics engine in (1). It cannot do stacking or complicated contact resolution, and it cannot handle arbitrary convex and nonconvex objects.
Conclusions
This project was a great learning experience. Although frustrating at times, I came out of it with a much better understanding of rigid body dynamics, and more importantly, a great foundation simulator for future work in rigid body physics. I recommend to anyone interested in realistic physics for computer games or simulations to spend the time to get acquainted with the formulas and build a little physics engine like this to play with.
References
- Nonconvex Rigid Bodies with Stacking by Eran Guendelman, Robert Bridson, and Ronald Fedkiw
- Physically Based Modeling Online Siggraph 2001 Course Notes
- Magic Software (matrix, vector, and quaternion code)