  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 withPerspective 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
 xp = x yp = y zp = -d Actually, we need to remember z. 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. )

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

8. CVV is a 2x2x2 cube centered at the origin.
9. The coordinates in this volume is called Normalized Device Coordinates (NDC).
10. Clipping is more efficient when performed in CVV, especially in hardware implementation.
11. The canonical view volume can also be conveniently mapped to 2D window by view port transformation. 12. 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(): 13. Similar transformations occur in perspective projection, glFrustum( l, r, b, t, n, f ) :  14. Viewing Volume Clipping
After the projection matrices, any primitives that lie outside the viewing volume are clipped.
15. Viewport Transformation • Defining the viewport

 void glViewport(GLint x, GLint y, GLsizei width, GLsizei height); Defines a pixel rectangle in the window into which the final image is mapped. The (x, y) parameter specifies the lower-left corner of the viewport, and width and height are the size of the viewport rectangle. By default, the initial viewport values are (0, 0, winWidth, winHeight), where winWidth and winHeight are the size of the window. Left Figure:  ```gluPerspective(fovy, 1.0, near, far); glViewport(0, 0, 400, 400) ```

Right Figure:  ```gluPerspective(fovy, 1.0, near, far); glViewport (0, 0, 400, 200); ```

To avoid the distortion, modify the aspect ratio of the projection to match the viewport:

 ```gluPerspective(fovy, 2.0, near, far); glViewport(0, 0, 400, 200); ```

• The Transformed Depth Coordinate

The depth (z) coordinate is encoded during the viewport transformation (and later stored in the depth buffer). You can scale z values to lie within a desired range with the glDepthRange() command.

 void glDepthRange(GLclampd near, GLclampd far); Defines an encoding for z coordinates that's performed during the viewport transformation. The near and far values represent adjustments to the minimum and maximum values that can be stored in the depth buffer. By default, they're 0.0 and 1.0, respectively, which work for most applications. These parameters are clamped to lie within [0,1].

far side is less precise • Hidden-Surface Removal

either

visible-surface algorithm -- find which surfaces are visible

or

hidden-surface-removal algorithms -- remove those surfaces that should not be visible to the viewer

• Object-space algorithm -- attempt to order the surfaces of the objects in the scene such that drawing surfaces in a particular order provides the correct image (e.g. BSP tree )
does not work well with pipeline architectures

• Image-space algorithm -- work as part of the projection process and seek to determine the relationship among object points on each projector
fits well with with rendering pipeline
e.g. opengl : z-buffer algorithm :
glEnable ( GL_DEPTH_TEST );

16. 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 #include #include using namespace std; void init(void) { glClearColor (1.0, 1.0, 1.0, 0.0); glShadeModel (GL_FLAT); } //print the transformation matrix template void print_mat ( T m[] ) { 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; double pd; 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); cout << "Projection Matrix:" << endl; print_mat ( p ); glGetDoublev(GL_MODELVIEW_MATRIX, &pd); cout << "Modelview Transformation Matrix:" << endl; print_mat ( pd ); glScalef (1.0, 2.0, 1.0); // modeling transformation glGetFloatv(GL_MODELVIEW_MATRIX,&p); cout << "Scale Matrix:" << endl; print_mat ( p ); glRotatef ( 45, 0, 0, 1 ); glGetDoublev(GL_MODELVIEW_MATRIX, &pd); 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); 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 ```

18. 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.

19. 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 void init(void) { glClearColor (0.0, 0.0, 0.0, 0.0); glShadeModel (GL_FLAT); } void display(void) { GLdouble eqn = {0.0, 1.0, 0.0, 0.0}; GLdouble eqn2 = {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); init (); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMainLoop(); return 0; } ``` 20. Pseudo Depth
21. Classical perspective projection drops z coordinates
22. But we need z to find closest object (depth testing)
23. 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
24. 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.
25. 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').
26. 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 )
27. 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 )
28. 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:

29. the point ( x, y, z, w ) represents the same point as does ( αx, αy, αz, αw )
30. thus ( x, y, z, 1 ) and ( x/w, y/w, z/w, 1/w ) are equivalent; w ≠ 0
31. 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
32. 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 )
33. To convert from homogenous coordinates to ordinary coordinates:
• divide all components by the fourth component
e.g. ( 3, 6, 2, 3 ) → ( 1, 2, 2/3, 1 ) → ( 1, 2, 2/3 )
34. To convert from ordinary coordinates to homogeneous coordinates
• append a 1 as the fourth component
e.g. ( 2, 3, 4 ) → ( 2, 3, 4, 1 )
35. What is the perspective matrix that brings point ( x, y, z ) to ( -d. x/z, -d. y/z, -d )? 36. 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: 