1

我试图弄清楚如何将 Collada(来自 Assimp)四元数转换为动画旋转,回到 FBX 的欧拉旋转。我确信这是一个简单的算法,我只是找不到正确的算法......我尝试的所有算法都是错误的,通常称为 ToEulerXYZ。也许是因为这些旋转是 X,然后是 Y,然后是 Z,而不是同时旋转?知道的人可能很容易提供帮助。

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

样本值:欧拉 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);
4

2 回答 2

1

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

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

于 2014-05-10T23:09:27.507 回答
1

想通了,感谢您的帮助。这是 Assimp 的一个细微差别。显然它出于某种奇怪的原因(错误?)向后读取旋转,因此您必须执行 ToEulerZYX,然后将 xyz 反向使用为 zyx。

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

                    keyValue.z = RadToDeg(keyValueOrig.x);
                    keyValue.y = RadToDeg(keyValueOrig.y);
                    keyValue.x = RadToDeg(keyValueOrig.z);
于 2014-05-11T14:54:39.923 回答