获取FBX节点全局转局部空间变换出错的技术问询
问题:旧格式模型转FBX时骨骼全局-局部变换计算错误
我正在将旧格式专有模型转换为FBX格式,部分场景下获取FbxNode的全局到局部空间变换矩阵时出现错误。旧格式中的骨骼变换采用局部到全局空间的定义,不同于多数现代格式使用的局部到父级空间定义——节点坐标系基于全局坐标系而非父节点坐标系。我需要基于骨骼的全局空间原点构建尽可能准确的骨骼结构:
- 仅通过
FbxNode::LclTranslation设置节点位置,会导致子骨骼与父骨骼无法物理连接(两者间无灰色连接条) - 调整父骨骼的
FbxNode::LclRotation使其X轴指向子骨骼原点,并将子骨骼位置仅沿X轴设置,可解决大部分连接问题,但仍有部分骨骼连接异常
相关代码如下:
FbxVector4 childGlobal = getChildOriginInGlobalSpace(); FbxAMatrix globalToParentLocal = GetLocalToGlobalXform(pParent).Inverse(); // 把子骨骼全局空间原点映射到父骨骼局部空间,部分节点计算结果错误 FbxVector4 childParentLocal = globalToParentLocal.MultT(childGlobal); const auto distToChildParentLocal = childParentLocal.Length(); FbxVector4 eulerXYZ; FbxVector4::AxisAlignmentInEulerAngle( /*pAB*/ {0.0, 0.0, 0.0, 1.0}, /*pA*/ {1.0, 0.0, 0.0, 1.0}, /*pB*/ childParentLocal, eulerXYZ); // 调整父骨骼朝向 pParent->LclRotation.Set(eulerXYZ); // 设置子骨骼在父局部空间的位置 pNodeChild->LclTranslation.Set({ distToChildParentLocal, 0.0, 0.0}); // 有问题的函数:返回的全局到父变换矩阵不正确 FbxAMatrix GetLocalToGlobalXform(FbxNode* pNode) { FbxAMatrix lLocalPosition; FbxAMatrix lGlobalPosition; FbxAMatrix lParentGlobalPosition; lLocalPosition.SetTRS(pNode->LclTranslation.Get(), pNode->LclRotation.Get(), pNode->LclScaling.Get()); if (pNode->GetParent()) { lParentGlobalPosition = GetGlobalDefaultPosition(pNode->GetParent()); lGlobalPosition = lParentGlobalPosition * lLocalPosition; } else { lGlobalPosition = lLocalPosition; } return lGlobalPosition; }
目前多数骨骼位置正确且父骨骼朝向正常,但红色标记的骨骼位置错误,原因是这些节点在父局部空间中的原点计算错误——GetLocalToGlobalXform()函数对部分节点返回了错误的变换矩阵。
我在获取节点全局变换时是否遗漏了枢轴、预/后旋转、节点几何变换等因素?尝试过使用FbxNode::EvaluateGlobalTransform()但无效,FBX相关文档对此描述甚少。已验证这些节点的全局空间原点正确(通过全局位置创建的白色虚拟体可证明),但父局部空间原点错误导致骨骼错位。
另外,我也曾尝试将局部到全局转换为局部到父级变换:
FbxMatrix mapLocalToParent = mapLocalToGlobal * mapParentLocalToGlobal.Inverse();
但发现变换中存在不必要的剪切,使用FbxNode::LclTranslation、FbxNode::LclRotation和FbxNode::LclScale构建骨骼树会因剪切未被处理而导致骨骼变形,因此该尝试无效。
内容的提问来源于stack exchange,提问作者legends2k
相关产品推荐
相关产品推荐

