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,使用四元数设置旋转键?的主要内容,如果未能解决你的问题,请参考以下文章