Skip navigation

On Rotation Matrices

A common problem you come across is GIVEN a vector describing a “look” direction, HOW CAN WE MAKE A ROTATION MATRIX THAT WILL “LINE UP” WITH IT? You often want to do something like this when you have a character model that you need to rotate to line up with the direction that the character is currently facing. For example, you are writing a 3d space simulator game and you need the ship’s model to be lined up precisely with the direction the ship is facing.

It turns out, this is easy to do. So easy to do in fact, you’ll kick yourself for not having known this. But it isn’t easy to understand how it works.

So, first, let’s understand the principles of what we’re doing here in 2d, then we’ll extend our answer to 3d.

Rotating something to line up with an object in 2d

Assume you work in a world of vectors. In your 2d game, you need to have the model of your character point in the direction that he is looking.

Have: (red arrow is direction the Triangle character is looking).

But the black triangle and black arrow indicate the stock direction the model faces.


The most obvious way to solve this problem is just a 2d rotation matrix.

Matrix that rotates a point t degrees counter-clockwise:

The Triangle starts with its Heading vector pointing (1, 0). What we need to do is rotate the Heading vector 60 degrees counter-clockwise.

To make a 60 degree CCW rotation, let’s use the CCW rotation matrix, plugging in 60 degrees for the rotation we want:

So we end up with this set of numbers that promise to rotate a set of points 60 degrees counterclockwise:

Now here’s another way to get that same matrix. Are you ready?

The red vector (which points in the direction we want to face) is called the forward vector. The blue vector, we’ll simply call the side vector. ASSUME BOTH THE forward AND side vectors are UNIT VECTORS (THIS IS VERY IMPORTANT!!)

Since we know the forward vector is a unit vector and it has a 60 degree angle with the x-axis, we can express it as:
xfwd = cos( 60 )
= 0.5

yfwd = sin( 60 )
= 0.86

So a unit vector in the plane, when broken down into its x, y components, is always going to be x=cos(t), y=sin(t) where t is the angle that the vector forms with the +x axis.

The blue vector makes (90+60=150) degree angle with the +x axis. So it can be expressed as:
xperpleft = cos( 150 )
= -0.86

yperpleft = sin( 150 )
= 0.5

So, speaking in terms of the orientation we want, we have two vectors:

forward (describes direction we want to look in)=( 0.5, 0.86 )
perpleft (90 degrees counter-clockwise perpendicular to the forward vector) = ( -0.86, 0.5 )

We could also derive the perpleft vector by noticing that ( -y, x ) is always going to be a 90 degree counter-clockwise rotated perpendicular to any vector you have.

side note:
You are sure that (-y,x) is a perpendicular to (x,y) because the dot product:
(x,y)*(-y,x) = -yx + xy = 0

and so, (-y,x) is always perpendicular to (x,y).

The other way to derive this is to construct the 90 degree CCW rotation matrix and notice that it always comes out to

[ cos(90)   -sin(90) ] [ x ]
[ sin(90)    cos(90) ] [ y ]

[ 0   -1 ] [ x ] = [ -y ]
[ 1    0 ] [ y ]   [  x ]

So, look at those again:

forward: ( 0.5, 0.86 )
perpleft: ( -0.86, 0.5 )

Does that look familiar?

So we can do this:

Assuming you use column vectors and not row vectors. If you’re using row vectors, you have to transpose it.

Isn’t that neat?

This extends to 3D:

At this point, I’ll direct you to Diana Gruber’s article and leave it at that.


One Comment

    • Anonymous
    • Posted December 6, 2012 at 4:05 am
    • Permalink

    thats a clockwise rotation matrix ! wrong

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: