Intersections

We now have a mathematical construct to represent a Ray.

// Our ray
ray = {
  o: (0, 0, 0)
  d: (dx, dy, dz)
}

The purpose of our ray tracer is to calculate whether this ray intersects with objects in our 3D virtual world!

How do we perform this calculation?

Intersection with a sphere

The surface of a sphere can be defined parametrically as a point in space (let's call it c for center) and a radius (r). The surface is the infinite number of points located at r units from the center c.

Consider the following configuration. We want to know if the red ray will eventually intersect the sphere:

How can we do this?

Well, there are certain things we know:

  • We know the origin of our ray: o

  • We know the center of the circle: c.

Knowing these two positions, we can calculate a vector that represents the distance to travel from o to c, using subtraction:

If we project OC onto our ray, we get point P, which will fall somewhere along the ray (the dotted part of the line represents the part of the ray that is beyond the first unit represented by our normalized direction).

Fortunately, it is easy to project one vector onto another normalized vector using the dot product. Imagine we have one vector d and another n. To project vector d onto normalized vector n, we use the formula:

proj(d,n)=(dˉnˉ)nˉproj(d,n) = (\bar{d}\cdot\bar{n})\bar{n}

The dot product is easy to calculate :

Thus, in our example, the projection can be calculated as follows:

Thus, op is the vector that takes us from o to p.

To calculate the actual value of P, we start from the origin of our radius and add our vector!

That's great, but how does knowing the position of p help us? If it is inside the sphere, we know that it undoubtedly intersects it. How can we tell if it is inside the sphere? It's simple! If the distance between c and p is less than or equal to the radius of the sphere!

How do you calculate the distance between two points? Well, you calculate the movement required to go from one to the other (subtraction), and you calculate the length of this vector (Pythagoras).

Great! We know there is an intersection! How do we find the exact intersection point p1?

We already know the length of cp, we know the value of r, and so using Pythagoras we can calculate the length of p -> p1 (let's call it a).

To obtain position P1, simply move back a units along our initial radius, but in the opposite direction:

There you go!

Now that we know the exact position of P in the world, we can start determining the color of the surface at that point!

Here is a pseudo-code summary of the calculations needed to calculate the intersection point:

circle-check

Note on the dot product

The dot product between two vectors is a very interesting and useful value.

Spatial relationship

If both vectors are normalized, the scalar product is equal to the cosine of the angle between the two vectors.

dˉnˉ=cosθ\bar{d}\cdot\bar{n}= \cos{\theta}

Why is this useful? Well, without having to calculate the angle θ, we can deduce things about the relationship between the two vectors.

The graph shows that:

  • if the scalar product = 1, then we are at 0°. Both directions are oriented in the same direction

  • if the scalar product = 0, then we are at 90°. Both directions are perpendicular.

  • if the scalar product > 0, the graph is somewhere between 0° and 90°, so it must be an acute angle

  • if the scalar product < 1, the graph is somewhere between 90° and 270°, so it must be an obtuse angle.

In the previous example, we wanted to know if the sphere was in front of the ray (and not behind it). The angle between our ray and the direction towards the center of the sphere must therefore be an acute angle. We calculate the dot product between these two (normalized) directions, and if it is negative, we know that it is an obtuse angle, and therefore that the sphere must be behind us!

Angle

We can, of course, obtain the angle (in radians) between the two directions using the inverse cosine:

θ=arccos(dˉnˉ)\theta = \arccos({\bar{d}\cdot\bar{n}})

This method returns a value between 0 and 2π. However, it does not return negative numbers, so we cannot tell whether the angle between the two vectors is to the left or to the right.

circle-info

How do you convert radians to degrees?

degrees=radians180/πdegrees = radians * 180/\pi

Projection

The dot product between an unnormalized vector and a normalized vector gives us the length of a projection of the unnormalized vector onto the normalized vector.

What is a projection?

Imagine that you are projecting light perpendicularly onto the normalized vector. The shadow of the other vector on the normalized vector is the projection!

Imagine we have a vector d and another vector n (which is normalized). To project vector d onto vector n, we use the formula:

proj(d,n)=(dˉnˉ)nˉproj(d,n) = (\bar{d}\cdot\bar{n})\bar{n}

Intersection with a plane

An infinite plane can be expressed parametrically as follows

  • suppose we have a point c in space, and a normal vector n

  • the plane is the set of points p where the vector pc is perpendicular to the normal n.

In the diagram, we assume that p is also on our ray. If the direction of the ray is normalized, we just need to find a multiplier t for this ray that will resize it enough to bring us to p.

pˉ=oˉ+tdˉ\bar{p} = \bar{o} + t\bar{d}

We don't know what t is yet—we have to calculate it!

But we need more information.

Looking at the diagram, we can also deduce that if p is on the plane, then the line pc must be perpendicular to the normal n. Fortunately, the dot product is our friend again! Indeed, if the dot product between two normalized vectors is 0, it means that the two vectors that created it are perpendicular!

(pˉcˉ)(nˉ)=0(\bar{p} - \bar{c})\cdot(\bar{n}) = 0

Let's replace p in our radius with the formula for the plane:

(oˉ+tdˉcˉ)nˉ=0(\bar{o} + t\bar{d} - \bar{c})\cdot\bar{n} = 0

Multiply the dot product:

oˉnˉ+tdˉnˉcˉnˉ=0\bar{o}\cdot\bar{n} + t\bar{d}\cdot\bar{n} - \bar{c}\cdot\bar{n} = 0

Solve for t:

tdˉnˉ=cˉnˉoˉnˉt\bar{d}\cdot\bar{n} = \bar{c}\cdot\bar{n} -\bar{o}\cdot\bar{n}
tdˉnˉ=(cˉoˉ)nˉt\bar{d}\cdot\bar{n} = (\bar{c} -\bar{o})\cdot\bar{n}
t=(cˉoˉ)nˉdˉnˉt = \frac{(\bar{c} -\bar{o})\cdot\bar{n}}{\bar{d}\cdot\bar{n}}

So we have a relatively simple formula for calculating t!

Let's first calculate the denominator:

If the denominator is zero or close to zero, this means that our radius is perpendicular to the normal, i.e., the radius is parallel to the plane and will never intersect it!

Next, let's calculate the numerator:

Now that we have t, we can calculate point p by substituting it into our radius formula:

All together :

Last updated