Thread: Problem multiplying rotation matrices together

  1. #1
    Banned
    Join Date
    Jan 2003
    Posts
    1,708

    Problem multiplying rotation matrices together

    I am using this for a game, but I didn't put it in the game forum because more people view GD. Plus it's math oriented, therefore you don't have to be into game programming to possibly help me.

    Anyway, from what I understand from OpenGL Game Programming you can multiply the Z axis rotation matrix by the Y axis rotation by the X axis rotation. It comes right out and says the final equations(the 'concatenation' of the three matrices), but I'm not exactly sure how they got there. I'm going to post the three matrices and then the final equations. Note the delta means the degrees travelled about that axis only. If I made any mistakes please point them out, it was a lot to copy. I tried making this as neat as possible, but the matrices keep being posted unaligned.

    Z axis rotation matrix:
    Code:
    cosDelta   -sinDelta 0 0
    sinDelta     cosDelta 0 0
    0 0  1  0
    0 0  0  1
    Y axis rotation matrix;
    Code:
    cosDelta  0 sinDelta  0
    0 1 0 0
    -sinDelta 0 cosDelta 0
    0 0 0 1
    X axis rotation matrix:
    Code:
    1 0 0 0
    0 cosDelta -sinDelta 0
    0 sinDelta cosDelta 0
    0 0 0 1
    Here are the final equation describing how the X image, Y image and Z image are related to the concatenation of the 3 matrices above
    X' = X[(cosZDelta) * (cosYDelta)] +
    Y[cosZDelta) * (sinYDelta) * (sinXDelta) - (sinZDelta) *(cosXDelta] +
    Z[(cosZDelta) *(sinYDelta) * (sinYDelta) - (sinZDelta) * (cosXDelta)]

    Y' = X[(sinZDelta) * (cosYDelta)]+
    Y[(sinZDelta) * (sinYDelta) * (sinXDelta) - (cosZDelta) * (cosXDelta)+
    Z[(sinZDelta) *(sinYDelta) * (cosXDelta) - (cosZDelta) * (sinXDelta)]

    Z' = -x*(sin?) + z*(cosYDelta)*(sinXDelta)]
    I'm not sure if the question mark is a mistake from the book or not, unfortunately I suspect it is, but when I know what I'm doing I'll be able to figure out what it's supposed to be.

    As I said I do not know how they multiplied the first three matrices together to get the final equations. I do know how to work with matrices, i.e the image matix will have the number of rows from the first matrix and the number of columns from the second matrix. I know how to multiply two matrices together (Matrix1Row[0][0] * Matrix2Column[0][0] add those together and continue until first column is filled). Anyay if anyone can shed some light onto what is going on I will be very happy.
    Last edited by Silvercord; 02-26-2003 at 10:56 AM.

  2. #2
    Registered User rahaydenuk's Avatar
    Join Date
    Jul 2002
    Posts
    69

    Re: Problem multiplying rotation matrices together

    Originally posted by Silvercord
    I am using this for a game, but I didn't put it in the game forum because more people view GD. Plus it's math oriented, therefore you don't have to be into game programming to possibly help me.

    Anyway, from what I understand from OpenGL Game Programming you can multiply the Z axis rotation matrix by the Y axis rotation by the X axis rotation. It comes right out and says the final equations(the 'concatenation' of the three matrices), but I'm not exactly sure how they got there. I'm going to post the three matrices and then the final equations. Note the delta means the degrees travelled about that axis only. If I made any mistakes please point them out, it was a lot to copy. I tried making this as neat as possible, but the matrices keep being posted unaligned.

    Z axis rotation matrix:
    Code:
    cosDelta   -sinDelta 0 0
    sinDelta     cosDelta 0 0
    0 0  1  0
    0 0  0  1
    Y axis rotation matrix;
    Code:
    cosDelta  0 sinDelta  0
    0 1 0 0
    -sinDelta 0 cosDelta 0
    0 0 0 1
    X axis rotation matrix:
    Code:
    1 0 0 0
    0 cosDelta -sinDelta 0
    0 sinDelta cosDelta 0
    0 0 0 1
    Here are the final equation describing how the X image, Y image and Z image are related to the concatenation of the 3 matrices above
    X' = X[(cosZDelta) * (cosYDelta)] +
    Y[cosZDelta) * (sinYDelta) * (sinXDelta) - (sinZDelta) *(cosXDelta] +
    Z[(cosZDelta) *(sinYDelta) * (sinYDelta) - (sinZDelta) * (cosXDelta)]

    Y' = X[(sinZDelta) * (cosYDelta)]+
    Y[(sinZDelta) * (sinYDelta) * (sinXDelta) - (cosZDelta) * (cosXDelta)+
    Z[(sinZDelta) *(sinYDelta) * (cosXDelta) - (cosZDelta) * (sinXDelta)]

    Z' = -x*(sin?) + z*(cosYDelta)*(sinXDelta)]
    I'm not sure if the question mark is a mistake from the book or not, unfortunately I suspect it is, but when I know what I'm doing I'll be able to figure out what it's supposed to be.

    As I said I do not know how they multiplied the first three matrices together to get the final equations. I do know how to work with matrices, i.e the image matix will have the number of rows from the first matrix and the number of columns from the second matrix. I know how to multiply two matrices together (Matrix1Row[0][0] * Matrix2Column[0][0] add those together and continue until first column is filled). Anyay if anyone can shed some light onto what is going on I will be very happy.
    Hi,

    Remember that although matrix multiplication is not commutative, it is associative, so it doesn't matter which two matrices you multiply together first in the above example, as long as the overall order is kept.

    So, you want to create a composite matrix, which has the effect of a rotation about Z, then a rotation about Y, then a rotation about X. Remember that the non-commutativity of matrix multiplication still stands with rotations; the fact that the result of combining rotations depends on the order in which you perform them is a geometric fact about rotations. It is easy to see that the non-commutativity of rotations is a geometric fact. Just hold a non-cubical rectangular box in your hands and try rotating it by 90 degrees successively about two different axes, note the resulting orientation, then return it to its original orientation and perform the same two rotations but in the opposite order. Therefore, we must multiply the three matrices (we will call them Z, Y and X respectively) in the order ZYX. But due to matrix associativity, it doesn't matter whether we evaluate ZY first or YX first. If you evaluate ZY first (call it P), then simply multiply that by X, (in the order PX) to get the final composite matrix. If you evaluate YX first (call it G), then simply multiply that by Z, (in the order ZG) to get the final composite matrix.

    By the way, your definitions for each individual rotation matrix are correct, and I'm sure you can now mulitply them together as explained to check the last bit.

    P.S. You've used 'delta' for your angle variable in all of the above rotations, I don't know whether or not you intended to do this, as it would obviously only allow a rotation of the same amount around each axis.

    I hope this helps,

    Regards,
    Last edited by rahaydenuk; 02-26-2003 at 12:50 PM.
    Richard Hayden. ([email protected])
    Webmaster: http://www.dx-dev.com
    DXOS (My Operating System): http://www.dx-dev.com/dxos

    PGP: 0x779D0625

  3. #3
    Banned
    Join Date
    Jan 2003
    Posts
    1,708

    Thumbs up

    That clears things up quite a bit, thank you very much!!! When I get this temporary matrix P do I still follow standard matrix multiplication (rows of P multiplied by columns of X or Z). Is it incorrect for ZX to be P and then multiply by Y?(it seems that it is incorrect to do that). These equations are eventually going to be used for changing the view vectors of the camera in a program I'm working on, therefore do I even need the rotation about the Z axis matrix?

    I meant for the deltas to be completely different variables

  4. #4
    Registered User rahaydenuk's Avatar
    Join Date
    Jul 2002
    Posts
    69
    Originally posted by Silvercord
    That clears things up quite a bit, thank you very much!!! When I get this temporary matrix P do I still follow standard matrix multiplication (rows of P multiplied by columns of X or Z).
    If we are defining P = ZY to start as previously, then to get the composite matrix ZYX, you will need to multiply P by X on the right, i.e. PX as this is then equal to (ZY)X = ZYX.

    If we are instead defining another matrix G = YX to start, then we need to multiply by Z on the left, i.e. ZG as this is then equal to Z(YX) = ZYX.

    Remember that due to the non-commutativity of matrix multiplication, you need to take into account whether you are multiplying one matrix by another on the left or the right. They will (in general) produce different results.

    All of these individual matrix multiplication operations are no different to what they were when you were just multiplying two matrices together. For example, to evaluate ZYX, take P = ZY and evaluate ZY just as standard matrix multiplication (i.e. rows of Z by columns of Y), then multiply the resultant matrix P by X to get PX in the standard fashion (i.e. rows of P by columns of X).

    Originally posted by Silvercord
    Is it incorrect for ZX to be P and then multiply by Y?(it seems that it is incorrect to do that).
    We are trying to find ZYX, and if we were to define P = ZX, multiplying either side of P (ZX) by Y would produce either YZX or ZXY, which is not equal (in general) to ZYX for matrices, due to the non-commutativity of matrix multiplication. So, yes this would be incorrect; you should start either by evaluating YX or ZY and then multiplying by the other matrix (the one left out) on the correct side.

    Originally posted by Silvercord
    These equations are eventually going to be used for changing the view vectors of the camera in a program I'm working on, therefore do I even need the rotation about the Z axis matrix?
    I'm not a game/graphics-programming expert, but I've done a bit of DirectX. If we assume that in camera space, the camera, or viewer, is at the origin, looking in the z-direction, as in DirectX, I can't immediately see a reason for wanting to have a rotation about the Z-axis in the view matrix transformation. I can see a rotation about the X-axis acting as adjustment of pitch (i.e. looking up and down), and then a rotation about the Y-axis as the adjustment for the camera rotating around, as if the user has turned his head, but unless you get complicated, then I see no *common* use for including a Z-axis rotation component in the view matrix transformation (obviously, you would probably need it for flight simulators etc.).

    Having said this, you should remember however that the view matrix, V is generally defined as a combination of a translation matrix, T and then the three rotational component matrices, X, Y and Z about their three respective co-ordinate axis, (V = T*X*Y*Z), so officially, it does include a rotational component about the Z-axis. I wouldn't worry, though if you find yourself not needing it.

    Originally posted by Silvercord
    I meant for the deltas to be completely different variables
    That's what I thought.

    Hope this helps,

    Regards,
    Last edited by rahaydenuk; 02-26-2003 at 05:43 PM.
    Richard Hayden. ([email protected])
    Webmaster: http://www.dx-dev.com
    DXOS (My Operating System): http://www.dx-dev.com/dxos

    PGP: 0x779D0625

  5. #5
    Banned
    Join Date
    Jan 2003
    Posts
    1,708
    hi there, sorry I didn't get a chance to respond last night. All of your answers and explanations were very concise therefore I do not currently have anymore questions (that's a good thing). I'm doing this for a game, so I should have this working within a few days. I can post it when I get it working if you want me to. I think I might try using this matrix (the concatenation of the Z Y and X rotation matrices) as well as the rotation about an arbitrary axis matrix.

    All right, take care, talk to you later.

  6. #6
    Registered User rahaydenuk's Avatar
    Join Date
    Jul 2002
    Posts
    69
    Originally posted by Silvercord
    hi there, sorry I didn't get a chance to respond last night. All of your answers and explanations were very concise therefore I do not currently have anymore questions (that's a good thing). I'm doing this for a game, so I should have this working within a few days. I can post it when I get it working if you want me to. I think I might try using this matrix (the concatenation of the Z Y and X rotation matrices) as well as the rotation about an arbitrary axis matrix.

    All right, take care, talk to you later.
    OK, glad I could help!

    I'd be interested in seeing your game, when you've got it working and I'm sure others would be too; I'll look forward to taking a look.

    Have fun!

    Regards,
    Richard Hayden. ([email protected])
    Webmaster: http://www.dx-dev.com
    DXOS (My Operating System): http://www.dx-dev.com/dxos

    PGP: 0x779D0625

  7. #7
    Banned
    Join Date
    Jan 2003
    Posts
    1,708
    I have thought of more questions. I am trying to figure out how these matrices are derived but I honestly don't get it 100%. I am using the Y axis rotation matrix for this example. I am drawing pictures of a triangle with the hypotenuse as the view vector. I am then trying to figure out why the new vector's X component is equal to the cos(theta) multiplied by the original x plus the sin(theta) multiplied by the original z component (X' = cos(theta) * X + sin(theta) * z). Likewise I do not know how the calculation for the new Z component is derived (-sin(theta) * x + cos(theta) * z). If you could explain this using properties of triangles and vectors I will probably have a much better understanding of what is going on here. I want to get a very fundamental understanding of this.

  8. #8
    Registered User rahaydenuk's Avatar
    Join Date
    Jul 2002
    Posts
    69
    Originally posted by Silvercord
    I have thought of more questions. I am trying to figure out how these matrices are derived but I honestly don't get it 100%. I am using the Y axis rotation matrix for this example. I am drawing pictures of a triangle with the hypotenuse as the view vector. I am then trying to figure out why the new vector's X component is equal to the cos(theta) multiplied by the original x plus the sin(theta) multiplied by the original z component (X' = cos(theta) * X + sin(theta) * z). Likewise I do not know how the calculation for the new Z component is derived (-sin(theta) * x + cos(theta) * z). If you could explain this using properties of triangles and vectors I will probably have a much better understanding of what is going on here. I want to get a very fundamental understanding of this.
    Deriving the rotation matrices is quite a complicated topic. There are quite a few ways to go about it, including by differential equations or by looking at vector components. The following website gives a couple of different derivations of Rodriques' Formula, which is used to find rotation matrices:

    http://www.cs.berkeley.edu/~ug/slide.../rotation.html

    I hope this helps,

    Regards,
    Richard Hayden. ([email protected])
    Webmaster: http://www.dx-dev.com
    DXOS (My Operating System): http://www.dx-dev.com/dxos

    PGP: 0x779D0625

  9. #9
    Banned
    Join Date
    Jan 2003
    Posts
    1,708
    I decided to skip out using the z axis rotation, because it does not seem like it will be used in my game (how can you even have a Z component in camera movement when you are checking for mousemovement in 2d screen coords?). I haven't multiplied matrices together in quite a while, but when I multiplied the Y axis rotation matrix by the X axis rotation matrix I got this matrix. I am pretty sure it is correct but I would be happy if you could check it for errors (better safe than sorry before putting it into code)

    concatenation between Y and X axis rotation matrices:

    cosYDelta sinYDelta + sinXDelta sinYDelta * cosXDelta
    0 cosXDelta -sinXDelta
    -sinYDelta cosYDelta * sinXDelta cosYDelta * cosXDelta

    the final equations (what it will look like in code because I am not using a matrix class)

    X' = X * cosYDelta +
    Y * sinYDelta * sinXDelta +
    Z * sinYDelta * cosXDelta

    Y' = Y * cosXDelta +
    Z * -sinXDelta

    Z' = X * -sinYDelta +
    Y * cosYDelta * sinXDelta +
    Z * cosYDelta * cosXDelta

  10. #10
    Registered User rahaydenuk's Avatar
    Join Date
    Jul 2002
    Posts
    69
    Originally posted by Silvercord
    I decided to skip out using the z axis rotation, because it does not seem like it will be used in my game (how can you even have a Z component in camera movement when you are checking for mousemovement in 2d screen coords?).
    Well you're right, you can only have rotation about two axis, as the mouse only has two axis of movement. Flight simulators etc., which would require rotation about the z-axis (for barrel-rolls etc.) would usually have the user press a mouse button to switch one of the mouse's co-ordinate axis to representing the z-axis rotation, or it would be done by keyboard.

    Originally posted by Silvercord
    I haven't multiplied matrices together in quite a while, but when I multiplied the Y axis rotation matrix by the X axis rotation matrix I got this matrix. I am pretty sure it is correct but I would be happy if you could check it for errors (better safe than sorry before putting it into code)

    concatenation between Y and X axis rotation matrices:

    cosYDelta sinYDelta + sinXDelta sinYDelta * cosXDelta
    0 cosXDelta -sinXDelta
    -sinYDelta cosYDelta * sinXDelta cosYDelta * cosXDelta

    the final equations (what it will look like in code because I am not using a matrix class)

    X' = X * cosYDelta +
    Y * sinYDelta * sinXDelta +
    Z * sinYDelta * cosXDelta

    Y' = Y * cosXDelta +
    Z * -sinXDelta

    Z' = X * -sinYDelta +
    Y * cosYDelta * sinXDelta +
    Z * cosYDelta * cosXDelta
    One little thing, I find it very confusing to read your matrix, maybe you could attach an image next time?

    From what I can see, it looks like you've made one typo, but apart from that it's fine. I've attached the correct product matrix for the y-axis rotation matrix multiplied by the x-axis rotation matrix (in that order) as an image for readability, so you can see where you made the mistake (you've used a '+' instead of a '*' for one element of the product matrix).

    In order to get the equations for x', y' and z', we need to use the product matrix we just found to transform the general x, y, z vector. This operation is shown in the aforementioned image file attached to this message.

    From looking at this image file, we can ascertain the following equations for x', y' and z' (where 'a' is the number of degrees to rotate about the y-axis and 'b' is the number of degrees to rotate about the x-axis (counter-clockwise)):

    x' = xCos(a) + ySin(a)Sin(b) + zSin(a)Cos(b)
    y' = yCos(b) - zSin(b)
    z' = -xSin(a) + yCos(a)Sin(b) + zCos(a)Cos(b)

    These are identical to what you found, thus implying that your earlier mistake in multiplying the matrices was most likely simply a typo.

    I hope this helps,

    Regards,
    Richard Hayden. ([email protected])
    Webmaster: http://www.dx-dev.com
    DXOS (My Operating System): http://www.dx-dev.com/dxos

    PGP: 0x779D0625

  11. #11
    Banned
    Join Date
    Jan 2003
    Posts
    1,708
    Yes that is identical to what I had myself. Sorry about the way I posted my matrices, if I have to do it again I'll make an image for you so it's easier to read. You have been really really really (^infinity) helpful. I was surprised that you replied so fast and you really know what you're talking about

    I haven't got this working yet (doesn't seem to do the rotations correctly) but I am trying to plug it into code right now. Like I said I'll upload the results.
    Thanks, talk to you later.

  12. #12
    Registered User rahaydenuk's Avatar
    Join Date
    Jul 2002
    Posts
    69
    Originally posted by Silvercord
    Yes that is identical to what I had myself. Sorry about the way I posted my matrices, if I have to do it again I'll make an image for you so it's easier to read. You have been really really really (^infinity) helpful. I was surprised that you replied so fast and you really know what you're talking about

    I haven't got this working yet (doesn't seem to do the rotations correctly) but I am trying to plug it into code right now. Like I said I'll upload the results.
    Thanks, talk to you later.
    OK, good luck, I'll look forward to seeing it!

    If you need any more assistance, don't hesitate to ask!

    One thing, which could be causing problems... ensure that you are feeding the trig functions the correct format argument (i.e. check whether you should be using degrees or radians and if you're using the correct one), this can be a very elusive bug, if you haven't met/aren't used to using radians.

    Regards,
    Richard Hayden. ([email protected])
    Webmaster: http://www.dx-dev.com
    DXOS (My Operating System): http://www.dx-dev.com/dxos

    PGP: 0x779D0625

  13. #13
    Banned
    Join Date
    Jan 2003
    Posts
    1,708
    Yes I had already implemented rotating the view vector and camera position (third person) as well as the actual model about the y axis. Obviously this involves both radians and degrees (radians for rotating the views, degrees for rotating the model). Plus we are doing radians heavily in math right now, so I'm really all set with that

    I am trying to plug this into code. I have been trying to get this working for 40 mins or so but this just does not work. Is there any problem with order here? Should I add any parenthesis anywhere? This really should be working, but it doesn't.

    Code:
     	Dir = View - Position; //this is the direction
    	RotDir.x = (Dir.x * cosYTheta) + (Dir.y * sinYTheta * sinXTheta) + (Dir.z * sinYTheta * cosXTheta);
    	RotDir.y = (Dir.y * cosXTheta) - (Dir.z * sinXTheta);
    	RotDir.z = (Dir.x * -sinYTheta) + (Dir.y * cosYTheta * sinXTheta) + (Dir.z * cosYTheta * cosXTheta);
    EDIT: this is how I derived the number of degrees and radians to perform the rotations. Everything worked for rotations about just the Y axis.

    Code:
    	
    	YRotation += ((360 * XDeviation) / SCREEN_WIDTH);		
    	XRotation += ((360 * YDeviation) / SCREEN_WIDTH);
    	float YDeviation = (MiddleY - MousePos.y) / 2;
    	float XDeviation = (MiddleX - MousePos.x) / 2;
    				  
    	float XDegRad = ((2 * PI) * XDeviation) / SCREEN_WIDTH; 
    	float YDegRad = ((2 * PI) * YDeviation) / SCREEN_WIDTH;
    	
    	float cosXTheta = (float)cos(XDegRad);
    	float sinXTheta = (float)sin(XDegRad);
    	
    	float cosYTheta = (float)cos(YDegRad); 
    	float sinYTheta = (float)sin(YDegRad);
    Last edited by Silvercord; 02-28-2003 at 09:18 AM.

  14. #14
    Registered User rahaydenuk's Avatar
    Join Date
    Jul 2002
    Posts
    69
    Originally posted by Silvercord
    Yes I had already implemented rotating the view vector and camera position (third person) as well as the actual model about the y axis. Obviously this involves both radians and degrees (radians for rotating the views, degrees for rotating the model). Plus we are doing radians heavily in math right now, so I'm really all set with that

    I am trying to plug this into code. I have been trying to get this working for 40 mins or so but this just does not work. Is there any problem with order here? Should I add any parenthesis anywhere? This really should be working, but it doesn't.

    Code:
    	RotDir.x = (Dir.x * cosYTheta) + (Dir.y * sinYTheta * sinXTheta) + (Dir.z * sinYTheta * cosXTheta);
    	RotDir.y = (Dir.y * cosXTheta) - (Dir.z * sinXTheta);
    	RotDir.z = (-Dir.x * sinYTheta) + (Dir.y * cosYTheta * sinXTheta) + (Dir.z * cosYTheta * cosXTheta);
    EDIT: this is how I derived the number of degrees and radians to perform the rotations. Everything worked for rotations about just the Y axis.
    Code:
    	float YDeviation = (MiddleY - MousePos.y) / 2;
    	float XDeviation = (MiddleX - MousePos.x) / 2;
    				  
    	float XDegRad = ((2 * PI) * XDeviation) / SCREEN_WIDTH; 
    	float YDegRad = ((2 * PI) * YDeviation) / SCREEN_WIDTH;
    	
    	float cosXTheta = (float)cos(XDegRad);
    	float sinXTheta = (float)sin(XDegRad);
    	
    	float cosYTheta = (float)cos(YDegRad); 
    	float sinYTheta = (float)sin(YDegRad);
    What do MiddleY and MiddleX represent?

    Regards,
    Richard Hayden. ([email protected])
    Webmaster: http://www.dx-dev.com
    DXOS (My Operating System): http://www.dx-dev.com/dxos

    PGP: 0x779D0625

  15. #15
    Banned
    Join Date
    Jan 2003
    Posts
    1,708
    MiddleX and MiddleY are the screen width and height divided by two. it is the center of the screen in screen coords. note that when using getcursorpos and setcursorpos those screen coordinates are setup like a regular cartesian system. the point 0,0 is actually in the middle of the screen. for everything else I think the positive y goes down the screen and 0, 0 is the top left corner.
    SetCursorPos(MiddleX, MiddleY); //sets cursor to exact middle of screen
    Code:
    	static float MiddleX = SCREEN_WIDTH / 2;
    	static float MiddleY = SCREEN_HEIGHT / 2;
    SCREEN_WIDTH and SCREEN_HEIGHT are #define'd compiler directives passed into the function that sets up the resolution.

    If there is anything else that I didn't explain good enough please ask me.

    Code:
    #define SCREEN_WIDTH 1024
    #define SCREEN_HEIGHT 768
    Last edited by Silvercord; 02-28-2003 at 09:22 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. adding matrices, help with switches
    By quiet_forever in forum C++ Programming
    Replies: 7
    Last Post: 09-04-2007, 08:21 AM
  2. Image rotation - doesn't always work
    By ulillillia in forum C Programming
    Replies: 12
    Last Post: 05-03-2007, 12:46 PM
  3. Problem in mouse position
    By Arangol in forum Game Programming
    Replies: 6
    Last Post: 08-08-2006, 07:07 AM
  4. Quaternion Rotation
    By psychopath in forum Game Programming
    Replies: 16
    Last Post: 07-23-2006, 03:28 PM
  5. Laptop Problem
    By Boomba in forum Tech Board
    Replies: 1
    Last Post: 03-07-2006, 06:24 PM