3
$\begingroup$

Running this code from Blender's scripting screen creates two matrices with the same to_euler(), to_scale(), and to_translation() properties (within at least 0.001%), but they produce slightly (~2% different) translations. This difference seems too large to attribute to round-off error. Is there something I'm missing?

m1 = Matrix(((-9.60141658782959, -0.5545974373817444, 0.5386476516723633, -30.135377883911133),
    (5.600399971008301, -0.7278052568435669, 0.7324938774108887, -11.959151268005371),
    (-0.019546210765838623, 0.10690498352050781, 3.481797695159912, 8.77576732635498),
    (0.0, 0.0, 0.0, 1.0)))
m2 = Matrix(((-9.60141658782959, -0.4610302448272705, 0.21047912538051605, -30.135377883911133),
    (5.600399494171143, -0.7900149822235107, 0.37331894040107727, -11.959151268005371),
    (-0.019546210765838623, 0.10970357060432434, 3.5729448795318604, 8.77576732635498),
    (0.0, 0.0, 0.0, 1.0)))
print('Scales')
print(m1.to_scale())
print(m2.to_scale())
print('Translations')
print(m1.to_translation())
print(m2.to_translation())
print('Rotations')
print(m1.to_euler())
print(m2.to_euler())
print('Transformations')
print(m1 * Vector((1,1,1)))
print(m2 * Vector((1,1,1)))

This outputs:

Scales
<Vector (11.1154, 0.9213, 3.5986)>
<Vector (11.1154, 0.9213, 3.5986)>
Translations
<Vector (-30.1354, -11.9592, 8.7758)>
<Vector (-30.1354, -11.9592, 8.7758)>
Rotations
<Euler (x=0.1194, y=0.0018, z=2.6136), order='XYZ'>
<Euler (x=0.1194, y=0.0018, z=2.6136), order='XYZ'>
Transformations
<Vector (-39.7527, -6.3541, 12.3449)>
<Vector (-39.9873, -6.7754, 12.4389)>

In the last 3 lines the transformations aren't equal, though everything else is.

$\endgroup$
  • $\begingroup$ They are two different matrices. Not sure that if the translation, rotation and scale components are the same it translates that the matrices are the same (as shown)... maybe it's akin to producing gimbal lock for Eulers Hence a different result when mutliplying by vector. $\endgroup$ – batFINGER Feb 26 '18 at 9:53
  • $\begingroup$ You have large scale, if you're multiplying by over 10-fold, that is going to multiply the error as well. $\endgroup$ – kheetor Feb 26 '18 at 13:08
  • $\begingroup$ After playing around with transforms I'm not sure about this theory. Some of your matrix values differ a lot, how are you generating them? If you visualize the matrices I bet you have easier time understanding them. You can reference Blender objects with bpy.context.selected_objects and object.matrix_world / object.matrix_local. $\endgroup$ – kheetor Feb 26 '18 at 13:22
  • $\begingroup$ @kheetor the math viz console addon is a great way to visualize matrices. $\endgroup$ – batFINGER Feb 26 '18 at 14:32
  • $\begingroup$ Could you please elaborate on how you produced m1 and m2 ? $\endgroup$ – batFINGER Feb 26 '18 at 15:06
2
$\begingroup$

Use Quaternions for unique rotation

As well as the matrices being distinctly different, the quaternion rotations returned from your matrices are distinctly different. See this blurb here on Mathematics of Eulers

Matrices m1 and m2 displayed in 3D view using Maths Vis Console Addon enter image description here

Adding some lines of code to your example,

print('Rotations Quaternion')
print(m1.to_quaternion())
print(m2.to_quaternion())
print('Rotations Quaternion to Euler')
print(m1.to_quaternion().to_euler())
print(m2.to_quaternion().to_euler())

To get a quaternion representation of the rotation

Rotations Quaternion
<Quaternion (w=0.2698, x=-0.0753, y=0.1302, z=0.9511)>
<Quaternion (w=0.2605, x=0.0147, y=0.0578, z=0.9636)>
Rotations Quaternion to Euler
<Euler (x=0.2136, y=0.2151, z=2.6118), order='XYZ'>
<Euler (x=0.1194, y=0.0018, z=2.6136), order='XYZ'>

Notice only the Euler result for Matrix m2 corresponds. Can decompose a Matrix into its components with Matrix.decompose() The rotation part is returned as a quaternion. Here is an example that decomposes and recomposes the matrix m2

v2, q2, s2 = m2.decompose()

S = Matrix.Scale(1, 4)
for i, axis in enumerate(s2):
    S[i][i] = axis
m = Matrix.Translation(v2) * q2.to_matrix().to_4x4() * S

print(Vector(m.to_euler()) -  Vector(m2.to_euler()))
print(m2 - m)

Produces the result

<Vector (-0.0000, 0.0000, 0.0000)>
<Matrix 4x4 (-0.0000, -0.0000, 0.0000, 0.0000)
            ( 0.0000, -0.0000, 0.0000, 0.0000)
            (-0.0000,  0.0000, 0.0000, 0.0000)
            ( 0.0000,  0.0000, 0.0000, 0.0000)>
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.