Collision Detection 3 - Ray Plane

Published On April 29, 2012

Ray - Plane

One of the most fundamental algorithms in 3D games is being able to calculate the arbitrary distance between a point with direction and a plane.

A few key concepts to understand is:


You can see we have 4 Vectors:

Ray Origin

– Is where the ray is starting from (I.E the end of the barrel in a gun)

Ray Direction

– Is a normalised vector describing which direction the ray points

Plane Normal

– The inverse slope of the plane in normalised length (similar to the Ray Direction)

Plane Translation(Plane Origin)

– I say translation because if the plane wasn't positioned it would always intersect at the origin, so it has to be moved in the world to where we want our plane to be, Its best not to think it as a point (as the plane has infinite points along it) but a translation of the whole plane from the origin.

Mathematicians at this point would love to get out their algebra and differentiate the equations to find out when these 2 'lines' meet, but it computer graphics it's often way too slow and cumbersome to bother with algebra solving. Instead we stick to the basics of physics and maths.

We start of by using a Dot product:

Basically the dot product can be used to tell us how 2 normalized vectors converge with each other, in that if a dot product gives 0 it means the both vectors are


to each other (I.e. not moving towards one another), if -1 or 1 they are


(Moving towards or away each other at full 'speed'), and all values in-between show the rate at which they are pointing to each other. Remember this is a scalar value, so think in 1 dimension:

If we dot product the


direction with the

Plane Normal

, we get a scalar value of how the direction is moving towards the


, if it is 0 we know the direction is parallel to the


(90 degrees to the plane's normal), and thus the ray will never hit the plane (We can stop the detection here if this is the case). However any value other than 0, the direction vector is moving at that amount towards the plane, and will hit eventually.

Anyone who has experience in physics will know the basic equation of

Distance = Speed * Time.

We can use this to find out when our


is going to hit the plane, if it takes negative time, we know the origin of the


started past the plane and wont intersect it.

But our ray does not have speed?

This is true, but speed is a fancy word for

Rate of change,

so by substituting the scalar value from the dot product, you get the

Rate of changetowards

the plane.

Because of this, it is important to note that Time should not be considered 'time' at all, but rather a value that represents how much 'rate of change' we need to cover a distance (distance/speed).

Now you might think you can get the distance by subtracting the

plane origin


ray origin

. However, the


is infinite in length, and the plane origin is actually just a random point on the plane - which could be anywhere. What we need is the point on the


that is


to the

ray origin

, then we can measure the time it takes to travel this distance.

We can actually skip a step at this stage and directly work out the correct distance to the closest point by using the dot product of the

Plane normal and origins


Like So:

DistanceToNearestPointOnPlane = Dot(PlaneNorm, PlaneO - RayO)

SpeedTowardsPlane = Dot(RayDir,PlaneNorm)

Substituting and rearranging:

T = D/S
Time = DistanceToNearestPointOnPlane / SpeedTowardsPlane

This Time value will now represent the amount of


needed to get between the


and the P


Collision Point

To get the exact point at which the ray hits the plane is easy:

RayOrigin + (Time * RayDir) = Collision Point (XYZ)

The above image shows how the calculation works if Time was equal to 3. The blue dot being the RayOrigin. (It has been flattened into 1 Dimension for illustration)


If your


is of unit length, you can directly compare lambda/time values from multiple Ray-Plane calculations to see which occurs first.

Also this works for 2D lines EXACTLY the same way! just omit the Z value in calculations or leave it 0;

[display-posts category="collision" posts_per_page="-1" include_date="true" order="ASC" orderby="title"]