# Thread: working with rotation matrices

1. ## working with rotation matrices

I have a rotation matrices, and I have to do a few things with it.
If the matrix represents the rotations around three axis,

1) how do you apply the rotation around 1 axis to another matrix ?
for example : I want one matrix to have only the y-rotation of the other matrix. For example, when I want a 3rd person camera.

2) how do you set the rotation around a specific axis to a value. But without touching the rotations around the other axis ?
For example, when I want a camera to look at a specific height.

2. Basically, the problem is to separate the different rotations of a matrix into rotation around the X-, Y- and Z-axis.

Here's one way, perhaps not the most efficient there is.

Take a vector v = (v1,v2,v3) (= (1,1,1) for example), and apply the rotation matrix to it:
u = (u1,u2,u3) = A*v

To calculate the X-rotation of A, calculate the angle between the projections of v and u to the YZ-plane.

v' = (0,v2,v3)
u' = (0,u2,u3)

Use v'*u' = |v'||u'|cos a to calculate the angle a, which is the rotation around the X-axis. You'll need to determine if the rotation is negative or positive too.

1) Use the above method to extract the Y-rotation and create a new matrix.

2) Extract the rotations and create a new matrix with one rotation changed.

3. Construct the X, Y, and Z rotation matrices. Multiply them together (concatenate them). This is your final rotation matrix. Multiply this by the translation matrix. Multiply this by the scaling matrix. This is your world matrix.

Multiply every vertex by the world matrix. Multiply this by the clip matrix. Multiply this by the view matrix. Multiply this by the projection matrix. Divide all vertices by their w component. Render.

Yet again I will post the matrices here. These are for Direct3D, left- handed matrices. You will have to change them somewhat for OpenGL. But I should mention some of this is available in our tutorials section.

Do a search. Read the tutorial on matrices for OpenGL. And you can also go to www.gamedev.net or www.gamasutra.com for very thorough explanations of these matrices, how they work, how to derive them, and why they work.

X rotation matrix
1,0,0,0
0,cos,sin,0
0,-sin,cos,0
0,0,0,1

Y rotaton matrix
cos,0,-sin,0
0,1,0,0
sin,0,cos,0
0,0,0,1

Z rotation matrix
cos,sin,0,0
-sin,cos,0,0
0,0,1,0
0,0,0,1

Translation matrix
1,0,0,0
0,1,0,0
0,0,1,0
dx,dy,dz,1

Scaling matrix
sx,0,0,0
0,sy,0,0
0,0,sz,0
0,0,0,1

Identity matrix
1,0,0,0
0,1,0,0
0,0,1,0
0,0,0,1

Projection matrix

Prepares for division by W - does not actually divide by W.

1,0,0,0
0,1,0,0
0,0,1,1/d
0,0,0,0

Projection divide - actually divides by W
[x,y,z,w]=[x/w,y/w,z/w]

Scale in arbitrary direction

Scale by factor of k in direction of unit vector n

S(n,k)=

1+(k-1)*(n.x*n.x),(k-1)*n.x*n.y,(k-1)*(n.x*n.z)
(k-1)*n.x*n.y,1+(k-1)*n.y,(k-1)*n.y*n.z
(k-1)*n.x*n.z,(k-1)*n.y*n.z,1+(k-1)*(n.z*n.z)

Axis-angle rotation matrix

Rotate theta radians around unit vector n.

R(n,theta)=

(n.x*n.x)*(1-cos)+cos,n.x*n.y*(1-cos)+n.z*sin,n.x*n.z*(1-cos)-n.y*sin
n.x*n.y*(1-cos)-n.z*sin,(n.y*n.y)*(1-cos)+cos,n.y*n.z*(1-cos)+n.x*sin
n.x*n.z*(1-cos)+n.y*sin,n.y*n.z*(1-cos)-n.x*sin,(n.z*n.z)*(1-cos)+cos

Projection onto cardinal axis or plane

XY plane
1,0,0
0,1,0
0,0,0

XZ plane
1,0,0
0,0,0
0,0,1

YZ plane
0,0,0
0,1,0
0,0,1

Projection onto arbitrary line or plane
P(n)=S(n,0)

1-(n.x*n.x),-n.x*n.y,-n.x*n.z
-n.x*n.y,1-(n.y*n.y),-n.y*n.z
-n.x*n.z,-n.y*n.z,1-(n.z*n.z)

Shearing matrices

Shear by factor of s and t respectively

XY shear
1,0,0
0,1,0
s,t,1

XZ shear
1,0,0
s,1,t
0,0,1

YZ shear
1,s,t
0,1,0
0,0,1

Reflection

Reflect about a plane through the origin perpendicular to unit vector n

1-2*(n.x*n.x),-2*n.x*n.y,-2*n.x*n.z
-2*n.x*n.y,1-2*(n.y*n.y),-2*n.y*n.z
-2*n.x*n.z,-2*n.y*n.z,1-2*(n.z*n.z)

Clip

winPhysX=winResX*pixPhysX*devResX
winPhysY=winResY*pixPhysY*devResY

zoomx=winPhysX
zoomy=winPhysY

zoom=1/(tan(fov/2))
fov=2*atn(1/zoom)

Projection divide:
[x,y,z,w]=[x/w,y/w,z/w]

Direct3D
zoomx,0,0,0
0,zoomy,0,0
0,0,(far/far-near),1
0,0,(far*near)/(near-far),0

OpenGL
zoomx,0,0,0
0,zoomy,0,0
0,0,(far+near)/(far-near),1
0,0,(2*near*far)/(near-far),0

Transform to screen space

ScreenX=((ClipX*winResX)/2*ClipW))+winCenterX
ScreenY=((ClipY*winResY)/2*ClipW))+winCenterY

Standard lighting

X - denotes component wise multiply

Light=Specular+Diffuse+Ambient

Specular

V - vector that points towards viewer
N - surface normal
L - points towards light source
R - reflection vector - reflecting l about n
H - halfway vector between V and L (for Blinn only)

theta - angle between r and v

All vectors are unit vectors.

PhongSpecular=((V dot R)^mGloss)*SourceSpecular X MaterialSpecular

BlinnSpecular=((N dot H)^mGloss)*SourceSpecular X MaterialSpecular

Diffuse lighting
Diffuse=(N dot L)*SourceDiffuse XMaterialDiffuse

Light attenuation

(i1/i2)=(d2*d2)/(d1*d1)

(dmax-d)/(dmax-dmin)

Final equation:

Light=i(max(N dot H,0)^mGloss*SourceSpecular XMaterialSpecular+max(N dot L,0)*SourceDiffuse X MaterialDiffuse)+GlobalAmbient X MaterialAmbient

Fog
Light=final color of pixel after lighting computation (from above)
f = fog density
FogColor=color of fog
FinalColor=final result of fog computation

FinalColor=Light+f*(FogColor-Light)

That should give you enough info to write a small rendering engine with any API and/or use vertex/pixel shaders to do the lighting.

If you don't want Y rotation included in your rotations, either zero it's members out in the world matrix (set them to identity 0,1,0,0) or don't include the Y rotation in your concatentation. Matrix multiplication or concatenation is cumulative.

I would highly recommend the book 3D Math Primer for Graphics and Game Development by Fletcher Dunn and Ian Parberry. It is published by WordWare in their Game Math library series and is available at www.amazon.com. All of this information and more is available in that book.

Please rate this thread or bring it to a mod's attention so they can either sticky it or put it in an easy to find place. I don't want to re-type all that.

4. Nice work Bubba, just a couple things differ from the way i learned them...

Y rotaton matrix
cos,0,sin,0
0,1,0,0
-sin,0,cos,0
0,0,0,1

Translation matrix
1,0,0,dx
0,1,0,dy
0,0,1,dz
0,0,0,1

Projection matrix
1,0,0,0
0,1,0,0
0,0,1,0
0,0,1/d,0

5. If I understood his question right, he already had a given rotation matrix and he needed to extract the Y-rotation from that matrix. His second problem was that he needed to change the rotation around one axis without changing the other two.
Originally Posted by Bubba
That should give you enough info to write a small rendering engine with any API and/or use vertex/pixel shaders to do the lighting.
What? Just posting matrices and formulas won't help anyone learning anything. Good reference though.

6. I'm just completely confused...he only asked for help with rotation matrices.

Please rate this thread or bring it to a mod's attention so they can either sticky it or put it in an easy to find place. I don't want to re-type all that.
*WHY* didn't you type it for a sticky in the first place? 90% of what you posted doesn't belong here dude, no offense.

7. I posted it all here even though it's not completely relevant because I'm sick of these types of questions when this information is all over the game programming board, all over www.gamedev.net, www.gamasutra.com, www.google.com, and even in our tutorials section which can be linked to from the main page.

Anything to do with rotation matrices or any matrices for that matter is somewhere on this board already which means no board search has been done on the topic and also means that google has not been used.

That's why.

I'll remove it if need be or perhaps put it in a completely different post so it can be stickied.
Do a search. This type of matrix question has been asked 10,000 times over.

1) how do you apply the rotation around 1 axis to another matrix ?
for example : I want one matrix to have only the y-rotation of the other matrix. For example, when I want a 3rd person camera.

2) how do you set the rotation around a specific axis to a value. But without touching the rotations around the other axis ?
For example, when I want a camera to look at a specific height.
Both of these question lend credence to the fact that the OP does not understand anything about matrix math or concatenation and that being true the OP has no business attempting to rotate anything anywhere. Learn the matrix math first, then you will understand how to use them and how they can be combined and used for transformations. No offense intended at all but you must learn matrix math before you just start plugging and chugging numbers into them.

Because you stated these questions the way you did, I know you do not understand how they work.

1) how do you apply the rotation around 1 axis to another matrix ?
for example : I want one matrix to have only the y-rotation of the other matrix. For example, when I want a 3rd person camera.
A 3rd person camera has nothing to do with the Y rotation or whatever it is you are talking about. It has to do with 3 basis vectors - up,look, and right. You rotate using the axis angle rotation matrix to arrive at your final matrix. You use the camera view matrix that we just computed as your view transformation matrix for the entire scene.

I want one matrix to have only the y-rotation of the other matrix.
I have no idea what you mean. Matrix math is cumulative. Each result can then be used in a chain of other matrices to produce new results and a new matrix.

2) how do you set the rotation around a specific axis to a value. But without touching the rotations around the other axis ?
For example, when I want a camera to look at a specific height.
Set your rotations by using three variables to represent x,y and z rotations. If you don't want to rotate around the other axes, then set their values to 0.0f and they won't rotate. You are building one rotation matrix from all this, not 3 different ones. When you multiply the three together you are creating one. But most of the time you don't want to multiply the three together - you can also derive an xyz rotation matrix from the information I gave you so that one matrix multiplication will rotate around x,y, z correctly and with no gimbal lock. Height has nothing to do with rotation. Height has to do with the Y value of the camera. The only time that height comes into play is if you are translating the camera away from the origin. The height of the camera then during an X rotation or rotation about the vertical is equal to the sine of the distance you translated from the origin.

There is also a class for a 3rd person camera on this board. I would recommend buying a book that explains this much better than I can in this small post.

8. I have to agree with Bubba here, I dont think his post was out of line at all in this case. This is the third question ive seen about the same(ish) thing in about a week. We need full explanations like this to point to so we don't end up answering the same question over and over.

9. One of the things the original poster tried to do was, given a rotation matrix A, extract the rotations around the X- Y- and Z-axis. Perhaps it has no practical use, but it could be seen as a mathematical exercise.

Here's how to do it (I typed it in MATLAB beause I didn't have a matrix library for C++ available)

A is a rotation matrix created by matrix multiplication of the X,Y and Z (in that order) rotation matrices.

Code:
```% 3x3 Rotation matrix A
%
% A is created by the rotation matrices
% A = Ax * Ay * Az
function [rx,ry,rz] = getRotationXYZ(A)

%Get the X-axis rotation
v  = [0; 0; 1];
u  = A * v;
rx = atan2(u(2),u(3))
%Remove the X-axis rotation from the matrix
Ax = [1 0 0;0 cos(rx) sin(rx); 0 -sin(rx) cos(rx)];
A = Ax' * A;
%Get the Y-axis rotation
v  = [1; 0; 0];
u  = A * v;
ry = atan2(u(3),u(1))
%Remove the Y-axis rotation from the matrix
Ay = [cos(ry) 0 -sin(ry); 0 1 0; sin(ry) 0 cos(ry)];
A = Ay' * A;
%Get the Z-axis rotation
v  = [0; 1; 0];
u  = A * v;
rz = atan2(u(1),u(2))```
The atan2 exists in C++ as well. This is perhaps not the most efficient way to do it, but it seems to work very well for the matrices I tried.

