Understanding Dot Product (with example)
|| Introduction to the problem
Hi and welcome, I should preface this by saying that the mathematics going into this post has been simplified for easy understanding and proving formulae and theory is not going to be talked over.
So first off, what are we dealing with here? The Dot Product is a mathematical operations that we can use to get outputs regarding the relationship between the vectors we are using them on.
If you’re already familiar, you can skip the next few sections and get to the part where I use it in a code example.
What is a vector / scalar?
To help understand what a vector is, we should start by describing what a scalar is. A scalar is an object with a value or magnitude (size). An example would be a float variable that determines the value for a character in a game. Speed = 100.
Vectors build upon this, they are objects that have not only just a magnitude, but also a direction. Below is an example of a vector U. Its pointing in a diagonal direction due to a positive x and y (i,j) components and has a magnitude (|U|) which we can figure out using vector.
We can calculate the magnitude of this 2D Vector is by using Pythagoras Theorem. We take the value of x² and y² and square root the addition of them both (both x and y are variables of any given value, an example in this scenario would be [5,8]).
What is Dot Product?
Now that we’ve gone over the fundamentals of vectors, we can now start to use them with operations such as Dot Product.
As stated in the introduction, Dot Product is a mathematical operation used to find the relationship between 2 vectors. The result is a scalar value.
There are 2 equations used to find the Dot Product
Equation 1: U • V = |U||V|Cos(θ)
Equation 2: U • V = UxVx + UyVy + (UzVz)*
* Only needed if the Vector is 3D
It is somewhat easy to tell which one seems less complex than the other however I’ll try to breifly explain what each equation is doing.
If you recall earlier, I did mention the |U| symbol and this is a fancy way of saying ‘the magnitude of a (given) vector’. The equation is asking for the magnitude of both vectors and then the Cosine of the angle between the vectors. Here’s a diagram explaining these visually.
With this particular equation, the Cos(θ) is what’s most intriguing and arguably allows you to more or less guess what a relative value of the Dot Product could be. I say this because Cosine of any angle will produce a value in the range between -1 and 1. From trigonometric knowlege, Cos(90) = 0. Therefore when the angle between 2 vectors is 90 degrees, a right angle, both vectors are perpendicular and anything multiplied by 0 is 0.
This means that when the vectors are perpendicular the Dot Product is 0.
Additionally, when the angle is > 90 degrees, as the angle approaches 0 from 90, the cosine value will go from 0 to 1. Therefore the Dot Product will have a positive sign. Alternatively if the angle is <90, the sign will be negative. (However this statement isnt entirely true as it only applies to the range of angles from 0–180, beyond this range the less obtuse angle will need to be used to calculate the Dot Product)
This equation is much simpler on paper, purely because we are multiplying the vectors by their relative components and then adding them together.
This is also the equation that is more commonly used as its much easier to work with as we don’t have to deal with an angle. Both equations ultimately give you the same scalar at the end of the calculations.
Now let’s get on with the fun stuff!
What are some use cases in Game Development?
It’s most commonly used when comparing vectors to see if they meet certain criteria to trigger events, some examples are, if an AI is looking at a player or not, if the player is looking directly at an object such as a cup or a table, if something is behind the player, if the player is moving towards or away from a direction, detecting whether or not a player is either facing downhill or uphill on a slope, etc.
There’s also a very well thought out example from a Naughty Dog GDC where Dot Products are used to calculate clipping for wheels:
Better yet, I’ll give you an example of which I am using in my own project, Primal Dominion: Aftermath.
In this example the function is used to determine how much a character should lean given by its velocity.
Let’s break the following 2 lines down first.
Line 1 I am using multiple operations to calculate the sign (-1/1) of a Dot Product. I am using 2 frames of reference for my vectors, they’re both the velocity of the character but the ‘old’ velocity is 1 frame old, this can give me a different direction and speed when comparing between ticks and thus can tell me which direction the character is going.
0 for idle, -1 for decel, +1 for accel.
On Line 2 I use the sign to determine whether or not to use an accel value or decel value. The syntax is a bit fancy but ultimately means, if Sign > 0 then use Accel, if not use Decel.
Following the code, I then unrotate the character’s worldspace rotation to a scaled local space vector
The last couple lines is then producing the final leaning value which is interpolated to produce a smoother rate of change awell as caching the current frame velocity for the next frame.
Alternatively you can extend this by adding a variable interpolation speed to signify ‘tiredness’ as the character will be faster to slouch into the direction.
Within unreals animation graph, I use that variable and do some small adjustments as the characters in question will lean different amounts. I drive this as an addititive rotation transform on the target bones such as Tail and Spine.
Heres an exaggerated version of the result: