Introduction

    This framework opens a window and draws a scene (via either OpenGL
    or student written code), and allows for some simple
    mouse/keyboard interactions.

    This framework contains a file named "scene.cpp", a new version of
    which will come with each project.  This file implements the scene
    needed to test and demonstrate its specific project.

    The framework also contains a nearly empty file named "render.cpp"
    which is where all student rendering code is expected to go.

    Details of these files and other follow:

Overview

    When the freamework starts up it goes through the following steps:

    * Open a window via GLUT and hooks up various mouse and keyboard
      callbacks.
    
    * Call CreateScene to create an object of type Scene which
      contains all the information needed to define the scene. This
      procedure is supplied anew for each project.

    * Call PreprocessScene to give the student a place to perform any
      needed pre-processing steps before the framework starts calling
      and drawing code.  This procedure is originally empty.

    * Enter the main event loop which handles all user interactions
      and calls DrawScene whenever the window needs redrawing.  This
      is where the student rendering code goes.

    * DrawScene may, if the student wishes, make use of a procedure
      called "DrawSceneWithOpenGL" to draw the scene using OpenGL.
      This allows the user to contrast OpenGL and student rendering
      code.

Interaction

    Once the window is opened, and the scene is created, the even loop
    handles the following mouse and keyboard interactions:

      * Left mouse button: Rotates the scene. (Using what I call the
        turntable rotation model.)

      * Mouse wheel: Zoom the scene in/out.

      * Right mouse button: Translates the scene around the screen.

      * Keyboard 'q', and ESC: Quit the program.

      * Keyboard 'g': Toggles between OpenGL rendering of polygons and
        student rendering code.

The environment of DrawScene

    Since all your code goes into DrawScene, you need a clear
    understanding of the parameters to, and environment of, DrawScene.
    The framework ensures the following at the time of the call to
    DrawScene.  

    * The signature of DrawScene is 
        void DrawScene(Scene& scene, int width, int height);

    * The parameter "scene" contains the scene to be drawn. (More on
      that later.)  This includes the polygons in world coordinates,
      the position and color of any lights, and a 4x4 matrices for the
      viewing and projection transformations.

    * The parameters height and width contain the size of the window.
      These may vary from call to call, but you can be assured that at
      the time of the call, these are the size of the window into
      which you are expected to draw.

    * When DrawScene is called, all pixels will be cleared to the
      background color.

    * When DrawScene returns, the framework will perform the GLUT
      operation (glutSwapBuffers) needed to actually get the new image
      visible on the screen.

    * When DrawScene is running, the OpenGL viewport is set up such
      that individual pixels can be accessed with integer coordinates.
      (0,0) is the lower left corner, and (width-1,height-1) is the
      upper right. Code to color pixels will look something like this:

         glBegin(GL_POINTS);   // Put OpenGL in point drawing mode
         for <whatever>
             ... lots-o-code ...
             glColor3f(r,g,b); // Set color for next pixel
             glVertex2i(x,y);  // Put that color at pixel (x,y)
         glEnd();              // End of point drawing mode

The anatomy of a Scene

    The parameter scene (of type Scene) contains the following items:

    * lights: A list of Light objects (std:vector<Light>) guarenteed
      to contain at least one Light.  A Light has two items, a world
      space position P and a color C.

    * ambient: A Color containing the amount of abmient light.

    * projection, and viewing: Transformation objects which contain a
      Matrix44 that represents the transformation from world to camera
      coordinates and camera to projection coordinates
      respectively. These objects contain two useful methods:

        * Transform: This method is used to transform a Vector4D.

        * InverseTransform: This method is used to transform a
          Vector4D by the inverse transformation.

    * objects: A list (std:vector<Object>) of objects.  Each object
      contains surface lighting characteristics and a list of polygons:

      * diffuse: A Color containg the object's diffuse color.

      * specular: A Color containg the object's specular color.

      * shininess: An integer exponent for the Phons shininess.

      * polygons: A list of polygons (std:vector<APolygon>), where each
        APolygon is a list (std::vector<Vertex> ) of vertices, and in
        turn each Vertex contains the following data items:
      
            * V: a Vector4D world coordinate position of the vertex.
       
            * N: a Vector3D world coordinate normal vector
       
            * prevIndex: The vertices of the parent APolygon for one
              (or more) loops.  this implements that looping by being
              the index of this vertices predecessor vertex.  Usually
              this value will be one less than this vertices index,
              but occasionally it will wrap around to a higher index.


Processing a Scene

    A polygon may have several loops of vertices defined by the
    prevIndex values.  If so the first loop is considered to be
    the outside of the polygon and any other loops are considered
    to be holes in the polygon.

    The code to process all polygons in a scene will look like this:
        for (int k=0;  k<scene.objects.size();  k++) {
            Object& obj = scene.objects[k];
            for (int j=0;  j<obj.polygons.size();  j++) {
                APolygon& poly = obj.polygons[j];
                // Do something with poly


    The code to process all edges of a polygon will look like this:
        for (int i=0;  i<poly.size(); i++)  {
            if (i && poly[i].prevIndex != i-1)
                // This (and all subsequent edges) are HOLE edges
                // BUT you may NOT need to know or use this information
            int prev = poly[i].prevIndex;
            Vector4D P = poly[prev].V;
            Vector4D Q = poly[i].V;
            // Now P to Q is one edge of the polygon.

    The code to transform a world coordinate Vertex4D W to screen
    coordinates, then to pixel coordinates will look like this:
        Vector4D T = scene.viewing.Transform(W);
        Vector3D S = scene.projection.Transform(T).Hdiv();
        S[0] = (S[0]+1.0)*width/2.0;
        S[1] = (S[1]+1.0)*height/2.0;

    The code to transform a pixel coordinate point (x,y,z) to
    projection coordinates, then to world coordinates will look like
    this:
        S = Vector4D(x*2/width-1.0, y*2/height-1.0, z)
        Vector4D T = scene.projection.InverseTransform(S);
        Vector3D W = scene.viewing.InverseTransform(T).Hdiv();

    The code to get the world space coordinates of the eye is
        S = Vector4D(0.0, 0.0, 0.0, 1.0))
        Vector3D Eye = scene.viewing.InverseTransform(S).Hdiv();

    The ambient light
        scene.ambient -- type Color

    The number of lights, and the position and color of light i:
        scene.lights.size() -- type int
        scene.lights[i].P -- type Vector3D
        scene.lights[i].C -- type Color

    An object's diffuse color (used also for ambient color), its
    specular color, and the shininess coefficient:
       obj.diffuse -- type Color
       obj.specular -- type Color
       obj.shininess -- type int