10. I posted it all here even though it's not completely relevant because I'm sick of these types of questions when this information is all over the game programming board, all over www.gamedev.net, www.gamasutra.com, www.google.com, and even in our tutorials section which can be linked to from the main page.

Anything to do with rotation matrices or any matrices for that matter is somewhere on this board already which means no board search has been done on the topic and also means that google has not been used.

That's why.
First of all you're wrong here. Before I asked this question here, I've spent more that a day searching for an answer. Maybe I didn't use the right keywords, or something like that, but anyway I didn't find an answer to the two questions I posted. Don't say I didn't try. I did try google, gamedev and this board.

Secondly, in the two posts you made, you didn't give me an answer to any of my two questions. And no, I don't want to use an already existing camera class. I'm trying to learn everything the hard way by doing it my way.

Sang-drax :

11. First of all you're wrong here. Before I asked this question here, I've spent more that a day searching for an answer. Maybe I didn't use the right keywords, or something like that, but anyway I didn't find an answer to the two questions I posted. Don't say I didn't try. I did try google, gamedev and this board.

Secondly, in the two posts you made, you didn't give me an answer to any of my two questions. And no, I don't want to use an already existing camera class. I'm trying to learn everything the hard way by doing it my way.
Extracting rotations from a matrix can be found in any matrix math discussion and the book I mentioned also shows how to do it. If you use atan, acos, or asin it will be deathly slow.
Search: extracting x,y,z rotations from a matrix

6th one down leads you here.

http://www.idevgames.com/forum/archi...hp/t-5085.html

Search:matrix math

As I said gamedev pops up almost immediately in that search.
http://www.gamedev.net/reference/art...article877.asp

A whole day eh?

The well known tutorial available on this board:
http://www.cprogramming.com/tutorial/3d/theBasics.html

Board search: matrix math
http://cboard.cprogramming.com/searc...earchid=149951

Board search: rotation matrices
http://cboard.cprogramming.com/searc...earchid=149951

I clicked on one of the posts and they led me to about ten other links related to math, 3D rotations, etc.

12. After reading all those links, and looking at the google searches you provided, I still didn't come up with a useful answer.

Sang-drax :
The algorithm you provided works in a few cases, but in many cases it doesn't. I already noticed that the algoritm gives wrong results when y or z is between - (Pi / 2) and (Pi / 2).

I could solve this if I knew if the angles lie either
between 0 and Pi / 2 or
between Pi / 2 and PI or
between - (Pi / 2) and 0 or
between Pi and - (Pi / 2)

I tried for more than an hour on paper, but I didn't find how to do it.

13. The original questions you asked are not difficult and can be accomplished with simple matrix mathematics. Perhaps you ought to explain in more detail what it is exactly you need to do.

I have first person camera classes up and running without gimbal lock issues and that adjust for ground objects and flying objects. I can also point the camera at any spot in 3D space, hence I can do flyby views, etc. The camera can rotate and move around/on any axis you choose.

14. I'll try to explain clear what exactly I want to do.

I want to be able to break up a rotation matrix into 3 matrices.
So, if R is given, I want to get RX, RY, and RZ.

I need to do this because I want my camera to follow the object that I move. To position the camera well, I use the following code :
cam->posx = object->posx - object->rot[2] * 5.0f;
cam->posz = object->posz + object->rot[10] * 5.0f;

So what I do is position the camera 5 units behind the object.

For giving the camera the correct rotation, I want to give it the same rotation around the y-axis. So if I rotate my object around the x-axis, I don't want my camera to rotate around the x-axis too. Same for z.

Another thing I want to do is to look at my object from preset views. I want to let the 'player' be able to choose from these presets. What I need to do for that is adjust the height of the camera, and its rotation arount the x-axis. So what I want to do is to let the camera keep its rotation around the y( and z )-axis, but set its x-rotation value to for example 40 degrees.

I hope I explained it clearly now.

edit : btw, the algoritm that sang-drax gave to split the rotation matrix into 3 matrices works well, except that I need to know for each angle if it lies :
between 0 and Pi / 2 or
between Pi / 2 and PI or
between - (Pi / 2) and 0 or
between Pi and - (Pi / 2)

