Logistics
  Grading Policy
  Syllabus
  FAQ
  Links
  
  PAs:
 
   
  1. Raster Graphics
  2. 3D Scene
  3. Ray Tracing
    Posted Images
  4. Animation
  
  HWs:
 
   
  HW1
  HW2
 

Don't see the menu?

EECS487 F09: Programming Assignment 2

EECS487 F09 Programming Assignment 2: Scene Graphs and Shaders

The project is due on Monday, 26 October, 2009 at 12:01 pm (one minute after noon).

Overview

In this project you will implement a simple model viewer that uses a simplified X3D scene graph as well as two simple programmable shaders.

You are given support code for this project that should compile under Windows and Mac OSX. The makefile has support for the CAEN Linux workstations but those do not have great graphics drivers and the programmable GPU shaders will not work there.
The support code links against GLUT and Expat libraries, parses an input X3D file, partially constructs a scene graph inserting various X3D nodes into it, and then passes the scene to the Glut renderer. The X3D file format is described in the X3D specification. Most of your tasks will be modifying the following source files:

  • x3.cpp
  • main.cpp
  • x3.h
Look for words YOUR CODE HERE to locate where to work, although you should look through all the supplied code and understand it.You will also modify the GLSL vertex and fragment shader files:
  • phong.vs and phong.fs
  • interesting.vs and interesting.fs

Graded tasks overview (100 points total)

  • Implement rendering of a cylinder node modifying X3Cylinder::Render() function. (10pts)
  • Implement simple camera navigation ("examine mode") by modifying the rendering of the X3Viewpoint class, as well as GLUT mouse callback functions. (10pts)
  • Implement proper modeling transformation sequence modifying X3Transform::Render() function. (15pts)
  • Setup point lights by modifying X3PointLight::SetupLights() and X3Transform::SetupLights() functions. (15pts)
  • Setup the material properties by modifying X3Material::Render() function. (10pts)
  • Compute the normals and render the IndexedFaceSet (mesh) node, modifying methods of X3IndexedFaceSet::Render() and X3IndexedFaceSet::Add(). (10pts)
  • Implement per-pixel Phong shading that matches the fixed-function per-vertex rendering (modify the phong.vs and phong.fs files). (15pts)
  • Implement some interesting shader (modify the interesting.vs and interesting.fs files). (10pts)
  • Writeup. (5pts)

Optional tasks (for fun, not credit)

  • Add the extrusion geometry node to the viewer.
  • Add the spotlight node to the viewer.
  • Add fog to the viewer.

Implementation details

Cylinder rendering

Modify the X3Cylinder::Render() function to render cylinders using all the provided data fields of the cylinder node. It may help to look at how the same function is implemented for the cone primitive.

Camera examine mode

The simple X3D viewer and parser included with the project does not include a camera class. All the viewing information is stored within the X3Viewpoint node. In the support code the camera is positioned at the location read from the Viewpoint position attribute (all other attributes of Viewpoint node are ignored in our viewer). The camera points toward the origin of the world coordinate system which is set up to have the positive y-axis pointing upward. The horizontal motion of the mouse (dragging with the left button pressed) causes the camera to rotate around the y-axis, called yaw, around the scene. You will need to implement zooming in and out (mapped to vertical motion of the mouse with the right button pressed), as well as vertical camera motion (mapped to the vertical motion of the mouse with the left button pressed) such that the camera tilts up and down, or changes pitch. The camera should remain pointed toward the origin of the world coordinate system (optionally, you can also compute the center of the bounding box of the whole scene and point toward it). You will need to modify the main.cpp file as well as the methods and fields of X3Viewpoint class.

Modeling transformation hierarchy

