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:
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
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 ) = (x0,y0,z0) + t (xd,yd,zd ) into f, resulting in f(r(t)). You will find values t0,t1,t2,... that correspond to ray intersections with the algebraic surface. Let x0 = r(t0) be the first of these intersections.
The surface normal at x0 is given by the partial derivatives of f with respect to the coordinates. Hence N = (df/d x,df/dy,df/dz). 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
df(x,y,z)/dx = b + 2 e x + f y + h z ...
df(x,y,z)/dy = c + f x + 2 g y + i z ...
df(x,y,z)/dz = 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
df(x,y,z)/dx = (f(x+h,y,z) - f (x,y,z))/h.
df(x,y,z)/dy = (f(x,y+h,z) - f ( x,y,z))/h.
df(x,y,z)/dz = (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.
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.