- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在开发一款新的视频游戏,并且我在骨骼动画方面被屏蔽了大约 5 周。我相信我已经缩小了问题的范围,但无法弄清楚我到底做错了什么。
我有一个简单的 12 顶点矩形对象,里面有四个骨骼。 This image显示对象在其绑定(bind)姿势中的样子,以及顶部骨骼绕 Y 轴旋转约 90 度时对象的样子。为了在我的应用程序中测试骨骼重量,这是我使用的简单示例。在我的应用程序中,我以编程方式将顶部骨骼转动约 90 度并让着色器渲染它。
不幸的是,我的应用程序没有产生相同的结果。绑定(bind)姿势显示正确,但是当应用顶部骨骼变换时,变换被夸大并且矩形的顶部只是在我旋转顶部骨骼的方向上拉伸(stretch)。
我已验证以下内容:
所以我将我的问题简化为这个单一的完整性检查。引用上面的第一个屏幕截图,我选择了一个顶点来使用我的骨骼方法进行变换。一个小顶点:-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/
因此,除了索引之外,当我创建一个新项目并选择 conda 解释器时,还会启动更多需要数小时的进程。下面是一个快照。这些过程是什么?完成后它们会占用空间吗? 最佳答案 PyCharm 运行 genera
我是一名优秀的程序员,十分优秀!