gpt4 book ai didi

c++ - glTF 骨骼矩阵是在局部空间还是模型空间中指定的?

转载 作者:行者123 更新时间:2023-12-03 07:22:25 32 4
gpt4 key购买 nike

所以官方文档说:

Note that the node transform is the local transform of the node relative to the joint, like any other node in the glTF node hierarchy as described in the Transformation section.


我对这里的节点和关节之间的区别到底是什么有点模糊。
假设我可以将 2 混为一谈,请转到 SimpleSkin示例 int models并查看json:
 "nodes" : [ {
"skin" : 0,
"mesh" : 0
}, {
"children" : [ 2 ],
"translation" : [ 0.0, 1.0, 0.0 ]
}, {
"rotation" : [ 0.0, 0.0, 0.0, 1.0 ]
} ],

"skins" : [ {
"inverseBindMatrices" : 4,
"joints" : [ 1, 2 ]
} ],
关节 1 是关节 2 的父节点。因此,如果我将该层次结构与任何其他节点层次结构一样对待,则 node1 的变换也将应用于节点 2,在给定值的情况下,节点 1 和节点 2 在静止时处于相同状态位置。
但是当您查看该示例的图表时:
enter image description here
他们不在同一个位置。但是,如果您认为变换彼此独立(即关节 1 的变换不影响关节 2),则关节 1 位于关节 2 上方,这至少与图表显示的一致(尽管不一致与动画描述的一样,因为它是应该旋转的顶部骨骼,而在这种配置中,它是底部骨骼)。

最佳答案

哦,伙计,您在教程中发现了各种缺陷。
一般来说是的,“node”和“joint”是一样的,只是它们是分开索引的。 glTF 2.0 使用数组索引号作为许多事物的标识,这种方法有利有弊。但在这种情况下:

nodes: [ { node index 0 }, { node index 1 }, { node index 2 } ]
其次是:
joints: [ 1, 2 ]
这意味着关节索引 0 由节点索引 1 表示,关节 1 由节点 2 表示。每个关节都是一个节点,但并非每个节点都是一个关节。这在阅读 JOINTS_0 时变得很重要。数组,因为这些将是 union 索引。但更重要的是,它是这样写的,因为 inverseBindMatrix数组的长度与关节数组的长度相同,因此那里有 1:1 的映射保证。
让我们讨论一下jointMatrix。 tutorial's implementation section有这段伪代码:
jointMatrix(j) =
globalTransformOfNodeThatTheMeshIsAttachedTo^-1 *
globalTransformOfJointNode(j) *
inverseBindMatrixForJoint(j);
但是,如果您对某些伪类感到有点烧伤,这里是 corresponding block of code in the sample viewer .它基本上相当于:
jointMatrix[j] = skinnedNode.inverseWorldTransform * 
jointNode.worldTransform * inverseBindMatrix[j]
节点的变换是相对于它们的父节点的,但是 inverseBindMatrix部分是相对于此 glTF 模型的世界指定的。所以宿主应用程序需要计算节点相对于glTF场景根的全变换,如果任何祖先动画,这个计算的结果将会改变。同样,我们需要知道一个不同节点的完整世界变换的逆,一个持有带有皮肤的网格(显然在示例查看器中错误标记为“parentNode”,它应该称为“skinnedNode”或类似名称, see call site)。
这是做什么的?我们需要蒙皮节点本身的“inverseWorldTransform”,以防某些愚蠢的艺术家将该节点移动到某个地方。对于这些绑定(bind)计算,它需要回到原点。我们当然需要关节节点本身的世界变换,即实际骨骼,它可能是动画的,也可能是由父关节的动画移动的,或两者兼而有之。最后,我们需要关节的 inverseBindMatrix,如果关节没有从静止位置移开,它将抵消关节的位置。这一切通常在 CPU 上运行,每帧最多运行一次,或者至少在动画系统或其他外力导致某些关节移动时运行。
这里要解决的部分问题是:持有蒙皮网格的节点可能在场景层次结构中具有特定位置,并且可能已移动到某个地方。骨架的根可能是层次结构中的不同节点,也可能在其他地方。绘制蒙皮网格的顶点着色器试图将其绘制在蒙皮节点说它应该在的位置,而不是骨架根说它应该在的位置。那是个问题。我们需要离开皮肤的位置,回到原点,然后下到关节的世界位置,并在那里绑定(bind)关节。来自顶点着色器的结果需要将蒙皮放置在关节周围,在关节的位置,无论蒙皮节点认为它在哪里。
如果您将蒙皮网格放置在场景根以外的某个位置,glTF 验证器会报错,并进行任何类型的变换。当使用皮肤时,所有位置信息都来自关节位置,而不是皮肤的位置。通过在上述计算中包含其世界倒数,皮肤的位置被丢弃。因此,如果蒙皮节点位于原点而不对其进行变换,那么您可以从这个方程优化整个术语。
但是,许多 glTF 模型确实在非根位置包含蒙皮,因此包含蒙皮网格位置的倒数,因为将从该位置调用顶点着色器。每个顶点都会移动到关节的实际位置,然后通过关节当前位置和关节静止位置之间的差异进一步移动自身。

关于c++ - glTF 骨骼矩阵是在局部空间还是模型空间中指定的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64745393/

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