Kinesia Online Course
Computer Graphics
Kinesia LLC, 2003

    1. Introduction
    2. Line Drawing
    3. Drawing Objects
    4. More Drawing Tools
    5. Normal Vectors and Polygonal Models of Surfaces
    6. Viewing I -- Affine Transformations
    7. Viewing II -- Projections
    8. Color
    9. Lighting
    10. Blending, antialiasing, fog ..
    11. Display Lists, Bitmaps and Images
    12. Texture Mapping
    13. Curves and Surfaces
    14. Games and SDL

    Viewing I -- Affine Transformations

    p.97, p.697

    1. The Camera Analogy

      A series of three computer operations convert an object's three-dimensional coordinates to pixel positions on the screen.

    2. Transformations :
        Represented by matrix multiplication, include modeling, viewing, and projection operations. e.g. rotation, translation, scaling, reflecting, orthographic projection, and perspective projection.

    3. Clipping :
        Since the scene is rendered on a rectangular window, objects (or parts of objects) that lie outside the window must be clipped.

    4. Viewport mapping:
        A correspondence must be established between the transformed coordinates and screen pixels.
    5. The transformation process to produce the desired scene for viewing is analogous to taking a photograph with a camera.

       

      1. Set up your tripod and pointing the camera at the scene --- viewing transformation.

       

      2. Arrange the scene to be photographed into the desired composition -- modeling transformation

       

      3. Choose a camera lens or adjust the zoom -- projection transformation

       

      4. Determine the size of final photograph -- viewport mapping

      To specify viewing, modeling, and projection transformations, you construct a 4 by 4 matrix M, which is then multiplied by the coordinates of each vertex v in the scene to accomplish the transformation

      v' = M v

    6. A Simple Example: Transformed Cube

      //cube.cpp
      #include <GL/gl.h>
      #include <GL/glu.h>
      #include <GL/glut.h>
      
      void init(void) 
      {
         glClearColor (0.0, 0.0, 0.0, 0.0);
         glShadeModel (GL_FLAT);
      }
      
      void display(void)
      {
         glClear (GL_COLOR_BUFFER_BIT);
         glColor3f (1.0, 1.0, 1.0);
         glLoadIdentity ();             /* clear the matrix */
                 /* viewing transformation  */
         gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
         glScalef (1.0, 2.0, 1.0);      /* modeling transformation */ 
         glutWireCube (1.0);
         glFlush ();
      }
      
      void reshape (int w, int h)
      {
         glViewport (0, 0, (GLsizei) w, (GLsizei) h); 
         glMatrixMode (GL_PROJECTION);
         glLoadIdentity ();
         glFrustum (-1.0, 1.0, -1.0, 1.0, 1.5, 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;
      }
      

      gluLookAt() specifies where the camera ( eye position ) is placed. By default, the camera is located at the origin, pointing down the negative axis.

      gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);:

      • camera at ( 0, 0, 5 )
      • aim camera lens towards ( 0, 0, 0 )
      • orientation of camera is specified by up-vector ( 0, 1, 0 )

      glFrustum() -- defines the projection transformation (
      a more commonly used alternative routine is gluPerspective() )

    7. Orthogonal Matrices

    8. Orthognality: An invertible n x n matrix M is called orthogonal if and only if M-1 = MT.

      Theorem. If the vectors V1,V2, ..., Vn form an orthonormal set, then the n x n matrix constructed by setting the j-th column equal to Vj for all 1 ≤ j ≤ n is orthogonal.

      Proof. Since Vj's are orthonormal, ( MTM ) ij = Vi.Vj = dij where dij is the Kronecker delta symbol. So MT M = I. Therefore, MT = M -1 .

    9. Length and Angle Preservation:
      • A matrix M preseves length if for any vector P we have |M P| = |P|

      • A matrix that preserves lengths also preserves angles if for any two vectors P and Q, we have ( M P ).( MQ ) = P . Q

      Theorem. If the n x n matrix M is orthogonal, then M preserves lengths and angles.

      Proof. Let M be orthogonal and P, Q are two vectors. Then

        ( M P ).( M Q )     ( vector dot product )
        = ( MP )T ( M Q )
        = PT M T M Q
        = PT Q
        = P . Q
      This implies that the matrix preserves angles. It also implies that the length of vector P is preserved when transformed by matrix M since |P|2 = P.P

      Example

        M =  
        1
        0
        0
        0
            0
        1
        0
        0
            0
        0
        -1
        0
            0
        0
        0
        1
           
    10. Homogeneous Coordinates

      Vectors and Points

    11. a vector v = ( 3, 2, 7 )

    12. a point P = ( 5, 3, 1 )

    13. They look the same but actually vectors and points are very different: a point has a location, but no size or direction, whereas a vector has a size and direction but no location

    14. The difference between two points is a vector

    15. Problem arises when one transforms points or vectors from one system into another

    16. It is useful to represent both points and vectors using the same set of basic underlying objects
    17. Homogeneous Representation of a Point and a Vector

      A vector

        v = ( v1, v2, v3, 0 )

      A point

        P = ( P1, P2, P3, 1 )

      Properties

      • The difference of two points is a vector. Why?

      • The sum of a point and a vector is a          

      • The difference or sum of two vectors is          

      • It is meaningful to sacle a vector: 3(x, y, z, 0 ) = ( 3x, 3y, 3z, 0 )

      • It is meaningful to form any linear combination of vectors: v = ( v1, v2, v3, 0 )
        u = ( u1, u2, u3, 0 )
        av + bu = ( av1 + bu1, av2 + bu2, av3 + bu3, 0 )
        which is a valid vector

      • What is the sum of two points? Does it make sense to form a linear combination of points?

    18. Affine Combinations of Points

      Consider a linear combination of two points P = ( P1, P2, P3, 1 ), Q = ( Q1, Q2, Q3, 1 ),
        cP + dQ = ( cP1 + dQ1, cP2 + dQ2, cP3 + dQ3, c + d )

    19. It is a valid vector if c + d = 0 ( why? )

    20. It a valid point only if c + d = 1

    21. Affine combination -- sum of the coefficients of a linear combination is 1
      Examples:
        0.3P + 0.7Q is a valid point
        2.7P - 1.7Q is a valid point
        P + Q is not a point
        0.3P + 0.9Q - 0.2R is a valid point
        P + Q - 0.8R is not valid

      Any affine combination of points is a legitimate point

    22. A point plus a vector is an affine combination of points
        Suppose P = Q + tv

        Let

        v = R - Q

        Then

        P = Q + t ( R - Q )

        or

        P = tR + ( 1-t )Q

        which is a valid point as t + (1-t) is 1. So a point plus a scaled vector is also a valid point.

    23. Point or vector ?
        Consider the general situation of forming a linear combination of m points
          m  
        A = ai Pi
          i=1  

        Is A a point or a vector?

        Answer:

        Calculate the sum of coefficients
          m  
        S = ai
          i=1  

        1. A is a point if S = 1
        2. A is a vector if S = 0
        3. A is meaningless for other values of S

    24. Example: The Centroid of a triangle

      We use the preceeding ideas to show that the three medians of the above triangle meet at a point that lies two-thirds of the way along each median. This point is the centroid. Proof:

        By definition, the median from A is the line from A to the midpoint of the opposite side. Thus

          D = ( B + C ) / 2

        The point that is two-thirds of the way from A to D lies at

          G = A + t ( D - A )     with t = 2 / 3

        which yields

          G = A + ( 2 / 3 ) ( ( B + C ) / 2 - A ) = ( A + B + C ) / 3

        Since this result is symmetrical in A, B and C, it must also be two-thirds of the way along the median from B and two-thirds of the way along the median from C. Hence the three medians meet there, and G is the centroid.

        This result generalizes nicely for a regular polygon with N sides: the centroid is simply the average of the location of the N vertices, another affine combination

    25. Linear Interpolation of two points

      Linear interpolation of between points R and Q:

        P = ( 1 - t ) Q + t R

      In one dimension, it can be implemented as:

        	float lerp ( float q, float r, float t ) 
        	{
        	  return q + ( r - q ) * t;	//same as ( 1 - t ) * q + t * r;
        	}
        	

      Point P(t) is tween ( in-between ) at t of points Q and R if t is a fraction and P(t) is computed the way along the straight line QR.

        	Point2 tween( Point2 P1, Point2 P2, float t )
        	{
          	  Point2 P;
          	  P.x = P1.x + ( P2.x - P1.x ) * t;
          	  P.y = P1.y + ( P2.y - P1.y ) * t;
          	  return P;
        	}
        	

    26. Tweening for Art and Animation

      Polyline Q formed by points: Q0, Q1, .., Qi, ... Qn-1

      Polyline R formed by points: R0, R1, .., Ri, ... Rn-1

      We construct polyline P with points: Q0, Q1, .., Qi, ... Qn-1 by 'interpolating' Q and R, i.e.

        Pi(t) = ( 1 - t ) Qi + tRi

        When   t = 0, Pi = Qi ( i.e. P = Q )

        When   t = 1, Pi = Ri ( i.e. P = R )

      So when t changes from 0, to 0.1, 0.2, ..., to 1, P begins with the shape Q and gradaully morphs to R.
      void drawTween(Point2 A[], Point2 B[], int n, float t, Point2 c)
      {   // draw the tween at time t between polylines A and B
        Point2 P0 = tween(A[0], B[0],t);
        cvs.moveTo(P0.x+c.x, P0.y+c.y);
       
        for(int i = 1; i < n; i++)
        {
          Point2 P;
          P = tween(A[i], B[i],t);
          cvs.lineTo(P.x+c.x, P.y+c.y);
        }
        cvs.lineTo(P0.x+c.x, P0.y+c.y);
      }
      	
      man ←→ woman

      Class Exercise:

        Try the "tween.cpp" example at /pool/u/class/cs420/tween. You need to modify the Makefile.

    27. Parametric Form for a Curve ( 2D )

      implicit form:

        F( x, y ) = 0

      e.g. Straight line through points P and Q:

        F(x, y) = ( y - Py )( Qx - Px ) - ( x - Px )( Qy - Py )

      e.g Circle with radius R centered at origin:

        F(x, y ) = x2 + y2 - R2

      Advantages:

      • easily test if a point lies on curve
      • meaningful to speak of inside, outside curve F(x, y) = 0     ( x, y ) on curve

        F(x, y) > 0     ( x, y ) outside curve

        F(x, y) < 0     ( x, y ) inside curve

      parametric Form:

      • based on the value of a parmeter
      • path of a particle travelling along the curve is ( x(t), y(t) )

      e.g. A line passing through points P at t = 0, and Q at t = 1

        x(t) = Px + ( Qx - Px )t

        y(t) = Py + ( Qy - Py )t

      e.g. ellipse with half width W, half height H

        x(t) = W cos ( t )

        y(t) = H sin ( t )     for 0 ≤ t ≤ 2π

      Advantages:

      • more convenient in to draw or analyze
      • suggests the movement of a point over time
      • can be drawn by:
        		//draw the curve ( x(t), y(t) ) using 
        		//  the array t[0] .... t[n-1] of "sample-times"
        		glBegin( GL_LINES )
        		  for ( int i = 0; i < n; ++i )
        		    glVertex2f( x(t[i]), y(t[i]) );
        		glEnd();
        	  
      • 3D curves:

        P(t) = ( x(t), y(t), z(t) )

        e.g circular helix

        x(t) = cos ( t )

        y(t) = sin ( t )

        z(t) = bt

    28. Quadratic and Cubic Tweening

      • partition 1 into ( 1 - t ) and t

      • 1 = 12 = ( ( 1 - t ) + t ) 2 = ( 1 - t ) 2 + 2 ( 1 - t ) t + t2

      • We can form an affine combination of points A, B, C : P(t) = ( 1 - t) 2A + 2 t ( 1 - t ) B + t2 C P(t) is a valid point. ( Why ? )

      • P(t) is a quadratic function of t, representing a curve called Bezier Curve

      • Similarly, we form a cubic curve from 4 points A, B, C, D with coefficients 1 = ( ( 1 - t ) + t ) 3 = ( 1 - t ) 3 + 3 ( 1 - t ) 2 t + 3 ( 1 - t ) t 2 + t3 or P(t) = ( 1 - t ) 3 A + 3 ( 1 - t ) 2 t B + 3 ( 1 - t ) t 2 C + t3 D
    29. 3D Affine Transformations

      Consider two points P and Q

      P =  
      Px
      Py
      Pz
      1
             
      Q =  
      Qx
      Qy
      Qz
      1

      An affine transformation can transform point P to point Q and the transformation can be represented by a matrix M

      M =  
      m11   m12   m13   m14  
      m21   m22   m23   m24  
      m31   m32   m33   m34  
      0 0 0 1

      Q can be found by

      Qx
      Qy
      Qz
      1
        =  
      m11   m12   m13   m14  
      m21   m22   m23   m24  
      m31   m32   m33   m34  
      0 0 0 1
      Px
      Py
      Pz
      1

      If mii = 1 and mij = for i ≠ j, we have the identity matrix:

      I =  
        1     0     0     0  
      0 1 0 0
      0 0 1 0
      0 0 0 1

      void glLoadIdentity( void );
      Sets the current matrix to the 4 x 4 identity matrix

      void glLoadMatrix{fd}(const TYPE *m);
      Sets the sixteen values of the current matrix to those specified by m.

      void glMultMatrix{fd}(const TYPE *m);
      Multiplies the matrix specified by the sixteen values pointed to by m by the current matrix and stores the result as the current matrix.

      Translation

      Scaling

      Rotations

      Rotation about an axis

    30. An Affine ( Modeling ) Transformation Code Example

      glLoadIdentity();
      glColor3f(1.0, 1.0, 1.0);
      draw_triangle();                   /* solid lines */
      
      glEnable(GL_LINE_STIPPLE);         /* dashed lines */
      glLineStipple(1, 0xF0F0); 
      glLoadIdentity();
      glTranslatef(-20.0, 0.0, 0.0);
      draw_triangle();
      
      glLineStipple(1, 0xF00F);          /*long dashed lines */
      glLoadIdentity();
      glScalef(1.5, 0.5, 1.0);
      draw_triangle();
      
      glLineStipple(1, 0x8888);          /* dotted lines */
      glLoadIdentity();
      glRotatef (90.0, 0.0, 0.0, 1.0);
      draw_triangle ();
      glDisable (GL_LINE_STIPPLE);
        
      void draw_trangle( void )
      {
         glBegin ( GL_LINE_LOOP );
           glVertex2f( 0.0, 25.0 );
           glVertex2f( 25.0, -25.0 );
           glVertex2f( -25.0, -25.0 );
         glEnd();
      }