600.120 Intermediate Programming
Summer 2013 -- Assignment 2
Due by 9am on Friday, 6/7

The purpose of this assignment is to work with more sophisticated I/O functions, text files and functions.

Part A: Wavefront Objects [35 points]

For the first part of our second assignment you will be interacting with a simple 3D model format called Wavefront OBJ. Your task is to write a program that will take a simple OBJ file and compute the normals for every face, creating a more detailed output file, also in OBJ format. The input file, input.obj, will lack normal directions for each face and you must calculate them using the cross product, writing the improved file to output.obj.

An OBJ file is a human-readable text file containing vertex positions in a 3D coordinate system. A simple example, box.obj, can be found here. This file was generated in Blender, an open-source modelling program. The example contains the 8 vertices and 12 triangles of an axis-aligned cube. (Since each of the six cube surfaces is a square, each is represented by two triangles.) While the OBJ format supports more complex data like quads, materials, and textures, we will be focusing on three simple data types: vertices, vertex normals, and faces (triangles). Each of these types of data starts with an identifier followed by integer or floating-point values.

The format of a vertex is:

"v" x y z

where x, y, and z are floating-point values indicating the coordinates of the vertex.

The format of a vertex normal is:

"vn" x y z

where x, y, and z are directional components with a combined length of 1.0.

The format of a face is:

"f" v1 v2 v3

where v1, v2, and v3 represent the corner vertices of that particular triangle. These values are given as integer indices referring to the relative order in which the vertex data appears in the OBJ file, starting at one. For example, "f 1 3 6" means a triangle with the first, third and sixth vertices as its corners.

OBJ files also support line comments starting with '#'. You must parse these lines and ignore any characters between '#' and the newline character. There is also an identifier 's' that indicates whether the geometry is smooth. A box is perfectly planar on each side, so this value is set to "off". The output file, output.obj, should contain identical comments, vertices, and smoothing of the input file, input.obj. The program should take no command-line parameters.

The solution (corresponding output file) to the example above (box.obj) can be found here. Twelve vertex normals have been added (one for each face) and the format of a face has changed. The format of a face is now:

"f" v1/t1/n1 v2/t2/n2 v3/t3/n3

where v1,v2,v3, t1,t2,t3, and n1,n2,n3 are integer indices indicating the relative ordering of each corresponding vertex, texture coordinate, and vertex normal.

You do not have to worry about texture coordinates for this assignment, so every vertex index and its normal index should be separated by two slashes. Note that for the box, each face uses the same normal for all three vertices. If the box were smooth we could want multiple normals per vertex instead.

A cross product takes two vectors a and b as input and results in a third vector c that is orthogonal to both a and b. Construct a and b from a triangle face by subtracting one corner vertex position from the other two: a = v2 - v1 and b = v3 - v1. (We subtract vectors by subtracting each corresponding x,y,z coordinate within them.) Order matters when evaluating the cross product because given two vectors there are two possible normal vectors: n and -n. Make sure you follow the right-hand rule or you will get your direction backwards. Faces are specified counter-clockwise, meaning that if the normal is pointed at your eye as you look at the triangle the order will appear counter-clockwise to you.

Finally, here is code to get you started. Don't forget the gcc option -lm for the math library. You must implement the methods as given. You may add other methods if you want.

You will probably want to use fscanf() and fprintf() for file reading and writing. Don't forget fopen() and fclose() for opening and closing your files. You may use an array to make accessing the vertices more efficient. float v[128][3]; will work because we guarantee a file will not have more than 128 vertices.


General assignment requirements, style and submission details: