1

我非常接近在 WebGL 中工作的骨骼动画。

背景

我有一个免费获得的带有僵尸行走动画的模型。我将整个内容下载到一个 Collada 文件中。我编写了一个解析器来获取所有顶点、法线、关节影响指数/权重和关节矩阵。我可以通过这样做来渲染角色的绑定姿势

joints[i].skinning_matrix = MatrixMultiply(joints[i].inverse_bind_pose_matrix, joints[i].world_matrix);

其中关节的世界矩阵是关节的 bind_pose_matrix 乘以其父级的世界矩阵。我通过执行以下操作得到了 inverse_bind_pose_matrix:

joints[i].inverse_bind_pose_matrix = MatrixInvert(joints[i].world_matrix);

所以真的,以绑定姿势渲染角色只是将身份矩阵传递给着色器,所以也许我根本没有做这部分。但是,我计算的反向绑定姿势矩阵与 Collada 文件提供的几乎相同,所以我很确定这些是好的。

这是我的模型处于绑定姿势:

绑定姿势

问题

一旦我继续尝试使用动画的单帧计算蒙皮矩阵(我随机选择了第 10 帧),它仍然像一个人,但肯定有问题。

我使用的是我最初计算的相同的 inverse_bind_pose_matrix。我正在使用一个新的世界矩阵,而是通过将每个关节的关键帧/动画矩阵乘以其父级的新世界矩阵来计算。

我没有在我的整个代码库的任何地方进行任何转置,尽管我认为我已经尝试过转置几乎任何矩阵组合都无济于事。

这是我的模型在他的动画第 10 帧姿势中:

动画姿势

一些相关代码

顶点着色器:

attribute float aBoneIndex1;
// up to aBoneIndex5

attribute float aBoneWeight1;
// up to aBoneWeight5

uniform mat4 uBoneMatrices[52];

void main(void) {
  vec4 vertex = vec4(0.0, 0.0, 0.0, 0.0);
  vertex += aBoneWeight1 * vec4(uBoneMatrices[int(aBoneIndex1)] * aPosition);
  vertex += aBoneWeight2 * vec4(uBoneMatrices[int(aBoneIndex2)] * aPosition);
  vertex += aBoneWeight3 * vec4(uBoneMatrices[int(aBoneIndex3)] * aPosition);
  vertex += aBoneWeight4 * vec4(uBoneMatrices[int(aBoneIndex4)] * aPosition);
  vertex += aBoneWeight5 * vec4(uBoneMatrices[int(aBoneIndex5)] * aPosition);

  // normal/lighting part

  // the "/ 90.0" simply scales the model down, problem persists without it.
  gl_Position = uPMatrix * uMVMatrix * vec4(vertex.xyz / 90.0, 1.0);
}

你可以在GitHub 上完整地看到我的解析器(如果你真的想......) ,你可以在这里看到模型。

4

0 回答 0