Search code examples
rotationquaternionseuler-anglesangle

Convert Quaternion back into Euler


I am trying to figure out how to convert Collada (from Assimp) Quaternions for animation rotation, back into Euler rotations for FBX. I am sure it is a simple algorithm, I just can't find the right one...all the ones I try are wrong, that are usually called ToEulerXYZ. Perhaps it's because these rotations are X, then Y, then Z, instead of simultaneous? Someone in the know can probably help easily.

Here are my test samples - I input euler angles, and then export collada and get the equivalent quaternion. I'd like to do the opposite (and from quaternion, get euler). Note, that I am aware won't always get same value, but just need values that yield same rotation.

Sample values: Euler X, Y, Z Quaternion X, Y, Z, W

0,0,0-> 0,0,0,1

0.000000,0.000000,45.000000-> 0,0,0.38268346,0.92387956

45,0,45-> 0.35355338, 0.14644660, 0.35355338,0.85355341

45,45,0 0.35355338,0.35355338,-0.14644660,0.85355341

45,45,45-> 0.19134171,0.46193978,0.19134171,0.84462321

30,45,60-> 0.022260016,0.43967974,0.36042345,0.82236314

If this helps, Assimp is generating the quaternion this way (under Assimp license):

                    angle = 60 * float( AI_MATH_PI) / 180.0f;
                    axis = aiVector3D( 0.0f, 0.0f, 1.0f);
                    aiMatrix4x4::Rotation( angle, axis, rot);
                    res *= rot;

                    angle = 45 * float( AI_MATH_PI) / 180.0f;
                    axis = aiVector3D( 0.0f, 1.0f, 0.0f);
                    aiMatrix4x4::Rotation( angle, axis, rot);
                    res *= rot;

                    angle = 30 * float( AI_MATH_PI) / 180.0f;
                    axis = aiVector3D( 1.0f, 0.0f, 0.0f);
                    aiMatrix4x4::Rotation( angle, axis, rot);
                    res *= rot;



                    aiVector3D scale;
                    aiQuaternion rotation;
                    aiVector3D translation;
                    res.Decompose(scale, rotation, translation);

Solution

  • Figured it out, and appreciate your help antont. It was a nuance of Assimp. Apparently it for some odd reason (bug?) reads rotations in backwards, and so you have to do ToEulerZYX, but then reverse use of xyz to zyx.

                        float3 keyValueOrig = quat.ToEulerZYX();
                        float3 keyValue;
    
                        keyValue.z = RadToDeg(keyValueOrig.x);
                        keyValue.y = RadToDeg(keyValueOrig.y);
                        keyValue.x = RadToDeg(keyValueOrig.z);