Fall 2006»CSCI 299 Vectors

CSCI 299 Vectors

Vectors for Game Development and Data Visualization

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.)

Introduction

(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.

Operations on Vectors

(adopted from VPython Reference Manual)

Addition, Subtraction, Multiplication, Division

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)
 

Accessing Components

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
 

Magnitude

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
 

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)
 

Normal

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)
 

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

Products and Angles

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)
 

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
 

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)
 

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)
 

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.

Rotation

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)
 

Useful Things You Can Do With Vectors

Position of Object

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!)
 

Velocity of Object

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
 

Bouncing Off the Wall

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)
 

Sources

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