Project1F18

Homework Assignment 1: Rendering Point Clouds

In this project the goal is to read a number of 3D point positions from a file and render them onto the screen.

Besides becoming familiar with the linear algebra involved in rendering 3D scenes, this project will get you familiar with the tools and libraries that will be your friends throughout the quarter. These will include GLFW and GLew, as well as GLm.

The goal of this step is to see the spinning cube from the starter code on the screen.

2. Read 3D Points from Files (25 Points)

A point cloud is a 3D collection of points, representing a 3D object. These point clouds are often acquired by laser scanning, but can also be acquired with the Microsoft Kinect and special software, or by processing a large number of photographs of an object and using Structure from Motion techniques (see Microsoft Photosynth or Autodesk 123D Catc).

In this project we're going to render the points defined in OBJ files. Note that OBJ files are normally used to define polygonal models, but for now we're ignoring that and use the vertex definitions to render points, ignoring all connectivity data. OBJ files are 3D model files which store the shape of an object with a number of vertices, associated vertex normals, and connectivity information to form triangles. Wikipedia has excellent information on the OBJ file format. The file format is an ASCII text format, which means that the files can be viewed and edited with a any text editor, such as Notepad.

Write a parser for the vertices and normals defined in OBJ files. It should be a simple 'for' loop in which you read each line from the file, for instance with the fscanf command. Your parser does not need to do any error handling - you can assume that the files do not contain errors. Add the parser to the starter code.

Use your parser to load the vertices from the following OBJ files and treat them as point clouds:

The files provided in this project only use the following three data types (other OBJ files may support more): v for vertex, vn for vertex normal, f for face.

The general format for vertex lines is:

v v_x v_y v_z r g b

Where v_x, v_y, v_z are the vertex x, y, and z coordinates and are strictly floats.

The values r, g, b define the color of the vertex, and are optional (i.e. they will be missing from most files). Like the vertex coordinates, they are strictly floats, and can only take on values between 0.0 and 1.0.

All values are delimited by a single whitespace character.

The general format for normal is the same as for vertices, minus the color info.

In summary:

• v: 'vertex': followed by six floating point numbers. The first three are for the vertex position (x,y,z coordinate), the next three are for the vertex color (red, green, blue) ranging from 0 to 1. Example:
`v 0.145852 0.104651 0.517576 0.2 0.8 0.4`
• vn: 'vertex normal': three floating point numbers, separated by white space. The numbers are for a vector which is used as the normal for a triangle. Example:
`vn -0.380694 3.839313 4.956321`

Lines starting with a '#' sign are comments and should be ignored.

In this homework assignment, you only need to parse for vertices and vertex normals, which are those lines of the file starting with a 'v' and 'vn'.

Write your parser so that it goes through the OBJ file, line by line. It should read in the first character of each line and based on it decide how to proceed, i.e., ignore all lines which do not start with a 'v' or 'vn'. The vertex definitions can be read with the fscanf command. Here is an example:

```FILE* fp;     // file pointer
float x,y,z;  // vertex coordinates
float r,g,b;  // vertex color
int c1,c2;    // characters read from file

fp = fopen("bunny.obj","rb");  // make the file name configurable so you can load other files
if (fp==NULL) { cerr << "error loading file" << endl; exit(-1); }  // just in case the file can't be found or is corrupt

c1 = fgetc(fp);
c2 = fgetc(fp);
if (c1=='v') && (c2==' ')
{
fscanf(fp, "%f %f %f %f %f %f", &x, &y, &z, &r, &g, &b);
}

fclose(fp);   // make sure you don't forget to close the file when done
```

Load all three models in at startup.

• -5 for any errors in the parser

3. Display the Points (35 Points)

To display the vertices you loaded, use the provided starter code. It contains hooks for rendering points with OpenGL, which are ready for you to use. Change the Display callback and replace the call to render the cube to render the OBJ object - don't call cube.draw() but call the respective OBJ object's draw command.

Use function keys F1, F2 and F3 to display the three models, respectively. Only one 3D model should be displayed at a time. At this point you can use any color to render the models (eg, white) - later on we will ask you to use normal coloring. (5 points per model)

Just like the cube spins during display, make your OBJ models spin as well. (5 points)

The points should be colored with normal coloring: use the vertex normals you parsed from the file, and map them into the range of zero to one. The x coordinate of the normal should map to red, y to green, z to blue. (10 points)

Use the glPointSize() command to allow the user to adjust the size of the points with the 'p' and 'P' keys (for smaller and larger points, respectively). (5 points)

• -5 if data sets load every time a function key is pressed, instead of just loading once at program startup and just switching to it at other times.

4. Fit the Model to the Screen (20 Points)

At this point some of the models may show up larger than the graphics window, some of them may be quite small. To see each model in its entirety at the biggest possible size, without exceeding the edges of the graphics window, you need to center the model in the window, and scale it up or down to fill the graphics window without exceeding it. Do this just after loading the files from disk, before you display them, by adjusting the model's coordinates accordingly.

Centering the model (10 Points)

Traverse (loop over) the vertices of each of your models and look at each dimension (x,y,z) independently. Find minimum and maximum coordinates along each dimension, then determine the center point of the model to be half way between minimum and maximum values. Shift all model coordinates by subtracting the coordinates of the center point.

Scaling the model (10 Points)

Uniformly scale (i.e., scale each dimension by the same amount) all models to the same size, so that they just fit within the graphics window. It is permitted to come up with empirical values for each data set by trial and error.

5. Extra Credit (10 Points)

For extra credit, we provide the options below. Points are cumulative, but you can get a maximum of 10 points of extra credit in total.

1. Create a visual effect to bring up the points of a model when initially loaded: for instance, randomize their initial position within a cube the size of the model, then move them gradually to their final locations by linearly interpolating between their randomized positions and their locations in the model. (5 points) For inspiration see the first few seconds of this video and imagine watching it in reverse.
2. Alternative point coloring: implement a different way to color the points, and support a key to switch between normal coloring and your alternative coloring. (5 points) Examples:
1. Color them based on their distance from the 3D model's coordinate origin (green is at origin, red is farthest from it, linearly interpolate between green and red for points in-between).
2. Color them based on the point's x/y/z coordinates (x->red, y->green, z->blue).
3. Create transitions between models: morph the points from one model to the next when switching between models. (10 points)
4. Variable point size: render larger points when they are closer to the viewer for a more realistic 3D effect. Follow the instructions at: http://www.informit.com/articles/article.aspx?p=770639&seqNum=7 (10 points)