4

Recently, I have been studying a number of matrix libraries used for WebGL to better understand the math that goes into the various transforms performed on matrices. Currently, I am trying to better understand the math used for rotational transforms.

Specifically, I already understand the transforms used for rotating around the three axes as well as how to generate these matrices (shown below).

enter image description here

However, I don't get the equations used to rotate around an arbitrary axis that isn't the x-, y- or z-axis.

I'm currently reading through WebGL Programming Guide, and in the provided library, they use the following JS to rotate around an arbitrary axis (where e is the array that contains the 4x4 matrix):

len = Math.sqrt(x*x + y*y + z*z);
if (len !== 1) {
  rlen = 1 / len;
  x *= rlen;
  y *= rlen;
  z *= rlen;
}
nc = 1 - c;
xy = x * y;
yz = y * z;
zx = z * x;
xs = x * s;
ys = y * s;
zs = z * s;

e[ 0] = x*x*nc +  c;
e[ 1] = xy *nc + zs;
e[ 2] = zx *nc - ys;
e[ 3] = 0;

e[ 4] = xy *nc - zs;
e[ 5] = y*y*nc +  c;
e[ 6] = yz *nc + xs;
e[ 7] = 0;

e[ 8] = zx *nc + ys;
e[ 9] = yz *nc - xs;
e[10] = z*z*nc +  c;
e[11] = 0;

e[12] = 0;
e[13] = 0;
e[14] = 0;
e[15] = 1;

From what I can tell, the first part of the code is used to normalize the 3D vector, but other than that, I honestly cannot make any sense of it.
For example, what do nc, xy, yz, zx, xs, ys and zs mean? Also, as an example, how did they come up with the formula x*x*nc + c to calculate e[0]?

As per a related SO post, I did find a reference to the following matrix for rotating about an arbitrary axis:

enter image description here

This seems to be related to (if not the same as) what the JS code above is doing.

How is this matrix generated? I've thought a lot about how to rotate around an arbitrary axis, but the only thing I could come up with was to break the 3D vector extending from the origin into its x, y and z components, and then perform three different rotations, which seems pretty inefficient.

Having one matrix to do all of that for you seems best, but I really want to understand that matrix and how it's generated.

Lastly, while I'm not sure, it seems like the matrix above does not account for a translation of the axis away from the origin. Could that be easily handled by simply using a 4x4 matrix instead with Tx, Ty and Tz values in the appropriate locations?

Thank you.

Community
  • 1
  • 1
HartleySan
  • 7,404
  • 14
  • 66
  • 119

2 Answers2

1

Please find the math overview here:

http://paulbourke.net/geometry/rotate/

There is a detailed explanation here:

http://web.archive.org/web/20140515121518/http://inside.mines.edu:80/~gmurray/ArbitraryAxisRotation/ArbitraryAxisRotation.html

You are correct about that rotation matrix not accounting for translation.

Yes, you can create a rotate-then-translate matrix by multiplying translation x rotation:

    1 0 0 t1      r11 r12 r13 0
T = 0 1 0 t2  R = r21 r22 r23 0
    0 0 1 t3      r31 r32 r33 0
    0 0 0 1       0   0   0   1

        1 0 0 t1   r11 r12 r13 0   r11 r12 r13 t1
T x R = 0 1 0 t2 x r21 r22 r23 0 = r21 r22 r23 t2
        0 0 1 t3   r31 r32 r33 0   r31 r32 r33 t3
        0 0 0 1    0   0   0   1   0   0   0   1

If you only want to rotate around an arbitrary axis away from origin (that is, around a line), look for the item "6.2 The normalized matrix for rotation about an arbitrary line" in the 2nd URL (http://web.archive.org/web/20140515121518/http://inside.mines.edu:80/~gmurray/ArbitraryAxisRotation/ArbitraryAxisRotation.html).

Peter O.
  • 32,158
  • 14
  • 82
  • 96
Everton
  • 12,589
  • 9
  • 47
  • 59
  • That does not seem to explain how the complex matrix above is derived (or am I missing something?). – HartleySan Mar 31 '14 at 23:38
  • 1
    Well it explains the complex matrix is the product of 7 matrices (T-1 Rx-1 Ry-1 Rz Ry Rx T) but it does not show the full math. You can find more detailed math here: http://inside.mines.edu/~gmurray/ArbitraryAxisRotation/ArbitraryAxisRotation.html – Everton Apr 01 '14 at 14:23
  • That second link was very helpful, but I'm still confused about several things: 1) How are α, β and γ related to θ? 2) I get the matrix math in section 3, but in section 4, how did they derive those matrices for Txz and Tz? 3) I'm assuming that sections 3 and 4 are somehow combined to arrive at section 5, but I don't get it. Could you please provide some more explanation? Thank you. – HartleySan Apr 02 '14 at 02:12
  • 1
    Consider the full transformation (Txz^-1 Tz^-1 Rz(θ) Tz Txz). Rz(θ) means the matrix to rotate by θ around the axis z. This is the matrix Rz(γ) from section 3, while the parameter θ is the desired rotation around the arbitrary axis (u,v,w). The trick is the compound transformation preceding Rz(θ) -- the matrices mutiplied at the right side of Rz(θ) -- moves the space in order to make the arbitrary axis (u,v,w) coincide with the axis Z (0,0,1). Then Rz(θ) can be used to rotate by θ around it. – Everton Apr 02 '14 at 03:09
  • Everton, thanks again for all of your help. After looking at that second link some more, I finally understand that section 3 is only there to show that rotating around the three axes separately is not possible because the order you rotate about the axes affects the final matrix. As such, we need another method to get what we want. Also, thanks to your previous explanation, I see the point of multiplying Rz(θ) by Txz and Tz, and then taking the inverse of Txz and Tz to essentially "undo" the transformations performed before the rotation. Now, with all of that said, I have a few questions: – HartleySan Apr 03 '14 at 02:19
  • 1) How do you derive the matrices for Txz and Tz? In other words, how do you know that those will properly rotate a vector about the z-axis and then xz-plane to align the vector along the z-axis? 2) How do you calculate the inverse of Txz and Tz for the expression Txz^-1 Tz^-1 Rz(θ) Tz Txz? 3) The author of the page wrote the transforms Txz^-1 Tz^-1 Rz(θ) Tz Txz, but given what Txz and Tz are set to, wouldn't the opposite order be more accurate (i.e., Txz Tz Rz(θ) Tz^-1 Txz^-1 instead)? – HartleySan Apr 03 '14 at 02:23
  • 4) What does, "Note that we use the components to form expressions for the cosines and sines to avoid using inverse trigonometric functions." mean? 5) Also, what does, "We require that the rotation vector not be parallel to the z-axis, else u = v = 0 and the denominators vanish." mean? I don't get this, because I thought the whole point of combining Txz and Tz was to align the vector along the z-axis? 6) Where is the second matrix in 5.1 coming from? I don't get it at all. Thanks again! – HartleySan Apr 03 '14 at 02:25
  • 1
    1) Notice that: 4.1 Txz : uses Rz with sin and cos calculated from the axis vector components (u,v,w) 4.2 Tz : uses Ry with sin and cos calculated from the axis vector components (u,v,w) 2) How to find the inverse matrix: http://www.mathsisfun.com/algebra/matrix-inverse.html – Everton Apr 03 '14 at 13:44
  • 1
    3) No, the author used the correct order. When you apply the combined transform matrix to a vector/point (that is, a row-matrix), you will find the effect is like applying each individual transform BUT beginning from the right (last matrix) to the left (first matrix). – Everton Apr 03 '14 at 13:45
  • 1
    4) It means the matrices for rotation around axis were used, but to obtain the sines and cosines, the author preferred to use the rotation axis components instead of playing with inverse trigo functions (http://en.wikipedia.org/wiki/Inverse_trigonometric_functions); I think this is because inverse trigo is computationally expensive (and option exists in this case of course). 5) Yes, the point is to align the rotation axis with Z, but those matrices won't work if the axis of rotation **starts already aligned to z**. – Everton Apr 03 '14 at 13:45
  • 1
    6) The second matrix from 5.1 (notice it is a row-matrix) just shows how to get the formulas to calculate (newX, newY, newZ) from (X,Y,Z) given the rotation matrix (first matrix from 5.1). That is, it shows how to do the rotation without the matrix-multiplication notation. – Everton Apr 03 '14 at 13:47
  • Wow! That was a lot to digest. Everton, thank you so much for your help and patience. It's slowly starting to make sense. After your last set of answers, I now understand the following (which should have been obvious before): sqrt(u^2 + v^2) is the length of the hypotenuse of the vector in 2D, x-y space. As such u/sqrt(u^2 + v^2) is the same thing as the cosine of theta, and v/sqrt(u^2 + v^2) is the same thing as the sine of theta. Also, yes, using the components makes a lot of sense so that when we need the inverse of the matrices, we don't have to use inverse cosine/sine. Thank you. – HartleySan Apr 06 '14 at 02:06
  • So now, if my understanding is correct, then the matrix generated by Txz-1, Tz-1, Rz(θ), Tz, Txz is all we need to rotate a vector in 3D space about an arbitrary axis that goes through the origin. Is that correct? Also, I now fully get what the author was saying about the second matrix in 5.1, which, as you stated, is indeed a row-matrix. Thank you. Likewise, looking forward, by assuming that u^2 + v^2 + w^2 = 1, then we can greatly simplify the matrix, as shown in 5.2. Next, looking at section 6, I don't really get the point of it, but it seems like by the end of section 5, we already have... – HartleySan Apr 06 '14 at 02:12
  • Everything we need to rotate vectors about arbitrary axes. Is this correct? At this point (while I haven't been crazy enough to calculate the inverses of Txz and Tz myself), I only have two questions: 1) Why does Txz in 4.1 only use u and v (i.e., the x and y components), but Tz in 4.2 uses u, x and w? Furthermore, what does -sqrt(u^2 + v^2)/sqrt(u^2 + v^2 + w^2) in Tz actually mean? 2) I can see that the matrix in 5.1 maps to the matrix I posted in my original question, but how does the element in row 1, column 1 simply from what we see in 5.1 to cosθ + u^2(1 - cosθ)? What is 1 - cosθ? – HartleySan Apr 06 '14 at 02:20
  • Everton, please ignore my second question. I just got it. By assuming that u^2 + v^2 + w^2 = 1, then the denominator goes to 1, and v^2 + w^2 is obviously equal to 1 - u^2. Thanks. I guess I now have one more question: For the sake of a 3D application using WebGL, would it be more computationally efficient to use the row-vector (the second matrix) in 5.2 for calculating the shift of a vertex about an arbitrary axis, or is it better to use use the first matrix in 5.2, and send that matrix to the vertex shader to do all the matrix math for me? Thanks. – HartleySan Apr 06 '14 at 02:25
  • 1
    1) Txz in 4.1 uses only u and v because they suffice to describe the rotation around the z axis into xz plane. Look at the projection of (u,v,w) into xy plane. Notice the angle between (u,w,0) and (u,0,0). It's the rotation around Z, and its cosine is u/sqrt(u^2+v^2). Thus we have the value for 1,1 of matrix Txz... And so forth. For Tz in 4.2, look at the projection of (u,v,w) into the xz plane, focusing at the angle between (sqrt(u^2+v^2),0,w) and (0,0,w). It's rotation around Z. Its cosine is w/sqrt(u^2+v^2+w^2). Thus we have the value for 1,1 of matrix Tz... And so forth. – Everton Apr 07 '14 at 01:48
  • 1
    About the WebGL question, I think you may find a informative topic here: http://stackoverflow.com/questions/20984554/better-to-multiply-matrices-in-javascript-or-a-shader – Everton Apr 07 '14 at 01:53
  • 1
    Not sure you got this part, so here it is: the point of section 5 is to derive the rotation around a vector at the origin (product of 5 matrices). Section 6 just generalizes the rotation to include a line away from origin (product of 7 matrices). – Everton Apr 07 '14 at 02:04
  • Well, I can't say I understand all of the math 100%, but after over a week of thinking about this constantly, and also you so kindly helping me out, I think I finally get it. I'm going to try and derive a lot of the matrices myself, and see where it gets me. Thank you so much for all of your help, Everton. – HartleySan Apr 08 '14 at 01:24
1

If you're rotating around angle theta, then in the code:

c = cos(theta);
nc = 1-cos(theta); // (or 1-c)
s = sin(theta);

So in the code,

x is just ux

xy is just uxuy

xs is just uxsinθ

and so on. So, in the formula, the third expression in the first row, which is uxuz(1-cosθ) + uysinθ becomes zx * nc - ys

With that in mind, you can see that the code is just an expression of the formula for R, except the code expresses it as a 4x4 matrix instead of 3x3. The 4th dimension is for translation, but the expression specifies a translation of zero in all three directions.

MiguelMunoz
  • 4,548
  • 3
  • 34
  • 51
  • That's actually very helpful in understanding how all the mathematical symbols are translated to variables. Thank you. – HartleySan May 23 '16 at 20:04
  • 2
    The code differs from the supplied formula by reversing the sign for every term that uses sin(theta). So zx * nc - ys should actually be zx * nc + ys. It's actually the formula for negative theta. This is because sine(-theta) = -sine(theta) and cosine(-theta) = cosine(theta) So you could say the code rotates in the opposite direction from the formula. – MiguelMunoz May 30 '16 at 19:51
  • Also extremely helpful to know. Is there any reason for doing things one way versus the other, or is it completely arbitrary and up to the coder to decide which way to go with things? Thanks. – HartleySan May 30 '16 at 23:27
  • The direction of rotation is entirely up to the coder. But the formula is presumably written for a standard coordinate system, where y increases as you go up. But many drawing implementations (such as the java Graphics object) have y increase as you go down. So that would also reverse the direction of rotation. So the code was probably written to compensate for that. – MiguelMunoz Jun 06 '16 at 21:10
  • Very interesting. I've learned a lot from your explanations. Thanks a lot. – HartleySan Jun 06 '16 at 21:39