Skip to content

Vectors and Normals

James Russell edited this page Apr 9, 2018 · 3 revisions

There are basically two kinds of vectors: a “programming vector” and a “Euclidean vector”.

In programming languages like C++, Python, or GDScript a “vector” is a variable that can hold 2 or more numbers and can be resized at any time. And by “resize” I mean that the computer can change how many numbers the vector can hold while the program is running.

But in trigonometry (and therefore 2D and 3D math) a “Euclidean vector” is basically an arrow that represents a direction and length in 2D or 3D.

Programming Vector

As far as we’re concerned right now, a programming vector is simply a variable that holds a coordinate in two or three numbers. In GDScript it looks like this:

var 2D_Vector = Vector2( 0.1 , 0.5 )
var 3D_Vector = Vector3( 0.5 , 0.2 , 0.7 )

If you were to print the “2D_Vector” variable onto the console it would look like this:

( 0.1 , 0.5 )

This is simply a coordinate. It just tells us a position, like the ones we used in the “Coordinate System” section.

Euclidean Vector

A Euclidean vector is a little different. It’s a component of trigonometry. In trigonometry a vector is basically an arrow that represents a direction and a length. Let’s look at the picture:

The blue arrow is what is called a “Euclidean vector”. Let’s call it “Vector_01”. In GDScript this vector would look like this:

vec Vector_01 = Vector2( 0.91 , 0.39 )

Do you see why this is confusing? Because this is the same as what I called the “programming vector”. But a “programming vector” and a “Euclidean vector” are still technically different. Just remember that when we create a vector in GDScript using “Vector2()” or “Vector3()” we are simply creating a variable that holds two or three numbers that can represent a Euclidean vector or a position.

In the previous picture the blue arrow is a vector. It starts at “(0.0 , 0.0)” and goes to “(0.91 , 0.39)”. But in the code the vector only holds one position:

vec Vector_01 = Vector2( 0.91 , 0.39 )

How can this be an arrow with only one position? The vector always starts at the origin, so there’s no need to specify the starting point.

Also note that in the picture it says that the arrow has a length of “1”. If we were to draw a line from the origin to the position specified in the vector above we would get a Euclidean vector. Then if you got an imaginary ruler and measured the line, it would be 1 unit long.

Normals

A normal is simply a vector with a length of 1. Let’s go back to the previous picture again:

On the bottom of the picture it mentions that the vector has a length of 1. When a vector has a length of 1 it’s considered to be a “normal”.

Let’s say you have a vector that has a length of 2.5. But you want to make it have a length of 1. How can you do so? By a method called “normalization”. Check the “Normalization” chapter for more information on how to normalize your vectors.

The reason you might want a vector to have a length of 1 is so you can find out the direction something is pointing, and if it has a vector length of 1 you don’t have to worry about getting incorrect results. And if you ever need to make it longer, shorter, or add another vector to it you can. For instance in order to get a dot product between two vectors they both need to have a magnitude of 1. You could then use the dot product to get the angle between two vectors.

Another reason you might want a normalized vector is for use with player velocity. Let’s say you have a player that presses the forward button. In order to find out which direction to move the player you need to get the direction the player is facing. In this script you do that by getting the Z axis normal of the transform:

get_global_transform().basis.z

Which might look like this:

In this example picture, the Z axis normal of the player is “(-0.425209 , 0.904983)”. When getting the transform normals they always have a length of 1 unless they have been manually manipulated. If you were to find out the length of this vector with the Pythagorean theorem (discussed at the beginning of the Normalization chapter) we would find the length to be 1.

And from these vectors we are able to find out the angle at which the player is facing in global or local space. So if we were to get the dot product of this normal against a vector that points straight north:

DotProduct = Vector2(-0.425209 , 0.904983).dot( Vector2(0.0 , 1.0) )
DotProduct =  0.904983

Which looks like this:

And if we were to get the angle of the player’s Z axis normal in radians:

Angle_Radians =  0.439457

We would get “0.439457” radians, or ~25 degrees. In Godot when rotating an object a positive number is CCW and a negative number is CW. I don’t know why this is but I’m sure there’s a reason.

Anyway, that’s vectors and normals.