繁体   English   中英

如何为骨骼动画变换顶点?

[英]How do I transform a vertex for skeletal animation?

我正在开发一款新的视频游戏,但我在骨骼动画方面已经被屏蔽了大约 5 周。 我相信我已经缩小了问题的范围,但无法弄清楚我实际上做错了什么。

我有一个简单的 12 顶点矩形对象,里面有四个骨骼。 此图像显示了对象在其绑定姿势下的样子,以及顶部骨骼围绕 Y 轴旋转约 90 度时对象应该是什么样子。 为了在我的应用程序中测试骨骼重量,这是我正在使用的简单示例。 在我的应用程序中,我以编程方式将顶部骨骼旋转 90 度并让着色器渲染它。

不幸的是,我的应用程序没有产生相同的结果。 绑定姿势正确显示,但是当应用顶部骨骼变换时,变换被夸大了,矩形的顶部只是在我旋转顶部骨骼的方向上拉伸。

我已经验证了以下内容:

  • 骨骼作为相对变换发送到着色器统一。 这意味着当我将顶部骨骼旋转 90 度时,骨骼 1-3 都是相同的,骨骼 4 是一个仅沿 Y 轴旋转约 90 度的矩阵。
  • 对于任何给定的顶点,骨骼都被正确加权(或者至少,它们在我的应用程序中的加权与 Blender 报告的相同)。

所以我把我的问题简化为这个单一的健全性检查。 参考上面的第一个屏幕截图,我选择了一个顶点来使用我的骨骼方法进行变换。 一个小顶点:-0.5、-0.5、4.0。 假设我正确应用了所有内容,骨骼应该将此顶点转换为 -0.95638、-0.5、2.63086。 为了使调试更容易,我使用了我的顶点着色器......

#version 330 core
layout (location = 0) in vec3 position; // The position variable has attribute position 0
layout (location = 1) in vec3 normal; // This is currently unused
layout (location = 2) in vec2 texture;
layout (location = 3) in ivec4 boneIDs;
layout (location = 4) in vec4 boneWeights;

out vec2 fragTexture;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

uniform mat4 bones[ 16 ];

void main()
{
  mat4 boneTransform =
    ( bones[ boneIDs[ 0 ] ] * boneWeights[ 0 ] ) +
    ( bones[ boneIDs[ 1 ] ] * boneWeights[ 1 ] ) +
    ( bones[ boneIDs[ 2 ] ] * boneWeights[ 2 ] ) +
    ( bones[ boneIDs[ 3 ] ] * boneWeights[ 3 ] );

  mat4 mvp = projection * view * model;
  gl_Position = mvp * boneTransform * vec4( position, 1.0f );

  fragTexture = texture;
}

...并将其放入下面这个简单的单元测试风格的函数中,只是为了转换我的测试顶点。

glm::mat4 id( 1.0f ); // ID 0
glm::mat4 bone( 1.0f ); // ID 1
glm::mat4 bone002( 1.0f ); // ID 2
glm::mat4 bone003( 1.0f ); // ID 3

// Keyframe is set to rotate bone003 -89.113 degrees along Y
bone003 *= glm::toMat4( glm::angleAxis( (float)glm::radians( -89.113 ), glm::vec3( 0.0f, 1.0f, 0.0f ) ) );

glm::mat4 xform =
    ( bone002 * 0.087f ) +
    ( bone003 * 0.911f ) +
    ( id * 0 ) +
    ( id * 0 );

glm::vec4 point = xform * glm::vec4( glm::vec3( -0.5f, -0.5f, 4.0f ), 1.0f );

这段代码模拟了我的顶点着色器的状态,其中上面的四个 mat4s 是骨骼 [0] 到骨骼 [3]。 bone003 是在转换 Bone.003 并删除其反向绑定后发送到我的着色器的内容。 尽管完全符合我目前对骨骼动画的理解,并且匹配了来自 Blender 的所有相关权重/值,但顶点 (-0.5, -0.5, 4.0) 被转换为 (-3.694115, -0.499000, -0.051035) 的无意义值)。 数学是对的,值是匹配的,但答案都是错误的。

所以,这就是我提出实际问题的地方:我在通过骨骼变换的影响来变换网格顶点时做错了什么? 我对骨骼动画的理解在哪里不正确?

这对我来说似乎是错误的:

  mat4 boneTransform =
    ( bones[ boneIDs[ 0 ] ] * boneWeights[ 0 ] ) +
    ( bones[ boneIDs[ 1 ] ] * boneWeights[ 1 ] ) +
    ( bones[ boneIDs[ 2 ] ] * boneWeights[ 2 ] ) +
    ( bones[ boneIDs[ 3 ] ] * boneWeights[ 3 ] );

您应该将顶点(在骨骼空间中)与每个骨骼矩阵相乘,并将得到的向量加在一起以处理权重,如下所示:

vec4 temp = vec4(0.0f, 0.0f, 0.0f, 0.0f);
vec4 v = vec4(position, 1.0f);
temp += (bones[boneIDs[0]] * v) * boneWeights[0];
temp += (bones[boneIDs[1]] * v) * boneWeights[1];
temp += (bones[boneIDs[2]] * v) * boneWeights[2];
temp += (bones[boneIDs[3]] * v) * boneWeights[3];

// temp is now the vector in local space that you
// transform with MVP to clip space, or whatever

让我知道这个是否奏效!

编辑:我想不是。 好吧:

顶点 (-0.5, -0.5, 4.0) 被转换为 (-3.694115, -0.499000, -0.051035) 的无意义值

真的是废话吗? 如果我只是注视它,围绕 Y 轴顺时针旋转 ~90 度会给出大约该值。 你的测试是“正确的”。 在这一点上,我开始认为骨骼层次结构有问题,或者关键帧的插值有问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM