# Custom exporter and problems with matrix and rotation order

I'm trying to write a custom exporter for cameras from/to Blender, but I'm having some problems with rotations and rotation order. In my mind I should be able to extract euler values from the world matrix in whatever rotation order I want, and as long as I make sure my camera in my other app use the same rotation order it should all work. But no.

Here's some example code:

import bpy
import mathutils
import math

item = bpy.data.objects["Camera"]

wm_src = item.matrix_world.copy()

wm = wm_src @ rot_mat

wm.transpose()

# Only works if rotation order is set to this.
rot = wm.to_euler("ZXY")

rotx = -math.degrees(rot.x)
roty = math.degrees(rot.y)
rotz = -math.degrees(rot.z)

rot_fix = (rotx, rotz, roty)

print(rot_fix)


This code works and the values match with the Alembic exporter.

However, it only works when I set the rotation order to ZXY. If I don't use ZXY, the camera is not rotated correctly. Am I missing something to be able to use whatever rotation order I want?

I'm not great with C++ code but is the Alembic exporter hardcoded to this order as well? It seems so.

Also, why do I need to transpose the matrix?

• For example, If I take the default camera in Blender (which is set to XYZ rotation order) and run the above code I get (-26.4, 46.7, 0.0). If I change the rotation order in the code snippet above to XYZ and keep the camera unchanged I get (-18.8, 43.5, 18.9). When applying those values to cameras with the correct rotation order the one with XYZ does not match. Nov 14 '19 at 21:24
• I think this could be just a matter of converting the axes?, Blender uses Y forward Z up. The camera object in blender looks -Z forward Y up. I don't know how it is in alembic. There is a helper method see from bpy_extras.io_utils import axis_conversion which creates a transform matrix from one def to the other. On the transpose, my guess is it is a quick way to invert an orthonormal matrix (eg a rotation matrix) Nov 15 '19 at 1:56
• (* -Y forward) Related blender.stackexchange.com/a/102356/15543 Nov 15 '19 at 2:07
• Thanks a lot. I did play with this before, but I must have missed something. Works perfectly now :). I did have to remove the transpose now though, not sure why. Nov 15 '19 at 12:19

With ther help of batFINGER and the other post, here's the working code:

import bpy
import mathutils
import math
from bpy_extras.io_utils import axis_conversion

item = bpy.data.objects["Camera"]

wm_src = item.matrix_world.copy()

m = axis_conversion(from_forward='-Y',
from_up='Z',
to_forward='Z',
to_up='Y').to_4x4()

wm = m @ wm_src

rot = wm.to_euler("XYZ")

rotx = math.degrees(rot.x)
roty = math.degrees(rot.y)
rotz = math.degrees(rot.z)

rot_fix = (rotx, roty, rotz)

print(rot_fix)