Gary King   gking@cs.stanford.edu  SUID: 4662144
Project 4 (Infinitum)
Partner: Dennis Hwang

------------------------------------------------

To run:
Use a Windows 9X or NT based system with a good OpenGL implementation
(e.g. nVidia RivaTNT/TNT2/GeForce, or any card that supports the ARB
multitexture extensions).  First, start the server (\bin\SrvStart.exe),
and select the number of clients that will be participating (1-8 can
'play').  Then start the game by running Infinitum.exe.  Command line
options are -window (forces the game to start in a window) and -noarb
(uses single-pass texturing, even if hardware multitexturing is
available).  After the full-motion video introduction (press Ctrl+Break to 
skip), you will be greeted with the UI.  To control the camera, you may
either click on the "Navigate" button and use the double-control pad at
the bottom of the screen (the controls should be self-explanatory), or use 
the following keys (all lower case):
'w' : track forward
'a' : pan left
's' : track back
'd' : pan right
'q' : look left
'e' : look right
'r' : move up
'f' : move down
't' : look up
'g' : look down
'ESC' : quit
The three buttons on the right side of the control bar (that have pictures 
of a tank, helicopter, and plane) will create a new tank, helicopter, or
plane.  The tank is created at ground level directly below the camera,
while the plane is created at an altitude of 400m and the helicopter at
500m.  While in Navigate mode, it is possible to click on any of the
created objects to select them.  To move objects around, click on the
"Control Units" button.  This will allow you to control the motion of the
objects in full 3D.  The Red attack button will fire a missile which does
200 points of damage to whatever it hits, but the actual firing is a bit
buggy.  When aircraft collide with each other they will do enormous
amounts of damage, and an aircraft colliding with the ground results in
instant death.  The 'goal' of the game is to destroy everyone else's
headquarters; however, this is an extremely easy task thanks to the
kamikaze-style attacks.  When in Control Units mode, it is impossible to
select new units - the main window becomes a control grid, with the left
side of the window equating to accelerating orthogonally to the front
vector of the object, etc.  The space bar will immediately stop any moving 
units.  Please note also that the tank's axes are reversed.  The bounding
boxes also do not properly rotate around the y-axis after an x-axis
rotation (this is a large reason why the missiles fire incorrectly).  This
is obviously because transformed coordinates are stored in the bounding
boxes, rather than re-transforming them every frame to match the object's
front vector.  This was a bug I intended on fixing, but due to finals will
not be able to accomplish.

Also note that it is possible to play all the clients on the same machine, 
but it is not recommended.  Playing both players on a RivaTNT-equipped PC
(Windows NT4 SP5, 128MB RAM, P2-300) resulted in about 10 fps gameplay,
which is *very* slow.
-------------------------------------------------
Technology:

Multipass rendering: I implemented the multipass effects (our engine
supports both opacity mapping *and* bump mapping (check GLobject.c if you
are incredulous), although we only had time to create opacity maps on the
tank) using the ARB multitexture extensions.  Although this is a
hardware-effect, it was actually probably harder to implement than
actually rendering multiple passes in the code, since the extensions are
barely documented anywhere (I did extensive research and testing to figure 
out the proper texture combination settings).  Even with the extensions
though, because bump maps are stored as an external 8-bit map apart from
the texture, bump mapping requires two passes (one to create the embossed
map and another to blend the texture on top).  Bump mapping is implemented 
through the use of the constant-jitter embossment technique - a grayscale
map is subtracted from a constant-shifted copy of itself, with the texture 
being blended on top of it.  Proper embossing requires the jitter value to 
be based on vertex normals; however, that, too, was canceled due to a lack 
of time.

Networking: UDP over Winsock.

Collision detection:  bounding boxes.

