BEHIND THE MAGIC EIGHT BALL AT SHARP SHARKEY'S GRITTY LITTLE POOL HALL README

Richard Bragg (rwbragg@stanford.edu)

For some screenshots, see my webpage at www.stanford.edu/~rwbragg/magic8.html
Feel free to link to this from the class page.

1.  What is it?
---------------
Behind the Magic Eight Ball is a realistic 3d pool game that allows a
player to practice his shots to perfect his game or to challenge an
opponent to a head-to-head duel.  The incredibly realistic ball dynamics
allow the user to do anything he would be able to do in a real game
including applying different spins to the cue ball, shoot with varying
amounts of power and spin, or even jump over other balls.  The winner of a
two-player game even gets a chance to visit the mysterious "Magic Eight
Ball" room, where Sharp Sharkey's Magic Eight Ball holds the answers to
all of life's questions.

In short, my attempt was to create a pool game that was realistic as
possible, so that someone who played pool would enjoy the game as much as
playing pool for real.  Since I am not a very good pool player mainly due
to the fact that I can't control the stick as much as I would like it to,
this was my chance to create a pool simulator where I could make the stick
do exactly what I asked of it, and then see if I really understood the
game...  I feel I have accomplished that goal, and now have a very fun
game that I can play without leaving the computer. 

2. Running the game
-------------------
The source code should compile on Linux, just by running the included
Makefile.  I'm not exactly sure what the minimum graphics requirements
are, but the game runs perfectly well using the Geforce3 cards in the
graphics labs, but runs much too slow on my computer with a lesser
graphics card. 
The executable included (pool3d) is for Linux and has already been
compiled - it should work as is if you don't change any of the existing
directory structure. 

3. How to play
---------------
The controls of the game are as follows:

In all the scenes:
	-Left/right arrow keys: rotate the view
	-Up/down arrow keys: move the view up or down 
	-S/X: zoom in/out

Irrelevant to game play - but might help performance on slow systems:
	-P: toggle between solid and wireframe modes
	-T: toggle texture mapping
	-L: toggle lighting

Shooting (also shown on the screen just in case):
	-Left/right arrow keys: position the direction of your shot
	-CTRL + arrow keys: move the cue stick offset from the center of
the ball - this can be used to apply topspin, backspin, or sidespin to
your shot 
	-A/Z: increase/decrease the cue angle, large angles here will
actually cause the ball to "jump" 
	-Spacebar: hold down to increase power, release to shoot
	
Shortcuts:
	-8: jump directly to the Magic Eight Ball room
	-N: stop all the balls where they are, ending a turn

4. Required Functionality
--------------------------
- 3d Viewing and Objects:
	Clearly this was done - everything in the game is 3d in both
appearance and behavior.  Most of the objects you see in the game were
found on the web (see section 10), but the pool table that I used was
modified a great deal.  The model I originally found had holes in the
model, it wasn't broken down into any groups, not all of the surfaces were
flat, and the mesh was very poorly done, with many skinny triangles that
made any interesting lighting effects useless.  While I did use the basic
features and dimensions of that model, I made so many modifications to it
that I must take some of the credit for that. 

- User Input
	Nothing happens without the user hitting the ball, and there are
many ways to do this.  See above for details on the controls.  Once the
ball is hit, you can still move the view around, but the action on the
table is at the mercy of the laws of physics! 

- Lighting and Smooth Shading
	I actually went to great lengths to make the two lamps above the
