In this assignment you will modify your solution from homework 3 to use OpenGL. You will also make it interactive, so that the user can examine (i.e. rotate, translate, and zoom) the rendered object. The program will also allow the user to choose a shading style (wireframe, flat, Gouraud).
Your code from Homework 0 will help for this lab. Mark Meyers' slides on OpenGL/GLUT should be very helpful, as well as the OpenGL links on the Resources page.
Homework 4 is due on Tuesday Nov. 4 at 11:59 pm
From homework 3, you should have a working parser that reads in an ivfile and store relevant data in some internal data structure. Instead of rasterizing polygons by manually computing lighting functions, we want OpenGL to do all the tedious work for us.
In OpenGL, lights have various colors components just as materials do: diffuse, specular, etc. You should set the specular and diffuse colors to the color given for the light in the OpenIV file. Set the ambient color to (0,0,0). See homework 0 for an example of setting up light and material properties.
All your matrix transformations are to be handled by OpenGL. OpenGL has three matrix modes -- projection, modelview, and texture. Each mode has a separate matrix stack, and you call glMatrixMode(...) to change the effective stack. You won't be using the texture matrix stack at all, and aside from perspective transform, which goes to the projection matrix stack, everything goes to the modelview matrix stack. OpenGL supports what your 4x4 transform library from homework 1 does: glTranslatef(..), glScalef(..), and glRotatef(..). Use them!
Note that OpenGL functions typically take rotation angles in degrees, so you'll need to convert the values given in the .iv files. Also, make sure the order of the parameters are correct! One common mistake is mixing up the order of angle and axis in glRotatef(..).
// perspective and camera are setup only once in the beginning of program
PROJECTION
Frustum
MODELVIEW
camera rotate -theta
camera -translate
for each frame:
push
// user mouse translate and rotation -- more details later
for each object:
push
transform(s)
//draw the polygons
pop
pop
glBegin(GL_TRIANGLES);
glVertex3d(...); glVertex3d(...); glVertex3d(...);
glEnd();
Your renderer should support multiple rendering modes and should allow the user to switch modes by pressing keys. It should also be able to display a wireframe version of the object (as in homework 2) when the user presses the w key (use glBegin(GL_LINE_LOOP) instead of glBegin(GL_POLYGON)), a flat-shaded version when the user pressed the f key, and a Gouraud-shaded version when the user pressed the g key. To get different shading models, use glShadeModel(...) . Refer to glutKeyboardFunc() docs to get key handling working. Alternatively, simply refer to homework 0 again for an example.
Using OpenGL to do these operations is required.
When the user clicks and drags using the middle mouse button, the objects should track (move parallel to the image plane). The magnitude of the movement should be proportional to the length of the mouse drag. The direction of the move should be that of the mouse drag.
When the user presses shift and drags using the middle mouse button, the camera should zoom (implement this as translation in the -z camera direction). The magnitude of the zoom should be proportional to the vertical displacement of the mouse drag.
When the user clicks and drags using the left mouse button, the
objects should rotate. There are many ways to do this - you should
pick something reasonably intuitive and explain how your rotation
works in your README file.
One approach is to make the axis of the rotation
perpendicular to the mouse drag line in the image plane (parallel to
the image plane and perpendicular to the drag line). The angle of the
rotation should be proportional to the length of the mouse drag. The
center of rotation should always be 3 units in front of the
camera. For any normalized axis of rotation (x, y, z) and angle of
rotation (theta), the 3x3 rotation matrix is: 
Another way to do rotation
is by using the arcball method.
The rotation should be interactive. That is, results should be visible as the user is dragging (not only after the mouse button is released). Never directly call your redisplay callback, however. Instead, simply call glutPostRedisplay() to let GLUT know that it needs to call your redisplay function. This way you get less "lag" while being interactive, since it takes input before waiting for the graphics card.
Note that after setting up the lights in the beginning of the program, there is no need to transform the light locations in any way when the object is dragged. The lights are stationary even as the rest of the scene is transformed.
HINT: Depending on how you implemented your mouse transforms, you may need to: get the current modelview transformation matrix, tell OpenGL to start over at the identity matrix, make your own transformations, and then multiply by the original matrix. Here's how that is done:
GLfloat oldMatrix[16];
glGetFloatv(GL_MODELVIEW_MATRIX, &oldMatrix[0]);
glLoadIdentity();
// apply mouse transforms here
glMultMatrixf(&oldMatrix[0]);
You do not need to handle OpenGL errors (presuming your code does not normally cause them!). However, if you'd like to check whether OpenGL errors are occuring, see the sample code here. This may save you a lot of trouble if OpenGL is behaving strangely.
Your program should be able to read in a scene description and produce an interactive rendering of the scene. The syntax for the program should be:
oglRenderer <xRes> <yRes> < <iv-file>
The xRes and yRes specify the image dimensions, while the iv-file is the scene description. Note that changing the image dimensions may change the appearance of the scene (due to aspect ratios of monitors, etc.). You can control this behavior by changing the viewport size with the callback you specify with glutReshapeFunc().
Include a README file with your code, saying what you did, how to compile it, and anything else you think we need to know.Feel free to implement a few additional features to your renderer. Points will be awarded based on the difficulty and implementation. You may want to talk to a TA before implementing the additions.
This extra credit will be worth 1 point.
Separator {
Transform {
translation 0 0 0
rotation 1 0 0 0
scaleFactor 1 1 1
}
Coordinate3 {
point [
0 0 0,
0 1 2,
0 2 3,
1 0 0,
1 1 3,
1 2 2,
2 0 1,
2 1 3,
2 2 2
]
}
LineSet {
numVertices 9
}
}
This extra credit feature is easy to implement; ignore the wireframe/flat/gouraud mode and just draw connected lines with glBegin(GL_LINE_STRIP). Of course you have to add the LineSet and numVertices features to your parser, and you have to make sure that you don't depend on the data being in the form of polygons. NOTE: More than one Separator can have a LineSet, so you must still draw all Separators. More than one Lineset per Separator is unnecessary. You should also disable lighting.
Care of The Complete Idiot's Guide to Ivview, we have a really cool OpenIV file of Lorenz's Strange Attractor, a beautiful and simple fractal:
A different view: