This lab looks at the structure and event handling code of a simple OpenGL program.
Download and extract either the C version or Java version of the simple cube program.
The C version can't be compiled unless the util directory from the earlier retro graphics code is in the parent directory of cCube
userid/CG/
util/
Retro/
cCube/
Compile and run the program (javac for Java, make for C). You should see a spinning wireframe cube. Use the right mouse button to bring up a menu which can change the color.
If the cube is spinning really fast and leaving multiple ghost images on the screen, you need to synchronise drawing to the monitor refresh rate. Type this line into your terminal:
$ setenv __GL_SYNC_TO_VBLANK 1
(It starts with a double underscore.)
Keystrokes may not work until you click the mouse on either the window itself or the title bar.
Add a global variable Step to the program and set the value to 0.5. In the program idle code, add this variable to Spin instead of the fixed value.
Add a new menu command, Reverse. When chosen it should reverse the direction in which the cube spins by changing the value of Step.
Add a keystroke (an accelerator) for the new menu command. (Don't copy and paste the code! The keystroke should invoke the menu handler.)
Does your reverse command work correctly when used several times in succession, not just once?
Add code so that when the left or right arrow keys are pressed, the speed at which the cube rotates speeds up in the appropriate direction. C programmers: the constant values for the arrow keys are described by man glutSpecialFunc. Java programmers: have a look at the supplied GlutWindow.java class for the key constants.
Add a line in the program resize/reshape code that prints out a message and the new width and height of the window. Start the cube program, and drag the window corner or edge to a new size. How many times is your code executed during this? Does it make a difference if you stop moving the mouse while still holding down the button?
Turn off the automatic spinning code for the cube for the following sections.
gluLookAt establishes the viewpoint, or digital camera position, for the 3D scene. Add keyboard handling code so that the A-W-S-D keys adjust the ViewPoint values to move you forwards, backwards, or sideways.
Keep pressing the key that moves the viewpoint in. What happens as you get very close to the point looked at, and when you overshoot? Think about the Y value of the viewpoint, and what it means to be looking at a specified point from different positions.
Change the gluLookAt section so that the point being looked at is calculated by adding 1 to one of the ViewPoint values. The effect we want is "I am here, looking at a point 1 metre (or whatever) in front of me." If you see nothing, try moving forwards and backwards until you do. You may need to use a negative offset instead of positive.
Try looking at a point that is both ahead and slightly above or below the point looking from to create the effect of walking forward with your head tilted either up or down.
Add a mouse button handler. C programmers: use glutMouseFunc. Java programmers: override the mouse method from class GlutWindow. (Section 11.6 of the textbook has more detail on GLUT keyboard and mouse handling.) When the mouse is pressed or released, print out the coordinates.
Where is the origin, point (0, 0), in mouse coordinates?
Add a mouse motion handler for movement while any button is being pressed, ie the user is dragging. (glutMotionFunc in C, method motion in Java.) When the mouse button is pressed, state DOWN in the button handler code, save the starting X and Y coordinates of the mouse in static variables and print them out.
As the mouse is dragged, the motion handler should subtract those starting values from the current mouse position passed to the motion handler and print out the relative mouse motion.
Try all the four different directions you can drag (up, down, left, right) and note which are positive and which are negative.
What happens if you drag the mouse entirely out of the cube program window and then let go the button?
The mouse coordinates are in pixels with the origin in the top left corner, while OpenGL has the origin at the bottom left corner. Programming is easier if you convert the mouse values into an OpenGL like coordinate frame. This is done by just replacing the mouse Y value with (window height - mouse Y). Try adding this code to your button and motion handlers and printing out the new values.
Add code to your mouse button handler so that when the left button is released (state UP) the relative distance that the mouse is moved along the X axis is added to the the current Spin value.
Reduce the mouse motion to a smaller floating point range by first multiplying the original mouse coordinates by, say, 0.01. Experiment with different scale values.
The cube stays still while the mouse is dragged and only changes position when the button is released. Can you change the mouse button and mouse motion handlers so that the cube spins as you drag, not just when you release the button? (Hint: you'll need to save some extra information in static variables.)