我想从 fbx
文件中读取 3D 模型,并在 iPhone 上的 openGL es 2.0
引擎中显示它(不使用 Unity
),并且我还想显示读取的 3D 对象的动画。
如何从 fbx
文件获取动画?
目前,我能够获取姿势名称列表,这些名称似乎是带有变换矩阵的,以及层、堆栈、层中所有姿势的完整列表和许多曲线。
如何将所有这些信息组合起来以显示正确的动画?
我还尝试解析 TakeInfo 中的一些信息,但对我来说结果有点奇怪,例如:
FbxTakeInfo *ltakeInfo = pScene->GetTakeInfo(lAnimStack->GetName());
FbxTime start = ltakeInfo->mLocalTimeSpan.GetStart();
FbxTime end = ltakeInfo->mLocalTimeSpan.GetStop();
self.startTime = start.GetSecondDouble();
self.endTime = end.GetSecondDouble();
这里我得到了每个解析层的
start = 0
和 end = 0.014
,所以我猜测这是不正确的(我想要显示的 fbx
文件包含一个网格和简单的5秒持续动画)。
更新
经过几个小时的调查,我得到了以下结果:
为了参考,这是我想要显示的测试对象的结构:
在这里,您可以看到很多骨头(更具体地说-19个)。如上所述,我能够在列表中获取19个带动画的obj(例如骨骼/obj的名称),以及每个组内有151帧的19个曲线组(帧速率为30,正好是5秒的动画-30 * 5 = 150 +1最后的单位矩阵)。如果我尝试逐个使用每个曲线组来应用于我的网格(我只能解析一个网格),我会看到应用于所有网格的不同部分的动画(例如垂直旋转或水平平移),因此我认为这些曲线在每个组中应该被准确地应用于特定的骨骼,结果我将获得我的网格的动画。问题是我不知道如何仅对选定的骨骼顶点部分进行动画处理。
现在的问题是如何将分成单独的骨骼的所有动画应用于整个obj(因为我只有一个网格)?
如何从包含所有曲线组的列表中获取每个帧的1个全局曲线列表?
更新2
感谢@codetiger的建议,我遵循评论中提供的链接中的说明,并使用该技术检索了特定骨骼材质的列表,包括开始和结束时间以及所需的变换,但这与我之前使用曲线获得的结果几乎相同——唯一的区别是,对于曲线,我应该从9个曲线(用于x y z的平移/缩放/旋转)创建材料,而不是使用完整矩阵,但问题仍然存在——如何将它们组合在一个全局矩阵中?
我使用的代码(找到了一些链接):
FbxNode* modelNode = _fbxScene->GetRootNode();
FbxAMatrix geometryTransform = GetGeometryTransformation(modelNode);
for (unsigned int deformerIndex = 0; deformerIndex < numOfDeformers; ++deformerIndex) {
FbxSkin* currSkin = reinterpret_cast<FbxSkin*>(mesh->GetDeformer(deformerIndex, FbxDeformer::eSkin));
if (!currSkin) {
continue;
}
unsigned int numOfClusters = currSkin->GetClusterCount();
for (unsigned int clusterIndex = 0; clusterIndex < numOfClusters; ++clusterIndex) {
FbxCluster* currCluster = currSkin->GetCluster(clusterIndex);
std::string currJointName = currCluster->GetLink()->GetName();
FbxAMatrix transformMatrix;
FbxAMatrix transformLinkMatrix;
FbxAMatrix globalBindposeInverseMatrix;
currCluster->GetTransformMatrix(transformMatrix);
currCluster->GetTransformLinkMatrix(transformLinkMatrix);
globalBindposeInverseMatrix = transformLinkMatrix.Inverse() * transformMatrix * geometryTransform;
FbxAnimStack* currAnimStack = _fbxScene->GetSrcObject<FbxAnimStack>(0);
FbxString animStackName = currAnimStack->GetName();
char *mAnimationName = animStackName.Buffer();
FbxTakeInfo* takeInfo = _fbxScene->GetTakeInfo(animStackName);
FbxTime start = takeInfo->mLocalTimeSpan.GetStart();
FbxTime end = takeInfo->mLocalTimeSpan.GetStop();
FbxLongLong mAnimationLength = end.GetFrameCount(FbxTime::eFrames24) - start.GetFrameCount(FbxTime::eFrames24) + 1;
for (FbxLongLong i = start.GetFrameCount(FbxTime::eFrames24); i <= end.GetFrameCount(FbxTime::eFrames24); ++i) {
FbxTime currTime;
currTime.SetFrame(i, FbxTime::eFrames24);
FbxAMatrix currentTransformOffset = modelNode->EvaluateGlobalTransform(currTime) * geometryTransform;
FbxAMatrix mat = currentTransformOffset.Inverse() * currCluster->GetLink()->EvaluateGlobalTransform(currTime);
}
}
}
这里我收到的矩阵是121而不是151 - 但是一些矩阵变换的持续时间比1帧的绘制时间长,所以我认为这里的数量也是正确的。
float duration = end.GetSecondDouble() - start.GetSecondDouble(); //return 5 as and expected
我猜测在
Autodesk SDK
中,有一种方法可以获得每个绘制调用的全局变换。你有什么建议吗?这可行吗?
为任何能够描述如何在iPhone上使用Autodesk SDK和openGLES 2.0显示动画的人添加悬赏...(抱歉,Facebook打错了)
这是我的翻译:
以下是我能获取到的内容
Blender
中的原始对象