Cylinder intersection

For the first time in a while I’ve added a new primitive type to the raytracer. The more I’ve messed about with procedural geometry the more I’ve become frustrated by the limit of building objects out of cubes and spheres. The remaining obvious primitive type is the cylinder. Once this is added to a raytracer you can make all kinds of fun rounded shapes. More on this later.

First of all though, lets look at the maths of tracing an arbitrary ray with an arbitrary cylinder. The first simplification is to get rid of the arbitrary bit about the cylinder. As discussed in this article about transformations a major simplification comes about by translating the ray so that you only need to calculate the intersection with a primitive based at the origin.

Intersecting a ray against a cylinder with a radius of 1, based at the origin, and one unit high, is a much simpler task. In fact, it simplifies right down to two dimensions. As described in Neil Dodgson’s raytracing cribsheet, the ray tracing algorithm just needs to check the ray in two dimensions against a circle centred at the origin. The formula for a circle is

Next up we order the values of t so that they're in ascending order and calculate the y value at the two intersection points with the circle. Note that the x and y discussed in the formulae are actually x and z when you convert everything into a 3d raytracer. Hence why y is the height of the intersection point.

So far we've worked out that the ray intersects a two dimensional circle if we eliminate the y coordinate. Now we can start to look at three dimensions to work out whether or not the ray intersects the cylinder.

We're raytracing against a capped cylinder with caps at y = 1, and y = -1, so there are now five different possibilities for intersections.

if y0 >1, and y1 >1, then the ray misses the cylinder entirely.

if y0 >1, and y1 <1, then the ray hits the cylinder cap placed at +1.
if y0 <1 and y0 >-1, then the ray intersects the side of the cylinder.