GLTF - 关节应该如何在动画期间变换
GLTF - how are joints supposed to be transformed during an animation
我正在尝试使用 gltf 2.0 资产实现骨骼动画。
我目前能够转换骨架并正确渲染模型。当编辑关节的变换(例如旋转)时,模型按预期移动。
问题是,一旦我尝试使用动画采样器输出的变换,骨架就完全错误了。我的测试表明,动画第一个关键帧的变换矩阵与初始姿势中关节的变换相匹配,但实际上它们完全不同!我不太清楚这些变换应该在渲染算法中的什么位置。
我的渲染算法大致是这样的:
render_scene() {
render_node(root_node, transform::IDENTIY)
}
render_node(node, outer_transform) {
next_transform = outer_transform * node.transform
if (node.has_skin) {
update_joint_matrices(next_transform, node.joints)
}
if (node.has_mesh) {
// draw calls
}
for child in node.children {
render_node(child, next_transform)
}
}
update_joint_matrices(outer_transform, joints) {
world_transforms = []
// Parent nodes are always processed before child nodes
for joint in joints {
if joint.is_root {
world_transforms[joint] = outer_transform * joint.transform
} else {
world_transforms[joint] = world_transforms[joint.parent] * joint.transform
}
}
joint_matrices = []
for joint in 0..world_transforms.len() {
joint_matrices[joint] = world_transforms[joint] * inverse_bind_matrices[joint]
}
// send joint matrices to the GPU
}
顶点着色器的相关部分如下所示:
void main() {
mat4 modelTransform;
modelTransform =
(inWeights.x * jointMatrices[int(inJoints.x)]) +
(inWeights.y * jointMatrices[int(inJoints.y)]) +
(inWeights.z * jointMatrices[int(inJoints.z)]) +
(inWeights.w * jointMatrices[int(inJoints.w)]);
}
gl_Position = projection * view * modelTransform * vec4(inPos, 1.0);
}
另外,还有一个note in the spec不太明白:
Only the joint transforms are applied to the skinned mesh; the transform of the skinned mesh node MUST be ignored.
好的,我解决了问题。
问题是我没有正确加载四元数。
四元数应解释为原始 XYZW 值。
我正在尝试使用 gltf 2.0 资产实现骨骼动画。
我目前能够转换骨架并正确渲染模型。当编辑关节的变换(例如旋转)时,模型按预期移动。
问题是,一旦我尝试使用动画采样器输出的变换,骨架就完全错误了。我的测试表明,动画第一个关键帧的变换矩阵与初始姿势中关节的变换相匹配,但实际上它们完全不同!我不太清楚这些变换应该在渲染算法中的什么位置。
我的渲染算法大致是这样的:
render_scene() {
render_node(root_node, transform::IDENTIY)
}
render_node(node, outer_transform) {
next_transform = outer_transform * node.transform
if (node.has_skin) {
update_joint_matrices(next_transform, node.joints)
}
if (node.has_mesh) {
// draw calls
}
for child in node.children {
render_node(child, next_transform)
}
}
update_joint_matrices(outer_transform, joints) {
world_transforms = []
// Parent nodes are always processed before child nodes
for joint in joints {
if joint.is_root {
world_transforms[joint] = outer_transform * joint.transform
} else {
world_transforms[joint] = world_transforms[joint.parent] * joint.transform
}
}
joint_matrices = []
for joint in 0..world_transforms.len() {
joint_matrices[joint] = world_transforms[joint] * inverse_bind_matrices[joint]
}
// send joint matrices to the GPU
}
顶点着色器的相关部分如下所示:
void main() {
mat4 modelTransform;
modelTransform =
(inWeights.x * jointMatrices[int(inJoints.x)]) +
(inWeights.y * jointMatrices[int(inJoints.y)]) +
(inWeights.z * jointMatrices[int(inJoints.z)]) +
(inWeights.w * jointMatrices[int(inJoints.w)]);
}
gl_Position = projection * view * modelTransform * vec4(inPos, 1.0);
}
另外,还有一个note in the spec不太明白:
Only the joint transforms are applied to the skinned mesh; the transform of the skinned mesh node MUST be ignored.
好的,我解决了问题。 问题是我没有正确加载四元数。 四元数应解释为原始 XYZW 值。