Due:

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 plus a binary executable for verifying your test cases. 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.

- well-commented source code (I actually read the comments and code)
- instructions for compiling (running should work as specified above)
- one or more interesting scene files and rendered images (with .rt1 and .ppm or .tiff extensions)
- brief description of each scene (this can be comments at the start of the file)

Naturally, the brackets do not appear in the actual file (but the colons do).

Blank lines and white space should be ignored

Lines with a ‘#’ as the first character are comments and should be ignored.

Colors should be specified in the range [0.0, 1.0]

Angles should be in degrees, and refer to the full angle (as opposed to the half angle)

# 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

As I described in class, one way you can implement some pretty simple
parsing is as follows. Open the file with fopen(). Write a simple procedure
to get each line of input. This procedure can include a loop using fgets()
to read a line and then test to see if it's all blank or a comment. Return
the first non-blank, non-comment line. Use sscanf() to get the useful data
out of the input line. sscanf() works in the presence of white space and
allows you to check that the expected number of tokens were read. Of course
you are free to continue using whatever method of parsing you used in the
original assignment assuming that it works and allows the program to be
executed with the specified command line.