pool table create circular spotlights on the pool table, and for the pool
balls' prominent specular reflections to be resulting only from those
lights.  These are both built-in OpenGL features but it took awhile
(including retooling the table's mesh as mentioned above) to get exactly
the look I was going for. 

- Texture Mapping
	Most of the scene is texture mapped.  Notice the changes in the
wood grain at the corners of the table, and the fact that the green felt
wraps completely to the bottom surface of the bumpers.  Since the pool
table model that I found on the web was all one object, I actually had to
manually break the model into its constituent parts in order to apply the
texture map in a desirable way.  The texture maps on the balls I made
myself from scratch!  Most of the other textures were obtained on the web
(see Section 10). 

5. Advanced Features (N=1 -> 2*N = 2)
-------------------------------------
- Simulated dynamics
- Collision detection
	Since the dynamics and collision detection are obviously
intimately related, I will discuss them both at once here.  I must first
say that I got most of my ideas from Chris Hecker's great articles on game
physics (see References), which are a must for anyone trying to do
accurate dynamic modeling.  I also got some great ideas for pool
specifically from Jeff Hacker's article (and its associated source code).
I did my best to include all of the physics phenomena I could to make this
as realistic as possible. 
	First of all, the balls move according to all the laws of physics.
Each ball keeps track of its position, velocity, orientation, and angular
velocity at all times.  External forces and torques can be applied to the
balls either from friction, collisions, or striking a ball with the cue
stick.  For each time step, the position and orientation are updated from
the velocity and angular velocity, which are updated from any external
forces and torques, which all together creates realistic motion.  A
maximum time step is specified to make sure that the motion appears to be
continuous. 
	There is a lot more to shooting pool than these simple equations,
though.  Obviously collision with a wall is different than collision with
another ball, and is even different than a collision with the table
surface.  Friction between these surfaces is also different.  Each type of
collision/contact was characterized by the two objects in collision
(ball-wall, ball-ball, ball-table, ball-floor, etc.) and each type of
collision had its own relevant parameters, as follows: 
- Coefficient of restitution: this measures the elasticity of a collision
- Coefficient of friction: this measures how much friction occurs between
two objects in contact 
- Damping coefficient: this measures how much velocity is lost after the
collision 
	Friction itself also is a little more complicated.  The
coefficient of friction, for instance, is different between two surfaces
in static contact and two surfaces contacting as they move relative to one
another.  Another issue is that when a ball is rolling its contact point
is not moving with respect to the surface- thus using the classical
friction model, the ball would roll forever without slowing down.  All of
these cases are handled in this game.  Contact surface relative velocity
is tested to determine whether static or kinetic friction is applied, and
any balls determined to be in the rolling state are given an additional
friction force to slow down the roll. 
	Another special case I had to deal with was dealing with gravity.
Obviously, if the ball was always in the plane of the table, I could just
throw out gravity and treat it as a 2D system.  That was not an option.
On the other hand, if I applied gravity at all times, I would have to
recalculate the table's reaction force at each time step, which would be
too many needless calculations.  A third option would be to apply gravity
only when the ball was off the table, but then there would be infinite
oscillations between the ball and table due to alternately having a upward
velocity and a downward force as the ball got near the surface of the
table.  I handled this by keeping track of when a ball left the table, and
only allowed the ball to leave the surface of the table when its upward
velocity was enough so that gravity would not return the ball back past
the table surface in the next time step.  This "escape velocity"
calculation seemed to have quite a realistic effect, and was really the
best of both worlds.  I didn't have to calculate the table reaction force
at every time step, and I could still handle vertical motion when
appropriate. 
	So how did I detect collisions or contact and when was it applied?
There were really two parts to this - first, I had to determine the actual
time when contact occurred, and simultaneously I had to determine the type
and direction of contact that occurred and respond accordingly. 
	The algorithm for determining the time of contact was obtained
from the Baraff paper and Hecker's article on collision response (see
references).  Basically, it involved stepping forward until collision was
detected, then continually trying again with a smaller last time step,
until the moment of exact contact was found.  At that point, using the
state of the objects at the time of collision, apply an impulse (both
force and torque) to the colliding objects that both prevented collision
and update their velocity/angular velocity to be consistent with the
result of the collision.   
	This algorithm made possible many of the interesting effects you
see in the game.  Since all of the possible collisions had all of the
parameters listed above, this is how I achieved spin transfer upon
collision between the balls and between the ball and a wall.  Also, by
increasing the cue stick angle so that you were shooting the ball into the
table, you could make the ball "jump" - in some cases, you could use this
to your advantage by jumping over other balls to make a cleaner shot.  In
some cases, many collisions would be detected at the same time, as in the
case of the break at the beginning of the game.  This was handled by
resolving all collisions at each time step until a satisfactory result was
obtained.  You might notice on a break that when the cue ball hits the
front ball on a break, the middle balls don't move much at first - just
like in the real game! 
	The only thing that remains was how a state of collision was
actually detected.  Well, since the balls were spheres, it was silly to do
anything more than simply testing the distances between their centers.  It
was very quick and clearly nothing could be more accurate.  But the table
was another story.  For this, I implemented a collision detection system,
borrowing some ideas from the V-Clip algorithm (see references).
Basically, the gist of my version of the algorithm is that I would
determine the closest feature (face, edge, or vertex) of the closest
polygon on a 3d object (the table in most cases) and calculate the
distance of the ball center to that feature using the clipping planes of
that closest feature.  The result would give me both a collision distance
and direction, by which the collision response effects discussed above
could be calculated. 
	To do this, there were a couple of things I had to do.  First, I
made a simpler version of the table model.  The version you see was
unnecessarily complicated (to get the lighting effects that I was after)
for efficient collision detection computation (though it also would have
worked - just a little slower).  Second, I also had to create a way to
load this model from the .obj format to something that I could use for my
collision detection routines.  I ended up implementing some functions that
used the data structures from the glm.h/glm.c source code, and created
collision objects (containing triangles, their edges, vertices, clipping
planes and normals) that I could use for collision detection.  The result
was actually such that it would work for collision detection between the
balls in the game and ANY objects that were loaded from the .obj format!
I didn't use this functionality, but clearly I could have brought in
another table model and everything should have worked just fine. 
	There is one more piece of information I used for collision
detection.  Clearly, for some polygons, the collision normals should
always be the same as the face normals (as in the case of a flat surface).
For other polygons, the collision normals will depend on the collision, as
in a collision with a polygon with an exposed edge (as in the bumper).  To
properly specify which model should be used, this information was kept in
the collision object to use when resolving collisions. 

6. Not-So Advanced Features, But Features Nonetheless
-----------------------------------------------------
- On screen control panel
	I had big plans for making something much more interesting here,
but I did do some simple things that I definitely feel are integral to the
game.  The player should know when it is his turn, which type of balls he
is shooting at, and how many are left.  All this is on the screen, as are
current parameters for your shot while you are preparing to shoot. 

- Sound (sort of)
	Well, technically there is no sound, but since I spent $16.95 to
gain access the ultimate sound archive, I had to include the .wav files I
intended to use.  I ended up just plain running out of time, and couldn't
add this feature.  From the sound-examples, I expected sl to be ready to
go on the sweet hall computers, but this wasn't the case, and I didn't
have time to figure out how to get it there at the last minute. 

7. Other points of interest
---------------------------
   - In trying the make the game as true-to-life as possible, I used all
of the regulation sizes, weights, etc. for my game.  I also made the game
engine work according to the actual regulation rules (with a couple of
exceptions that I will mention).  All of this information was found in
"The Rule Book" - a must for any sports fans. (see references) 
	
   - Once such exception was that instead of allowing the user to place
the cue ball at the start of the game or after a scratch, I decided to
have the cue ball drop in from off the table - this was an opportunity to
show the 3d nature of the game, and was especially cool, if there happened
to be balls in the way of the ball dropping in - you might even get some
balls knocked in before your shot! 

   - I had seen on another pool game (Havok.com) that you could see the
balls under the table after you made them.  I thought this was a cool
idea, so in my game, whenever you make a shot, the ball is dropped to the
trough under the table, where you can see the made balls through an
opening in the table's base. 

   - No game is any good without a closing scene.  In this game, the
winner of a two player game gets a trip to the "Magic Eight Ball" room,
where they are greeted by a giant 8 ball on a stool, and can ask it a
question.  The Magic Eight Ball knows all and is always ready with an
answer. 

   - Time was updated using the algorithm presented in the help session to
