1

How would you, as safely as possible, rotate an existing 3x3 rotation matrix by a vector?

The math would look something like this:

[X] * [1, 0, 0]
[Y] * [0, 1, 0] = New Rotation Matrix
[Z] * [0, 0, 1]

I've browsed both GLM and Eigen without help. They only seem to reference 4x4 matrices.

Intent:

I'm basically trying to rotate an existing 3x3 rotation matrix by a rotation vector.

I'd appreciate any input.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
COOKIES
  • 434
  • 4
  • 14
  • have a read of this question. https://math.stackexchange.com/questions/336/why-are-3d-transformation-matrices-4-times-4-instead-of-3-times-3 – Richard Hodges May 21 '17 at 06:32
  • Interesting... So you're proposing converting to 4x4 then rotate then back to 3x3? – COOKIES May 21 '17 at 06:41
  • I would propose only using 4x4 matrices and vectors everywhere as is the norm in 3d graphics. – Richard Hodges May 21 '17 at 06:43
  • 3
    I have no idea what you intend to do here. A matrix times a vector will result in a vector. You can not "rotate by a vector". You can interprete a vector as a rotation (e.g., interpreting it as Euler angles or scaled axes). Maybe you want to "translate by a vector"? – chtz May 21 '17 at 06:44
  • Only reason to why I need 3x3 is because I'm passing it to cameraParams.R OpenCV parameter which only accepts a 3x3 matrix. – COOKIES May 21 '17 at 06:45
  • OpenCV in some cases interpretes 3d vectors as scaled axis rotation. You can convert them to a 3x3 matrix (and back) using `cv::Rodrigues`. – chtz May 21 '17 at 06:50
  • How do you mean? @chtz – COOKIES May 21 '17 at 06:52
  • if you want to rotate matrix by vector (around `0,0,0` but use that vector as axis) that is done differently.... first obtain 2 perpendicular vector to your vector than construct `3x3` matrix representing that coordinate system than convert your matrix into it rotate by your angle around that axis which you use with your original vector and lastly convert your matrix back .... – Spektre May 21 '17 at 08:17
  • Hmm.. Got any examples/references of that, @Spektre? – COOKIES May 21 '17 at 08:20
  • Take your time @Spektre, I greatly appreciate it!! Thanks – COOKIES May 21 '17 at 08:29
  • @COOKIES finished editing ... I strongly recommend to read the 2 links in **#1** ... – Spektre May 21 '17 at 08:41
  • Thank you so much @Spektre. I'll give them a read now – COOKIES May 21 '17 at 08:42

2 Answers2

2

Assuming you are dealing with scaled axis rotation vectors, you can use AngleAxis:

Matrix3f R1 = ...;
Matrix3f R2 = AngleAxisf(vec.norm(), vec.normalized()) * R1;

Of course, you might want to normalize vec yourself so that the norm is computed only once:

float a = vec.norm();
Matrix3f R2 = AngleAxisf(a, vec/a) * R1;
ggael
  • 28,425
  • 2
  • 65
  • 71
1

You can not multiply vector and matrix and expect matrix result. To rotate your 3x3 matrix M around (0,0,0) and vector W as rotation axis you need to do this:

  1. construct 3x3 matrix representing rotation coordinate system

    so you need 3 basis vectors U,V,W which are perpendicular to each other. We already got W so exploit the cross product to get the others:

    // normalize
    W = W / |W| 
    // U is any non-zero non-parallel vector to W
    U = (1,0,0)
    if (|dot(U,W)|>0.7) U = (0,1,0)
    // V is perpendicular to U,W
    V = cross(W,U)
    // U is perpendicular to V,W
    U = cross(V,W)
    

    Now construct the 3x3 matrix from U,V,W depending on the layout of matrices you use it would be one of these

         | Ux Uy Uz |        | Ux Vx Wx |
    A =  | Vx Vy Vz | or B = | Uy Vy Wy |
         | Wx Wy Wz |        | Uz Vz Wz |
    

    for more info see:

  2. Convert M to A/B

    I am used to OpenGL and its math is using B layout so I will use it from now on (the only difference between A and B is that the matrices are inversed which for orthogonal 3D 3x3 rotation matrix is the same as transposed) So take each vector from M convert it to B like this... Let assume your M has 3 basis vectors X,Y,Z so

    X' = inverse(B)*X
    Y' = inverse(B)*Y
    Z' = inverse(B)*Z
    

    so construct M' from X',Y',Z'

  3. rotate M' around z

    so just multiply M' by simple rotation matrix R around z axis with some angle.

        | cos(angle) -sin(angle) 0 |
    R = | sin(angle)  cos(angle) 0 |
        |     0           0      1 |
    
    M''= M' * R(angle)
    
  4. M''convert back to original coordinate system

    so:

    X''' = B*X''
    Y''' = B*Y''
    Z''' = B*Z''
    

    and construct your new M from X''',Y''',Z'''. That is all.

Spektre
  • 49,595
  • 11
  • 110
  • 380