FBXSDK,使用四元数设置旋转键?

Posted

技术标签:

【中文标题】FBXSDK,使用四元数设置旋转键?【英文标题】:FBXSDK, using Quaternions to set rotation keys? 【发布时间】:2018-05-24 23:54:24 【问题描述】:

我正在尝试使用 Autodesk FBXSDK 编写文件保存应用程序。我使用欧拉旋转可以正常工作,但我需要更新它以使用四元数。

相关函数为:

bool CreateScene(FbxScene* pScene, double lFocalLength, int startFrame)

    //Create Camera
    FbxNode* lMyCameraNode = FbxNode::Create(pScene, "p_camera");
    //connect camera node to root node
    FbxNode* lRootNode = pScene->GetRootNode();
    lRootNode->ConnectSrcObject(lMyCameraNode);
    FbxCamera* lMyCamera = FbxCamera::Create(pScene, "Root_camera");
    lMyCameraNode->SetNodeAttribute(lMyCamera);


    // Create an animation stack
    FbxAnimStack* myAnimStack = FbxAnimStack::Create(pScene, "My stack");

    // Create the base layer (this is mandatory)
    FbxAnimLayer* pAnimLayer = FbxAnimLayer::Create(pScene, "Layer0");

    myAnimStack->AddMember(pAnimLayer);

    // Get the camera’s curve node for local translation.

    FbxAnimCurveNode* myAnimCurveNodeRot = lMyCameraNode->LclRotation.GetCurveNode(pAnimLayer, true);

    //create curve nodes
    FbxAnimCurve* myRotXCurve = NULL;   
    FbxAnimCurve* myRotYCurve = NULL;
    FbxAnimCurve* myRotZCurve = NULL;

    FbxTime lTime;                         // For the start and stop keys.  int lKeyIndex = 0;                // Index for the keys that define the curve



    // Get the animation curve for local rotation of the camera.
    myRotXCurve = lMyCameraNode->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, true);
    myRotYCurve = lMyCameraNode->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, true);
    myRotZCurve = lMyCameraNode->LclRotation.GetCurve(pAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, true);


    //This to add keys, per frame.  
    float frameNumber = startFrame;

    for (int i = 0; i < rec.size(); i++)
    
        lTime.SetFrame(frameNumber);  //frame number

        //rx
        lKeyIndex = myRotXCurve->KeyAdd(lTime);
        myRotXCurve->KeySet(lKeyIndex, lTime, recRotX[i], FbxAnimCurveDef::eInterpolationLinear);

        //ry
        lKeyIndex = myRotYCurve->KeyAdd(lTime);
        myRotYCurve->KeySet(lKeyIndex, lTime, recRotY[i], FbxAnimCurveDef::eInterpolationLinear);

        //rz
        lKeyIndex = myRotZCurve->KeyAdd(lTime);
        myRotZCurve->KeySet(lKeyIndex, lTime, recRotZ[i], FbxAnimCurveDef::eInterpolationLinear);

        frameNumber += 1;

    

    return true;

理想情况下,我希望在这里传入四元数数据,而不是欧拉 x、y、z 值。 fbxsdk可以做到这一点吗?还是我需要先转换我的四元数数据,然后继续传入欧拉? 谢谢。

【问题讨论】:

【参考方案1】:

接受的答案不起作用。虽然the documentation 绝对暗示应该这样做,

创建一个等效于当前四元数的 Euler XYZ。

一位 Autodesk 员工 claims 不是

DecomposeSphericalXYZ 不会转换为欧拉角

我的测试证实了这一点。在当前的 FBX SDK 中,至少有两种相对简单的方法可以将 quat 转换为他们所谓的 euler 或适合 LclRotation 的东西。首先是通过FbxAMatrix

    FbxQuaternion fq = ...;
    FbxAMatrix fa;
    fa.SetQ(fq);
    FbxVector4 fe = fa.GetR();

第二个是通过FbxVector::SetXYZ

    FbxVector4 fe2;
    fe2.SetXYZ(fq);

我已经成功地从这两种方法中的 XYZ 旋转序列 → 四元数 → 欧拉出发,并检索到相同的旋转序列。当我使用DecomposeSphericalXYZ 时,我得到的FbxVector4 略有不同。我还没有试图弄清楚“球坐标中的欧拉”是什么意思。

【讨论】:

【参考方案2】:

您总是需要回到欧拉角,因为您只能获得 XYZ 旋转的动画曲线。您唯一可以控制的是轮换顺序。

但是,您可以使用 FbxQuaternion 进行计算,然后使用 .DecomposeSphericalXYZ() 获取 XYZ 欧拉角。

【讨论】:

谢谢!我最终使用:Eigen::Quaternionf q(rw, rx, ry, rz); auto euler = q.toRotationMatrix().eulerAngles(0, 1, 2); //roll, pitch, yaw 但也会看看.DecomposeSphericalXYZ() 再次嗨,使用 Eigen 仍然给我奇怪的欧拉翻转,所以我正在调查你的答案。 DecomposeSphericalXYZ 给了我其他欧拉问题,在不同的轴上旋转而不是预期。我正在使用:fbxsdk::FbxQuaternion fbxQuat(rx, ry, rz, rw); fbxsdk::FbxVector4 fbxeuler = fbxQuat.DecomposeSphericalXYZ();,然后将前三个值 `fbxeuler []0 作为 X,fbxeuler [1] 作为 Y,fbxeuler [2] 作为 Z。这是正确的吗?再次感谢! 是的,应该是这样。你能发布一些代码来显示旋转应该如何以及它是如何出现的吗?角度分解的顺序可能存在一些差异。另外,请检查您是否在 FBX 中使用 XYZ 旋转顺序

以上是关于FBXSDK,使用四元数设置旋转键?的主要内容,如果未能解决你的问题,请参考以下文章

四元数法

四元数运动学笔记旋转的雅克比矩阵

四元数 3 轴旋转

四元数绕轴旋转的分量

四元数运动学笔记四元数和旋转相关的约定表述

将四元数拆分为轴旋转