Syllabus   Blank Homework   Quizzes  
Notes   Labs   Scores   Blank


Lecture Notes
Dr. Tong Yu, Sept. 2013
All the materials presented here are adopted from the textbook and the listed references.
    1. Introduction
    2. Line Drawing
    3. Drawing Objects
    4. More Drawing Tools
    5. Vertex Array
    6. Normal Vectors and Polygonal Models of Surfaces
    7. Viewing I -- Affine Transformations
    8. Viewing II -- Projections
    9. Color
    10. Lighting
    11. Blending, antialiasing, fog ..
    12. Display Lists, Bitmaps and Images
    Appendix. Games and SDL

    Viewing II -- Projections
    1. Projection Transformations

    2. What is projection? 3D Setup:

      From 3D to 2D:

      COP -- Center of Projection
      VRP -- View Plane

    3. Purpose -- define a viewing volume
      1. to determine how an object is projected onto the screen,
      2. to define which objects or portions of objects are clipped out of the final image

    4. Perspective Projection
      • The farther an object is from the "camera", the smaller it appears in the final image.
         
        Cube rendered with
        Orthographic Projection
          Cube rendered with
        Perspective Projection

         
        Scene rendered with Orthographic Projection   Scene rendered with Perspective Projection

      • Vanishing Points:
      • A vanishing point is a point in a perspective drawing to which parallel lines appear to converge.

      • One-point perspective : one vanishing point, any objects that are made up of lines either directly parallel with the viewer's line of sight or directly perpendicular to it

      • Two-point perspective: two vanishing points, One point represents one set of parallel lines, the other point represents the other. ( e.g. Looking at a house from the corner, one wall would recede towards one vanishing point, the other wall would recede towards the opposite vanishing point. )

      • Three-point perspective: three vanishing points e.g. looking up at a tall building from the corner, the third vanishing point is high in space

        Examples:
        Perspective Projection distortion: parallel lines appear to converge at a point ( vanishing point ).
        A painting (The Piazza of St. Mark, Venice) done by Canaletto in 1735-45 in one-point perspective.
        Painting in two point perspective by Edward Hopper
        Painting approximately in three point perspective (City Night, 1926) by Georgia O'Keefe.

      • Accomplished through the use of a frustum shaped viewing volume.

      • Field of View

      • View Frustum = volume bounded by Near plane + far plane + field of view

      • Objects outside the frustum are clipped.

      • Projection Transformation
        e.g. Viewer is at origin looking in the negative z-axis
      • Objects that fall within the viewing volume are projected toward the apex of the pyramid, where the camera or viewpoint is.
        void glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);
        Creates a matrix for a perspective-view frustum and multiplies the current matrix by it. The frustum's viewing volume is defined by the parameters: (left, bottom, -near) and (right, top, -near) specify the (x, y, z) coordinates of the lower-left and upper-right corners of the near clipping plane; near and far give the distances from the viewpoint to the near and far clipping planes. They should always be positive.

        Let

          l   =   left     r   =   right
          b   =   bottom     t   =   top
          n   =   near     f   =   far

        The transformation matrix is given by

        ( i.e. corresponds to glFrustum( l, r, b, t, n, f ); )

        Any point (x, y, z) lying inside the frustum is projected to a point (x', y', z') on the near clipping plane z = -n with
          l ≤ x' ≤ r  and  b ≤ y' ≤ t
        This is the same as

      • Alternatively, may use gluPerspective() to create the viewing volume:

        1. specify the angle of the field of view ( θ ) in the y-direction
        2. Field of view or vision ( FOV ) is the extent of the observable world that is seen at any given moment, determining how much of the world is taken into the picture
        3. Larger field of view = smaller object projection size
        4. specify the aspect ratio of width to height ( w/h )

        • Calculating Field of view

        Therefore

        #define PI 3.14159265389
        
        double calculateAngle(double size, double distance)
        {
            double radtheta, degtheta; 
        
            radtheta = 2.0 * atan2 (size/2.0, distance);
            degtheta = (180.0 * radtheta) / PI;
            return (degtheta);
        }
          

        Example: Suppose all the coordinates in your object satisfy the equations

        -1 ≤ x ≤ 3, 5 ≤ y ≤ 7, and -5 ≤ z ≤ 5.

        and the 'camera' is at ( 8, 9, 10 )

        Then the center of the bounding box is (1, 6, 0).
        The radius r of a bounding sphere is the distance from the center of the box to any corner, , say (3, 7, 5). That is,

        r = ½ size   =

        Thus,

        Distance d   =

        and


        void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far);
        Creates a matrix for a symmetric perspective-view frustum and multiplies the current matrix by it. fovy is the angle of the field of view in the y-z plane; its value must be in the range [0.0,180.0]. aspect is the aspect ratio of the frustum, its width divided by its height. near and far values are the distances between the viewpoint and the clipping planes, along the negative z-axis. They should always be positive.

    5. Orthographic Projection

      • Center of Projection ( COP ) is at infinity
      • the viewing volume is a rectangular parallelepiped ( i.e. a box )
      • the size of the viewing volume does not change from one end to the other
      • used for applications for architectural blueprints and CAD ( computer aided design )


    6. Projection Transformation
    7. xp = x
    8. yp = y
    9. zp = -d
      Actually, we need to remember z.
    10. void glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far);
      Creates a matrix for an orthographic parallel viewing volume and multiplies the current matrix by it. (left, bottom, -near) and (right, top, -near ) are points on the near clipping plane that are mapped to the lower-left and upper-right corners of the viewport window, respectively. (left, bottom, -far) and (right, top, -far) are points on the far clipping plane that are mapped to the same respective corners of the viewport. Both near and far can be positive or negative.

      The corresponding transformation matrix for glOrtho(l, r, b, t, n, f ) is:


      ( Correction: R34 should be -(f+n)/(f-n). See derivation of R below. )

    11. OpenGL maps the visible volume into a canonical view volume (CVV)

    12. CVV is a 2x2x2 cube centered at the origin.
    13. The coordinates in this volume is called Normalized Device Coordinates (NDC).
    14. Clipping is more efficient when performed in CVV, especially in hardware implementation.
    15. The canonical view volume can also be conveniently mapped to 2D window by view port transformation.

    16. Orthographic projcection can be broken into two parts:
      • Translation, which centers view volume at origin
      • Scaling, which reduces viewing volume of arbitrary dimensions to canonical cube:

      • 2x2x2 cube, centered at origin
      • Translation sequence moves midpoint of view volume to coincide with origin
        e.g., midpoint of x is (xmax + xmin)/2

      • So, translation matrix T is:
      • Scaling factor is ratio of cube dimension to viewing volume dimension.
      • So, scaling matrix S is:

      • The composite matrix R = S x T is the required matrix used by glOrtho():

    17. Similar transformations occur in perspective projection, glFrustum( l, r, b, t, n, f ) :
    18. Viewing Volume Clipping
        After the projection matrices, any primitives that lie outside the viewing volume are clipped.
    19. Viewport Transformation

    20. Manipulating the Matrix Stacks

      void glPushMatrix(void);
      void glPopMatrix(void);

      void glMatrixMode( GLenum mode );
      Specifies whether the modelview, projection, or texture matrix will be modified. mode: GL_MODELVIEW, GL_PROJECTION, GL_TEXTURE.

      To examine the transformation matrix:

        void glGetIntegerv ( GLenum pname, GLint *params );
        void glGetFloatv ( GLenum pname, GLFloat *params );
        void glGetDoublev ( GLenum pname, GLDouble *params );
        void glGetPointerv ( GLenum pname, GLint **params );

      Example

      /*
       *  cube_mat.cpp
       *  This program demonstrates examining the transformation matrix values.
       *  
       *  A wireframe cube is rendered.
       */
      #include <GL/glut.h>
      #include <stdlib.h>
      #include <iostream>
      
      using namespace std;
      
      void init(void)
      {
         glClearColor (1.0, 1.0, 1.0, 0.0);
         glShadeModel (GL_FLAT);
      }
      
      //print the transformation matrix
      template<class T>
      void print_mat ( T m[][4] )
      {
        cout.precision ( 4 );
        cout << fixed;
        for ( int i = 0; i < 4; ++i ) {
          cout << "\t";
          for ( int j = 0; j < 4; ++j )
            cout <<  m[j][i] << "\t";
          cout << endl;
        }
        cout << endl;
      }
      
      void display(void)
      {
         float p[4][4];
         double pd[4][4];
      
         glClear (GL_COLOR_BUFFER_BIT);
         glColor3f (0.0, 1.0, 0.0);	  	//green color
         glMatrixMode (GL_PROJECTION);
         glLoadIdentity ();             	// clear the matrix 
                 				// viewing transformation  
         glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
         
         
         glMatrixMode (GL_MODELVIEW);
         glLoadIdentity();
         glGetFloatv(GL_PROJECTION_MATRIX,&p[0][0]);
         cout << "Projection Matrix:" << endl;
         print_mat ( p );
         
         glGetDoublev(GL_MODELVIEW_MATRIX, &pd[0][0]);
         cout << "Modelview Transformation Matrix:" << endl;
         print_mat ( pd );
         
         glScalef (1.0, 2.0, 1.0);      	// modeling transformation 
      
         glGetFloatv(GL_MODELVIEW_MATRIX,&p[0][0]);
         cout << "Scale Matrix:" << endl;
         print_mat ( p );
         
         glRotatef ( 45, 0, 0, 1 );
         glGetDoublev(GL_MODELVIEW_MATRIX, &pd[0][0]);
         cout << "Scale Rotation Matrix:" << endl;
         print_mat ( pd );
         glutWireCube (1.0);
         
         glFlush ();
      }
      
      void keyboard(unsigned char key, int x, int y)
      {
         switch (key) {
            case 27:
               exit(0);
               break;
         }
      }
      
      int main(int argc, char** argv)
      {
         glutInit(&argc, argv);
         glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
         glutInitWindowSize (500, 500);
         glutInitWindowPosition (100, 100);
         glutCreateWindow (argv[0]);
         init ();
         glutDisplayFunc(display);
         glutKeyboardFunc(keyboard);
         glutMainLoop();
         return 0;
      }
      
      Outputs:
      Projection Matrix:
              1.5000  0.0000  0.0000  0.0000
              0.0000  1.5000  0.0000  0.0000
              0.0000  0.0000  -1.1622 2.5676
              0.0000  0.0000  -1.0000 5.0000
      
      Modelview Transformation Matrix:
              1.0000  0.0000  0.0000  0.0000
              0.0000  1.0000  0.0000  0.0000
              0.0000  0.0000  1.0000  0.0000
              0.0000  0.0000  0.0000  1.0000
      
      Scale Matrix:
              1.0000  0.0000  0.0000  0.0000
              0.0000  2.0000  0.0000  0.0000
              0.0000  0.0000  1.0000  0.0000
              0.0000  0.0000  0.0000  1.0000
      
      Scale Rotation Matrix:
              0.7071  -0.7071 0.0000  0.0000
              1.4142  1.4142  0.0000  0.0000
              0.0000  0.0000  1.0000  0.0000
              0.0000  0.0000  0.0000  1.0000
      

    21. Additional Clipping Planes

    22. In addition to the six clipping planes of the viewing volume (left, right, bottom, top, near, and far), you can define up to six additional clipping planes to further restrict the viewing volume.

    23. Each plane is specified by the coefficients of its equation:
        Ax + By + Cz + D = 0.
      void glClipPlane(GLenum plane, const GLdouble *equation);
      Defines a clipping plane. The equation argument points to the four coefficients of the plane equation, Ax + By + Cz + D = 0. Clip away space of Ax + By + Cz + D < 0.
      plane is GL_CLIP_PLANEi, where i is an integer specifying which of the available clipping planes to define.

      You need to enable each additional clipping plane you define:

        glEnable(GL_CLIP_PLANEi);

      You can disable a plane with

        glDisable(GL_CLIP_PLANEi);

      Example: Clipped Wireframe Sphere
      /*
       *  clip.cpp
       *  This program demonstrates arbitrary clipping planes.
       */
      #include <GL/glut.h>
      
      void init(void)
      {
         glClearColor (0.0, 0.0, 0.0, 0.0);
         glShadeModel (GL_FLAT);
      }
      
      void display(void)
      {
         GLdouble eqn[4] = {0.0, 1.0, 0.0, 0.0};
         GLdouble eqn2[4] = {1.0, 0.0, 0.0, 0.0};
      
         glClear(GL_COLOR_BUFFER_BIT);
      
         glColor3f (1.0, 1.0, 1.0);
         glPushMatrix();
         glTranslatef (0.0, 0.0, -5.0);
      /*    clip lower half -- y < 0          */
         glClipPlane (GL_CLIP_PLANE0, eqn);
         glEnable (GL_CLIP_PLANE0);
      /*    clip left half -- x < 0           */
         glClipPlane (GL_CLIP_PLANE1, eqn2);
         glEnable (GL_CLIP_PLANE1);
      
         glRotatef (90.0, 1.0, 0.0, 0.0);	//make z-axis vertical
         /* 
         poles along z-axis, 20 longitudinal slices (passing through poles)
         16 latitude cuts ( parallel to equator ) 
         */
         glutWireSphere(1.0, 20, 16);		
         glPopMatrix();
      
         glFlush ();
      }
      
      void reshape (int w, int h)
      {
         glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
         glMatrixMode (GL_PROJECTION);
         glLoadIdentity ();
         gluPerspective(60.0, (GLfloat) w/(GLfloat) h, 1.0, 20.0);
         glMatrixMode (GL_MODELVIEW);
      }
      
      int main(int argc, char** argv)
      {
         glutInit(&argc, argv);
         glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
         glutInitWindowSize (500, 500); 
         glutInitWindowPosition (100, 100);
         glutCreateWindow (argv[0]);
         init ();
         glutDisplayFunc(display); 
         glutReshapeFunc(reshape);
         glutMainLoop();
         return 0;
      }
          

    24. Pseudo Depth
    25. Classical perspective projection drops z coordinates
    26. But we need z to find closest object (depth testing)
    27. Keeping actual distance of P(x,y,z) from eye is cumbersome and slow to compute for each point of interest:
        distance =
          ___________
         x2 + y2 + z2 
    28. Suppose near plane is at z = -d, traditionally point (x, y, z) maps to:
        (x', y', z' ) = ( -d⋅x / z, -d⋅y / z, -d )
      We then lose track of the z value.
    29. Introduce pseudodepth: all we need is a measure of which objects are further if two points project to the same (x', y'). So we project (x, y, z) to (x*, y*, z*, with x* = x', y* = y').
    30. Of course, we can set z* to -z to keep track of the depth but its more efficient and looks better if we choose a function with the same denominator ( z ). So we let
        (x*, y*, z* ) = ( -d ⋅ x / z, -d ⋅ y / z, -(a ⋅ z + b) / z )
    31. Choose a, b so that pseudodepth varies from -1 to 1 (canonical cube), then
        a = - ( f + d ) / ( f - d )
        b = - 2 f d / ( f - d )
    32. Generalized Homogeneous Coordinates

      Previously, 4th component is either 0 or 1; works well with affine transformations, involving matrix multiplications

      Trouble with perspective transformation:

      It involves a division by the z coordinate! But matrix multiplications of affine transformations only have addition and multiplications! How can we combine this perspective transformation with the affine transformations ( translation, rotation, scaling )?

      The trick: Consider two sets of coordinates to represent the same point if one is a non-zero multiple of the other --> extending the homogeneous coordinate representation:

    33. the point ( x, y, z, w ) represents the same point as does ( αx, αy, αz, αw )
    34. thus ( x, y, z, 1 ) and ( x/w, y/w, z/w, 1/w ) are equivalent; w ≠ 0
    35. e.g. the point (1, 2, 3 ) has the representations ( 1, 2, 3, 1 ), (2, 4, 6, 2), (0.03, 0.06, 0.09, 0.03 ), (-1, -2, -3, -1) , and so on
    36. So, representations ( -d. x/z, -d. y/z, -d, 1 ) and ( x, y, z, -z /d ) represent the same point ( -d. x/z, -d. y/z, -d )
    37. To convert from homogenous coordinates to ordinary coordinates:
      • divide all components by the fourth component
      • discard the fourth component
      e.g. ( 3, 6, 2, 3 ) → ( 1, 2, 2/3, 1 ) → ( 1, 2, 2/3 )
    38. To convert from ordinary coordinates to homogeneous coordinates
      • append a 1 as the fourth component
      e.g. ( 2, 3, 4 ) → ( 2, 3, 4, 1 )
    39. What is the perspective matrix that brings point ( x, y, z ) to ( -d. x/z, -d. y/z, -d )?

    40. one problem remains: the matrix above is singular; i.e. noninvertible. Why?

      Solution: we don't care about the z coordinate after the transformation; all we care about are the x and y coordinates where the point is rendered on the screen

      The point ( x, y, z ) now maps to ( -d. x/z, -d. y/z, 1/z-d ), which will be projected onto the screen at ( -d. x/z, -d. y/z, 0 )
      The third component has been peeled off for depth testing

      The matrix is nonsingular: