Project 3
CS351: Introduction to Computer Graphics
Due 11:59pm, October 29th


This project will help you familiarize yourself with three-dimensional modeling and viewing, and user input, and makes you write an OpenGL program from scratch. Completing the basic assignment will be worth 100 points. Focus first on the mechanics of viewing and interaction, and only worry about making a fancy model, and other special features, if you have time.

The project is to model an object in 3D, and move it around using the ``glass-ball'' (aka ``arc-ball'') user interface. The idea if the interface is that we imagine the object to be embedded in a clear glass trackball. When you hold any mouse button down in the window containing the object, moving the mouse spins the glass trackball, and the object along with it. Notice that the object should rotates around an axis perpendicular to the direction that the mouse is moving. Moving the mouse with the buttons released does nothing.

The model can be anything except the icosohedron and the cube, which are in the book, and a pyramid or cylinder with fewer than 5 sides, which are too easy.

Here are some step-by-step instructions, if you're wondering where to begin.

Step 1: Study some examples.

Look at the animation example on pages 20-25 of the OpenGL book. Using the OpenGL man pages, figure out what every OpenGL and glut call in the program does, since you'll probably have to change most of them. Also look at the code for modeling an icosohedron on pages 86-89.

Step 2: Build a 3D cube

Let's start with something simple, and get the 3D viewing and interaction working. First, build a cube centered at the origin. You'll need to specify the vertices and faces of the cube. To get started without using normal vectors, make every face of the cube a different color, so that you can see where one face ends and another begins.

Step 3: Look at your cube in 3D

Use glOrtho (pages 127-8) to specify an orthographic projection of your cube to the screen, that is, a projection which just drops the z coordinate of each 3D point. Remember that only world coordinate points inside the box defined in the glOrtho command appear in the window!

At this point you'll probably be looking straight at one face of the cube, so it will just look like a square.

Step 4: Turn on depth buffering.

You'll need to tell both OpenGL and the glut that you want depth buffering. See pages 175-176 in the OpenGL book.

NOTE: Putting glEnable(GL_DEPTH_TEST) right after the glutInitDisplayMode call, as it seems to suggest on page 176, will not work. Calling glEnable before glutCreateWindow has no effect.

The best way to keep track of what to call when (and make your code more modular) is to keep all initialization of the glut in main, before calling init, and put initialization for OpenGL (including calls to glEnable) in init.

At this point you should see still just see a single face of the cube.

Step 5: Build the operator interface.

Now let's rotate the cube and see if it's all there. You'll need to specify the callback routine for mouse motion. The way you tell the glut you have such a routine is using glutMotionFunc(). Look this up in the on-line glut documentation. This function will get called many times as you move the mouse in the window with the button down. Each time, you'll want to rotate the cube by a little bit.

NOTE: The mouse position at the upper left corner of the window is (0,0).

Now write the callback routine to implement the glass-ball interface. You'll have to figure out what axis to rotate around, and how to use the difference between the new and old x-y positions of the mouse to determine how much to rotate. Try and refine the feel of the interface so it really seems like you're moving the cube with the mouse.

If your program produces really freaky looking images, you probably did not succeed in turning depth buffering on; return to Step 4.

Step 6: Specify normals and turn on lighting

To see the cube as one color, with lighting, rather than with different colored faces, you will need to specify a normal vector for every vertex, and specify the same color for every vertex. Take a look at the information on computing surface normals on page 88. Here is a C function that turns on lighting for an OpenGL program; call it at the end of init(). Feel free to use this function and don't worry too much about what it does. We'll study lighting in more detail later.

Your colors will disappear when you turn on lighting; the vertex colors are now controlled by the lighting calculations. To tell the lighting calculations about colors, you use glMaterial. In the lighting example, the array mat_properties is an RGBA color specification. Change that to change the color of your object. You should probably keep your object all one color - the only reason we were coloring the faces different colors in Step 2 was for debugging purposes.

Step 7: Fix the jump

You probably have noticed that your cube "jumps" when you move the mouse without pushing the button, and then click down on the mouse button in the window. Why is this? You can fix it by implementing a callback function for the mouse buttons. Use glutMouseFunc() to tell the glut about your new callback function.

Step 8: Make a more interesting model

Replace the cube with a cylinder, cone, sphere, pear, building, vase, character, plant, or whatever. Do not use any glut drawing functions like glutSolidSphere, etc.

Step 9: Optional improvments

Here are some ideas for improving the basic assignment, besides making interesting objects.

Step 10: Documentation.

Write a README file including a) your name and UTID, b) how to compile and run your program, and c) a few short paragraphs on what you did. If you use any code you found on the web, (Nate's glm.c or GLUI by Paul Rademacher), please note that in your documentation.

Step 11: Turn in your assignment.

Turn in the source file of your program, the Makefile, the documentation, the executable, and any additional files.