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:
- The plane is infinite in length
- Unless the ray is parallel to the plane, the ray will eventually hit the plane (due to it being infinitely long)
- Despite the guarantee of hitting the plane the ray still may hit the plane behind the point you started your ray from.
You can see we have 4 Vectors:
– Is where the ray is starting from (I.E the end of the barrel in a gun)
– Is a normalised vector describing which direction the ray points
– 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 areperpendicular
to each other (I.e. not moving towards one another), if -1 or 1 they areparallel
(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 theRay
direction with thePlane Normal
, we get a scalar value of how the direction is moving towards theplane
, if it is 0 we know the direction is parallel to theplane
(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 ofDistance = Speed * Time.
We can use this to find out when ourRay
is going to hit the plane, if it takes negative time, we know the origin of theRay
started past the plane and wont intersect it.
But our ray does not have speed?
This is true, but speed is a fancy word forRate of change,
so by substituting the scalar value from the dot product, you get theRate of changetowards
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 theplane origin
. However, theplane
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 theplane
to theray 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 thePlane normal and origins
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 ofRayDir
needed to get between theRayOrigin
and the Plane.
- If its negative, the Ray origin was behind the plane, and so the Ray does not intersect the plane
- If it is positive, a collision occurs, at this value along the ray.
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)
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"]