我正在构建一个小型游戏引擎并使用fbx sdk来进行ipmort fbx网格和动画,这意味着我想在我自己的类中存储动画 . 现在,有两种方法可以实现这一目标:

  • 第一种方法是仅存储关键帧 . 如果我只存储关键帧,我将在fbx文件中包含原始动画数据,我可以随时操作或调整动画 .

  • 第二种方法是以固定的速率对帧进行采样 . 我没有存储关键帧,而是从fbx文件中获取了一些我需要的帧并存储它们 . 这样,我可能会丢失原始动画数据,因为当我对帧进行采样时,所选择的帧可能不是关键帧,从而导致细节的轻微丢失 .

从我的角度来看,第一种方式是最好的方式,但互联网上的大多数tutorails都使用第二种方式 . 例如,here . 以下是它的片段:

for (FbxLongLong i = start.GetFrameCount(FbxTime::eFrames24); i <= end.GetFrameCount(FbxTime::eFrames24); ++i)
{
    FbxTime currTime;
    currTime.SetFrame(i, FbxTime::eFrames24);
    *currAnim = new Keyframe();
    (*currAnim)->mFrameNum = i;
    FbxAMatrix currentTransformOffset = inNode->EvaluateGlobalTransform(currTime) * geometryTransform;
    (*currAnim)->mGlobalTransform = currentTransformOffset.Inverse() * currCluster->GetLink()->EvaluateGlobalTransform(currTime);
    currAnim = &((*currAnim)->mNext);
}

请注意,函数EvaluateGlobalTransform(..)是一个fbxsdk函数,它似乎是我们和我们可以依赖的fbx动画之间唯一安全的接口 . 另外,似乎第二种方式(使用EvaluateGlobalTransform以特定的速率进行采样)是完成这项工作的标准且普遍接受的方式 . there是一个解释说:

“FBX SDK为您提供了许多方法来获取您可能想要的数据 . 不幸的是,由于不同的DCC工具(Max / Maya / etc),您可能无法获得所需的数据 . 例如,让我们说您可以找到根骨骼并在动画中对其进行平移 . 您可以通过多种方式访问变换 . 您可以使用LclTransform属性并在不同时间请求FbxAMatrix . 或者您可以使用获得矩阵的时间 . 或者您可以使用评估者的EvaluateNode函数一次评估节点 . 最后,最复杂的版本是您可以从属性中获取曲线节点并查看曲线的键 . 给出所有这些选项你可能会想到让曲线成为可能的方法 . 不幸的是,例如,Maya将动画数据烘焙到一组与Maya中实际设置的按键无关的按键 . 原因是曲线Maya使用与FBX支持不同秒 . 因此,即使您直接获得曲线,它们也可能有数百个键,因为它们可能已被烘焙 . 这意味着,除非Max拥有FBX支持的曲线,否则它可能会烘焙它们,你将无法找到你的术语中原来的两个构成的东西 . 通常,您将迭代时间并以固定速率对场景进行采样 . 是的,它有点糟糕,通常你会想要在采样后简化数据 . “

To sum up:

  • 第一种方式:

优点:易于操作和调整,精确的细节,更少的内存消耗(如果你动态生成顶点变换矩阵)

缺点:难以获得这些关键帧,不适用于某些fbx文件

  • 第二种方式:

优点:易于选择框架,适用于所有fbx文件

缺点:难以改变动画,大内存消耗,细节不准确

So, my questions are:

  • 第二种方式真的是常见的方法吗?

  • 像Unreal和Unity这样的着名游戏引擎使用哪种方式?

  • 如果我想使用第一种方法,即使它在某些情况下可能不起作用,我怎样才能从fbx文件中获取关键帧(即不使用EvaluateGlobalTransform但使用FbxAnimStack,FbxAnimLayer,FbxAnimCurveNode,FbxAnimCurve,FbxAnimCurveKey)?