gpt4 book ai didi

c++ - 如何变换骨骼动画的顶点?

转载 作者:搜寻专家 更新时间:2023-10-31 02:12:54 27 4
gpt4 key购买 nike

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

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

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

我已验证以下内容:

  • 骨骼作为相对变换被发送到着色器制服。这意味着,当我将顶部骨骼旋转 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 );

这段代码模拟了我的顶点着色器的状态,其中上面的四个 mat4 是 bones[0] 到 bones[3]。 bone003 是在转换 Bone.003 并移除其反向绑定(bind)后发送到我的着色器的内容。尽管 完全 符合我目前对骨骼动画的理解,并且匹配来自 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 ] );

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

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

让我知道这是否有效!

编辑:我猜那时不会。好的:

the vertex (-0.5, -0.5, 4.0) is transformed to the nonsense value of (-3.694115, -0.499000, -0.051035)

这真的是废话吗?绕 Y 轴顺时针旋转约 90 度,如果我只是观察它,就会得到大约那个值。你的测试是“正确的”。此时我开始认为骨骼层次有问题,或者关键帧的插值有问题。

关于c++ - 如何变换骨骼动画的顶点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42059089/

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