Very important questions about multiplying matrix with vectors and rotation matrix

Hi guys,

I’m having some rather basic but extremly important questions about the matrix multiplications in blender. Say I have a coordinate whose Vector representation is v1 and I have a 3x3 rotation matrix rotMat, which one of the following is correct equation for applying the matrix to the vector:

  • v2 = rotMat * v1
  • v2 = v1 * rotMat

Furthermore, suppose I’ve resized v1 to 4D, and the matrix mat I have is now a 4x4 matrix, which one of the following is the correct equation for applying the matrix to the vector:

  • v3 = mat * v1
  • v3 = v1 * mat

Now, in my experience, in both cases the second equation, i.e. vec * mat, gives the correct results in blender. However, in most of the textbooks I’ve seen, the correct equation would be mat * vec.

To complicate things further, now I have three matrices, rotX, rotY, and rotZ, each representing a rotation around the X, Y, Z axises respectively. Now, if I wish to apply the rotations in the order of X->Y->Z to a vector v, which one of the following is correct?

  • v4 = v * rotX * rotY * rotZ
  • v4 = rotX * rotY * rotZ * v
  • v4 = rotZ * rotY * rotX * v
  • v4 = v * rotX.transpose() * rotY.transpose() * rotZ.transpose()
  • v4 = rotX.transpose() * rotY.transpose() * rotZ.transpose() * v

In accordance with my previous blender experience, the first option should work – but it does not.

However, here is the confusion: I’ve just found some java code that can take 2 vectors and produce all12 set of Euler/Cardan angles with different order of rotations, e.g. XYZ, ZXY, ZYX, etc. This can be extremly useful for animating armature objects.

I’ve converted the core part of this code into python, but I’ve run into problem during the test phase. For each axis-only transformation matrix, the matrices produced by the java code is in fact the transpose of the same matrices produced by Blender.Mathutil.Euler().toMatrix(). For example, if I want to have a rotation matrix around the X-axis by 54.7 degrees, the code: Blender.Mathutils.Euler(angle, 0, 0).toMatrix() would generate the following matrix:


[1.000000, 0.000000, -0.000000](matrix [row 0])
[0.000000, 0.577350, 0.816497](matrix [row 1])
[0.000000, -0.816497, 0.577350](matrix [row 2])

However, the java code would generate the following matrix:


0.9999999999999998      0.0     -0.0
-0.0    0.5773502691896257      -0.8164965809277259
0.0     0.8164965809277259      0.5773502691896257

It’s obvious that the above two matrices are transpose of each other.

Now, this poses a problem: to carry out the rotation order of X->Y->Z, I thought I had to use the first equation in the last list, but the correct results is produced only with the last equation in the last list. I don’t know how this would affect how blender interpretes the final transformation matrix.

Thanks a lot for reading.

The original java code can be found at:

http://www.spaceroots.org/mantissa-doc/org/spaceroots/mantissa/geometry/Rotation.html

-D

Not a compleate answer but some notes…
Recent versions of blender (2.43) - resizing the vector is not required to transform a 3d vector by a 4x4 matrix.

vec * matrix works, interesting that other apps do it the other way, maybe we’re wrong :confused:

If your interested in applying the rotations in a different order, the BVH importer I wrote has a function that does this, see - import_bvh.py in blender 2.43.

That’s good to know! :smiley:

Well, the bible of computer graphics – “Introduction to Computer Graphics” by Foley, Van Dam, Feiner, Hughes and Phillips, represents vectors as column vectors, therefore all multiplications between vectors and matrices are done in the order of [u]mat * vec[/b]. For example, Blender represents the rotation matrix around the X-axis as:


[1.0, 0.0, 0.0](matrix [row 0])
[0.0, cos, sin](matrix [row 1])
[0.0, -sin, cos](matrix [row 2])

But Foley, et.al represents the same rotation matrix as:


[1.0, 0.0, 0.0](matrix [row 0])
[0.0, cos, -sin](matrix [row 1])
[0.0, sin, cos](matrix [row 2])

I’m not sure how it works though. Can it convert XYZ to ZXY?

Thanks a lot!

-D

Ok, I’m now totally confused. What exactly does the following code do?


mat1 = Blender.Mathutils.Vector(x, y, z).toMatrix()

Does this create an euler rotation in the order of X->Y->Z ? If it does, then how is it different from the following code:


mat2 = Blender.Mathutils.Euler(x, 0, 0).toMatrix() * Blender.Mathutils.Euler(0, y, 0).toMatrix() * Blender.Mathutils.Euler(0, 0, z).toMatrix()

Shoud mat1 and mat2 be identical? If not, what would be the right order of combination to make them identical?

I’ve just tried your eulerRotate function in the bvh import, and I’m sorry to say that it cannot correctly change the rotation order. The only working code for converting different orders of rotations seems to be the java code I found
on the internet, I will post it here later this afternoon. However, this code doesn’t seem to work perfectly with blender. For example for an Z->X->Y rotation, I have to multiple the matrices in the order of: vec * rotY * rotX * rotZ (i.e. inverse the order of rotation, but the results seemed quite good).

Thanks a lot!

-D

double post

did you mean

mat1 = Blender.Mathutils.Euler(x, y, z).toMatrix() # was Vector

toMatrix makes a 3x3 rotation matrix from the euler rotation AFAIK.

The function in import_bvh definetry changes the order the axises are applied.

Probably a bit of trial and error should work it out…

No, I know that Blender.Mathutils.Euler(x, y, z).toMatrix() gives you a matrix. My question is what is the order of rotation produced by this matrix … my guess is that it’s X->Y->Z.

I know it does, but it doesn’t seem to produce the right angles.

I’ve been doing that for the last 3 hours and still have no luck. On the other hand, that Rotation java code I found is rather good … except that I’m not sure it uses the right-handed Cartesian coord system … stay tuned, I will release my code as soon as I figure out how to get the whole thing working.

-D

Ok, here is the final code, it DOES NOT handle co-linear cases, and you have to reverse the matrices in the multiplication to get it working, but it works:

www.csse.unimelb.edu.au/~jingy/download/Rotation.py