Programming assignment 3 - .obj File Loader/viewer

CS 354 - Introduction to Computer Graphics
Fall, 2015
Don Fussell

Note additional requirement below

DUE Tuesday Oct 13 at 11:59pm

In this assignment, you'll expand on your work in Assignment 2 to become more familiar with OpenGL and scene descriptions by creating your own 3D model viewer. Your system will read input files in .obj format, apply transforms that you specify interactively, and render the results. You'll also implement more sophisticated camera control than in the previous assignment. Here are some objects that you should be able to parse and display along with code for parsing them. You may also be able to parse and render other objects in this format that you find on the web, but at a minimum you must be able to handle the ones we're giving you.

.obj files contain a rather simple ASCII format that's very easy to parse. Design your user interface to allow interactively selecting files to be read into your scene.

Object loader

Each line of an .obj file contains a record of some sort. The first character of the line indicates what the type of record is, and thus what to do with the rest of the line. The only ones you need to implement are: There are several other record types that you'll encounter, but you're free to ignore them. Once you've loaded the model, compute normals for both faces and vertices. Assume counter-clockwise winding for the face normals, then average the incident face normals to produce normals for each vertex. Note that the parser in loader.h assumes a Trimesh object with methods for adding vertices and faces is provided in geom.h (not provided). Such an object maintains a list of vertex positions and defines the face mesh using indices into this vertex list. Designing this will be one significant part of this assignment. You are free to modify loader.h as you see fit to accomplish the project.

Camera control

Being able to move the camera around is crucial when trying to examine an object, so the second part of this assignment is to add orbit-style camera control. In this type of camera control, there's a point of interest that the camera is looking at. The camera can orbit around the point, zoom in and out, and move the point around by panning.

Implement these controls with the following mouse operations:

Make sure that you set the camera controls to sensible defaults when starting up! The initial point of interest should be the center of the object, and the zoom level should comfortably fit the object in the window. Your camera must do perspective projection, not orthonormal projection. As before, you're free to use the built-in OpenGL transformation and perspective functions to implement your camera; you don't need to do any of the matrix math yourself. You are also allowed to use gluLookat as before if you choose.

Rendering

In addition to the camera, you will also implement several rendering modes.

Implement the following list of rendering options:

As you'll see, solid mode is not very useful; all it displays is a solid block of pixels in the outline of the object. To make the display a little more sensible, you'll implement a shaded mode as well. For shaded mode, you can use OpenGL's default lighting. The following code snippet shows you how to do this:

glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
// draw triangles here
// use glNormal3f() to submit a vertex normal with each vertex
glDisable(GL_LIGHTING);

Interactive control

You must implement a REPL style interactive command based control system for all these features except the camera control. Using keyboard commands through the terminal (stdin for instance), you should be able to manage the process of reading in, transforming, and deleting objects. The command loop should output a prompt to the keyboard, await a newline-terminated text string command, parse and execute the command, and return to command mode with a prompt. The commands you must be able to handle include:

There are a few things worth noting here. First, you aren't meant to type the angle brackets in the commands, they just indicate the presence of a parameter. The objectfilename is a character string, all the other parameters are floating point numbers.

Next, the notion of a current object needs to be maintained, and because you can add or delete objects at any time, you'll need to maintain a stack of objects to keep track of which one is current. You'll push an object onto that stack when you execute an L command, and you'll pop an object off the stack when you execute a D command. Of course, this means you'll need to keep around internal representations of objects to redisplay them for as long as they're resident.

Note that the transformations added to the modeling transform should be applied to the objects in the order they are specified. So you aren't just postmultiplying a new matrix to the MODELVIEW matrix each time, since that would cause the effects of the transforms to be in the opposite order they were specified.

None of the transforms that were specified before an object is loaded should be applied to that object; all of the transforms that are specified after it is loaded should apply to it.

The V and W commands allow you to get very different effects by specifying the same transformation parameters. This spec stays in effect until it is changed. You should be in V mode if you want the effects to be relative to your viewing position (so for instance rotation commands about primary axes will produce pitch, yaw and roll effects, and translations will do panning and zooming, but of course these are being done conceptually by moving objects, not by changing your view). In W mode, you move objects with respect to a fixed world coordinate system, the coordinates in which the vertices of the objects as they are read in are specified.

Additional Requirement

As described in class, you must also implement a command line switch that allows an initial command file to be loaded when the program is first run. This switch will be of the form -f filename where the filename is the full filename of the command file to be input. This file will contain a sequence of the commands described above just as you would input them from the keyboard and your program will parse and execute them just as if they had been entered from the keyboard before any interactive input is processed. The file should be optional, if the switch is not given, no initial file is processed.

Extra credit

As you will presumably notice doing it, there are many ways to enhance this project if you're so inclined. Here are some suggestions:

Notes:


Last modified: 10/08/15 by Don Fussell fussell@cs.utexas.edu