May 29, 2015

Exploring the Cross Product and Dot Product

One of the more confusing areas of the math behind 3D game design has been the use of cross products and dot products.  I've had it explained often to me, but it has always been in terms of pure mathematical usage and things don't often "click" when I hear them described by formulas and graphs.

The use of these two is important to understand, as they are used to "move" objects and characters around a 3D scene using player controlled inputs and a controlled, bounded scene.

Dot Product
The Dot Product can be found many times in physics engines and lighting systems more than the game itself, but has uses in all areas.  Firstly, remember that Vectors can be used to describe a position in space as well as a magnitude in change of direction.  The Dot Product is going to describe magnitude of a change in position of two vectors.  What this means is that you are going to take two vector types and get a single floating point number in return.

Here is a simple example: Let's say we want to calculate the intensity of light on an object.  The intensity is a single floating point number, right?  This number could be multiplied on an RGB object to apply the intensity, but it is one number.  So, our formula is going to take two direction vectors and return a single intensity value, a number we will call <light intensity>.

To get this one number, we can take two vectors from our 3D scene to calculate it.  Our first vector will be the position of a point on the object we want to test for intensity.  This specific vector is the normalized value of the surface position.  Normalization of a vector is another process you'll need to find out more about later, but for simplicity you can think of this as a direction vector that points straight out of the surface of the object we are trying to light.  If we think of this in terms of variables in code <surface point>.normalize() gives us <surface normal>.

The next vector we need for our formula is the direction from the point on the surface to our light source.  Because we want the light source to have an effect on the intensity, its position needs to be part of the formula.  This is vector distance, so remember all we have to do is subtract the two to find this distance.  Light position vector minus surface point vector (from above) gives us the <point-to-light direction>.

Our final formula is going to look like this, <surface normal> dot <point-to-light direction> = <light intensity>.  We can now use this light intensity to multiple the color values RGB to yield a final color to draw.  This process is the basics of what a lighting shader will do automatically for you in most 3D game engines.

Another usage of a dot product could be to find if an object is parallel to a planar surface.  This would be using the result as an angular result, instead of intensity like in the previous example.  Take the up vector of a plane dot with the forward vector of an object (the direction it is "looking").  If the result is 0, then both are facing the same direction.

One last game related example, a pad on a racetrack that boosts your race car.  The vector direction of your race car dot the forward vector direction of the boost pad will give you the intensity of the boost.  If your race car cross the boost pad perpendicular, then no boost is given to the card.  If the race car crosses the pad in the same direction as the boost, then you get maximum intensity delivered to the boost.  Conversely, if the race car crossed the pad backwards it would slow the car down, possibly to a stop or reverse.

Let's recap in shorthand:
Our formula is vector dot vector = angle number of two vectors.
The math behind this is: (v1.x * v2.x) + (v1.y * v2.y) + (v1.z * v2.z).

Cross Product
A Cross Product is used quite a bit in the actual game mechanics of moving objects around.  The Cross Product is going to take two vectors like the Dot Product does, but it will produce a new vector.  This new vector will be perpendicular to the first two vectors.  Also, order of operations matter for Cross Product as reversing the order will produce a direction vector pointed in the opposite direction of the first product.  Like adding and subtracting two vectors, this is the multiplication operation of two vectors.

A simple example: I have a character that I need to turn to the right.  I know the direction vector for forward and I know the direction vector for up.  Using a cross product I can find the right direction.

So, we take them as such <forward vector> * <up vector> = <right vector>

Another example, I have a ball in my 3D scene that just got kicked and we want it to hit a wall and slide along that wall (no physics bouncing).  I know the direction the ball is traveling and I know the normal vector of the plane that represents the wall.

So, we take the cross of those two things we know: <ball direction vector> * <wall plane normal> = <temporary vector>.  Notice I have named our result temporary vector.  That is because it is not the complete answer for the ball to slide along the wall, it is the vector perpendicular to the normal of the plane and the interruption of the ball if it were to travel through the wall.  To get the answer we want, we need to do one more cross product operation.  Take the temp and cross with the plane normal again: <temporary vector> * <wall plane normal> = <ball slide direction>.  And, now we have a direction vector that the ball may travel along.

You may also use this technique to take the dot product of two vectors (which would be the angle between the two vectors) and then the cross product to tell you which axis the dot product is rotating around.

Let's recap this in shorthand:
Our formula is vector x vector = perpendicular vector.
The math behind this is more complex than the dot product:
result.x = (v1.y * v2.z) - (v2.y * v1.z)
result.y = (v2.x * v1.z) - (v1.x * v2.z)
result.z = (v1.x * v2.y) - (v2.x * v1.y)

In closing, understanding these two operations is important to understanding movement and placement of objects and their relations.  Searching the internet will get you more mathematical explanations and images that can visual demonstrate the concepts.  I wanted to give more practical examples of their usage in game design.

May 28, 2015


For some time now, I've wanted to start a blog around one of my biggest hobbies, game design.  Game design can sometimes be a pretty mysterious place and I've had the opportunity to learn quite a bit in my time doing it.  I'll write up entries on things that I have learned or found difficult over the years and hopefully someone will find this useful.  This will include things like tools I've used, technique in programming, procedural methods, "How'd they do that" posts, and 3D Math examples.  The posts will stay mostly from a programming point of view, but I'll have to do some art posts eventually (art is my kryptonite).

When it comes to comments I'll probably try and keep to myself unless someone asks a specific question I can answer.

Enjoy reading and hopefully you'll learn something from it.