CS 424: Computer Graphics, Fall 2013
Lab 5: Normal Vectors and Viewing

In this lab, you will improve the pyramid from the previous lab by adding normal vectors, so that it will work properly with lighting. You will also work with viewing transformations in the form of a simulated "camera" and by programming a walk-through of a simple world.

Once again, you have your choice of working either in C or in Java. The files that you will need for C can be found in the directory /classes/cs424/lab5-glut. The files for use with JOGL are in /classes/cs424/lab5-jogl. You will also need a copy of your solution to the first exercise from the previous lab, the one that draws a multicolored pyramid.

Note that you will work on only two programs for the four exercises in this lab. You will turn in two programs, one program for exercises 1 and 2, and another program for exercises 3 and 4.

This lab is due at the beginning of lab next week. You should copy your work into your homework folder in /classes/cs424/homework. Your work should be in a folder named lab5 or something very similar.

Exercise 1: Normal Vectors for the Pyramid

When you drew a pyramid in a previous lab, lighting was turned off because the normal vectors that are required for proper lighting calculations were missing. For the first exercise this week, you should add normal vectors to the program and turn on lighting. (To turn on lighting, you just have to find the right four lines in the program and uncomment them. Look in the main() function in the C version and in the init() method in the Java version.) You have to figure out what to use for the normal vector at each vertex. Since the sides of the pyramid are flat, you should use the same normal vector at each vertex of a given side, and that vector should be perpendicular to the side. You can figure out the normal vectors by looking at the geometry. Here's the answer for one side.

In the picture on the left, I've drawn a red line down the side of the polygon from the point (0,1,0) to (1,-1,0). On the right, I've drawn the line again, to make it easier to see the geometry. From (0,1,0) to (1,-1,0), the line goes over 1 in the x direction and down two in the y direction. You can see that the normal vector to the side should go over 2 in the x direction and up 1 in the y direction. The z component of the normal vector is 0. So the normal vector for the three vertices of the triangle is (2,1,0). Note that any multiple of this vector, such as (1,0.5,0), would also work; normal vectors are not unique. Here's a screenshot from my solution to this exercise:

Note: To do this exercise, you need a solution to Lab 4, Exercise 1 that draws four separate triangles for the four sides of the pyramid. If you used a triangle fan for those four sides, you will have to re-do the exercise. Alternatively, you can ask me for a copy of my solution to the exercise to use instead of your own as a starting point.

Exercise 2: Camera and Trackball

This is a short exercise on using the camera and simulated trackball utility that was discussed in Section 8 of the notes. You should modify your program from the previous exercise so that it uses the mouse with a camera and trackball to rotate the pyramid, instead of using the arrow keys. You will have to read about how to do this in the notes. It's pretty easy!

For JOGL, you need the file Camera.java. For C, you will need camera.c and the header file camera.h.

If you just add a camera with the default settings, the pyramid will be too small for the window. You should make the view of the pyramid in the new version of the program about the same size as it was in the old version.

Exercise 3: Avatar

The third exercise is to allow the user to move around in a "world," using the arrow keys. This means that you have to apply a viewing transformation that will place the user's point of view in the world, and program the arrow keys so that the user can move forward and backward by pressing the up and down arrow keys and can rotate to the left or to the right by pressing the left and right arrow keys. In the notes, I call this type of moving viewpoint an "avatar." I discuss how it can be implemented in the next-to-last part of Section 8, "Putting the Viewer into the World." (However, you are not dealing with a complicated scene graph in this exercise; you just have to set up a fairly simple viewing transformation.)

The starting point for the assignment is the file Avatar.java for Java or Avatar.c for C. This program already defines a wold consisting of a large disk with several objects sitting on it. The top of the disk lies in the xz-plane, so that the y-axis is perpendicular to the disk. The origin is at the center of the top of the disk. Here is what the world looks like from "space", which is not the view that the avatar will have:

When the original program is run, it uses the default viewing transformation in which the viewer is at (0,0,0), looking along the negative direction of the z-axis. This puts the viewer exactly at ground level. This initial view is shown in the picture on the left below. Of course, the avatar's eye shouldn't be at ground level. In the picture on the right below, the viewing transformation puts the viewer 3 units above ground level, still looking in the same direction. This will be the avatar's first view, before it has moved.


Your avatar's viewpoint should always be about three units above the ground. The left and right arrow keys move the viewer parallel to the xz-plane, so the x and z coordinates of the viewpoint can change. There are already variables in the program to hold the x and z coordinates. The direction that the viewer is facing can also change, when the user presses the left or right arrow keys. There is already a variable named angle in the program to record the direction that the user is currently facing; it can be used to store the angle that the viewer's direction of view makes with the negative direction if the z-axis. The HOME key should reset the view.

The up-arrow key should move the viewer forward in the direction that the user is currently facing. This makes things difficult, since the change that you have to make to x and z will be mathematical functions of the angle and the distance that you want to move. Here are the formulas that you need (in Java -- for C, just leave out the "Math."):

double dx = -distance * Math.sin(angle/180*Math.PI);  // amount by which x changes
double dz = -distance * Math.cos(angle/180*Math.PI);  // amount by which z changes

Note the minus signs! Going backwards is similar. By the way, there is nothing to stop the user from going inside an object or walking off the disk into space.

Exercise 4: World Improvment

As a final, short exercise, add at least three more objects to the world from Exercise 3. You can use other GLUT shapes, and you can reuse some of the GLUT shapes that were already used. An icosahedron would be nice. You might even want to add a copy of your pyramid from Exercise 1