Navigation: DirectX 9.0

Tutorial 4 - 3D Vectors


Overview

3D Vectors are extremely useful in 3d games and I think simple vector math is fun! I want to make this a crash course for anyone who doesn't really get them. And I will also go over some functions provided by the d3dx9 library to help you make the most of them.

What is a Vector?


Figure 8.


Simply put, a 3d vector is an x,y and z value. In DirectX we use the D3DXVECTOR3 structure to hold an x,y and z value, for example:

D3DXVECTOR3 MyVector;
MyVector.x = 0;
MyVector.y = 0;
MyVector.z = 0;

This sets x to 0, y to 0 and z to 0.

A vector is also a line, because if you draw a line from the position 0,0,0 to x,y,z, you have a line.

Direction

Because we can represent a line by an x,y,z value, we can say that a vector has a direction. The direction of a vector is from the start of the vector 0,0,0 to the end of the vector x,y,z. Like an arrow pointing in some direction.

Magnitude

You can think of a vector as a line pointing in some direction, or an arrow. The length of the arrow is called it's magnitude. We can use the following formula to get the magnitude of a vector:

length = sqrt(x^2 + y^2 + z^2);

Or:

length = sqrt(x*x + y*y + z*z);

You can also use the D3DX function D3DXVec3Length() to get the length of a vector:
D3DXVECTOR3 V(1,5,7);
float length = D3DXVec3Length(&V);

Adding


Figure 9.


If you have a 3d point, P, and you move it by a vector, v1, it will have moved by the length of the vector in the direction the vector is pointing.

To move a point, (x,y,z) by a vector you simply add the x, y and z of the vector to the point for example:

New P = P + v1:

New P x = Px + v1x;
New P y = Py + v1y;
New P z = Pz + v1z;

In code you could have:
D3DXVECTOR3 P(5,7,1);
D3DXVECTOR3 v1(2,-1,0);
D3DXVECTOR3 NewP = P + v1;

Subtracting

If you subtract a vector from a point P, P will have moved in the opposite direction of the vector by the length of the vector.

If you subtract a 3d point, P1 from P2 (P2 - P1), you get a vector that points from P1 to P2 (See Figure 10.).


Figure 10.

Multiplying

If you multiply the x,y and z components of a vector by some amount, this has the same effect as increasing or decreasing it's magnitude. For example v1 x 2 will double the length of the vector, v1, or v1 x 0.5 will halve the length of the vector, v1. It's direction will remain unchanged unless you multiply by a negative value, it's direction will be reversed.

Unit Vectors (Normalized Vectors)

Unit vectors are vectors that have length 1. By using a unit vector you can represent any direction as a vector of length one, and transform a point P so P moves in that direction and here's the clever bit, you can decide how far P moves in that direction by multiplying the vector by the distance you want P to move.

Unit vectors are also called Direction Vectors for this reason.

You can turn any vector into a direction vector by dividing it's x,y and z components by it's length. For example:

DirectionVector.x = V.x / magnitude;
DirectionVector.y = V.y / magnitude;
DirectionVector.z = V.z / magnitude;

A vector of length 1 is said to be a normalized vector.

Equation of a Circle

Here is a very useful equation I learned when I started out as a programmer. It can let you control the direction you want something to travel in. For example, say you have a car in a game and you want to change the direction it is travelling in - You can use this equation to produce a direction vector that you can use to make a car travel in whatever direction you want:
x = cos(angle);
y = sin(angle);

if angle is 0, x will be 1 and y will be 0. Remember to convert degrees to radians for cos and sin functions. D3DXToRadian(degree). When angle is 90, x will be 0 and y will be 1. Therefore, angle 0 - 360, will produce a circle that starts at the x axis, where y is 0 and x is 1 and moves in a clockwise direction as angle increases from zero to 360, provided positive Y points down-the-way.

Then, when you supply an angle to this equation you get a direction vector, (x,y). You could do the same thing for the x and z axis if working in 3d, for example, to rotate around the Y axis, set y to 0, and use the following equation:
x = cos(angle);
z = sin(angle);
y = 0;
Plug-in the angle and you get a direction vector.

You can then make an object move along that direction vector by the distance you want it to travel.

Angle Between Vectors

There are other useful properties of vectors such as something called the dot product of two vectors, A and B is equal to length of A x length of B x cos(theta):
A . B = lengthA*lengthB*cos(theta)

The dot product is simply a number calculated as follows:
float DotProduct = (x1*x2 + y1*y2 + z1*z2)

We can rearrange the equation above to get the angle between two vectors:
cos(theta) = (A . B)/(lengthA*lengthB);

theta = acos((A . B)/(lengthA*lengthB));

Where theta is the angle between the two vectors. In fact the 360 degree angle between two vectors can be found by this function:
float Get360AngleBetweenVectors(float x1, float y1, float x2, float y2)
{
	float dot = x1*x2 + y1*y2;
	float det = x1*y2 - y1*x2;
	float angle = atan2(det, dot);
	return D3DXToDegree(angle);
}

Cross Product

The Cross Product is a vector given by two other vectors, or in 2 Dimensions, one other vector. It is a vector perpendicular to the other two vectors or another vector. For example, a perpendicular vector is a vector at right angle(90degrees) to another vector:

Figure 11.

In two dimensions, the cross product is equal to (-y, x)

D3DX Functions

Finally, to conclude this tutorial, here are some useful functions from the d3dx library(d3dx9.h):
D3DXVECTOR3 V1;
D3DXVECTOR3 V2;
float dotProduct = D3DXVec3Dot(&V1, &V2);

D3DXVECTOR3 CrossProduct;
D3DXVec3Cross(&CrossProduct, &V1, &V2);

float length = D3DXVec3Length(&V1);

D3DXVECTOR3 DirVector;
D3DXVec3Normalize(&DirVector, &V2);