3d glTF'的含义;皮肤基质中的s逆(全局转换)
我想用骨骼动画渲染网格。在设置动画之前,我只想使用动画的第一个关键帧渲染网格,即使用骨骼层次变换渲染网格。我忽略了glTF中的场景结构;我只是使用3d glTF'的含义;皮肤基质中的s逆(全局转换),3d,gltf,scenegraph,skeletal-animation,skeletal-mesh,3d,Gltf,Scenegraph,Skeletal Animation,Skeletal Mesh,我想用骨骼动画渲染网格。在设置动画之前,我只想使用动画的第一个关键帧渲染网格,即使用骨骼层次变换渲染网格。我忽略了glTF中的场景结构;我只是使用网格[0]来获取网格,使用蒙皮[0]来获取其骨架 据我所知,最终的蒙皮矩阵(作为制服馈送到顶点着色器)是经过计算的 for(骨骼中的骨骼){ bone.skin_-xform=反向(全局_-xform)*bone.global_-xform*bone.inv_-bind_-xform; } 当我完全这样做的时候,我看到我的模型是地面以下11.4(5.
网格[0]
来获取网格,使用蒙皮[0]
来获取其骨架
据我所知,最终的蒙皮
矩阵(作为制服馈送到顶点着色器)是经过计算的
for(骨骼中的骨骼){
bone.skin_-xform=反向(全局_-xform)*bone.global_-xform*bone.inv_-bind_-xform;
}
当我完全这样做的时候,我看到我的模型是地面以下11.4(5.7+5.7)个单位(Z=0的平面;世界上有+Z作为向上)。当我只渲染网格而不进行任何蒙皮时,即仅使用位置、法线和纹理坐标,它位于地面上。我还能够推断出为什么在剥皮时会发生这种情况
以下是gltf的相关部分
"skins" : [
{
"inverseBindMatrices" : 6,
"joints" : [
0,
...
}
],
"nodes" : [
{
"name" : "Root",
"rotation" : [
0,
0,
1,
0
],
"translation" : [
0,
0,
-5.709875583648682
]
},
{
"mesh" : 0,
"name" : "Body",
"skin" : 0
},
{
"children" : [
0,
1
],
"name" : "Armature",
"translation" : [
0,
0,
5.709875583648682
]
}
]
我读过glTF的,还有。虽然文档中根本没有提到这一点,但以下是教程和参考指南中关于inverse(global\u xform)
的内容:
必须使用网格所附着节点的全局变换的逆变换变换顶点,因为此变换已使用模型视图矩阵完成,因此必须从蒙皮计算中取消
因此,Body
的全局变换必须反转并使用。这将导致translateZ(-5.7)
。Root已经有了一个translateZ(-5.7)
的局部变换,所以我知道网格到地面的偏移量为-11.4。但是,如果我按原样使用Body
的全局变换,而不使用反转,那么在上面的公式中就没有问题了
为什么参考指南要求我们反转根骨骼父骨骼的全局变换?我错过了什么?当我从Blender导入这个模型时,我注意到电枢对象上的变换确实是translateZ(5.7)
你说的
我忽略了glTF中的场景结构;我只是使用网格[0]来获取网格和蒙皮[0]来获取其骨架
然而,(标准的相关部分)说(强调矿山)
顶点必须使用网格所附着节点的全局变换的逆变换进行变换,因为此变换已使用模型视图矩阵完成
因为您说您要从glTF中提升网格和骨架,而不需要场景结构反转(全局变换)
。这是因为网格的模型视图矩阵对于逆(全局变换)
没有非单位变换来抵消偏移。使用three.js可以很好地工作,因为它使用所有节点层次渲染整个场景,这与您的不同
然而,如果我使用身体的整体变换,没有反转,在上面的公式中没有问题
这是正确的用法,因为Root
的全局变换是其所有父变换与Root
的局部变换的串联
root.global_xform = armature.local_xform * body.local_xform * root.local_xform
根据您的评论,我看到电枢对象有一个非身份转换作为其位置。通常情况下,作为身份更好
这里有一个更详细的解释和计算。我们看到根节点的局部变换为TranslateZ(-5.7)
;它的父节点电枢
节点的局部变换为TranslateZ(5.7)
;他没有父母了。因此,根的全局变换实际上是身份。以下是蒙皮顶点着色器中的方程式
point’ = P * V * Mesh * Skin * point
point’ = P * V * Mesh * (InvMeshGlobal * Global * InvBind) * point
5.7 * (-5.7 * 5.7 * -5.7 * InvBind)
5.7 * (-5.7 * I * InvBind)
因此,只有在渲染整个场景层次时才需要InvGlobalXform
(上面写为InvMeshGlobal
),而您只需要获得网格及其骨架,忽略存在mesh
和skin
的节点之外的祖先节点。我可以想出两个解决办法
解决方案1
- 出口前,确保网和电枢在搅拌器中应用了位置、旋转和刻度
Root
及其父电枢
局部变换都将成为标识,即Root的全局变换将是标识
- 忽略
Mesh
和InvMeshGlobal
变换
- 整个等式只需要
InvBind
解决方案2
- 存储根的祖先转换
- 使用祖先变换得到根的适当全局变换;通常成为身份
- 忽略
Mesh
和InvMeshGlobal
变换
- 等式中需要
Global
和InvBind
解决方案(1)仅在输入网格和骨架没有全局旋转或平移时有效;解决方案(2)在这里也适用。与解决方案(1)不同,解决方案(2)需要存储祖先变换。这可能是因为(作为一名艺术家的我)工作流程不佳,电枢对象在Blender中不应进行翻译吗?当我选择电枢对象并应用位置并导出glTF时,一切正常。我还看到,电枢
节点现在没有转换,即标识;它的工作原理与预期的一样。