The scene graph represents the scene as a directed acyclic graph (it is not a simple tree since some nodes can be reused multiple times using DEF/USE node attributes) and the traversal of this graph is performed when the scene is rendered. The grouping nodes such as scene, group, and transform traverse their children so that each child renders itself. The transform node adds the ability to specify the transformation between the child coordinate system and the parent coordinate system so that children can be specified with respect to their parent nodes. The X3Transform in the source code has all transforms except for the scaleOrientation transform which we skip.

Lighting setup

In our viewer we shall only implement point lights and each point light will effect the whole scene, therefore a separate pass is needed to setup light positions (and other parameters) before the scene is rendered. Each point light can be located within the child nodes of the hierarchy and is thus transformed by the current modeling transformation of its parent (this allows a light to be located near a particular object). The recursive traversal of the nodes to find the lights is done by using SetupLight method of the nodes which should be implemented very similar to the Render methods. You will thus need to modify the SetupLight method for the X3Transform class to get proper transformations, as well as set up OpenGL lighting parameters for X3PointLight within X3PointLight::SetupLights() method to match X3D specification for lighting. In our simplified viewer we have no fog and no spot light factor so ignore those parts. Be careful to match X3D lighting parameters onto OpenGL light and material parameters (note for instance that shininess in X3D gets multiplied by 128 so check the colors and intensities as well). If no lights are specified within the file a default light is added to the scene (see the DisplayCallback function). Make sure to assign properties to the light with proper the id: GL_LIGHT0 + light_index.

Material setup

While working on the light setup from the previous section you will also need to setup material properties within the X3Material::Render() method. Note that lights are setup once before rendering the whole scene whereas materials will vary from node to node.

Computation of mesh normals and mesh rendering

X3IndexedFaceSet represents a polygonal mesh node that contains a list of vertex indices and a coordinate node that stores the (x,y,z) point coordinate list into which the indices refer. Polygon index lists are separated by -1. Many models mostly use quads and triangles. Thus, after reading the index list we process it to extract two separate lists of quads and triangles (stored in the appropriate fields of the X3IndexedFaceSet class). In our simplified X3D handling we shall assume that only coordinates are given (no normals or colors so everything non-coordinate is skipped in the parser); however, we need normals in order to compute lighting. Therefore, you will need to fill in the vector of normals which works as follows -- loop through each polygon (first triangles, then quads), and compute the normal for each polygon, then add that normal to the normals accumulated for each vertex of the polygon. After you went through all the polygons normalize the normals for each vertex, thus averaging the normals of the faces that contain each vertex).

You will also need to implement mesh rendering within the Render method of the X3IndexedFaceSet class. First draw triples of vertices in a loop for each triangle (specifying glNormal) before each vertex call and using the GL_TRIANGLES rendering mode and then proceed to quads using GL_QUADS. Look inside X3Box::Render for an example of what you need to do, except that you will have a loop between the glBegin and glEnd calls and you will have a normal specified before every vertex. Once you are done with this task you will be able to see the famous graphics teapot model.

GLSL shaders

The last two programming tasks will be done in a C-like language. You will first need to implement a per-pixel version of the lighting model where most of the work will be done in the fragment shader phong.fs, but the vertex shader phong.vs must first prepare the data for it. The final color in the fragment shader should be assigned to the vector glFragColor.rgb. In this task you can assume that there are exactly two lights (0 and 1) enabled in the scene.

The "interesting" shader task is an open-ended task and you can implement any nice or weird looking shader. Examples of interesting shaders may include the brick procedural texture or some cartoonish looking textures (note that the provided interesting.vs/fs already implements some simple cartoon shading so you need to come up with something a bit more interesting). Be original; do not simply take some random dot product, multiply by 4, take the square root, and convert to rods per hogshead. Think it through and make sure to explain and understand the choices that you made.

Support code details

First of all, download the support code archive from /afs/umich.edu/class/eecs487/f09/PAs/pa2.tgz

The executable should be called with one command-line argument -- the name of the X3D scene file (there are a bunch of them provided in the data folder, there are many on the web, and some graphics packages can export to X3D).