Simulated Dynamics:  When a collision occurs (partially randomly do to
terrible collision detection) objects will react in a somewhat realistic
fashion.  Since the Avatar engine (see Avatar.*) supports jerk, angular
acceleration, etc.-based motion, the physics engine roughly calculates
moments of inertia, momentum, energy transfer, etc. and adjusts the
objects accordingly.  It is slightly buggy, but working.

Hierarchical Scene Graph:  My 3DS loader properly handles all the
sub-objects in a 3D Studio file and converts them into my self-created
GLobject format.  The GLobject format keeps all of the sub-object
properties in-tact, making it possible to animate small parts of objects
(see the helicopter rotor spinning).

View Frustum Culling:  I did not implement the standard frustum culling
technique.  What I do is check if any angle between the camera's front
vector and the vectors from the 8 corners of an object's bounding box to
the camera's center is less than 60 (approx).  The caveat to this
technique is when viewing a very tall object very closely at a very high
angle (i.e. the headquarters) it will occassionally disappear.  This could 
be alleviated in most cases by also testing the center of the object.
Again, I didn't have time before submission to fix this.

"Fractal" Terrain.  Although I did not implement a proper noise function
(I did want to write a Perlin noise generator), the terrain is generated
by quadtree-subdividing a 512x512 bitmap and adding the average of the
four corners of the nearest sub-box to a random number (see Terrain.c).
Then everything is converted into 32-polygon (8x4) chunks that are
textured.  Normals are per-surface.  Although I had a technique worked out 
for calculating vertex normals, this just didn't make it in time.

Sound.  I did actually write a working DirectSound engine (see Sound.zip); 
however, when a good friend of mine (Daniel Dannenberg) wrote a custom
Impulse Tracker song for us, I decided to scrap my (still-buggy) audio
engine and use FSound instead, which included an IT player.

Full-motion video introduction.  After hunting around the GLUT source to
locate the name of the window, I hacked out a routine to play AVI files on 
top of OpenGL contexts.  I think the opening of our game demonstrates that 
quite well.

On-Screen Control Panel.  The beautiful control panel was designed by
Dennis.

-------------------------------------------
Resources:
Some of the textures in the terrain were downloaded from various net sites 
linked to on 3DCafe, but all were modified by me (in Photoshop) to work
better as tiles.  The textures on the tank were quickly thrown together by 
me.  The models were designed by Dennis, and the song was written by Danny 
(as mentioned before, and in the credits).  The FMV intro was a quick-hack 
rendered in 3D Studio MAX and edited in Adobe Premiere by me.  All the UI
images were created by Dennis.

The timer code (as mentioned in Timer.c) is a C conversion of Bryan Cook's
C++ class that was posted to the newsgroup.

I copied *no* canned source code in the development of this project.  In
addition to the Red Book and FvD, I used the Microsoft Platform SDK for
Winsock and MCI information, nVidia and ATI Developer support for
ARB_multitexture information, and Martin van Velsen and Robin Fercoq's
3DS_SPEC.txt document that details (most of) the 3D Studio file format.
Some additional hacking was done in order to perfect my loader.
Additionally, comp.graphics.*, x2ftp.oulu.fi, and Gamasutra proved
invaluable resources for suggesting techniques, whether or not I actually
implemented them.

---------------------------------------------

Images:

Infinitum.jpg

This demonstrates the massive polygon and unit-pushing capabilities we
used in Infinitum.  Each plane is composed of 6 sub-objects, totalling 122
faces, each helicopter has 5 sub-object, totalling 80 faces (the rotor is
animated separately for each helicopter), the headquarters has 5
objects totaling 436 faces, and each tank has 7 sub-objects totaling 276
faces, plus a texture and opacity map.  The terrain has 32768 faces, each
textured and lit, generated fractally at startup.  Yes, that means
that in excess of 600k tris/sec are rendered with this game running
at 60fps. This scene shows several tanks trying to infiltrate a
well-defended (but poorly-played) enemy base.  Not seen in this image are
the 20+ forces the infiltrating player has in reserves.