Ray tracing to general second order surfaces

First, let's look at a special case: ray tracing to an unit radius cylindrical tube.

The implicit function for a unit diameter infinitely long cylindrical tube along the z axis is:

x2 + y2 - 1 ≤ 0
We can solve the ray equation manually, like we did for the sphere, as follows:

  • Substituting in V+tW for (x,y,z):
    (Vx + t Wx)2 + (Vy + t Wy)2 - 1 ≤ 0
  • Expanding out:
    (Wx2 + Wy2) t2 + (2 Vx Wx + 2 Vy Wy) t + (Vx2 + Vy2 - 1) ≤ 0
  • Which just equals:
    (WW) t2 + 2(VW) t + (VV - 1) ≤ 0
  • So to solve the quadratic equation in t:
    A = WW
    B = 2 (VW)
    C = VV - 1

But this doesn't give us the ability to transform the cylinder, nor would it generalize to other quadratic shapes, including cones, paraboloids and hyperboloids.

So instead, let's work on the general case of being able to transform any implicit quadratic function by a 4×4 matrix, and then ray trace to the transformed surface described by that transformed function.

The general second order implicit surface:

Any quadratic implicit surface can be expressed as follows:

ax2 + by2 + cz2 + dyz + ezx + fxy + gx + hy + iz + j ≤ 0
The ten coefficients of this equation can be stored as a vector:
[a, b, c, d, e, f, g, h, i, j]
The unit sphere, the infinite unit cylinder and the infinite unit cone, respectively, can all be expressed in such a form:
Sphere: x2 + y2 + z2 - 1 ≤ 0 [1, 1, 1, 0, 0, 0, 0, 0, 0, -1]
Cylinder: x2 + y2 - 1 ≤ 0 [1, 1, 0, 0, 0, 0, 0, 0, 0, -1]
Cone: x2 + y2 - z2 ≤ 0 [1, 1, -1, 0, 0, 0, 0, 0, 0, 0]
Raytracing to a general second order implicit surface:

Ray tracing to a general second order surface just requires substituting the ray into this ten-coefficient equation to get a quadratic equation in t, exactly as we did above in the case of the cylinder:

  • Substituting in V+tW for (x,y,z):
    a(Vx+tWx)2 + b(Vy+tWy)2 + c(Vz+tWz)2 + d(Vy+tWy)(Vz+tWz) + e(Vz+tWz)(Vx+tWx) + f(Vx+tWx)(Vy+tWy) + g(Vx+tWx) + h(Vy+tWy) + i(Vz+tWz) + j ≤ 0
  • Expanding out:
    a(Vx+tWx)(Vx+tWx) + b(Vy+tWy)(Vy+tWy) + c(Vz+tWz)(Vz+tWz) + d(Vy+tWy)(Vz+tWz) + e(Vz+tWz)(Vx+tWx) + f(Vx+tWx)(Vy+tWy) + g(Vx+tWx) + h(Vy+tWy) + i(Vz+tWz) + j ≤ 0
  • Rearranging terms:
    (aWx2 + bWy2 + cWz2 + dWyWz + eWzWx + fWxWy) t2 + (2aVxWx + 2bVyWy + 2cVzWz + d(VyWz+VzWy) + e(VzWx+VxWz) + f(VxWy+VyWx) + gWx + hWy + iWz) t + (aVx2 + bVy2 + cVz2 + dVyVz + eVzVx + fVxVy + gVx + hVy + iVz + j) ≤ 0
  • So to solve the quadratic equation in t:
    A   = aWx2 + bWy2 + cWz2 + dWyWz + eWzWx + fWxWy
     
    B   = 2(aVxWx + bVyWy + cVzWz) + d(VyWz+VzWy) + e(VzWx+VxWz) + f(VxWy+VyWx) + gWx + hWy + iWz
     
    C   = aVx2 + bVy2 + cVz2 + dVyVz + eVzVx + fVxVy + gVx + hVy + iVz + j


Applying a linear transform to a second order surface

Let us first review the simpler case of linear surfaces: Half space P = (a, b, c, d) contains point p = (x,y,z), if and only if ax + by + cz + d ≤ 0. This can also be expressed as the product:

a b c d   •   x
y
z
1
  ≤   0

or, in other words, L pT ≤ 0. To find the plane that contains transformed points MpT, you need to replace L with LM-1.

Similarly, we can express quadratic equation

ax2 + by2 + cz2 + dyz + ezx + fxy + gx + hy + iz + j ≤ 0
as the following double product:

x y z 1   •  
af eg
0b dh
00 ci
00 0j
  •   x
y
z
1
  ≤   0

or in other words, p Q pT = 0, where Q denotes the 10 quadratic coefficients arranged into the above 4×4 matrix.

This means that if you want to find the three-variable quadratic equation that contains transformed points MpT, you need to replace Q by   (M-1)T Q M-1   because that will give you:

(M pT)T     (M-1)T Q M-1     (M pT)     =

pT MT     (M-1)T Q M-1     M pT     =

p Q pT

when you create the product of

(M-1)T P M-1
you can end up with non-zero values in all sixteen slots of your 4×4 matrix. This is because in addition to x*y, x*z, x*1, y*z, y*1, z*1 terms, you also end up with y*x, z*y, 1*z, z*y, 1*z, 1*z terms, as follows:
x*x x*y x*z x*1
y*x y*y y*z y*1
z*x z*y z*z z*1
1*x 1*y 1*z 1*1
Since multiplication of numbers is commutative, you can just add the six numbers in the lower left (shown in magenta above) into their mirror locations on the upper right, as follows:
AE IM
BF JN
CG KO
DH LP
    →
AE+B I+CM+D
0F J+GN+H
00 KO+L
00 0P
This will leave you with just the ten unique coefficients of the quadratic in three variables, in the upper right of your transformed matrix.

Computing the surface normal:

Once you have computed your transformed values for [a,b,c,d,e,f,g,h,i,j], you can use high school differential calculus to compute its vector valued derivative:

f(x,y,z) = ax2 + by2 + cz2 + dyz + ezx + fxy + gx + hy + iz + j

f'(x,y,z) = [  2ax + ez + fy + g  ,  2by + dz + fx + h  ,  2cz + dy + ex + i  ]

Just normalize this derivative to get the normal at the surface point:
N = normalize(f'(x,y,z))