The goal of this machine problem is to understand and code up the intersection of a ray with (1) a composite object modeled using constructive solid geometry on primitives, and (2) an algebraic surface of arbitrary degree. These ray intersections will need to be written into a ray tracing system to generate images

You should write a ray tracer from scratch that supports refraction, CSG and algebraic surfaces. The ray tracer should cast shadow rays but for now it is ok if a glass object casts a dark shadow (as if it were opaque for the purposes of shadowing other objects).

Model an original piece of glassware using CSG operations on algebraic surfaces. For example, a glass is as simple as a cylinder, truncated by intersecting it with two planes, and hollowed by subtracting a paraboloid. You should also include a high degree algebraic surface in your scene. I'd like to see how creatively you can design drinking glassware, but other glass sculptures are also acceptable.

You will need to use robust methods for finding roots. Source is included
here
for the Graphics Gems I chapter on using Sturm Sequences to isolate
the roots of a polynomial, by D.G. Hook and P.R. McAree. Once roots are
isolated, you will need to refine them using either Newton's method, *regula
falsi* or simple bisection. Code for finding the roots of a quadratic,
cubic and quartic polynomial is provided
here
but I would like you to be able to intersect arbitrary algebraic surfaces.

I recommend you first implement refraction on something simple like spheres. Then implement CSG on spheres. Then implement more general algebraic surfaces.

Grades will be assigned according to the following scale:

- Basic Ray Tracing (50%)

Correct ray casting, shading, refraction and shadowing. You do not need to implement any extravagant ray tracing acceleration techniques (though for your own sanity you should), but your ray tracer should capitalize on reasonable speedups. - Algebraics (15%)

Partial credit (5%) is assigned if you intersect low degree (cubic, quartic) algebraics, but for full credit you will need to intersect arbitrary degree algebraics. - Constructive Solid Geometry (15%)

Partial credit (5% each) is available if you handle some but not all three CSG operations: union, intersection and subtraction (which can be implemented as intersection of one object with the complement of the other). - Documentation (10%)

Your code should be documented legibly, such that you could understand what you were doing five years from now. Also include clear execution instructions and an explanation of the features and limitations of your code. - Picture (10%)

You will need to construct a scene that demonstrates the above assignment requirements in a*visually interesting way.*These assignments provide an opportunity for you to show off to your friends, and impress me and the other graphics faculty enough to recommend you to a good grad school or job after you graduate. The pictures resulting from this assignment will be posted in an online gallery for the other students to see. Make them jealous.

My primary grading activity will be to look at the pictures (I'll check source only if I feel I have to). This means your pictures should demonstrate that you can cast rays correctly, intersect with algebraic surfaces correctly, etc. It would be wise to have notes with each picture explaining what the picture demonstrates and why.

The program is due:

**The late penalty is 10% per day with a maximum of 5 days late**

For those of you who want to use/modify the ray tracer from last semester's graphics course, look here for the CS318 mp4 code and libraries . There is an included makefile (for Unix/X11) that works on the csil-sunb

A version of the cs318 ray tracer starter kit that uses libgfx but not FLTK is available here . This version uses GLUT which doesn't have as many features but is a lot more portable.

Here is how to compute the normal of an algebraic surface. The algebraic surface is defined implicitly by a trivariate polynomial

*f*(*x*,*y*,*z*) = *a* + *b x* + *c y* + *d
z* + *e x*^2 + *f xy* + *g y*^2 + *h xz* + i* yz*
+ j* z*^2 + ...

We find the intersecion by plugging the ray equation **r**(*t* ) = (*x*0,*y*0,*z*0)
+ *t* (*xd*,*yd*,*zd* ) into f, resulting in *f*(**r**(*t*)).
You will find values *t*0,*t*1,*t*2,... that correspond to ray
intersections with the algebraic surface. Let **x**0 = **r**(*t*0)
be the first of these intersections.

The surface normal at **x**0 is given by the partial derivatives of *f*
with respect to the coordinates. Hence *N* = (d*f*/d* x*,d*f*/d*y*,d*f*/d*z*).
This value is called the gradient of *f* at **x**, and denotes the
direction of greatest change in *f*. Note that this is different than
parametric surfaces (whose surface normal is df/du x df/dv). For the above
equation, its partials are

d*f*(*x,y,z*)/d*x* = *b + *2* e x + f y + h z* ...

d*f*(*x,y,z*)/d*y* = *c + f x + *2* g y + i z* ...

d*f*(*x,y,z*)/d*z* = *d + h x + i y + *2* j z* ...

If you implement an general method for representing trivariate polynomials, you will also need to implement a method to compute its partial derivatives. Partial derivatives can also be estimated using forward differences for arbitrary functions as

d*f*(*x,y,z*)/d*x* = (*f*(*x+h,y,z*) - *f* (*x,y,z*))/*h*.

d*f*(*x,y,z*)/d*y* = (*f*(*x,y+h,z*) - *f* (* x,y,z*))/*h*.

d*f*(*x,y,z*)/d*z* = (*f*(*x,y,z+h*) - *f* (* x,y,z*))/*h*.

for some small positive *h* but the result is only approximate and this
approximation can be problematic in some cases.

Here is an example ray intersection derivation for the cone defined by

f(x,y,z) = x^2 + y^2 - z^2.

You need to plug the parametric ray

x = x0 + t*xd,

y = y0 + t*yd,

z = z0 + t*zd

into the function, which will yield

(x0 + t*xd)^2 + (y0 + t*yd)^2 - (z0 + t*zd)^2.

Then you need to collect terms with similar powers of t, into

(xd^2 + yd^2 - zd^2)*t^2 + 2.0*(x0*xd + y*yd - z0*zd)*t + (x0^2 + y0^2 - z0^2).

That puts the equation into A t^2 + B t + C form to solve as a quadratic.

The field of graphics has had a chronic problem with the formula for a torus. Pat Hanrahan's solution in "An Introduction to Ray Tracing" had an error. Eric Haines and Larry Gritz came up with a different solution but there's too had an error. Here is the updated solution, from Ray Tracing News 3(7) :

A = (xd^2 + yd^2 + zd^2)^2

B = 4*(x0*xd + y0*yd + z0*zd)*(xd^2 + yd^2 + zd^2)

C = 2*(xd^2 + yd^2 + zd^2)*(x0^2 + y0^2 + z0^2 - R^2 - r^2) + 4*(x0*xd + y0*yd + z0*zd)^2 + 4*R^2*zd^2

D = 4*(x0*xd + y0yd + z0zd)*(x0^2 + y0^2 + z0^2 - R^2 - r^2) + 8*R^2*z0*zd

E = (x0^2 + y0^2 + z0^2 - R^2 - r^2)^2 - 4*R^2*(r^2 - z0^2)

These are the coefficients for the quartic At^4 + Bt^3 + Ct^2 + Dt + E.

You could use the fact that the ray direction is unitized to replace xd^2+yd^2+zd^2 with 1 but doing so prevents you from transforming the torus by applying the inverse transformation to the ray. While translations and rotations do not affect ray direction length, scaling does.