1

我阅读了 glTF 的 github教程中的 Skins 部分,但无法理解其jointMatrix工作原理。

在教程中,它被定义为

jointMatrix(j) =
  globalTransformOfNodeThatTheMeshIsAttachedTo^-1 *
  globalTransformOfJointNode(j) *
  inverseBindMatrixForJoint(j);

我对globalTransform和取消感到困惑。在我看来,jointMatrix是这样的

jointMatrix(j) =
  jointSpaceToModelSpace(j) *
  jointTransform(j) *
  modelSpaceToJointSpace(j);

在顶点着色器中

// assume 'joint' is a matrix computed from weighted aggregation of all jointMatrix(j)
vertex_world_space = model-view-proj * joint * vertex_model_space;

我的问题是

  • 为什么jointMatrix这样定义?
  • 我的版本有什么问题?
4

1 回答 1

2

要记住的一件事是顶点着色器是在蒙皮网格节点的上下文中执行的,而不是骨架根或关节。这意味着模型视图矩阵可能处于“无意义”的位置:这个蒙皮节点可能已经被赋予了转换,但它不会受到影响,因为它的所有顶点都由关节控制。如果蒙皮节点不是根节点,glTF 验证器甚至会发出警告,因为这个原因,应用于蒙皮本身的变换是无操作的。

因此,皮肤中任何特定顶点所需的步骤是:

  1. 撤消皮肤的世界到节点转换(如果有)。
  2. 应用关节的世界到关节变换。
  3. 撤消关节的“休息”位置。

这三个步骤对应于您在教程中列出的三个步骤。

让我们谈谈第三个。每个关节都有一个“休息”位置。例如,手臂骨骼可能位于皮肤原始形状(绑定姿势)的左臂中,而腿骨可能位于右腿中。这些骨头不位于原点,它们散布在模型周围。但是我们不希望它们在静止位置时拉动顶点,例如手臂骨骼可能在原点的上方和左侧,但在静止时不应向上和向左拉动任何顶点。

因此,每个关节都有一个“逆绑定矩阵”,可以消除关节在其自身静止位置自然产生的影响。当关节移动时,它相对于它自己的静止位置移动,并且那个增量(步骤 2 和 3 之间的差异)是应用于目标顶点的。

如果皮肤本身试图移动,什么也不会发生。在教程着色器的末尾应用了这样的变换u_modelViewMatrix,并且在步骤 1 中应用了该变换的逆,因此它们相互抵消。如果您想移动整个蒙皮网格,正确的方法当然是重新定位整个骨架,而不是蒙皮节点。移动根关节将在步骤 2 中对网格中的所有顶点应用新的变换。

于 2021-03-17T17:55:01.483 回答