My question is, how can I convert a Blender Z-Up RH rotation to Y-Up RH (Maya, Houdini, etc.) rotation?

(I believe Blender uses a Right-Handed Z-Up orientation... correct me if wrong)


Position seems pretty basic. I am simply getting the position column of the world matrix like so:

posX = lightObj.matrix_world[0][3]
posY = lightObj.matrix_world[2][3]
posZ = lightObj.matrix_world[1][3]

(swizzling Z and Y)

Rotations on the other hand seem to need more than a simple swizzle. I have figured out how to get the Blender world space rotation in XYZ by doing this:


Now if only I knew what to do with it... I have searched for conversion formulas online and come up with several incomplete/incorrect implementations.

  • $\begingroup$ Related: Is it possible to make Blender a Y-up world? $\endgroup$ – gandalf3 Apr 29 '14 at 22:19
  • 1
    $\begingroup$ I'm not sure if it's correct, but in the past I've gotten correct-looking results by swizzling X > Z, Y > X, Z > Y. $\endgroup$ – gandalf3 Apr 29 '14 at 22:30
  • $\begingroup$ I think swizzling works in some cases but not all, as in the swizzle is different in different quadrants or something. From what I gather I might need to build a matrix to convert coordinate systems, or make use of quaternions... $\endgroup$ – PolyMesh Apr 29 '14 at 22:39
  • $\begingroup$ Just rotate all your objects by -90° around the x-axis. The rotation matrix will do the zwizzle for you. Just make sure you are rotating the objects relative to the world center, not relative to the object center. Then the relative positions of different objects will also be transformed correctly. $\endgroup$ – maddin45 Apr 30 '14 at 6:50
  • $\begingroup$ maddin45, I am not able to get this to work. I am getting a x = -90 rotation matrix, multiplying to the matrix_world of the object, then getting euler from there and results are pretty different. Can you tell me what I am doing wrong with this method? $\endgroup$ – PolyMesh Apr 30 '14 at 7:39

Finally got it! There were a few problems with my earlier attempts. The one that was throwing me off the most was incorrect position (because the rotations never looked consistently right with a wrong position)

It turns out I had the position wrong because the +Y in Blender is actually -Z in a Y-Up RH coordinate system. Or in other words when converting the code is:

posX = lightObj.matrix_world[0][3]
posY = lightObj.matrix_world[2][3]
posZ = -lightObj.matrix_world[1][3] # note the negative

(swizzle YZ and negate Z)

Another problem I encountered... It turns out there is a special case when exporting lights, which I didn't realize earlier. In Blender, the cone of a spotlight with zero rotations aims straight down, where in Maya, Houdini, and my game engine, spotlights face down the -Z. (If blender were to match this it would aim down the +Y)

So with these in mind, I came to this for rotations:

# for objects
obj = bpy.data.objects['objName']
mm = bpy_extras.io_utils.axis_conversion(from_forward='Y', from_up='Z', to_forward='-Z', to_up='Y')
om = obj.matrix_world.to_3x3()
t = mm * om
v = t.to_euler('XYZ')
print('pos:(%s, %s, %s)' % (obj.matrix_world.translation.x, obj.matrix_world.translation.z, -obj.matrix_world.translation.y))
print('rot:(%s, %s, %s)' % (degrees(v.x) + 90.0, degrees(v.y), degrees(v.z)))
# not totally sure why we need the +90 in X, but assume it has something to do with compensating for the axis_conversion

# for spot lights (they face straight down in Blender)
obj = bpy.data.objects['spotLightName']
mm = bpy_extras.io_utils.axis_conversion(from_forward='Y', from_up='Z', to_forward='-Z', to_up='Y')
om = obj.matrix_world.to_3x3()
t = mm * om
v = t.to_euler('XZY') # not sure why this needs to be XZY for spot lights and XYZ for objects
print('pos:(%s, %s, %s)' % (obj.matrix_world.translation.x, obj.matrix_world.translation.z, -obj.matrix_world.translation.y))
print('rot:(%s, %s, %s)' % (degrees(v.x), degrees(v.y), degrees(v.z)))
# note: there is no need for the axis_conversion rotation compensation due to the spotlight facing down already

As you can see in the comments, there are still things I am not clear on and not sure I am doing right, so please feel free to comment/correct me where wrong.

I have a feeling something might be off with my rotation order stuff, but I don't know what it should be. All I know intuitively is that it makes sense to use XZY since that is what I am swizzling to, that should match the post-swizzled rotation order so it is XYZ in both systems right?


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.