将四元数转换回欧拉

时间:2014-05-10 22:47:32

标签: rotation quaternions euler-angles angle

我试图找出如何将Collada(来自Assimp)Quaternions转换为动画旋转,然后转换为FBX的Euler旋转。我确信这是一个简单的算法,我找不到合适的算法...我尝试的所有都是错的,通常称为ToEulerXYZ。也许是因为这些旋转是X,然后是Y,然后是Z,而不是同时?知道的人可能很容易帮助。

这是我的测试样本 - 我输入了欧拉角,然后导出collada并获得等效的四元数。我想做相反的事情(从四元数来看,得到欧拉)。请注意,我知道并不总是得到相同的值,但只需要产生相同旋转的值。

样本值: Euler X,Y,Z 四元数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

如果这有帮助,Assimp会以这种方式生成四元数(在Assimp许可下):

                    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);

2 个答案:

答案 0 :(得分:1)

根据文档,默认的FBX Euler旋转顺序确实是XYZ。 FBX SDK的Quat类有一种方法可以通过这种方式将quat转换为euler:http://docs.autodesk.com/FBX/2014/ENU/FBX-SDK-Documentation/index.html?url=files/GUID-3E0DCCD0-5F9A-44D0-8D5E-423237D49DB6.htm,topicNumber=d30e9965中的DecomposeSphericalXYZ

因此,鉴于您的ToEulerXYZ是正确的,它应该工作。确保你没有混合度和弧度......

答案 1 :(得分:1)

想出来,感谢你的帮助。这是阿西姆的细微差别。显然它出于一些奇怪的原因(bug?)向后读取旋转,所以你必须做ToEulerZYX,然后反向使用xyz到zyx。

                    float3 keyValueOrig = quat.ToEulerZYX();
                    float3 keyValue;

                    keyValue.z = RadToDeg(keyValueOrig.x);
                    keyValue.y = RadToDeg(keyValueOrig.y);
                    keyValue.x = RadToDeg(keyValueOrig.z);