gpt4 book ai didi

c# - 了解 OpenGL 引擎的 GLTF2.0 文件的蒙皮部分

转载 作者:行者123 更新时间:2023-11-30 15:51:49 25 4
gpt4 key购买 nike

我有一个简单的 blender 模型,它由三个网格组成,三个骨骼分别控制一个网格。动画只是骨骼围绕 y 轴旋转立方体并返回。中心骨骼是两个外部骨骼的父级。

Blender screenshot

然后我使用 GLTF2.0(文本版本)导出插件导出这个场景,现在正尝试将其导入我新制作的 opengl 引擎(c# xamarin android)。

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

我读了:

显示网格很容易,但现在我无法让动画正常工作。在我的 gltf 文件中,我看到三种皮肤:

"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 绑定(bind)到皮肤而不是关节?
  • 当我从关键帧(每个骨骼)获得正确的旋转、缩放和平移时,我如何计算每个骨骼的矩阵,我需要将其传递到我的顶点着色器?
  • 文件中的每个骨骼节点都有自己的旋转、平移、缩放值,但没有矩阵。这是为什么?是不是少了什么?
  • gltf 文件将骨骼(关节)引用为节点 ID,但作为属性传递给着色器的权重/关节 ID 数组与这些骨骼 ID 不匹配:关节 ID 数组包含即 0、1、2对于骨骼 ID,但骨骼位于节点 4、5、6 - 如何为传递给着色器的每个 jointId 找到正确的骨骼?

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

编辑

GLTF example model download

编辑 #2

好吧,我想我正在掌握它的窍门......慢慢地。

  • 对于由骨架控制的每个网格,文件中都有一个皮肤。我认为每个网格都需要一个反向绑定(bind)矩阵,以便能够将网格转换为骨骼空间(并且 - 如果需要 - 返回)。

  • 我仍然不知道如何在将最终变换传递给着色器之前正确计算它们。

  • 这一点我仍然不明白。

  • 由于每个皮肤都有一个包含三个(或最多 4 个)关节的列表,因此这些关节的最终变换需要传递给顶点着色器。如果您有 8 个关节,但当前要绘制的网格仅受其中 4 个的影响,为什么要传递所有 8 个矩阵而不是仅传递您需要的 4 个。

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

最佳答案

我试着一一解答你的问题

  • Why are there three skins? Why is the inverseBindMatrices bound to a skin and not to a joint?

正如您已经发现的,每个网格有一个皮肤。事实上,在您的特定情况下,您可以将所有三个网格合并为一个,并没有真正限制这个一般原则。然而

I think there needs to be an inverse bind matrix for each mesh in order to be able to transform the mesh to bone space (and - if need be - back).

每个网格每个关节都有一个逆绑定(bind)矩阵。该属性的名称是复数形式的 inverseBindMatrices 是有原因的,它引用了 bufferview,后者又引用了 buffer 中的一些数据。

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

Every bone node in the file has its own rotation, translation, scale values but no matrix. Why is that? Isn't there something missing?

您还需要什么?每一个仿射变换都可以分解为平移、旋转和缩放,所以数据是完整的。 glTF 规范定义生成的矩阵应按 T*R*S 的顺序计算。

  • When I have the right rotation, scaling, translation from a key frame (per bone), how do I calculate the matrices for each bone that I need to pass to my vertex shader?

对于每个骨骼节点 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).

  • The gltf file referse to a bone (joint) as a node id, but the weights/jointId-Arrays that get passed as attributes to the shader do not match these bone ids: jointIds-Array contains i.e. 0,1,2 for the bone ids, but the bones are in nodes 4,5,6 - how do I find the right bone for each jointId passed to the shader?

jointIds 数组包含对关节的引用,而不是骨骼(因此得名)。蒙皮着色器根本不关心骨骼,骨骼所做的只是在这里定义关节的层次结构,因此它们会影响 M_global 的实际值,因此也会影响 M_joint 矩阵。第 i 条目仅引用相应皮肤的 joints 数组中的第 i 关节,因此它需要 M_joint( i).

  • Since every Skin has a list of three (or max. 4) Joints, these are the Joints of which the final transformations need to be passed to the vertex shader.

为什么 皮肤 被限制为 4 个关节。皮肤可以有任意多的关节。

If you have 8 Joints but the current to-be-drawn Mesh only gets affected by 4 of them, why should you pass all 8 matrices instead of only the 4 you need.

为什么要为只需要 4 根骨骼的网格定义 8 根骨骼的皮肤? glTF 数据格式不会阻止您存储不相关的信息,或以低效的方式存储信息。

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

关于c# - 了解 OpenGL 引擎的 GLTF2.0 文件的蒙皮部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55989429/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com