CMSC 435/634: Introduction to Computer Graphics

Assignment 1
Development Suggestions

This is a big assignment. Start NOW, or you will probably not finish.

Plan ahead

I recommend laying out a plan of attack before coding. Data structures are less of an issue for the basic assignment, but if you plan to attempt any additional primitives, a common effective strategy is to create a generic object class with spheres, polygons, cones, etc. classes derived from it, each with a specialized virtual method to compute the intersection of a ray with that primitive type. To assist in your planning, here is an outline of the steps your ray tracing program will need to do:

  1. Read file format into scene data and list of objects
  2. For each pixel:
    1. Calculate pixel location in world space
    2. Calculate ray from eye point through the pixel and into the scene
    3. Calculate ray-object intersections, choose smallest/closest
    4. Set the pixel to that color
  3. Write all pixels out to your PAM file


You can use C or C++, but I recommend C++: a vector class with addition, scalar multiplication, and dot product operators will make many operations more compact and more like the vector math equivalent. C++ includes STL data structures that can be useful for this assignment. Also, several other concepts of ray tracing map well into C++.


For a file format as simple as this one, it isn't necessary to get too fancy with the parsing. The easiest method is probably to read a line at a time (e.g. with fgets), identify the type of line by looking at the first character, then parsing it with sscanf. There are C++ fstream equivalents for these functions, but even when programming in C++, I still generally prefer to use the stdio-style functions.

Parse debugging

If you read a line at a time, it is easy to count lines as you parse. If you ever see unexpected input, you can print the line number and line contents to help identify where the error occurred.

Test input

It is very difficult to find the error in one of hundreds or thousands of triangles without a systematic approach and simplified data.

Note that you can easily write your own nff files by hand, which can be very handy for debugging. I recommend that you start with a test scene looking from (0,0,0) at (0,0,1) containing a triangle sphere centered on the Z axis, say with coordinates (0,1,1), (-1,-1,1) and (1,-1,1). With a single triangle, it's easier to tell if your loading is working, and with a simple view it is easier to tell if your ray positions are correct.

Start by trying to find intersections with a 1x1 pixel image, which should give you a ray straight down the Z axis hitting the triangle at (0,0,1). Move the triangle around, making sure you get the right answer when you miss it, when your ray direction is parallel to it, or when it is behind you. Then, you can scale up to 2x2 or 3x3 images to make sure your ray position code is correct. Once you have the basics working, move up to a larger window so you can visually tell if your polygon is rendering as a triangle.

Only when you are confident of your ray direction computation and intersection code should you switch to the SPD scenes. If you still run into problems, you can successively eliminate polygons from the SPD file to find the one that is not being computed correctly

Debugging output

It is also worthwhile getting image output working early. Printing debugging values works OK for one pixel/one primitive scenes, but for larger images and scenes, outputting values other than colors at each pixel can be a valuable debugging tool. For example, displaying a barycentric coordinate as color can really help to see if it is aligned correctly to the polygon edge and scaled to the size of the triangle.

Viewing files remotely

I have provided a starter Makefile that will build a program from any .c or .cpp files in the directory, run it on tetra-3.nff, then convert the result to a png image (called tetra-3.png). If you develop on the GL system remotely (with ssh, TeraTerm or puTTY), you will need a way to view your results. The easiest is to copy this .png file to your ~/../pub/www directory on the GL system. Then you can visit in any web browser to see the image.

You can even modify the Makefile to do the copy to your www directory as part of its build process, which would make your debug cycle just edit, make, reload.