CS40 Midterm project: Ray Tracing

Due 11:59pm Tuesday 4 November 2014

You may work with one partner on this assignment. This lab will count as your midterm project and use a variety of techniques that you have learned so far. You will design and implement a ray tracer. Your ray tracer should model spheres, triangles, and rectangles, using the Phong lighting model for ambient, diffuse, and specular lighting. You should also model shadows.


Getting started
Use the setup40 script to set up the appropriate git repos with the right permissions set for partners and instructors. Suppose users molly and tejas which to work together. Molly can start by running
[~]$ setup40 projects/raytrace tejas
Once the script finishes, Tejas should run
[~]$ setup40 projects/raytrace molly
Please note that the script tries its best to ease the initial creation and cloning of git repos and it tries to be smart and check that each partner agrees that they are partners. That said, there are some race conditions and if there are uncooperative formations of partners, the script and the instructor will get confused. If you play nice with the script, it will play nice with you.

If all goes well, Tejas and Molly should each have a local clone of a common git repo in their own ~cs40/projects/raytrace directory. You can use git status to confirm this.

If you wish to work by yourself (not recommended), use the syntax

[~]$ setup40 projects/raytrace none
Copying starter code
Both partners should modify their own ~/cs40/projects/CMakeLists.txt as this file is not under version control. Just add the line
add_subdirectory(raytrace)
to the end of the file and save.

For the next step only one partner should copy over the starting code

[~]$ cd ~/cs40/projects/raytrace
[raytrace]$ cp ~adanner/public/cs40/projects/raytrace/* ./
Now push the changes to your partner
[raytrace]$ git add *.h *.cpp *.txt
[raytrace]$ git commit -m "midterm start"
[raytrace]$ git push
Even if your are working by yourself, you must run git push or I can't see/grade your work. If you are working with a partner, your partner can now pull the changes. In this case if Tejas wishes to get files Molly pushed, he would run
[~]$ cd ~/cs40/projects/raytrace
[raytrace]$ git pull
Data
See input.txt for a sample test file describing a scene to model and the viewpoint from which to raytrace the final image.
Overview
Some of the source files provided have been used in previous assignments.

rgbImage, png_reader, png_writer and rgbColor are from Project 01. Recall that in the RGBImage class pixel 0,0 is in the upper left.

view, material, light and ray are very lightweight classes or structs that just are containers for grouping related elements together. In many cases, there is no associated cpp files since the member variables can be accessed directly. Feel free to modify these classes/structs if you like, but you shouldn't need to add a ton of stuff to these files to get a basic ray tracer working.

Shape.h describes a virtual base class, much like the drawable class from Project 02. It is important that each shape you add to your scene is able to compute intersections with rays and the shape. Also each shape should compute normals for points on the shape. You should implement spheres, triangles, and rectangles as classes derived from the Shape class. I have started this for you in Sphere.h, but you need to add some stuff and implement the appropriate methods in Sphere.cpp. Don't forget to update your CMakeLists.txt file. You will need to add Triangle and Rectangle classes from scratch.

That leaves the parser, which reads a text file like input.txt and converts it into an internal format that your raytracer can use. Writing parsers in C++ can be very tedious. I got you started by writing some helper function in parser.h. Reading this file may be helpful as you parse some commands I have left out. Reading parser.cpp is probably less helpful. It has the tedious and annoying details of C++ string manipulation. raytracer.cpp contains the start of a full parser that opens the input file and parsers each command line by line. Check out parseLine which is similar to a giant switch statement (except you can't switch on string types). When you run the parser initially, you will find some commands are completely missing and some are only partially implemented. Examine the other parts of parseLine and use it to fill in any missing details. It is recommended that you store all the information about the input file in the m_scene object. I use two QHash dictionaries in the parser to refer to certain color and material variables by a string name, like "red". Take a look at a few examples in the parser and feel free to ask questions.

To make material handling a bit easier, there is a notion of the "current" material. Changing the properties of a material through the used of mat amb color changes the "current" material which can be saved as a special name and retrieved later. When you create a new sphere, triangle, or rectangle, you do not need to specify nine material coefficients. The semantics is that these objects should just use the "current" material at the time the object is created. It's very OpenGL-esque, for better or worse.

As for implementing the actual raytracer, it is helpful to have a function that can convert i,j png pixel coordinates to world coordinates using the origin, horiz and vert point/vector information. For each pixel, create a ray from the eye to the pixel position in world coordinates then have a function that traces one ray and returns a single RGBColor which can be assigned to the final output png file.

Don't try to handle all the components at once. Focus on maybe getting the ambient lighting working for one sphere or one rectangle in the center of the image. Once you have the basic outline correct, adding diffuse and specular lighting should be easier.

Notes about ray-tracing can be found in chapters 12.2 and 12.3 of the text. A review of the Phong lighting model can be found in chapter 6.3. Note, the text describe a light source as having separate red, green, and blue intensities, whereas we only define a single (white) intensity for each light.

Requirements
Additional Components
A modest amount of credit will be reserved for adding some more advanced ray tracing components to your system. I do not expect you to implement all of these ideas, but you should attempt to implement at least one of the following features. How you design and implement your solutions (and how you adjust the parser) is up to you.
Hints, Tips, and Updates

You do not need a draw method in your shape classes. The drawing is done by the rays traveling through the image plane.

You do not need a perspective or ortho projection matrix. As all rays originate from the origin and go through the image plane, you will get a perspective effect from simply tracing rays.

Submit
You should regularly commit your changes and occasionally push to your shared remote. Note you must push to your remote to share updates with your partner. Ideally you should commit changes at the end of every session of working on the project. You will be graded on work that appears in your remote by the project deadline.