The following keystrokes are defined in the GLUT window (you may map more operations to keys inside KeyboardCallback function but you should not change the predefined keys below).

  • ESC: quits the program
  • 'p': activates the per-pixel phong shaders.
  • 'i': activates the interesting shaders.
  • 'n': disables shaders (no shader, fixed-function pipeline mode).

The code needs to be linked against GLUT and Expat libraries, and the compilation requires the corresponding header files. The Mac OSX machines in the CSE building lab seem to have both installed. For the Windows version, you will need to copy common/bin/libexpat.dll to somewhere in your path. If you have a Linux machine with good drivers then you may simply use the Makefile file provided with the project archive.

Windows specific:

Copy libexpat.dll to somewhere on you path. Specify the X3D file name in the Debugging options or run the program from a command line. Visual Studio project files are not provided. Please create your own project following the instructions in my GL/GLUT writeup. Please submit your project files.

Mac specific

Anyone using Mac OSX 10.5.x or 10.6.x will get the following warnings when compiling:

../common/src/glew.c: In function 'NSGLGetProcAddress':
../common/src/glew.c:80: warning: 'NSAddImage' is deprecated (declared at /usr/include/mach-o/dyld.h:230)
../common/src/glew.c:89: warning: 'NSLookupSymbolInImage' is deprecated (declared at /usr/include/mach-o/dyld.h:182)
../common/src/glew.c:91: warning: 'NSAddressOfSymbol' is deprecated (declared at /usr/include/mach-o/dyld.h:188)

These are due to the fact that there is not a current implementation of GLEW for Leopard and Snow Leopard. These warning may be ignored without problem or difficulty.

Submission Guidelines

As with PA1, to incorporate publicly available code in your solution is considered cheating in this course. To pass off the implementation of an algorithm as that of another is also considered cheating. For example, if the assignment asks you to implement sort using heap sort and you turn in a working program that uses insertion sort in place of the heap sort, it will be considered cheating. If you can not implement a required algorithm, you must inform the teaching staff when turning in your assignment, e.g., by documenting it in your writeup.

Code that does not compile will be heavily penalized. Make sure your code compiles and works on CAEN machines. You will need to turn in your source files together with appropriate Makefile (and/or IDE project files) and a write-up in text format (writeup-uniqname.txt) that discusses:

  1. Your platform - Mac OS X, Windows, or Linux
  2. Anything about your implementation that is noteworthy (e.g., your method for clipping lines, or color interpolation)
  3. Feedback on the assignment.
  4. Name your file writeup-uniqname.txt. For example, the person with uniqname ysoserious would create writeup-ysoserious.txt .

Copy your code, write-up, and any other supporting files (Makefiles or IDE project files etc.) to the following directory on IFS /afs/umich.edu/class/eecs487/f09/SUBMIT/<uniqname>/pa2. This path is accessible from any machine you've logged into using your ITCS (umich.edu) password. Report problems to ITCS.

For accessing the umich.edu AFS partition from CAEN machines you might first have to obtain AFS tokens. On Linux, this is performed using the gettokens command on the terminal, followed by your ITCS password. On Windows, invoke the Start Menu -> All Programs -> Communication Tools -> Open AFS -> Authentication which will create a lock icon in your system tray. Click that to get the AFS authentication dialog, click "Obtain New Tokens..." and enter your ITCS uniqname and password for the umich.edu cell. 

Turn in ONLY the files you have modified. Do not turn in support code we provided that you haven't modified.

Do not submit any binary files (object, executable, or image) with your project.

The timestamp on your source files and your writeup will indicate the time of submission and if this is past the deadline your submission will be considered late. Therefore, you are allowed multiple "submissions" without late-policy implications as long as you respect the deadline.

Test the compilation! Your submission must compile without errors and warnings on CAEN machines. Mention the platform in your writeup. 

General Information

The General Information section from PA1 applies. Please review it if you haven't read it or would like to refresh your memory.