Jeremiah Darais

Assignment 1

Image Result

screenshot

Source Code

Design Choices

Everything is a Vector. To consolidate as much functionality as possible, I have a Vector3 and a Vector4 class. Even the Color class extends from Vector4 (Though it seems that I could get away with a 3-component color model since alpha is never used) This may come back to haunt me, but it has worked well so far.

I decided to embed a scratch-pad into the hit record so if any important information (i.e. normal, barycentric coordinates) is a byproduct of an intersection calculation, a primitive can store that data in the hit record. If it is asked for its normal, it can assume that the HitRecord it is given is the same one it wrote into at intersection time. I have to be careful with this, though, and make sure that a primitive only writes data into the scratch-pad if it is the new closest intersection with the ray. Otherwise, it could overwrite the data that some other primitive stored and will try to use later.

I wasn't exactly sure what the best approach was for light/matierial communication. Some materials only need the normal and light direction to calculate lighting, but for a point light, the distance is also needed to calculate shadows. I ended up creating a class that inherits from Ray called LightRay, that packages all the light information for a material to interact with, including light color and distance in addition to the origin (the point of contact on the primitive) and direction (normalized direction to the light) that a Ray normally contains. A light is given a point in space to light, it calculates the LightRay information, and passes it to the material. Theoretically, a light can implemented differently to apply a shape mask, calculate range fallof, etc. For a directional light (of infinite distance), the light need only return a LightRay with the origin at the point it is given, a direction parallel to the light direction, and a distance of FLT_MAX, which is effectively infinity.