CS4451: Assignment 5

SOOGL (a Simple Object-Oriented Graphics Library)

Due: 10am, Monday November 22th


Purpose

To implement a simple, object-oriented, hierarchical retained mode graphics library of the sort discussed in class.

A Conceptual Model for Object-oriented Graphics

The conceptual model of our object-oriented retained-mode library is based on two simple and powerful concepts: graphical objects for building graphical scenes and properties for specifying the behavior of the graphical objects. The library uses the "damage-repair model": whenever a graphical object or property changes (is damaged), the image is repaired without programmer intervention.

Graphical objects (GOs) represent all the logical entities in the graphical scene: geometry (e.g., lines, polygons, spheres, etc.), lights and cameras of various sorts, and groups of other GOs. One special type of group, the root GO, represents a window into which graphics are rendered. GOs can be grouped together in any valid directed acyclic graph (DAG). In particular, any subgraph rooted at a group GO can be linked into any number of other scene graphs as a child of some other group GO.

Each property is a defined by some value that specifies how some attribute of the graphical scene changes over time. A property could either be a constant value, or a time-variant function that takes the current time and returns a value. All attributes that describe

Associated with each GO g is a partial mapping of properties to values determined by the properties that have been set on g. A property that has been set on g affects not only g but all the descendants of g that do not override the property. A root GO sets an initial default value for each named property.

The Simplified SOOGL Model

SOOGL simplifies the conceptual model somewhat. In particular, there are only a small set of GOs and properties in the system, and not all property values inherit down the scene graph. The few properties that do inherit were chosen either because inheritance is necessary (in the case of transformations), or because it was easy to implement (see below).

Furthermore, not all properties can be specified as time-variant functions (ie. most properties can only have simple, constant values). The few that can have their value specified by a time-variant function where chosen because they provide a good demonstration of which you would want such functionality.

Furthermore, the set of properties, and the choice of which ones can be time-variant functions, where chosen so that SOOGL is sufficiently powerful to implement assignments #3 and #4 in a straightforward manner.


Task

Write a C library that provides a retained mode library on top of GLUT and OpenGL. This is a simple library based on the concept of an object-oriented library that uses a DAG of group nodes to structure the scene, and has properties (possibly time-based) attached to the nodes to specify the behavior of the scene.

The header file for the library, "soogl.h", is here. A simple test program using this library is here. More complex test programs using this library are here and here. These files, plus binaries for the Sun and SGI, are in ~cs4451/a5-samples. Additional test programs will be posted to the newsgroup/class account.


Turn in

Your submission should consist of a single file "soogl.c" which implements the library. The TAs will evaluate it using the test programs provided, as well as other test programs that may not have been provided (which may test parts of the library not explicitely tested by the posted programs). Your source file should be commented with the usual comments. If you do the optional part of the assignment, you should include it in the same file.

Your submission MUST be mailed to the class account as a single, uuencoded tar file (using the process described in the course newsgroup). Using MIME attachments to turn in files is NOT acceptable; the TAs may deduct up to 25% off your grade for incorrectly submitted assignments, so if you are unsure of how to submit, talk to the TAs BEFORE THE ASSIGNMENT IS DUE.

The time the mail is received will be used to determine whether or not the program is late, so be sure to allow a couple of minutes for the mail system to transmit your file if you are working right up to the deadline.

IMPORTANT: If the TA has to edit your file, you will lose up to another 25%.


Due date

This program is due before class on Monday, November 22th. This means it must be received by 9:59am EDT on Monday to not be considered late.

Additional Instructions

Make sure you understand the library before you start implementing it. It has been carefully designed to be powerful enough to be interesting, while being fairly straightforward to implement. In particular:
  • Objects are represented to the user of your library as unique integers. This means your internal data structures can avoid complex uses of pointers; use whatever data structure you feel comfortable with. For example, it is acceptable to use an array to hold the objects (although it must not by of a fixed size) and return the index of the object as the integer identifier. You want your data structure to be efficient to traverse (so redraw is fast), but it does not necessarily need to be efficient to manipulate when things are changed.
  • You do not have to implement stacks to store property values, as the few properties that inherit values down the DAG correspond to OpenGL state. Therefore you can use the OpenGL state manipulation and storage commands (Attribute Groups and Matrix Stacks) to save and restore the values of state as you traverse the stack. Look up the discussion of attribute stacks in the OpenGL book; you should already be familiar with matrix stacks. There are four properties that are inherited down the DAG:  the shading model, the rendering mode, the object material, and transformations.
  • There are three properties in the system that support "dynamic" values: each can either have a constant value that can be changed explicitely from within the user program, or a dynamic value that has the value of the property specified as a function of time. These are the material or transformation attached to a node, and the intensity of a light (which can only be associated with a light node).
  • Only a few simple geometric nodes have been included in the library: spheres, cubes, teapots, and polygons. These are supported directly by GLUT and OpenGL. We have included a couple of properties that control how these are displayed. The "shade model" property determines if an object is smooth or flat shaded (see glShadeModel), and the "draw mode" object determines if an object is drawn as polygons, lines or points (see glPolygonMode).
  • There a four kinds of lights, which are directly equivalent to the OpenGL lights. None of the properties of lights inherit down the DAG, but are stored directly in the light node and used when needed.
  • There is one kind of camera, a perspective camera, that corresponds to the OpenGL perspective projection you have been using.
  • There are two kinds of group nodes (the internal nodes of the DAG): a plain group, and a root node that also serves to associate a scene graph with a GLUT window. There can be multiple root nodes, each of which must be associated with a different GLUT window.

You library should do the following things:

  • The initialization routine should initialize GLUT and its own internal data structures, as well as set up any necessary OpenGL defaults.
  • The display routine for each window does the multiple graph traversals: to deal with the camera, deal with the lights, and then to render. Read the GLUT documentation to make sure you understand how multiple windows work. The most important issue for you is that each window must have a display callback specified for it (when you call glutDisplayFunc, you are specifying the callback for the current window). You can use glutSetWindow(id) to specify which window to operate one: all glut and OpenGL commands will go to that window. glutGetWindow() will return the id of the current window.
  • When any attribute of any object is changed (ie. the intensity of a light or the radius of a sphere), you should redraw the scenes containing the affected object (however, you can cheat and make this redraw easy to do: see the HINT below).
  • If there is a dynamic property linked into the scene graph, your library should redraw constantly. If there are no dynamic properties, it should redraw only when something changes.

    HINT: A simple way to handle redrawing when a change occurs is to force all windows to redraw when anything changes (by issuing glutPostRedisplay() to each root window). To handle the addition of a dynamic property to a graph, mark each root window as needing to be redrawn continuously when a dynamic property is added to any node. Any time a window is redrawn, it can check to see if there are any dynamic properties attached to the scene graph for the window, and stop the continuous redraw for that window if there are no dynamic properties. For this assignment, these unnecessary redraw of each window is acceptable; in a real system, you would keep parent pointers and explicitely compute which graphs need to be redrawn, but we don't want to keep parent pointers here.

  • You should only use display lists for the "geometry" objects (sphere, cube, teapot, polygon), and you should only use them to contain the geometry (ie. the single command to create them). Do not store any materials, lights, etc., in display lists.

Additional Comments

The implementation of this library is fairly complex, and should be done incrementally. We will post more detailed information about how this will be graded as the due date grows closer, but the majority of the grading will involve compiling your library and linking it with a number of test programs: each program will test progressively more complex parts of the library. The most basic test program will be the one linked to above. Pay close attention to what you need to implement in order to have that test program work. In particular, you do not need to support dynamic properties, property inheritance (of material, drawmore, shademodel or transformations), or to allow the camera or light nodes to be transformed within the scene graph. This is a good example of where to start:  support a simple hierarchy with properties attached to the leaf nodes.

Additional test programs will require your library to support property inheritance, dynamic properties, embedding the camera and lights in the graph, and so on.


EXTRA CREDIT

There is one extra credit for this assignment, and that is to handle picking. The header file has a few routines to perform picking on the scene graph, which provide the information needed to do OpenGL picking in a window. You should implement these routines.