如何计算没有逆绑定矩阵和通道的 GLTF 关节的变换?

问题描述 投票:0回答:1

所以我有以下 C++ 代码来计算发送到顶点着色器的最终骨骼矩阵:

void Skeleton::UpdateBoneTransforms(const Animation& animation, float animationTime, Bone& pNode, const glm::mat4& parentTransform)
{
    auto global_transform = glm::mat4(1.0f);

    bool has_animation = animation.m_BoneAnimations.find(pNode.index) != animation.m_BoneAnimations.end();

    if (pNode.index != boneHierarchy.index && has_animation)
    {
        const auto& node_anim = animation.m_BoneAnimations.at(pNode.index);

        auto translation = node_anim.GetInterpolatedPosition(animationTime);
        auto translation_matrix = glm::translate(glm::mat4(1.0f), glm::vec3(translation.x, translation.y, translation.z));

        auto rotation = node_anim.GetInterpolatedRotation(animationTime);
        auto rotation_matrix = glm::toMat4(rotation);

        auto scale = node_anim.GetInterpolatedScale(animationTime);
        auto scale_matrix = glm::scale(glm::mat4(1.0f), glm::vec3(scale.x, scale.y, scale.z));

        auto nodeTransform = translation_matrix * rotation_matrix * scale_matrix;

        global_transform = parentTransform * nodeTransform;

        boneTransformMatrices[pNode.index] = global_transform * boneOffsetMatrices[pNode.index];
    }

    for (auto& child : pNode.children)
        UpdateBoneTransforms(animation, animationTime, child, global_transform);
}

现在这工作正常,但我发现一个模型,其中指尖骨骼有一个恒等的逆绑定矩阵,动画没有使指尖骨骼变形的通道,但它们各自的 gltf 节点确实具有非零平移和旋转。阅读 gltf 规范,我似乎无法弄清楚在这个矩阵数学中节点的本地属性应该去哪里?如果我无法插入任何关键帧,我是否应该在 0.0 秒处使用节点的本地属性作为单个关键帧?

c++ opengl glm-math gltf
1个回答
0
投票

是的,当没有 glTF 动画以该节点为目标播放时,该节点的本地平移/旋转/缩放修改器将生效。当动画播放时,其每个输出都针对特定节点的特定通道,在动画持续时间内覆盖节点的本地变换。

您提到逆绑定矩阵对于其中一些节点来说是恒等的,但节点的局部平移/旋转不是。在这种情况下,蒙皮将“永久”使网格变形,将其从原始网格数据中存储的绑定姿势更改为默认姿势。

这可能不是很常见,因为模型作者可能只是烘焙了默认姿势并完全摆脱了骨架。但万一他们认为骨架稍后可用于其他目的,是的,在这种状态下运送 glTF 是有效的。

© www.soinside.com 2019 - 2024. All rights reserved.