COMP3004 Principles of Computer Graphics                          Coursework 2
Philip Richard Boulain                                <prb102@ecs.soton.ac.uk>
                             Alice in the Machine

+-- PREAMBLE ----------------------------------------------------------------+
| This was, as you may have guessed already, a coursework submission. This   |
| readme file was one of the deliverables for it, and survives unmolested    |
| other than by the addition of this preamble.                               |
|                                                                            |
| Other changes since the submission are OS X build compatability and a fix  |
| to how the playing cards are handled which removes a graphical glitch.     |
|                                                                            |
| TO BUILD FOR MAC, you need to edit the Makefile. You need to uncomment the |
| MACFLAGS value, and change the LDFLAGS in use to be MACFLAGS. gcc will     |
| spew forth warnings about not using library information, but should work.  |
| What doesn't, for me, is mouselook. I don't know why. It's probably some   |
| horrible perversity of GLUT, use of which was mandated over SDL.           |
|                                                                            |
| LICENSE. Please, don't base anything on this code. It's provided for       |
| historic interest, and is a rushed mess using bad tech (GLUT). You can     |
| technically consider it three-clause BSD, but I stress again that it's not |
| worth making modified versions. Port this to Mandala or something. ;)      |
+----------------------------------------------------------------------------+

Controls
--------
This coursework implements mouselook, so deviates a little from the normal
controls:
 * To rotate the camera, move the mouse. Press `Y' to invert the Y-axis motion.
 * To move forwards and backwards in the direction you are looking, use either
   the arrow keys, `W' and `S', or the left and right mouse buttons.
 * You can `strafe' left and right without turning by pressing the left and
   right arrow keys, or `A' and `D'.
 * You can move up and down with the spacebar and `X' key respectively.

The keyboard movement is based on actual key up/down events, instead of
keyboard repeat, so should be smoother than `normal'.

The following keys also have an effect:
 F  Freeze/unfreeze the simulation. This serves two purposes:
     * Stops all animation, so that you can take a screenshot with GIMP, etc.
     * Releases the mouse, so that you can interact with other applications.
    Movement will automatically unfreeze the simulation.
 T  Start the automatic tour. The tour can be interrupted by other movement.
 O  Show the camera co-ordinates in the terminal.
 P  Position the camera for the screenshot and freeze.
 H  Reposition the camera at the in-world help screen.
 Q  Quit immediately.


Building
--------
The simplest way to build the project is to use the provided makefile. Just
invoke "make", followed by "./alice". If you get errors regarding usleep(),
uncomment line 11 of the Makefile.

If you'd rather not use `make', the following command should also work:
gcc -o alice -lGL -lGLU -lglut -L/usr/local/lib --ansi --pedantic -Wall *.c

If performance is unsatisfactory, try adjusting the constants at the top of
"world.c" and re-building. Notably, reducing INFIN_REPEATS will give a large
improvement, at the cost of a reduced effect. Using the "-O3" gcc flag also
helps a little.


The World
---------
You start in the "help room", which contains the help screen. On your left is
the "mirror room", containing some PDP-11s and a `mirror' through to an old
machine room, in which the Cheshire Cat has taken residence. On your right is
the "tea room", where the Mad Hatter's tea robot has broken down and leaked a
bit (alas, the actual tea flood wasn't finished in time), and there are some
flying, glowing mushrooms. Behind you is the "infinity room" -- try to see if
you can find the bottom. =)


Architecture
------------
This project is 100% ANSI C, but can benefit from the GNU libc implementation.

The `core' of the program is alice.c. This contains all the interface and
driving code, and contains one instance of a universe. The universe contains
state such as the camera position, and one world. The world contains state
about the specific enviroment, as is partly a result of this coursework
building on the first. world.c also includes the methods for rendering and
animating the world, as well as a method which clips the camera within its
boundaries. (There is full clipping of all world items except for the floating
mushrooms and falling cards, both of which would get in the way of the camera.)

Almost everything in the world is built out of triangle objects, which are
defined along with verticies in vertex.c. Triangles contain position, normal,
colour (transparency) and texture information, and can be built into linked
lists -- drawing a whole, textured room can be done with the line:
  triangle_draw(some_triangle_pointer);
once the triangle list has been set up, which is the role of world.c's
world_init() method. Entering each triangle manually would be tedious, so
there are utility functions triangle_makeroom() and triangle_makewall(), which
allow simple construction of triangle lists for four-vertex rooms and
two-vertex wall sections respectively, complete with automatic normal and
texture co-ordinate calculations. `x' versions of these functions allow manual
overriding of the height of the `room'. The mirror in the mirror room, the
PDP-11s, and the platforms in the infinity room are built entirely out of
`rooms' and `walls' using this method. The only exceptions are the GLUT
teapot, and the mushrooms and teapot legs which are built from a modified
version of the cylinder rendering code from my coursework one submission.

Moving objects - including the camera - are modelled using a structure called
a `movable', in movable.c. This represents a (possibly relative) point in 3D
space with rotation and velocity. The falling cards are animated simply by
giving them random initial positions, spin, and falling velocities, then
calling:
  movable_animate(this_card.position, elapsed);
on each one. Movables have a method which moves them to another movable, and
this allows an easy way to teleport the camera to another movable. This is how
the `jump to help screen' and `jump to screenshot position' keys work.
Movables are even used for the tour animation -- the camera is interpolated
along a list of them with timing information.

