Project1F20

From Immersive Visualization Lab Wiki
Jump to: navigation, search

Contents

Homework Assignment 1: Point Clouds

In this project the goal is to load 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 make you familiar with the tools and libraries that you will be using throughout the quarter. These will include GLFW and GLew, as well as GLm.

Note that parts 1 and 2 of this project can be done with your knowledge from week 1, parts 3 and 4 require linear algebra which we will be covering in week 2.

1. Get Your Development Environment Ready (20 Points)

We recommend that you start by getting your development software ready.

The goal of this step is to see a spinning cube. The number keys '1' and '2' should switch between a solid cube and a point model of the cube which only consists of the 8 vertices of it.

Note: When you work on the following sections of the homework assignment, you don't need to retain the functionality of the number keys.

2. Read 3D Points from Files (30 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 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 use the following three data types (other OBJ files may support more): 'v' for vertex, 'vn' for vertex normal, 'f' for face. But in this project you only need to parse those lines that start with a 'v'.

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 may be missing from the files). Like the vertex coordinates, they are floats, and can only take on values between 0.0 and 1.0.

All values are delimited by a single whitespace character.

In summary: 'v' is for vertex and is 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 - you can ignore the color since we're going to render all points in the same color. Example:
v 0.145852 0.104651 0.517576 0.2 0.8 0.4

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

Write your parser so that it traverses 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'. Here is an example of how to read the vertices:

std::ifstream objFile(objFilename); // The obj file we are reading.
std::vector<glm::vec3> points;

// Check whether the file can be opened.
if (objFile.is_open())
{
	std::string line; // A line in the file.

	// Read lines from the file.
	while (std::getline(objFile, line))
	{
		// Turn the line into a string stream for processing.
		std::stringstream ss;
		ss << line;
		
		// Read the first word of the line.
		std::string label; 
		ss >> label;

		// If the line is about vertex (starting with a "v").
		if (label == "v")
		{
			// Read the later three float numbers and use them as the 
			// coordinates.
			glm::vec3 point;
			ss >> point.x >> point.y >> point.z;

			// Process the point. For example, you can save it to a.
			points.push_back(point);
		}
	}
}
else
{
	std::cerr << "Can't open the file " << objFilename << std::endl;
}

objFile.close();

The above code is just an example, you will have to make minor modifications to it in order to make it work within the starter code.

To avoid long load times during program execution, you need to load all three models into memory at startup.

Grading:

  • -5 for any errors in the parser
  • -5 if all models aren't loaded at program startup

3. Display the Points (30 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 (or other keys of your choice) to display the three models, respectively. Only one 3D model should be displayed at a time. Use a color of your choice to render the models, except white.

Allow the user to adjust the size of the points with the 's' and 'l' keys (for smaller and larger points, respectively). Repeated key presses should keep decreasing/increasing the point size down/up to reasonable limits.

Grading:

  • -5 if the point size is not adjustable
  • -5 if there is no way to switch between the models

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

At this point some of the point 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 (resize) (i.e., scale each dimension by the same amount) all models so that they approximately fill the graphics window without exceeding it too much. The approach is to calculate the maximum distance any one of the points is from the center of the model, then scale the model up or down about its center so that it is as large as it can be without being cut off by the window edges. You can use an empirically determined (by trial and error) scale factor, but your algorithm needs to be independent of the data set used - if we gave you a new OBJ file it should still work.

Grading:

  • -5 if any of the three given files aren't centered correctly
  • -5 if any of the three given files aren't sized correctly

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. Simple scaling of the object does not count.
  2. Create transitions between models: morph the points from one model to the next when switching between models. (5 points)
  3. Variable point size: render larger points when they are closer to the viewer for a more realistic 3D effect. The point size needs to update as the object rotates. Follow the instructions at: http://www.informit.com/articles/article.aspx?p=770639&seqNum=7 (10 points)

Submission Instructions

Once you are done with the homework project, record a video demonstrating all the functionality you have implemented.

The video should be no longer than 5 minutes.

Ideally, you will talk over the video to explain what you are showing. Alternatively, you can display text for this purpose.

To create the video you don't need to use video editing software, but you should use software to capture your screen to a video file.

  • For Windows users we recommend the free OBS Studio.
  • On Macs you can use Quicktime to record off the screen.

Upload this video at the Assignment link on Canvas, and comment which functionality you have or have not implemented and what extra credit you have implemented. If you couldn't implement something in its entirety, please state which parts you did implement.

  • Example 1: I've done the base project with no issues. No extra credit.
  • Example 2: Everything works except an issue with x, I couldn't get y to work properly.
  • Example 3: Sections 1-2 and 4 work.
  • Example 4: The base project is complete and I did z for extra credit.

Finally, zip up your source code (only .cpp, .h, executable and shader files) and submit the zip file at the Assignment link on Canvas as well. Do not include the .obj files.