首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >从*.FBX文件读取和显示动画

从*.FBX文件读取和显示动画
EN

Stack Overflow用户
提问于 2016-08-15 08:19:47
回答 1查看 3.4K关注 0票数 9

我想从fbx文件中读取3d模型,并在openGL es 2.0引擎中在iPhone上显示它(不使用Unity),还想显示读取3d对象的动画。

如何从fbx 文件中获取动画?

目前,我能够得到的姿势名称列表,如我所理解的,与转换矩阵,在层中的姿势的完整列表,堆栈,层,和许多曲线。

如何将所有信息组合在一起以显示适当的动画?

我还试图在TakeInfo中解析一些信息,但结果有点奇怪,例如:

代码语言:javascript
复制
    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 = 0end = 0.014,所以我认为这是不正确的(我想要显示的fbx文件包含一个网格和简单的5秒持续时间动画)。

更新

经过几个小时的调查,我发现了接下来的事情:

作为参考,这是我想显示的测试obj的结构:

在这里,你可以看到很多骨头(更具体的- 19),我能够得到(如上所述)在列表中的19个动画obj (像骨头/obj的名字)和19组曲线在151帧内每帧(帧速率30秒正好5秒的anim。- 30*5=150 +1最后恒等矩阵)。

如果我试着用每个曲线组逐一对我的网格(我只能解析一个网格),我看到不同部分网格的动画应用于所有的网格(例如垂直旋转或水平平移),所以我认为每个组中的这条曲线应该精确地应用到特定的骨头上,因此我会为我的网格获得动画。问题是,我不知道如何动画只选定的骨头顶点部分。

现在的问题是,如何应用所有的动画分割成一个单独的组特定于整个obj (因为我只有一个网格)?

如何从包含所有曲线组的列表中获得每个帧的1条全局曲线列表?

Update2

由于@codetiger的建议,我遵循注释中提供的链接中的指示,使用这种技术,我能够检索具有开始和结束时间并需要转换的特定于骨的垫子的列表,但这几乎和我以前在曲线上得到的一样--我应该用9条曲线创建mat (转换/缩放/旋转x y z)而不是使用完整的矩阵,但问题仍然存在--我如何将它们组合到一个全局矩阵中?

我使用的代码(很少找到它的链接):

代码语言:javascript
复制
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个矩阵,但是一些矩阵转换的持续时间超过了一个框架的绘制时间,所以这里的q-ty也是正确的。

代码语言:javascript
复制
float duration = end.GetSecondDouble() - start.GetSecondDouble(); //return 5 as and expected

我猜Autodesk SDK有一种方法可以让每个drawCall得到一个全局转换

有什么建议吗?这个是可能的吗?

添加赏赐任何人谁可以描述如何在iPhone上显示动画在openGLES 2.0与自动桌面SDK.(对不起错误,而不是Facebook)

这是我能得到的

blender中的原始对象

如果我分别画骨(相同的VBO,不同的变换,每根骨头的指标一致)

EN

Stack Overflow用户

发布于 2016-08-26 05:31:29

下面是如何在OpenGL ES中渲染动画网格。这将为您提供关于您需要从文件中读取哪些细节的票价信息。

方法1:(GPU剥皮)

这种方法只适用于有限数量的骨骼,基于硬件的能力。通常这取决于你可以发送到着色器的矩阵的数量。

使用BindAttributes一次将网格信息绑定到GPU,并以制服将矩阵发送到着色器。

步骤1:读取所有骨矩阵并创建一个矩阵数组,并以制服将此数据发送给着色器。

步骤2:在顶点着色器中,像下面的着色器那样计算gl_position

代码语言:javascript
复制
attribute vec3 vertPosition;
attribute vec3 vertNormal;
attribute vec2 texCoord1;
attribute vec3 vertTangent;
attribute vec3 vertBitangent;
attribute vec4 optionalData1;
attribute vec4 optionalData2;

uniform mat4 mvp, jointTransforms[jointsSize];

void main()
{
    mat4 finalMatrix;

    int jointId = int(optionalData1.x);
    if(jointId > 0)
        finalMatrix = jointTransforms[jointId - 1] * optionalData2.x;

    jointId = int(optionalData1.y);
    if(jointId > 0)
        finalMatrix = finalMatrix + (jointTransforms[jointId - 1] * optionalData2.y);

    jointId = int( optionalData1.z);
    if(jointId > 0)
        finalMatrix = finalMatrix + (jointTransforms[jointId - 1] * optionalData2.z);

    jointId = int( optionalData1.w);
    if(jointId > 0)
        finalMatrix = finalMatrix + (jointTransforms[jointId - 1] * optionalData2.w);

    gl_Position = mvp * finalMatrix * vec4(vertPosition, 1.0);
}

在这个着色器中,我在属性optionalData1 & optionalData2中发送了权重绘制信息。数据打包如下:(BoneId1,BoneId2,BoneId3,BoneId4)和(Weight4Bone1,Weight4Bone2,Weight4Bone3,Weight4Bone4)。因此,在这种情况下,您是有限的,最多有4块骨头影响到每个属性。碎片着色部分是常见的。

方法2:(CPU剥皮)

如果您不能忍受GPU剥皮中的限制,那么唯一的方法就是在CPU端进行计算。

步骤1:计算当前帧中的顶点位置,方法是将属于影响顶点的骨头的矩阵相乘。

步骤2:收集当前帧的新位置,并将信息发送到顶点属性中的GPU。

步骤3:重新计算每个帧中的新顶点位置,并更新属性缓冲区。

这种方法将计算的负载带到CPU。

票数 4
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38951625

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档