Glass Ball Interface
ECS175: Computer Graphics
Due 7:00pm, Fri. May 19

Please do this project without a partner.

This project will help you familiarize yourself with three-dimensional modeling and viewing, animation and user input, and makes you write an OpenGL program from scratch. Focus first on the mechanics of viewing and interaction, and then think about making an interesting model, and other special features, if you have time. A program which allows the user to correctly rotate a simple model, with correct normal vectors, is worth a B, and an interesting model (built by you, not loaded from a file) will get you an A.

The project is to model an object in 3D, and move it around using the ``glass-ball'' (aka ``arc-ball'') user interface. This applet uses the "glass-ball" interface, so you can see how it works. The idea 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 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. Since the next and last assignment will be virtual world, possibly undersea, you might get a head start by making a handy object like a fish or a submarine.

Here is Prof. Staadt's code which reads in a .obj file and rotates it using an incorrect (but all too common) user interface. It is a gzipped tar archive.

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. Remember to orient all faces counter-clockwise.

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 185-187 in the OpenGL book.

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

A good 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 in the icosohedron example, although note that in this case you want every vertex of a face to get the same normal. 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, which use the vertex normals. 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, space station, etc. Build at least one such object which does not use any glut drawing functions like glutSolidSphere, etc.

Step 9: Optional improvments

Here are some ideas for improving the basic assignment.

Step 10: Documentation.

Write a README file including a) your name, 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, (eg. Nate's glm.c), please note that in your documentation, and also the source of any models or textures you used.

Step 11: Turn in your assignment.

Turn in the source file of your program, the Makefile, the documentation, the executable, and any additional files. Please limit yourself to one "found" model and one texture, we don't want to run out of disk space.