Project 2: Ray Tracing Instances and Acceleration
Start Assignment
Due Friday by 11:59pm
Points 100
Submitting a file upload
Objective
For this project, you will continue to add new capabilities to your ray tracer. First, you will add axis aligned boxes as a new kind of primitive. Then you will create named objects and be able to make multiple replicas (instances) of such objects in your scene. Instead of copying the primitives from a named object, you are going to render an instance by transforming the ray by the inverse of the transformation matrix for the object. Next, you will create a new kind of object that is simply a list of other objects. Finally, your most difficult task will be for you to create a ray tracing acceleration data structure. You can choose to implement either of these three options: 1) bounding volume hierarchies, 2) grids, or 3) k-D trees.
Project Description
You have several goals for this project:
- Add axis aligned boxes as a new primitive
- Be able to create a named object and make instances of such a named object
- Create a list of objects and place them into an acceleration data structure for faster rendering
- Create a scene that includes many copies of one of the large meshes (bunny, dragon, buddha, lucy).
You should re-factor your code so that the different varieties of objects you can render are all subclasses of one based Object class. Triangles and boxes should be subclasses of Object. An instance of a named object should be a subclass of Object. Your ray acceleration data structure should be a subclass of Object. By doing this, you should be able to have one list of objects that contain all of the items to be rendered in your scene. Each object should be able to perform ray / object intersection, returning information about the closest hit, if any. Each object should also be able to return an axis aligned bounding box (AABB) that completely encloses the object. This will be very useful for implementing your ray acceleration data structure.
In order for you to create named objects, you should maintain two separate lists of objects: the list of objects that will appear in the scene, and a list of named objects. A named object will only appear in a scene if one or more instances of it are made.
However you implement these new capabilities, your results should appear almost exactly like the examples shown below in Results.
Begin with Your Project 1 Code
There is no provided code for this project. Since this project builds on top of Project 1A and 1B, you should start with your project 1B code and add the new capabilities to it.
Provided Scene Files
There are several SCENE FILE that are being provided for this project. You should modify your code so that pressing one of the keys 1-9, 0, and "a" will load in the appropriate scene file. Notice that there are some .cli files (e.g. bun500.cli) that are not full scene files, but that are used by some of the scenes (with the new read command). These files will not create an image on their own, and so you do not need to be able to read these in directly.
Scene Description Language
As in Project 1, each scene is described by a text file with suffix ".cli". Each of these .cli files are just plain text files, and you are encouraged to look at them. Sometimes you may find it useful to modify a copy of these files to make debugging easier. Below are the new commands that you will implement. Your ray tracer should also keep the functionality of all of the commands from Project 1A and 1B. box xmin ymin zmin xmax ymax zmax
Create an axis aligned box primitive, and put it on the list of objects in your scene. Do NOT create your boxes out of triangles. You should intersect the ray with the six planes that describe the box, each of which is perpendicular to one of the axes. Consult our textbook Physically Based Rendering for details about this. You won't be rendering these boxes directly very often, but you will eventually make use of AABB's in creating your acceleration data structure.
Just like triangles, boxes should be modified by the current transformation matrix when the box is created. Do this by transforming the minimum and maximum corners of the box. This will cause the expected results for translations and scaling. Don't worry that rotating an axis-aligned box will have unexpected results.
named_object
Remove the most recently created object from the list of scene objects, convert this object to a named object, and place it in your collection of named objects. A named object can be a triangle, an axis aligned box, or an acceleration data structure that contains multiple objects.
instance
Create Your Own Scene
One of the requirements for this project is for you to create your own scene that draws many instances of one of the large mesh files provided for this project. Your scene should include at least 20 copies of the mesh you decide to instance. More is better! You can pick from among any of the four large meshes we are providing: bunny (69k triangle version), buddha, dragon, lucy. We will be showing to the class some of these scenes.
Include Code that Reports Rendering Time When your program starts to render a given scene, it should start a timer by calling this routine: int timer; // global variable void reset_timer() { timer = millis(); }
When your scene is done rendering, you should then call this routine, which will print out how long it took to render the scene: void print_timer() { int new_timer = millis(); int diff = new_timer - timer; float seconds = diff / 1000.0; println ("timer = " + seconds); }
You May Use Processing's Matrix Inverse Routine When you implement object instancing, you will help to do this by storing the inverse of the current transformation matrix, C-1. To calculate this inverse, you are allowed to use the PMatrix3D class' inverse function that is built into Processing: PMatrix3D
Results
Below are the images that your program should generate for a given scene, when you press the keys 19, 0, and "a". Notice that we ran out of digits, so jumped to the letter "a". The final scene should of course be the one that you create that contains many instances of one of the large mesh objects.