make sure that things happened at the right speed regardless of the speed
of the computer. 

   - Unexpected happenings. Though it is rare, there is the potential in
any game for problems to occur.  In the unlikely event that a ball enters
a collision situation that it cannot get out of due to any reason, this
will trigger a "magic pocket" to be formed, and the ball is seamlessly
removed from the table as the game continues.  Yes, it is admittedly a
hack that I added at the last second in case there were any problems in my
demo, but it is better than the program crashing, and someone playing the
game would definitely find it a cool feature rather than an annoying
program crash. 

8. External programs used
-------------------------
QME Lite - used to build new 3d models and edit existing 3d models.  I
used this a ton, especially in making the table have all the properties I
wanted. 
UVMapper - used to generate texture coordinates on the obj files, for
great texture mapping effects 
3D Exploration - used to preview my models and textures, and convert
between 3d formats 
Corel PhotoPaint & Paint Shop Pro - used both of these to make textures,
including the ball textures, which I made from scratch (no pun intended) 
Visual C++ - used for most of my development

9. External code used
---------------------
glBDF - used for on-screen fonts
texture.h/texture.c - used to read in textures from rgb format
glm.h/glm.c - used to read in objects from obj format

I also looked at the source code from Jeff Lander's sample application
(associated with his article listed below), where he implemented a very
simple pool game that had no ball rotation or pockets or complexity in
general (it only had two balls).  I used some of his ideas for the data
structures to use and general ideas on the overall structure of the
simulation.  I also actually used some of his utility code for some of the
simple math routines (dot products, cross products, etc. - see
vecmath.h/vecmath.c)  I clearly could have written these myself, but since
he had a file with just these mathematical functions, it seemed silly to
redo this stuff when I was creating my physics engine.  I actually ended
up adding some extra utilities to this file to do some other mathematical
operations I needed. 

10. External sources of assets
------------------------------
Objects 
   -Pool table (before my extensive modifications) - 3D Caf
   -Stool, cuestick, cue rack, triangle, lamps - 3D Caf
   -Pool table base - Havok.com (included in their pool game distribution)

Textures
   -Wood on table and stools - Francesco Franceschi
   -Metal on lamps - Mann Made Images
   -Logs, Carpet, Stucco (on ceiling) - Textureartist.net
   -Felt on table and ball textures - all me

11. References
-----------------
Baraff, David.  An Introduction to Physically Based Modeling: Rigid Body
Simulation II - Nonpenetration Constraints.   SIGGRAPH '97 course notes.


Eberly, David.  Distance Between a Point and a Triangle.  Magic Software
Website. 

Hecker, Chris.  Physics, The Next Frontier.  Game Developer Magazine,
October/November 1996. 

Hecker, Chris.  Physics, Part 2: Angular Effects.  Game Developer
Magazine, December 1996/January 1997. 

Hecker, Chris.  Physics, Part 3: Collision Response.  Game Developer
Magazine, March 1997. 

Hecker, Chris.  Physics, Part 4: The Third Dimension.  Game Developer
Magazine, June 1997. 

Lander, Jeff.  Physics on the Back of a Cocktail Napkin.  Game Developer
Magazine, September 1999. 

Midgley, Ruth, ed.  The Rule Book.  St. Martin's Press, 1983.

Mirtich, Brian.  V-Clip: Fast and Robust Polyhedral Collision Detection.
Mitsubishi Electric Research Laboratory, Technical Report TR-97-05. 


12.  Final thoughts
---------------------
I have never worked harder on a class project than on this one - I spent
nearly every waking hour the last two plus weeks on it, and never went
home from my office the last three days.  I was pretty stressed up until
the very end, despite my endless work, I wasn't actually able to play a
full game without any problems until about 11 pm the night before the
demo.  But, in retrospect, it was also a lot of fun. I learned a ton,
including that the people in this class are capable of incredible things.
I thought my project was really good as I worked mostly by myself in my
own lab, but I was amazed by what people came up with for the competition.
Wow. 
