raytrace <scene description filename> <image output filename>The input format has been extended to describe a set of (right, circular) cylinders as well as the lights and spheres from the former assignments. Each cylinder is axis-aligned, and may be aligned with the X, Y, or Z axis. The cylinder may have infinite or finite length. Setting the length parameter to any negative value indicates an infinite length cylinder. Finite length cylinders begin with the base at the origin and extend for the specified length along the specified axis in the positive direction. Cylinders may be translated away from the actual axes by specifying the base center. For finite-length cylinders, this effectively specifies the location of the center of its base, and the rest of the cylinder extends in the positive direction of the specified axis. For inifinite-length cylinders, there is no actual base, but the base-center still describes the displacement of the cylinder from the coordinate axis.
Finite-length cylinders may also be rendered with or without caps (the caps will never be visible for infinite cylinders). These caps are planar discs that cover the ends of the cylinder, turning the finite cylinder into an enclosed solid.
The cylinders should be illuminated just the same as the spheres in the previous assignment. Thus, reflections and refractions are possible, as well as local illumination. As in the previous assignment, you should assume that transparent primitives do not overlap in space. Also, you may assume that finite cylinders without caps will not be transparent (because they are not really solids).
This assignment includes a sample scene (my test executable from the previous assignments works for this assignment as well). Be careful, there are a number of tricky situations that may occur in both the intersection and normal computations.
Except for the file parser, intersection routines, and normal routines, all of my code knows only that it is dealing with a primitive or list of primitives. This makes the design much simpler and avoids coding things multiple times for the two primitive types.
Notice that a circle is just a sphere in one lower dimension. This means that all the forumas you used for spheres pretty much apply to the cylinder computations. The implicit function for the sphere or circle is:
Here, X is a point on the sphere or circle, C is the center, and r is the radius. The equation for the ray is:(X-C).(X-C) - r^2 = 0
P is the start of the ray and V is the direction. Substituting this formua for X in the implicit equation yields:X = P + t*V
Regrouping the terms by powers of t yields:(P+tV-C).(P+tV-C) - r^2 = 0
Now you just solve for t using the quadratic formula to get 0, 1, or 2 possible intersections.(V.V)*t^2 + 2*(P.V - C.V)*t + P.P + C.C - 2*P.C - r^2 = 0
For cylinders with caps, you will also have to consider the intersections of the ray with the planes of the cylinder caps. Planes have the implicit form:
N is the normal of the plane. For axis-aligned cylinders, the normal will be a unit vector in the direction of the axis and d is the distance of the plane from the origin. Substituting the ray for X yields:(N.X) - d = 0
There will be either 0 or 1 intersection. The intersection only counts if it is within the cylinder's circle, of course.N.(P+tV) - d = 0N.P + t*(N.V) = dt = (d - N.P) / (N.V)
For capped cylinders, you will need to consider the intersection of a ray with not only the cylinder walls, but with the two caps. As always, the closest positive intersection is the one used. Also, for the normal computation, you will have to decide if the point is on a wall or cap to figure out what normal to return.
# comment lines start with # and may appear anywhere
RESOLUTION: [x resolution] [y resolution]
FIELD_OF_VIEW: <full x field-of-view>
BACKGROUND: <red> <green> <blue>
MAX_BOUNCES: [maximum recursion level]
NUM_LIGHTS: [number of lights]
LIGHT
POSITION: <x> <y> <z>
DIRECTION: <x> <y> <z>
INTENSITY: <red> <green> <blue>
EXPONENT: <exponent>
CUTOFF: <angle>
ENDLIGHT
LIGHT
…
ENDLIGHT
LIGHT
…
ENDLIGHT
…
#in other words, one LIGHT…ENDLIGHT block for each light
NUM_SPHERES: [number of spheres]
#similarly, one SPHERE…ENDSPHERE block for each sphere
SPHERE
CENTER: <x> <y> <z>
RADIUS: <radius>
DIFFUSE_COLOR: <red> <green> <blue>
DIFFUSE_COEFFICIENT: <coefficient>
SPECULAR_COLOR: <red> <green> <blue>
SPECULAR_COEFFICIENT: <coefficient>
SPECULAR_EXPONENT: <exponent>
TRANSMISSION_COLOR: <red> <green> <blue>
TRANSMISSION_COEFFICIENT: <coefficient>
REFRACTION_INDEX: <index of refraction>
ENDSPHERE
SPHERE
…
ENDSPHERE
SPHERE
…
ENDSPHERE
# and finally, the cylinders
NUM_CYLINDERS: [number of cylinders]
CYLINDER
AXIS: <X, Y, or Z>
CAPS: <Y or N>
BASE_CENTER: <x> <y> <z>
RADIUS: <radius>
LENGTH: <length>
DIFFUSE_COLOR: <red> <green> <blue>
DIFFUSE_COEFFICIENT: <coefficient>
SPECULAR_COLOR: <red> <green> <blue>
SPECULAR_COEFFICIENT: <coefficient>
SPECULAR_EXPONENT: <exponent>
TRANSMISSION_COLOR: <red> <green> <blue>
TRANSMISSION_COEFFICIENT: <coefficient>
REFRACTION_INDEX: <index of refraction>
ENDCYLINDER