15. Well if you start with a rotation matrix with all the values in it, I'm almost positive that rotation can be inverted. Take the inverse of the matrices you want to 'remove' from the final matrix and multiply the final matrix by these matrices. This will get you back to the original matrices.

Also you could use a matrix stack. Put each rotation in a separate matrix, like X,Y and Z. When you multiply one matrix by another, push the resulting matrix onto a stack. To effectively undo the previous concatentation you only need to pop the stack to arrive at your original matrix or the previous matrix in the chain.

But your real problem is that you are approaching the problem the wrong way. You don't need to orient your camera using 3 separate distinct rotations. At best this will result in huge gimbal lock, and at worst it will completely fall apart. I will show you some code from my camera class to illustrate.

Code:
```void Camera::pitch(float angle)
{

D3DXMATRIX T;
D3DXMatrixRotationAxis(&T, &_right,	angle);

// rotate _up and _look around _right vector
D3DXVec3TransformCoord(&_up,&_up, &T);
D3DXVec3TransformCoord(&_look,&_look, &T);
}

void Camera::yaw(float angle)
{
D3DXMATRIX T;

// rotate around world y (0, 1, 0) always for land object
if( _cameraType == LANDOBJECT )
D3DXMatrixRotationY(&T, angle);

// rotate around own up vector for aircraft
if( _cameraType == AIRCRAFT )
D3DXMatrixRotationAxis(&T, &_up, angle);

// rotate _right and _look around _up or y-axis
D3DXVec3TransformCoord(&_right,&_right, &T);
D3DXVec3TransformCoord(&_look,&_look, &T);
}

void Camera::roll(float angle)
{
// only roll for aircraft type
if( _cameraType == AIRCRAFT )
{
D3DXMATRIX T;
D3DXMatrixRotationAxis(&T, &_look,	angle);

// rotate _up and _right around _look vector
D3DXVec3TransformCoord(&_right,&_right, &T);
D3DXVec3TransformCoord(&_up,&_up, &T);
}
}

void Camera::getViewMatrix(D3DXMATRIX* V)
{
// Keep camera's axes orthogonal to eachother
D3DXVec3Normalize(&_look, &_look);

D3DXVec3Cross(&_up, &_look, &_right);
D3DXVec3Normalize(&_up, &_up);

D3DXVec3Cross(&_right, &_up, &_look);
D3DXVec3Normalize(&_right, &_right);

// Build the view matrix:
float x = -D3DXVec3Dot(&_right, &_pos);
float y = -D3DXVec3Dot(&_up, &_pos);
float z = -D3DXVec3Dot(&_look, &_pos);

(*V)(0,0) = _right.x; (*V)(0, 1) = _up.x; (*V)(0, 2) = _look.x; (*V)(0, 3) = 0.0f;
(*V)(1,0) = _right.y; (*V)(1, 1) = _up.y; (*V)(1, 2) = _look.y; (*V)(1, 3) = 0.0f;
(*V)(2,0) = _right.z; (*V)(2, 1) = _up.z; (*V)(2, 2) = _look.z; (*V)(2, 3) = 0.0f;
(*V)(3,0) = x;        (*V)(3, 1) = y;     (*V)(3, 2) = z;       (*V)(3, 3) = 1.0f;
}```
I took most of this from a camera class sample in one of my books, Introduction to 3D Game Programming with DirectX9 by Frank Luna.

This camera class works very well and I saw no reason to change it so I learned the how and why of the class and then changed some names to suit my needs. It's a very good class and I think the yaw, pitch, and roll functions will help you a lot.

D3DXVec3TransformCoord simply multiplies a vector by a matrix or transforms a vector using a matrix. D3DXMatrixRotationAxis simply constructs an axis-angle rotation matrix, which already has been supplied to you in this thread.

Even though this class does not suffer from gimbal lock, it would be much better if it used quaternions...which might be what you are looking for. Euler angles are great except that they cannot be easily interpolated. Quaternions solve this and allow for smooth interpolation from one 3D orientation to another.

Here are my 3 basis vectors:

1,0,0 - right vector
0,1,0 - up vector
0,0,1 - look vector