This section is intended to give you a working knowledge of vectors, so that you may apply it in the context of game development and data visualization. (This material is compiled from various sources as noted.)

(adopted from The Game Programming Wiki)

Vectors are an essential part of graphics, physics, game logic and even a lot of AI for games. They are not very complicated but to use them effectively you'll need to know a few things.

A *point* is a position in space. A *vector* has *direction* and *magnitude*. The two are distinct concepts but have the same representation, so they are often confused. It is common to use vectors to represent both, since a point can be thought of as a vector starting from the origin.

In game programming most points and vectors will have 2 or 3 dimensions, but occasionally they may have 4. Points and vectors may be written as *(x,y)* or *(x,y,z)*. In VPython points and vectors are represented as `vector(x,y)`

or `vector(x,y,z)`

, where *x, y,* and *z* are floating-point numbers.

(adopted from VPython Reference Manual)

Vectors can be added to or subtracted from each other. Also they can be multiplied or divided by an ordinary number (a scalar). For example,

v1 = vector(1,2,3)

v2 = vector(10,20,30)

print v1 + v2 # outputs (11, 22, 33)

print v1 - v2 # outputs (-9, -18, -27)

print v1 * 2 # outputs (2, 4, 6)

print v1 / 2 # outputs (0.5, 1, 1.5)

v2 = vector(10,20,30)

print v1 + v2 # outputs (11, 22, 33)

print v1 - v2 # outputs (-9, -18, -27)

print v1 * 2 # outputs (2, 4, 6)

print v1 / 2 # outputs (0.5, 1, 1.5)

You can refer to individual components of a vector:

v = vector(10,20,30)

print v.x, v.y, v.z # outputs 10 20 30

print v.x, v.y, v.z # outputs 10 20 30

If the vector represents a point, the **magnitude** of the vector represents the (Euclidean) distance of the point from the origin. You can refer to the square of the magnitude:

v = vector(1,1,1)

print mag(v) # outputs 1.7320508075688772, which is the same as sqrt(1**2 + 1**2 + 1**2), i.e., sqrt(3)

print mag2(v) # outputs 3, the magnitude squared

print mag(v) # outputs 1.7320508075688772, which is the same as sqrt(1**2 + 1**2 + 1**2), i.e., sqrt(3)

print mag2(v) # outputs 3, the magnitude squared

You can access (and modify!) the magnitude of a vector `v`

using `v.mag`

, and the square of the magnitude using `v.mag2`

:

v = vector(1,1,1)

print v # outputs (1, 1, 1)

print v.mag # outputs 1.7320508075688772, which is the same as sqrt(3)

v.mag = 5 # set magnitude of v to 5

print v # outputs (2.88675, 2.88675, 2.88675)

print v # outputs (1, 1, 1)

print v.mag # outputs 1.7320508075688772, which is the same as sqrt(3)

v.mag = 5 # set magnitude of v to 5

print v # outputs (2.88675, 2.88675, 2.88675)

An important operation on vectors is **normalization**. In essense, this scales a vector of any direction and magnitude to a vector with the same direction and magnitude of 1.

v1 = vector(4,5,6)

print mag(v1) # outputs 8.77496438739

n1 = norm(v1) # get the normal vector

print mag(n1) # outputs 1.0

print n1 # outputs (0.455842, 0.569803, 0.683763)

# another example

v2 = vector(4,-5,0.06)

print mag(v2) # outputs 6.40340534403

n2 = norm(v2) # get the normal vector

print mag(n2) # outputs 1.0

print n2 # outputs (0.624668, -0.780835, 0.00937001)

print mag(v1) # outputs 8.77496438739

n1 = norm(v1) # get the normal vector

print mag(n1) # outputs 1.0

print n1 # outputs (0.455842, 0.569803, 0.683763)

# another example

v2 = vector(4,-5,0.06)

print mag(v2) # outputs 6.40340534403

n2 = norm(v2) # get the normal vector

print mag(n2) # outputs 1.0

print n2 # outputs (0.624668, -0.780835, 0.00937001)

**Note:** It is illegal to normalize vector (0,0,0), since this involves division by zero (i.e., `norm(v1) = v1 / mag(v1)`

).

The **angle** between two vectors, v1 and v2, is given by `v1.diff_angle(v2)`

(in radians).

v1 = vector(1,0,0) # vector coincides with x axis

v2 = vector(0,1,0) # vector coincides with y axis (vertical to v1)

radians = v1.diff_angle(v2)

print radians # outputs 1.5707963267948966 (i.e., pi/2 radians == 90 degrees)

degrees = radians * 180/pi # convert to degrees

print degrees # outputs 90.0

v3 = vector(-1,0,0) # vector coincides with negative x axis (opposite of v1)

print v1.diff_angle(v3) # outputs 3.1415926535897931 (i.e., pi radians == 180 degrees)

v2 = vector(0,1,0) # vector coincides with y axis (vertical to v1)

radians = v1.diff_angle(v2)

print radians # outputs 1.5707963267948966 (i.e., pi/2 radians == 90 degrees)

degrees = radians * 180/pi # convert to degrees

print degrees # outputs 90.0

v3 = vector(-1,0,0) # vector coincides with negative x axis (opposite of v1)

print v1.diff_angle(v3) # outputs 3.1415926535897931 (i.e., pi radians == 180 degrees)

**Note:** The following conversion formulas might come in handy:

`radians = degrees * pi/180`

`degrees = radians * 180/pi`

The **dot product** of two vectors, v1 and v2, is given by `dot(v1, v2)`

. This is a number equal to the product of the magnitudes of the vectors, times the cosine of the angle between the two vectors.

v1 = vector(3,4,5)

v2 = vector(5,6,7)

print dot(v1,v2) # outputs 74.0

dotProduct = mag(v1)*mag(v2)*cos(v1.diff_angle(v2))

print dotProduct # also outputs 74.0

v2 = vector(5,6,7)

print dot(v1,v2) # outputs 74.0

dotProduct = mag(v1)*mag(v2)*cos(v1.diff_angle(v2))

print dotProduct # also outputs 74.0

If you take the dot product of two normalized vectors, you can get the angle between the vectors using acos(dotProduct).

If the two vectors are normalized, the dot product gives the cosine of the angle between the vectors. That's another way to get the angle between the two vectors (i.e., use `acos(dotProduct)`

).

v1 = vector(3,4,5)

v2 = vector(5,6,7)

dotProduct = dot(norm(v1), norm(v2))

print dotProduct # outputs 0.998... (i.e., the cosine of their angle)

print cos(v1.diff_angle(v2)) # outputs 0.998... (yeap!)

print acos(dotProduct) # outputs 0.066... (i.e., the angle in radians)

print v1.diff_angle(v2) # outputs 0.066... (the same)

v2 = vector(5,6,7)

dotProduct = dot(norm(v1), norm(v2))

print dotProduct # outputs 0.998... (i.e., the cosine of their angle)

print cos(v1.diff_angle(v2)) # outputs 0.998... (yeap!)

print acos(dotProduct) # outputs 0.066... (i.e., the angle in radians)

print v1.diff_angle(v2) # outputs 0.066... (the same)

A nice property of the dot product is that if you multiply one of the vectors by the cosine of the angle, you get the projection of the other vector onto that vector.

If the dot product is 0, the two vectors are at 90°. If the dot product is positive, the angle between the vectors is less than 90°. If its negative, the angle is greater than 90°.

Using **normalized** vectors, if the dot product is 1, the vectors are parallel and in the same direction. If the dot product is -1, the normalized vectors are parallel but in the opposite direction.

The **cross product** of two vectors, v1 and v2, is given by `cross(v1, v2)`

. This is a vector perpendicular to the plane defined by the two vectors, in a direction defined by the right-hand rule: if the fingers of the right hand bend from v1 toward v2, the thumb points in the direction of the cross product. The magnitude of this vector is equal to the product of the magnitudes of v1 and v2, times the sine of the angle between the two vectors.

v1 = vector(2,0,0) # vector coincides with x axis

v2 = vector(0,2,0) # vector coincides with y axis

print cross(v1,v2) # outputs (0, 0, 4) (vector coincides with z axis)

v2 = vector(0,2,0) # vector coincides with y axis

print cross(v1,v2) # outputs (0, 0, 4) (vector coincides with z axis)

The cross product of two vectors corresponds to the area of the parallelogram they form. This can be used to calculate the areas and volumes of artifacts.

To **rotate** a vector v1 around a vector v2 for a given angle use `rotate(v1, angle, v2)`

.

v1 = vector(1,0,0) # vector coincides with x axis

v2 = vector(0,0,1) # vector coincides with z axis

# rotate v1 across the z axis 90 degrees

v3 = rotate(v1, pi/2, v2)

# rotate v1 across the z axis 180 degrees

v4 = rotate(v1, pi, v2)

print v3 # outputs (6.12303e-017, 1, 0), approx. (0, 1, 0)

print v4 # outputs (-1, 1.22461e-016, 0), approx. (-1, 0, 0)

v2 = vector(0,0,1) # vector coincides with z axis

# rotate v1 across the z axis 90 degrees

v3 = rotate(v1, pi/2, v2)

# rotate v1 across the z axis 180 degrees

v4 = rotate(v1, pi, v2)

print v3 # outputs (6.12303e-017, 1, 0), approx. (0, 1, 0)

print v4 # outputs (-1, 1.22461e-016, 0), approx. (-1, 0, 0)

You can use a vector to store the **position** of an object in space (2D, 3D, etc.). In this case, the magnitude is the distance from the origin.

s.pos = vector(2,3,4) # location of spaceship in 3D space

print mag(s.pos) # outputs 5.38... (distance of spaceship from origin)

s.pos = s.pos + vector(2,3,4)

print s.pos # outputs (4, 6, 8)

print mag(s.pos) # outputs 10.77..., (spaceship has moved!)

print mag(s.pos) # outputs 5.38... (distance of spaceship from origin)

s.pos = s.pos + vector(2,3,4)

print s.pos # outputs (4, 6, 8)

print mag(s.pos) # outputs 10.77..., (spaceship has moved!)

You can use a vector to store the (instantaneous) **velocity** of an object. In this case, the magnitude of the vector is the (instantaneous) **speed** of the object. The normal of the vector is the **direction** of the object.

s.pos = vector(2,3,4) # location of spaceship in 3D space

s.velocity = vector(-5,2,1) # velocity of spaceship

s.speed = mag(s.velocity) # speed of spaceship (displacement per unit time)

s.direction = norm(s.velocity) # direction of spaceship

print mag(s.pos) # outputs 5.38..., spaceship's distance from origin

s.pos = s.pos + s.speed * s.direction # move spaceship at this speed and direction

print s.pos # outputs (-3, 5, 5)... spaceship has moved!

print mag(s.pos) # outputs 7.68..., spaceship's new distance from origin

# But s.speed * s.direction == s.velocity, since mag(v)*norm(v) == v, thus...

s.pos = s.pos + s.velocity # ... has the same effect

print s.pos # outputs (-8, 7, 6)... spaceship has moved!

print mag(s.pos) # outputs 12.20..., spaceship's new distance from origin

s.velocity = vector(-5,2,1) # velocity of spaceship

s.speed = mag(s.velocity) # speed of spaceship (displacement per unit time)

s.direction = norm(s.velocity) # direction of spaceship

print mag(s.pos) # outputs 5.38..., spaceship's distance from origin

s.pos = s.pos + s.speed * s.direction # move spaceship at this speed and direction

print s.pos # outputs (-3, 5, 5)... spaceship has moved!

print mag(s.pos) # outputs 7.68..., spaceship's new distance from origin

# But s.speed * s.direction == s.velocity, since mag(v)*norm(v) == v, thus...

s.pos = s.pos + s.velocity # ... has the same effect

print s.pos # outputs (-8, 7, 6)... spaceship has moved!

print mag(s.pos) # outputs 12.20..., spaceship's new distance from origin

To bounce an object off a plane, get a vector perpendicular to the plane (see cross product above). Use this vector, v, as the axis to rotate the velocity vector of the object 180 degrees.

velocity = vector(3,4,5) # velocity of object

perVector = vector(-1,0,0) # vector perpendicular to plane y,z

newVelocity = rotate(v1, pi, v2)

print newVelocity # outputs (3, -4, -5)

perVector = vector(-1,0,0) # vector perpendicular to plane y,z

newVelocity = rotate(v1, pi, v2)

print newVelocity # outputs (3, -4, -5)

- The Game Programming Wiki, Vector.
- Wikipedia, Vector (spatial), October 10, 2006.
- VPython, The vector Object, Reference Manual.
- Bram de Greve, 3D Geometry Primer: Vector Arithmetic, August 21, 2000.
- Johan van Mol, Bouncing off sloped walls, September 10, 2006.
- Alex Diener, Vector Tutorial.
- Alex Diener, Quaternions Tutorial - representing 3D rotations.
- Sparknotes SAT Physics, Speed, Velocity, and Acceleration.
- Biosolid Mechanics: Modeling and Applications - application
- Alan Buzbee, Vectors, Students of Game Design.

(Printable View of http://www.cs.cofc.edu/~manaris/?n=Fall2006.CSCI299Vectors)