C++ 如何为骨骼动画变换顶点?
我正在开发一款新的视频游戏,我在骨骼动画方面被屏蔽了大约5周。我相信我已经缩小了问题的范围,但无法找出我到底做错了什么 我有一个简单的12顶点矩形物体,里面有四块骨头。显示对象在其绑定姿势中的外观,以及顶部骨骼绕Y轴旋转约90度时对象的外观。为了在我的应用程序中测试骨骼重量,这是我正在使用的一个简单示例。在我的应用程序中,我通过编程将顶部骨骼旋转约90度,并让着色器对其进行渲染 不幸的是,我的应用程序没有产生相同的结果。绑定姿势会正确显示,但当应用顶部骨骼变换时,变换会被放大,矩形的顶部仅沿我旋转顶部骨骼的方向拉伸 我已核实以下情况:C++ 如何为骨骼动画变换顶点?,c++,opengl,C++,Opengl,我正在开发一款新的视频游戏,我在骨骼动画方面被屏蔽了大约5周。我相信我已经缩小了问题的范围,但无法找出我到底做错了什么 我有一个简单的12顶点矩形物体,里面有四块骨头。显示对象在其绑定姿势中的外观,以及顶部骨骼绕Y轴旋转约90度时对象的外观。为了在我的应用程序中测试骨骼重量,这是我正在使用的一个简单示例。在我的应用程序中,我通过编程将顶部骨骼旋转约90度,并让着色器对其进行渲染 不幸的是,我的应用程序没有产生相同的结果。绑定姿势会正确显示,但当应用顶部骨骼变换时,变换会被放大,矩形的顶部仅沿我旋
- 骨骼作为相对变换发送到着色器。这意味着当我将顶部骨骼旋转90度时,骨骼1-3都是同一的,而骨骼4是一个仅沿Y轴旋转约90度的矩阵
- 对于任何给定的顶点,骨骼都会正确加权(或者至少,在我的应用程序中,骨骼的加权与Blender报告的相同)
#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是骨骼[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度,如果我只是盯着它看的话,就会得到这个值。你的测试是“正确的”。此时,我开始认为骨骼层次有问题,或者关键帧插值有问题。不幸的是,这会产生相同(不正确)的结果。