CS 424: Computer Graphics, Fall 2015
Lab 6: Light and Material in OpenGL 1.1

This lab asks you to make some 3D objects and place them on a "stage." The scene uses lighting, and the objects will need materials. Initially, only basic lighting is turned on. As part of the lab, you will have to improve the lighting. Some of the objects will be GLUT shapes, which come with the necessary normal vectors. But some will be polyhedra that you need to draw yourself, using data from a collection of polyhedron objects.

You can do this lab in either Java or C. To do the lab in Java, you will need the files Lab6.java and Polyhedron.java, which you can find in /classes/cs424/lab6-files-java. To do the lab in C, you will need the files lab6.c, polyhedron.c, and polyhedron.h, which you can find in /classes/cs424/lab6-files-c. You will only need to work on one file, Lab6.java or lab6.c. If you choose to work in C, note the compilation command that is given in the comment at the beginning of lab6.c.

This lab is due next Thursday, October 15. Submit either the file Lab6.java or the file lab6.c to your homework folder in /classes/cs424/homework. (However, because of Fall break, I promise that I won't look for your work until Saturday, October 17.)

Rotate the Stage

The "stage" is a 20-by-20 slab, one unit thick, perpendicular to the y-axis. The top of the stage is at y = 0; that is, it lies in the xz-plane. You should place objects so that they rest on the top of the stage. Before you start, the program draws nothing but the stage.

It would be nice to be able to rotate the stage, to get a better view of the objects. As part of the lab, you should implement that rotation. (You can do this part at any time, since it's independent of the other parts of the lab.)

The program already has mouse event handling set up. You just need to add some code to do the rotation. I would like to see rotation about the y-axis. (The effect can be seen in the demo, raycaster-input.html, from Subsection 5.3.2, with the "Mouse Action" in the demo set to "Rotate".)

You will need to add a rotation about the y-axis to the display() function. The mouseDragged() function has to change the y-rotation by an amount that depends on how far the mouse has moved in the x-direction (left/right).

You might consider allowing some rotation about the x-axis as well, as long as you limit the range of angles to a fairly small interval. That would make it possible to tilt the stage to some degree.

Working with Materials

The program has a two dimensional array named materials that contains material properties that are supposed to imitate some actual common materials such as bronze and green plastic. I would like you to use some of these materials on your objects. (But it would be nice to invent at least one additional material of your own.)

Each row of the array specifies a material. A row is a 13-element array of floats. The meaning of the data is described in a comment in the program. It will be convenient to have a subroutine that takes a 13-element array of floats and uses the data from the array to set the OpenGL material properties. (Actually, the code for using an array of this form in both C and Java can be found in Subsection 4.2.1.)

Add Some GLUT Objects

To begin, use GLUT to draw several objects on the stage. The objects should look like they are standing on the stage, not floating above it. In some cases, you might want an object that actually extends inside the stage. For example, you can have an object that looks like a hemisphere by drawing a complete sphere whose equator lies along the stage. Remember that the top of the stage is the xz-plane, y = 0.

There are more GLUT shapes than we have covered in lab or class. Some of them are described near the end of Subsection 3.6.1. The full lists for JOGL and for FreeGLUT can be found online. (Don't miss the teapot!)

At least one object should be a wireframe object that is drawn with lighting disabled. Remember that when lighting is disabled, color is set by glColor*. Also, note that it is possible to increase the line width by calling glLineWidth(w), where w is specified in pixels. GLUT has commands for drawing wireframes, such as glutWireSphere() and glutWireCone(). The wireframe versions have the same parameters as the solid versions.

Aside from the wireframes, each of the other GLUT objects should have its own material.

Add Some Polyhedra

The file Polyhedron.java (for Java)—or the files polyhedron.c and polyhedron.h (for C)—defines the following variables of type Polyhedron that represent various polyhedra:

dodecahedron
icosahedron
octahedron
rhombicDodecahedron
socerBall
stellatedDodecahedron
stellatedIcosahedron
stellatedOctahedron
tetrahedron
truncatedIcosahedron
truncatedRhombicDodecahedron

You can view these polyhedra, without lighting, in the demo, polyhedron-viewer, from Subsection 3.4.1.

An object, poly, of type Polyhedron has properties poly.vertices, poly.faces, and poly.faceNormals that define the polyhedron. Read the comment at the start of Polyhedron.java or polyhedron.h for more information. (These properties have different forms in Java and in C; in Java, they are two-dimensional arrays; in C, they are one-dimensional. If you are working in C, in particular, be sure that you understand the data format. Note that in C, the lengths of the arrays are given as additional Polyhedron properties. In Java, of course, the length is a property of the array object itself.)

The polyhedra are centered at (0,0,0). Note that there is also a numeric property poly.maxVertexLength that says how big the polyhedron is; this might help you decide by how much the polyhedron needs to be scaled when you add it to the stage.

You should write a subroutine that takes an object of type Polyhedron as parameter and renders the polyhedron. You can use glBegin/glEnd to draw each face. The normal vector that you need for the face can be found in the faceNormals property of the object.

Once you have your subroutine, you should use it to add several polyhedra to the stage, each with its own material.

(If you have the time, you might want to draw the edges of at least some of the polyhedra as well as the faces. To get the edges to look really good, you need to understand "polygon offset," which is covered in Subsection 3.4.1.)

Improve the Lighting

The program that you are working on for the lab has only basic lighting. That is, the default GL_LIGHT0 is turned on. This light, by default, has diffuse and specular color both set to (1,1,1,1), and has position set to (0,0,1,0).

You should improve the lighting of the scene. Do not try to make moving lights. Set their positions in the initialization method, the same place where lighting is enabled. Use three or four lights (definitely no more than four!). You might consider adding a point light above the stage and two more point lights in front of the stage and offset to the left and right. You might or might not want to keep the default position for light zero. Note that the positions do not necessarily need to be symmetrical. It might even look better if they are not symmetrically placed. The light positions are set in eye coordinates, with the viewer at (0,0,0), looking in the direction of the negative z-xis.

You will have to set the light colors for the new lights that you add. (The default color is black; that is, if you don't change the color, the light gives off no light at all.) You will not be able to use light colors equal to (1,1,1,1). The problem is that if you have too much light in a scene, the material colors of your objects become saturated and washed out. To get the scene to look good, you will need RGB color components for your lights that are substantially less than 1.0.

Don't Forget Your Midterm Project!

Remember that you should continue to work on the midterm project. Now that we have encountered light and material in OpenGL 1.1, you can think about how you will add material properties to your scene graph. Remember that you don't need to follow the OpenGL API exactly. For example, you might decide to always use the same value for the ambient and diffuse material properties. You might also think about what kind of support for lighting you will provide in your API.