I'm working on pulling geometry and it's transformation from a 3DS Max exported FBX (Z-up) to an OpenGL model format (Y-up). The main problem is I intend to keep the transformations as Translation and XYZ rotations.

Right now I pull all position transforms simply going from (x y z) to (x z -y) and everything looks good. However the geometry rotation comes in as Euler angle rotations ( X Y Z ). Rotating these has turned into a nightmare. I know I can get a matrix and just multiply it by the RotX-90 mat but pulling those Eulers back is not reliable.

What seems to almost work is this, and it's what seemed to give correct results most of the time. It jut seems bad for the case ( 92.83, -89.41, 53.53) for example when it looks like it's loosing a 90 deg rotation on X.

Matrix rot90 ( 1,  0, 0, 0,
               0,  0, 1, 0,
               0, -1, 0, 0,
               0,  0, 0, 1);

RotMat = RotX * RotY * RotZ
RotMat = Rot90X * RotMat 
Quaternion = Convert from RotMat
NewX = Quaternion.Pitch
NewY = Quaternion.Yaw
NewZ = Quaternion.Roll

I know the god of bit shifting must have some civil way of doing this. Any tips/suggestions would be greatly appreciated.

ps. exporting the FBX with Y up won't work as it just seems to apply a transformation on the root node, not to actually swap vertices y-z positions.

  • \$\begingroup\$ If you rotate around the x axis counter-clockwise 90 degrees, you get he y-up scenario \$\endgroup\$
    – Bálint
    Commented Feb 14, 2017 at 7:51

1 Answer 1


If you want to convert Z_UP to Y_UP, rotating around X by -90d will give you same look, but if you want to convert/change positions from Z_UP to Y_UP then:

Converting positions in Z_UP (x y z) to (x z -y) will give you same look in Y_UP if all transforms are IDENTITY. You also need to convert transforms, cameras and light orientations (because default is [0 0 -1] in RH):

  • Convert all positions, normals... to Y_UP
  • Converting position of transform is very easy -> (x y z) to (x z -y)
  • You need to convert rotation to new coord sys with correct order:
    • First you can decompose affine matrix and get rotation matrix and scaling factors
    • Then extract euler angles using XYZ
    • Then convert XYZ sequence to new coord-sys (Y_UP)
    • Apply new rotation
    • Convert scaling factors to Y_UP
    • Combine Translate, Rotate and Scale as new Affine Transform Matrix
  • You may need to add extra rotations to camera and lights to fix orientations. For instance if camera has idendity transform then it looks toward -Z but -Z is -Y in Y_UP

I hope this will help!

  • \$\begingroup\$ I understand all you said, and I already do most part of it. The problem I face is for the 3rd point: "Then convert XYZ sequence to new coord-sys (Y_UP)" You can't just get rotation angles and swap them as with the position (at least it seems to me now). \$\endgroup\$
    – Enam Desak
    Commented Feb 15, 2017 at 19:16
  • \$\begingroup\$ @EnamDesak why not? after swapping XYZ angles then you have to find new sequence/order e.g. XZY and get rotation matrix from func like glm_euler_xzy(vec3 angles, mat4 out) not glm_euler_xyz(...), as you said you can't just swap XYZ angles and apply rotation as XYZ. \$\endgroup\$
    – recp
    Commented Feb 15, 2017 at 19:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .