Some time ago I needed to solve analytically the intersection of a ray and a cone. I was surprised to see that there are not that many resources available; there are some, but not nearly as many as on the intersection of a ray and a sphere for example. Add to it that they all use their own notation and that I lack math exercise, after a bit of browsing I decided I needed to write a proof by myself to get a good grasp of the result.
So here goes, the solution to the intersection of a ray and a cone, in vector notation.
- We define a ray with its origin
and its direction as a unit vector .
Any point on the ray at a signed distance from the origin of the ray verifies: .
When is positive is in the direction of the ray, and when is negative is in the opposite direction. - We define a cone with its tip
, its axis as a unit vector in the direction of increasing radius, and the half angle between the axis and the surface.
Any point on the cone verifies: - Finally we define
the intersection or the ray and the cone, and which we are interested in finding.
We can multiply the second equation by itself to work with it, then reorder things a bit.
Remember the mouthful earlier about
We replace
Reorder a bit:
There we go, we have our
From there, you know the drill: calculate the determinant
- If
, the ray is not intersecting the cone. - If
, the ray is intersecting the cone once at . - If
, the ray is intersecting the cone twice, at and .
But wait! We don’t have one cone but two, so we have to reject solutions that intersect with the shadow cone.
Note that there is also the corner case of the ray tangent to the cone and having an infinity of solutions to consider. I’ve completely swept it under the rug since it doesn’t matter in the context I was, but if it does to you, you’ve been warned about it. Also remember to check the sign of
Now for a little sanity test, let’s consider the corner case
I also tried the cases
Finally, to demonstrate that the result is indeed correct, here is a glorious ray traced cone scene on ShaderToy:
I hope this can prove useful to others too.
Oh, and Happy New Year by the way!