Viewing the raytracer's output of whatever scene is being processed is a critical aspect of the software. An easy and oft-used first check of new additions to a raytracer is the simple "does it look right?" test, for which some method of displaying the output is required.
A common way to provide such output is by constructing a virtual camera. We define this camera as follows:
After constructing this camera, the raytracer itself uses the camera's origin as the origin for the rays it shoots, pointed in a direction based off of the other camera variables. In every raytracer I have ever built (and I have a hunch this holds true for most people), I've flipped some negative or plus sign and ended up debugging for thirty or forty minutes. This time around, I flipped the order of a cross product and ended up with the strange results in the accompanying image. Come to think of it, this "flipping the order of a cross product" is a theme in raytracing, and will pop back up when we discuss normals in a later section.
After fixing this, the camera worked well! The image below is a sequence built by rotating the camera in a circle about the (world-space) origin. Below is the math used to determine the basis vectors for the camera, as well as how to shoot a ray from the camera origin out through a pixel in the final image.
// Compute the basis vectors for our camera space
this->w = look;
this->u = up.cross(w);
this->v = w.cross(u);
this->s = aspect_ratio / (2 * tan(fov));
// Create a ray shot from the camera through a point <x,y>
Vector direction;
direction.x = u.x*(x*0.5*aspect_ratio) + v.x*(y*0.5) + w.x*-s;
direction.y = u.y*(x*0.5*aspect_ratio) + v.y*(y*0.5) + w.y*-s;
direction.z = u.z*(x*0.5*aspect_ratio) + v.z*(y*0.5) + w.z*-s;
Ray* r = new Ray(origin, direction, Color());