Applications of the dot product
Here you can see the full diagram of the dot product! In the following, we will explore, how these parts can be used for various operations.
In all of the following visualizations, you can move around any points (gray circles) with your mouse.
Introduction
I have seen a few people without a background in math or computer science struggling with writing code for game scripts. While having comprehensive understanding of math isn't needed, I feel that grasping the basic concepts can spare you a lot of problems.
This small course aims to show you some basic operations of the dot product that might be usable in a game development context. Each section will contain some explanations, interactive diagrams and formulas to give you all you need get started. Additionally, I will try to list problems, that can be solved with the given operation. Semi formal proofs are also given, so if you want a slightly deeper understanding about how something works, you can check those out.
Generally, all the diagrams can be manipulated in some way by dragging the marked points to show you visually and with calculations what is happening.
The two basic geometric properties associated with the dot product are distances and angles, which makes it usable in many contexts. Basically, every time you have a problem involving any of these two properties, there is a good chance, the dot product is involved in one way or another.
I will always suggest drawing the geometry you are interested in! For example, your character will send out an energy wave in an arc with some extent. Now, when you draw this on a page, you might quickly see, that it looks very similar to the diagram in the section about cones! Then you already have a quick recipe to get a base implementation.
If you just only find some more insight into what the dot product means, then I am already happy with the results!
With that, let's get going!
Basics
Before we start with the actual applications, let's just recap the basics.
We will write vectors in bold face like . We will use only 2D vectors here, but all the formulas work in any dimension (3,4, ...), as aside from computing the value of the dot product itself, we won't need any coordinates. We will write coordinates of a vector in a normal font with the coordinate as a subscript to the vector name. For example, the x-coordinate of is written as .
This will not be a full introduction into vectors, but as a quick recap:
-
A vector can be represented as an arrow with a length and direction
- A vector has no position, so you can draw it anywhere
- You can draw it, by starting at a point and then moving along the coordinate axes with the distance for each given by the vector coordinates
-
You can add () and subtract () two vectors, by adding and subtracting each component
- Adding a vector to another vector geometrically corresponds to attaching to the tip of . The result is then the vector from the start of to the tip of
- Subtracting is like addition, just that you attach in the opposite direction
-
You can scale a vector by a number (a so called scalar) :
- Geometrically, this corresponds to stretching the length of the vector by , leaving its direction unchanged. Though if is negative, the vector will point in the opposite direction
-
Points are often treated just like vectors, but generally you should think about them like a vector attached to the origin
- To get a vector from a point to a point , you calculate
In the following, we only have to deal with one angle, the angle between two vectors. We will write it, if needed, as (alpha). The angle between two vectors is the smallest angle between them, which is when they coincide and when they point in opposite directions. You can see this below.
When writing out angles, we will generally use degrees here, as many may not be that familiar with radians, but I highly advise you to get comfortable with radians, as it is the unit that math functions work with. If you mix the two units, you might run into very hard to track bugs.
The dot product will be written with a dot between two vectors. So the dot product of and is
There are two equivalent definitions of the dot product:
(For higher dimensions, you would just add more terms for the appropriate coordinate in the sum)
Here, denotes the length of a vector (we don't use to make it easier to read). This is computed as the square root of the sum of all squared components of a vector, so for 2D it is (Pythagoras!):
You can think about the two definitions as follows:
is used to "mechanically" compute the value of the dot product, as we only need to know vector coordinates. It is more of a helper function. In pretty much all game engines and programming languages/libraries that support vectors, you will also have a function, that does this for you, usually just called 'dot' (or 'Dot', as can be seen in Unity).
is used when we want to think about the geometric meaning of the dot product, as it contains both distances (the lengths) and the angle.
From this, we can already gather a few computation rules already.
Since , the order of the vectors doesn't matter.
This is called the commutative property.
It is a bit tedious, but from the first definition, we can see that:
We will quickly verify this with a 1D vector (only x-coordinates), but you can try to prove it yourself by adding y or z or any number of coordinates.
This is called bilinearity, which is just a fancy way of saying that you can do scalar multiplication outside the dot product or inside and that addition can get split into two dot products (just like with normal numbers).
As a quick reminder, here is a visualization of one way to define the cosine (and sine) of an angle:
If we imagine a unit circle (circle with radius 1) and choose the point on the circle corresponding to the angle , then the x-coordinate of that point is the cosine and the y-coordinate is the sine of that angle.
We will see a very similar image in the different operations again.
That is basically all we really need here, so let's get started with the applications.
If you are curious, the full geometry of the dot product can be seen in the following diagram. The dot product can be visualized as the area spanned by the projection of one vector onto another (covered here) and the length of that other vector. When either or both vectors have length 1, you can find some useful special cases!
Angle/Cosine of angle between two vectors
Applications
-
Checking, how close one viewing direction is to another one
- Calculate the angle or cosine and test, whether the value is smaller/larger than some threshold
-
Compute terms in lighting calculations, such as Phong shading
- The cosine often appears in lighting, as it represents the portion of light arriving at a surface with a normal from some direction
-
As this is a very basic property, it is used in many of the following operations as well
Procedure - Find the angle/cosine of the angle between and
- Compute the length of both vectors:
- Compute the dot product:
- The cosine of the angle is:
- (OPTIONAL) The angle is:
- Depending on the language and use case, it might be a good idea to clamp the values of the cosine to the range (
clamp(a.dot(b)/(a.length()*b.length()),-1.0,1.0)). Mathematically, the result will never exceed that range, but due to the way numbers work in a computer, sometimes, the values might be very very slightly smaller or larger, which theacosfunction does not like
In many cases, it is useful to have some idea about angles between vectors. For example, let's say you want an interface, where you can specify the direction in which to throw a paper plane. For calculations or information UI, you might want to find the angle to the ground or the optimal throwing direction.
So our goal is to find the shortest angle between two vectors. Though, in many cases, we don't actually need the angle itself, as the cosine is enough. For example, we want to check, whether the angle is smaller than some maximum angle . We can instead just use for comparisons. The cosine starts at its highest value at and decreases until the highest angle (Note: The actual cosine function does extend past this range, but we will only get these angles). So if we want to express , we can instead use . The diagram will make the shape of the cosine with respect to the angle a bit clearer.
As this operation is very general, it is part of many others. Thus the most direct applications listed above are comparing directions and just computing cosine terms directly, as they come up a lot in shading calculations.
Derivation
Since we have , we can get the cosine by dividing through the equation.
Length of a vector
Applications
- Checking, how close one point is to another
- Checking, which vector is larger than another
Procedure - Find the (squared) length of a vector
- Compute the dot product:
- The squared length is equal to the value of step 1:
- (OPTIONAL) The length is:
Distance is something that comes up all the time. Is an object in range? How strong is the influence of a power up at a far away point? What is the closest enemy?
We already know, how to compute the length of a vector, but when multiplying a vector by itself using the dot product, we actually get the squared length, which is in many cases all we need. For example, if you want to check, whether a vector's length is smaller than some value . You can express this as ( is also possible) As both sides of this inequality are greater than zero, we are allowed to apply a square operation on both sides. Thus we have:
Of course, you can do the same with a greater sign.
This allows you to skip a whole square root operation, which today isn't much, but if you do it a lot it might still cost some computation power.
One obvious application, is checking whether a point is less than a certain radius away from another point. For example, if you want to check, whether a player is in the influence area of some item that has a specified radius. Let the player be at position , the item at and the radius be . Then we can apply the above.
Let be the vector from the item to the player. If , then the player is influenced by the item, otherwise not.
You can see this in the diagram below.
Derivation
We know that the length of a vector is computed as .
The dot product is:
For other dimensions, this is the same. For example in 3D, we have . In the dot product, the z-term is added as well, so the result will be the same.
Actually, in some math contexts, the length is just defined via the dot product!
Check, if a vector lies in a cone
Applications
- Checking, whether a player is in the vision cone of an enemy
- Checking, if a spotlight shines in a specified direction
- Check, if your arc shaped attack hits an enemy
Procedure - Check, whether a vector lies in a cone with direction , maximum opening angle and radius .
If your cone does not have a maximum radius, you can skip step 1). You could also add a minimum radius by adding a second distance check with a or check instead
-
Compute the squared distance of :
- If , vector is outside
- Otherwise, it is inside the radius. We also need to check the angle
-
Compute the cosine of the angle between and :
-
Compute (can be precomputed, if it doesn't constantly changed)
- If , vector is outside
- Otherwise, it is inside the angular constraint
-
If either the distance or angular constraint said, the vector is outside, it is outside. Otherwise it is inside (you can early return at step 1.1)
This operation is basically just a combination of the distance check and the cosine angle calculation. As mentioned in the latter, instead of checking , we can instead use .
Let's say, we have our player character at position and the enemy at . The enemy is looking in a direction , has a field of vision (half angle) of and can see units far. The vector from the enemy to the player is . Using this and the above procedure above, we can determine, whether the enemy can spot us!
You can see this scenario in the diagram below.
Derivation
This is a consequence of the previous entries distance check and angle calculation.
Checking, if two vectors point into the same half space
Applications
-
Checking, whether two objects are moving towards/away from each other
-
Compute the relative position of both objects
-
Compute the relative velocity of both objects (movement direction):
-
If , then the objects are moving away from each other, otherwise they are moving towards each other
-
-
Checking, whether an object is in front of a wall
-
Take the normal describing the direction of the wall and a point on the wall
-
Compute the vector from to the object position :
-
If , then the object is in front of the wall, otherwise it is behind
-
-
Check, whether the light shines on the back or front side of a surface
Procedure - Check, whether a vector points in the same or opposite half space of (and vice versa)
-
Compute the dot product
- If both vectors point into the same half space
- If both vectors point into opposite half spaces
- Otherwise ( ) both vectors are perpendicular to each other
A vector can divide space into points pointing in the same half space, the opposite one or being perpendicular. In 2D, this means, this division line can be visualized as a line perpendicular to the vector. In 3D it is a plane and in higher dimensions it is a hyperplane.
Intuitively you can think about a compass. Let's take north as our vector direction. Then north-east and north-west point into the same half space (north itself of course also points in the same one). east and west are perpendicular. south, south-east and south-west all point in the opposite half-space.
We can also formulate this with angles. If the angle between two vectors is less than , they point in the same half space. If the angle is exactly , they are perpendicular. Otherwise (the angle is greater than ), they point in opposite half spaces.
The above procedure is very efficient, as it only requires a single dot product.
You can see this in the diagram below:
Derivation
If you have a look at the diagram in the angle section, you can check out the ranges of the cosine for the angles between the vectors. Importantly, these angles are only in the range .
For , we see that . For , and for the rest .
So to determine, which half-spaces the vectors point into, we just need to check the sign of the cosine.
The dot product is . But and are both zero or positive, so they have no influence on the sign of the dot product! That means, we don't need to divide by the vector lengths to get the sign of the cosine and we can skip that computation.
Projection of one vector onto another
Applications
- A player in 2D moves along a slanted terrain, whose ground is defined by a direction. Which part of the player's movement direction points in the ground direction
- For a simple racing game you define the track by different line segments and want to show the player position on a mini map. The player is not exactly on that line! How far along the closest line segment is the player? This is the projection of the player position on the line segment!
Procedure - Project a vector onto a vector
-
Compute the dot product
-
The projection is:
- Note: If is normalized (), then you can skip the division. Sometimes, you know the length beforehand, for example, if you enforce it via code or generate it via special means.
Projecting a vector onto another vector means: How much of points into the direction of . In other words. We draw a line perpendicular to that goes through the tip of . Where that line intersects is the tip of the projection of . Like the shadow of onto .
Let's say you have a line segment between two points and . The vector between them is . This could be a segment of a racing game track. The player is at position . How far along the way from to is the player? This is the projection! You can compute the vector (so both and have the same reference point). With this, the above procedure gives us the projecti
Derivation
We can think about the definition of the cosine in the unit circle again, as seen in the basics
Now, let's say we are not in the unit circle, but instead one with radius . What happens to the coordinate? Well, the circle will basically look the same, but it is scaled with a factor of ! The coordinates are, of course, scaled as well, so the x-coordinate is instead of .
The x-coordinate is just the circle point projected onto the x-axis.
Now, let's say our vector corresponds to the x-axis and to the vector to the circle point. The angle of that point is the angle between the two vectors. The radius is just the length of : .
Plugging that into the scaled circle x-coordinate results in: . This is just the dot product divided by !
Thus our projection of onto is:
The last line results from just being a number, so we can move it into the dot product due to its property of linearity.
Additionally, this means, the projection of a vector onto a normalized vector is just the dot product!
We can see this in action in the following diagram.
Decomposing a vector with respect to another
Applications
- While moving on a surface, determine the movement vector on the surface plane and the part pointing outside of it
- Constrain something to only walk along a line or plane
Procedure - Decompose a vector with respect to into a vector parallel to () and one perpendicular to (, such that
- Compute the dot product
- Compute the projection vector of onto :
- Compute the perpendicular projection vector :
In the previous section, we found th projection of a vector onto another vector . This is just an extension to that. Instead of just computing the length of the projection, we also want the vector corresponding to it, so a vector with the length of the projection pointing in the same direction as . And from the previous diagram, there is another vector: The perpendicular part from the tip of the projection to the tip of .
How can this be useful? First of all, having the direction in addition to the length allows you to show the projection itself. Let's say you have a spaceship game, where the ship can move in all directions. Let's say you fly to the right and there is a vertical wall. If you keep going in the same direction, the wall will block you so you don't move at all. But if the wall is angled, you will expect to keep moving, but maybe not with the same speed, since you are still partially pressing into the wall. And maybe you want to bounce your player a bit away from the wall when they ram into it. You could handle all the specific wall angles, or you could decompose the vector into the part pointing along the wall normal and the other one being in the wall plane. Movement is then only the part in the wall plane and the bounce happens in the direction of the normal. This is of course a simple scenario, but an actual implementation can be very similar to this (and a physics based solution is also very similar)!
You can see the decomposition in the diagram below:
Derivation
From the previous section, we know how to compute the projection of a vector onto another (which is a signed length).
To get a vector with that length pointing in the same direction as , we just need to normalize and multiply it with the length of the projection.
We then compute the perpendicular part as described in the procedure: .
As was constructed to point into the same direction as , we know they are parallel. But we also need to show, that really is perpendicular to .
For that we use the dot product rule from the section about half spaces. The dot product must be zero.
Thus, really is perpendicular to !
Just as a formality, we show, that we can reconstruct from its decomposition: