You will be doing your work this semester in a GitHub respoitory. Before you get started on any of the assignments, you should create a GitHub repository from the class template repository that contains some hopefully helpful code, input files, and grading rubrics. To create your repository:
git pull template
If Eigen is not already installed on your machine, install it. (Do not put Eigen in your GithHub repository.)
To use Eigen (in particular Eigen::Vector3d will make your life easier), add
-I<path_to_eigen> -I/usr/include/eigen3/ -I/usr/local/include/eigen3to your compilation flags (<path_to_eigen> is the path to your Eigen installation if it is non-standard, the latter two include paths are common installation paths for Eigen and will make it easier for you to work on other systems and for the Instructor and TA to use your makefile) and add
#include <Eigen/Dense>in relevant header and code files.
To make sure you do not have last-minute problems, you must commit and push something to your repository by the Initial Submission date above.
For this assignment, you must write a C or C++ program that will render triangles using ray tracing and the barycentric coordinate intersection method. The input is in a simple text format called NFF, containing information about the view and objects in the scene. You will read an NFF scene from a file given on the command line, and ray trace the single image described there. Rays that hit an object should be rendered in the triangle color, while rays that do not hit any object should use the background color of the scene. Do not try to include any of the more advanced ray tracing features you may read about (shadows, reflection, refraction, lights, etc.), we will get to those in the next assignment. Your output should be an image file in PPM format.
You can run my program here on the University's GL machines:
~adamb/public/hide/hide input.nff output.ppmYour program should support the following usage:
./hide input.nff output.ppm
Tip: I use the std::getline funciton and std::strstream class for parsing. getline is good for reading the file into a string. It is easy to match the first character of that string in a switch statement, then depending on the case, I create a strstream (or many strstreams) to parse the line(s) of input into variables. For example, I have code that looks like
case 'b': { std::stringstream ss(line); ss>>ch>>bcolor[0]>>bcolor[1]>>bcolor[2]; break; }to get the background color.
The PPM format is one of the simplest image formats available. See the man page for 'ppm' on the university GL server for a description.
To create a PPM file, first you should store your image in an array of bytes in y/x/color index order:
unsigned char pixels[HEIGHT][WIDTH][3];When filling in this array, remember that it is in y/x order, not the more familiar x/y order. The final index is the color component, with r=0, g=1 and b=2. Color values range from 0 to 255. For example, this would store a floating point color value of .5 into the green component at x,y:
pixels[y][x][1]= .5*255;Once you've filled in the pixels array, actually writing the PPM file is quite simple:
FILE *f = fopen("hide.ppm","wb"); fprintf(f, "P6\n%d %d\n%d\n", WIDTH, HEIGHT, 255); fwrite(pixels, 1, HEIGHT*WIDTH*3, f); fclose(f);Alternatively, you could use the C++ file stream i/o:
std::ofstream out(fname, std::ios::out | std::ios::binary); out<<"P6"<<"\n"<<WIDTH<<" "<<HEIGHT<<"\n"<<255<<"\n"; unsigned char val; for (unsigned int y=0; y<HEIGHT; y++) { for (unsigned int x=0; x<WIDTH; x++) { val = pixels[y][x][0]; out.write (&val, sizeof(unsigned char)); val = pixels[y][x][1]; out.write (&val, sizeof(unsigned char)); val = pixels[y][x][2]; out.write (&val, sizeof(unsigned char)); } } out.close();Or more simply:
std::ofstream out(fname, std::ios::out | std::ios::binary); out<<"P6"<<"\n"<<WIDTH<<" "<<HEIGHT<<"\n"<<255<<"\n"; out.write(pixels, WIDTH*HEIGHT*3*sizeof(unsigned char)); out.close();But, of course, C++ does not allow
unsigned char pixels[HEIGHT][WIDTH][3];But, C++ does allow
unsigned char *pixels = new unsigned char[WIDTH*HEIGHT*3];
Ray tracing is a popular rendering technique, and the internet contains lots of resources for ray tracers in general and things like ray-object intersection in particular. Other than the PPM snippet above, YOU MAY NOT USE ANY OUTSIDE CODE. All code that you use must be your own.
This is a big assignment. Start NOW, or you will probably not finish. No, really, I promise you will not be able to do it in the last two days. Even before we get to all of the details of the ray tracing itself, you can still start working on your file parsing.
Some implementation tips from a previous instructor.
Turn in this assignment electronically by pushing your source code to your proj1 GitHub directory by 11:59 PM on the day of the deadline. We will be looking for multiple checkins documenting your development process.
Do your development in the proj1 directory so we can find it. Be sure the Makefile will build your project when we run 'make' (or edit it so it will). Also include a README.txt file telling us about your assignment. Do not forget to tell us what (if any) help did you receive from books, web sites or people other than the instructor and TA.Check in along the way with useful checkin messages. We will be looking at your development process, so a complete and perfectly working ray tracer submitted in a single checkin one minute before the deadline will NOT get full credit. Do be sure to check in all of your source code, Makefile, README, and updated .gitignore file, but no build files, log files, generated images, zip files, libraries, or other non-code content.