The infinity room effect is one of the most interesting, and is inspired by a
technique called "WarpZones" from the Unreal engine (although it is
implemented differently). The world draw method draws the same part of the
infinite room several times above and below `ground level', and hides the ends
with a specially-designed texture. Fake doorways are added on the other
`floors'. When the camera tries to traverse to another floor, it wraps around
back to the current one -- but, because all floors are the same, it looks as
if it has actually travelled successfully. This is how the tour appears to fly
up two floors yet still arrives back at the help screen.

Finally, there are several techniques to try and keep the speed up:
 * All textures are cached on-card, using glGenTextures(). This is handled
   transparently by the texture object, texture.c. In fact, the texture object
   abstraction allowed me to change to this from simply resetting the texture
   each time by simply modifying methods in texture.c.
 * Primitive occlusion is implemented on a per-room basis; notably, the
   infininty room cannot see the other two rooms and vica versa. (This is why
   the framerate increases as you enter the other two rooms.) The lights in
   the infinity room are also enabled and disabled as you enter and leave;
   this is not just for effect, but because one of them is actually the same
   light as one of the mushroom lights because I hit the limit.
 * Backface culling is enabled. This has the advantage of making incorrect
   normals really obvious. Unfortunatly, it creates a tiny crack in the GLUT
   teapot.


Inspiration and Help
--------------------
The robotic teapot in the "tea room" is inspired by last year's graphics
assignment submission by Richard Leigh (rtl101). I haven't used any of his
code.
All code is my own work; most textures are not (see "Textures" section).
Alice references:
 * Mirror (`looking glass') onto another world.
 * Cheshire Cat smile on one of the PDP-11s.
 * Rich's tea robot now bears a Mad Hat. ("You must have a cup of tea!")
 * Armies of playing cards in the infinity room.
 * Weird, glowing mushrooms, because Alice was one one heck of a bad trip. ;)
PDP-11/Machine references:
 * The infinity room is covered in circuit boards.
 * The infinity room console is that of a PDP-11.
 * There are PDP-11s either side of the mirror, and the mirror shows a whole
   room full of them.


Files
-----
readme.txt      The file you are currently reading.
screenshot.jpg  The requested screenshot, as seen from the `P' location.
Makefile        Automatic compilation and distributable generation instructions.
alice.c         The main C file, containing the interface and main() methods.
universe.*      Representation of most global data, e.g. the camera's movable.
world.*         Code for the specific world - stores, creates and handles the
                animation and rendering of all world objects. Also performs
                camera clipping.
vertex.*        Representation of verticies and triangles. Includes methods to
                easily generate simple rooms and walls, render triangles, and
		automatically compute normal vectors.
texture.*       Representation of a texture, plus simplistic PNM loading code.
shapes.*	Primitive code from coursework 1, colouring removed and normal
                generation added.
movable.*       A representation of a point in space with velocity, used for
                the camera and animated objects.
smalloc.*       `Safe' malloc() which tests the return code for errors.
*.pnm           Textures. See the "Textures" section.


Textures
--------
The following textures are sourced from Google image searches, and are not my
own work:
gravel128.pnm
  Cropped from http://absolutedesign.com/dave/travel/rally_images/gravel.jpg
  Dave Laird, 2000
brushedmetal512.pnm
  http://www.noctua-graphics.de/images/download/tex/metal/iron05.jpg
  Noctua Graphics (Free textures section), viewed on 17 Dec 2004
dimpledmetal512.pnm
  http://www.noctua-graphics.de/images/download/tex/metal/iron01.jpg
  Noctua Graphics (Free textures section), viewed on 18 Dec 2004
patchyrust512.pnm
  Cropped from http://www.noctua-graphics.de/images/download/tex/metal/metbgr02.jpg
  Noctua Graphics (Free textures section), viewed on 17 Dec 2004
rust512.pnm
  Mirrored at http://home.comcast.net/~ddtuts/tutorials/rust/rust.jpg
  http://home.comcast.net/~ddtuts/rustpipe.html viewed on 17 Dec 2004
  Original creator unknown.
crystalmetal512.pnm
  http://www.noctua-graphics.de/images/download/tex/metal/zinc01.jpg
  Noctua Graphics (Free textures section), viewed on 17 Dec 2004
circuit512.pnm
  Cropped from http://www.noctua-graphics.de/images/download/tex/technical/plati01.jpg
  Noctua Graphics (Free textures section), viewed on 17 Dec 2004
pdp11s256.pnm
pdp11panelb512.pnm
  From http://www.psych.usyd.edu.au/pdp-11/
pdp11b512.pnm
  From http://www.nue.org/people/amagai/images/photo/dec20/pdp11.jpg
  (pdp11 processor handbook)
pdp11c512.pnm
  From http://hampage.hu/pdp-11/
cardback512.pnm
  From http://www.kolumbus.fi/sackab/kgb/all_htm/KGBpict_4.htm
cardace512.pnm
  From http://www.apt-p.com/APTPMerchandise.htm
gold128.pnm
  From Judy's Soap and Creations
  Viewed at http://www.soapandthings.com/Pictures/celestial%20gold%20glitter.jpg on 18 Dec 2004

The following *are* my own work:
darkplastic256.pnm
  Created in GIMP
helpscreen512.pnm
  created in Sodipodi (a SVG editor), exported to PNM via the GIMP
  512 appears to be the largest texture GL was happy with -- 1024 didn't apply correctly

The following are derivative works:
circuitfade512.pnm
	Derivative of circuit512.pnm, modified in the GIMP to give the illusion of infinite depth.
pdp11scat256.pnm
	Derivative of pdp11s256.pnm, with added Cheshire cat smile.
