Glass Ball Interface
ECS175: Computer Graphics
Due 11:00pm, Wds. 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. Completing the basic assignment
will be worth 90 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.
Since the next and last assignment will be a space-flight simulator,
you might get a head start by making a handy object like a space station;
we'll discuss some nice space station shapes next week.
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
(or here).
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
(or here).
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, or here)
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, or
here.
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 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.
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, besides making interesting
objects.
- Read in objects from a file.
Add the option for the user to give the program an additional argument,
ie a file to load). If an argument is not given, your program should
draw the OpenGL model you built. There are many modeling formats,
perhaps the easiest to use is "obj". Nate Robins has an OpenGL reader.
Simply search for "glm.h" to find the ".c" and ".h" files, then search for
interestin .obj files.
Be sure that the program that you had in can also display some
model that you built yourself, to ensure you understand how models are
defined.
- Animate your object, so that parts of it move in addition to the
spinning controlled by the trackball.
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 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, we don't want to run out of
disk space again.