首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解OpenGL引擎GLTF2.0文件的剥皮部分

理解OpenGL引擎GLTF2.0文件的剥皮部分
EN

Stack Overflow用户
提问于 2019-05-05 06:31:14
回答 1查看 3.7K关注 0票数 4

我有一个简单的搅拌机模型,它由三个网格组成,三个骨头控制每个网格。动画只是骨头旋转立方体一点点围绕y轴和背部。中骨是这两块外骨的母体。

然后,我用GLTF2.0 (文本版本)导出插件导出这个场景,现在我尝试将它导入到我新开发的引擎(c# )中。

由于我想完全理解OpenGL中的GLTF2.0格式和骨骼动画,所以我尝试自己实现GLTF2.0。

我读到:

显示网格是容易的,但现在我被困在使动画工作。在我的gltf文件中,我看到了三个皮肤:

代码语言:javascript
复制
"skins" : [
    {
        "inverseBindMatrices" : 21,
        "joints" : [
            4,
            5,
            6
        ],
        "skeleton" : 0
    },
    {
        "inverseBindMatrices" : 22,
        "joints" : [
            4,
            5,
            6
        ],
        "skeleton" : 0
    },
    {
        "inverseBindMatrices" : 23,
        "joints" : [
            4,
            5,
            6
        ],
        "skeleton" : 0
    }
]

这让我很困惑,因为我每个网眼都有一个骨结构,而不是每个网眼有三个骨头。我想我会收集类实例中的所有骨头(比如Bone.cs),每一根骨头都有一个孩子骨骼的列表,并为它的父骨提供一个字段。然后我收集实例中的动画(类Animation.cs),每个动画实例都有一个包含给定时间戳的旋转、缩放和平移的关键帧列表。当动画时间戳被设置为2.5秒时,我查找与该时间戳最近的两个关键帧,并为这些关键帧插值旋转、缩放和平移。

实际问题

  • 为什么有三张皮?为什么inverseBindMatrices被绑在皮肤上而不是关节上?
  • 当我有正确的旋转,缩放,从关键帧(每个骨头),我如何计算矩阵的每一块骨,我需要传递给我的顶点着色?
  • 文件中的每个骨节点都有自己的旋转、平移、缩放值,但没有矩阵。为什么会这样呢?是不是少了什么东西?
  • gltf文件将骨头(关节)引用为节点id,但是作为属性传递给着色器的权重/ jointId数组与这些骨id不匹配: jointIds-Array包含骨id为0、1、2,但骨头位于节点4、5、6--如何为传递给着色器的每个jointId找到正确的骨头?

我希望你能帮助我。亲切的问候!!如果需要的话,我可以提供更多的代码,但我认为,如果我从整体上理解了这个主题,那么我就可以自己做了。

编辑

GLTF示例模型下载

编辑#2

好吧,我想我已经掌握了it...slowly的诀窍了。

  • 对于每个由电枢控制的网格,文件中有一个皮肤。我认为每个网格都需要有一个逆约束矩阵,这样才能将网格转换为骨空间(如果需要的话)。
  • 在将它们传递给着色器之前,我仍然不知道如何正确地计算最终的转换。
  • 这一点我仍然不知道。
  • 因为每个皮肤都有三个(或最多)的列表。( 4)节点,这些节点的最终转换需要传递给顶点着色器。如果你有8个关节,但当前要绘制的网格只受其中4个的影响,你为什么要传递所有的8个矩阵而不是你需要的4个。

这一切仍然笼罩在怀疑之中。也许这对其他人有帮助。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-07 20:10:23

我试着一个接一个地回答你的问题

  • 为什么有三张皮?为什么inverseBindMatrices被绑在皮肤上而不是关节上?

正如你已经发现的,每个网格都有一个皮肤。THe的事实是,在您的具体情况下,您可以将所有三个网格合并为一个,这并不真正限制这一一般原则。然而,

我认为每个网格都需要有一个逆约束矩阵,这样才能将网格转换为骨空间(如果需要的话)。

有一个逆约束矩阵,每个的联合,每个网格。出于某种原因,该属性的名称为inverseBindMatrices复数,它引用了一个bufferview,后者反过来引用了buffer中的一些数据。

在这里改变你问题的顺序,因为这样会更有意义:

文件中的每个骨节点都有自己的旋转、平移、缩放值,但没有矩阵。为什么会这样呢?是不是少了什么东西?

您还需要些什么?每一次仿射变换都可以分解为平移、旋转和缩放,这样数据就完成了。glTF规范定义了结果矩阵应按T*R*S顺序计算。

  • 当我有正确的旋转,缩放,从关键帧(每个骨头),我如何计算矩阵的每一块骨,我需要传递给我的顶点着色?

对于每个骨节点i,可以将局部转换计算为M_local(i) = T(i)*R(i)*S(i)。您将通过应用完整的层次得到联合矩阵,因此基本上是M_global(i) = M_global(parent(i)) * M_local(i),然后可以将连接矩阵构造为M_joint(i) = inverse(globalTransform) * M_global(i) * inverseBindMatrix(i)

  • gltf文件将骨头(关节)引用为节点id,但是作为属性传递给着色器的权重/ jointId数组与这些骨id不匹配: jointIds-Array包含骨id为0、1、2,但骨头位于节点4、5、6--如何为传递给着色器的每个jointId找到正确的骨头?

jointIds数组包含对关节的引用,而不是对骨头(因此名)的引用。剥皮着色器根本不关心骨头,骨头所做的就是在这里定义关节的等级,因此它们影响到M_global的实际值,因此也影响到M_joint矩阵的实际值。i-th条目只引用相应皮肤的joints数组中的i-th连接,因此需要M_joint(i)

  • 因为每个皮肤都有三个(或最多)的列表。( 4)节点,这些节点的最终转换需要传递给顶点着色器。

为什么skin只限于4个关节。皮肤可以有一个人喜欢的关节。

如果你有8个关节,但当前要绘制的网格只受其中4个的影响,你为什么要传递所有的8个矩阵而不是你需要的4个。

你为什么要为一个只需要四块的网眼定义一个8块骨头的皮肤呢?glTF数据格式不会阻止您存储不相关的信息,也不会阻止您以低效的方式存储信息。

这里要注意的一点是,关节之间的等级仍然是由skeleton的骨节层次来定义的。因此,您可以在单个skin中省略任意的关节,但是这些骨节点(以及它们的潜在动画)仍然可以影响最终的关节矩阵--对于任何由骨头定义的关节来说,它都低于骨骼骨级中“遗漏”的骨头。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55989429

复制
相关文章

相似问题

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