Nico van Bentum
Nico van Bentum

Reputation: 347

How to calculate transform for GLTF joint with no inverse bind matrix and no channels?

So I have the following C++ code to calculate the final bone matrices I send to the vertex shader:

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);
}

Now this works fine, but I found a model where the fingertip bones have an inverse bind matrix that is identity, the animation has no channels deforming the fingertip bones, but their respective gltf nodes do have non-zero translation and rotation. Reading the gltf spec I can't seem to figure out where in this matrix math the nodes' local properties are supposed to go? if I can't interpolate any keyframes, should I just use the nodes' local properties as single keyframes at 0.0 seconds?

Upvotes: 0

Views: 173

Answers (1)

emackey
emackey

Reputation: 12448

Yes, when no glTF animations are playing that target that node, the node's local translation / rotation / scale modifiers are in effect. When an animation plays, each of its outputs targets a particular channel of a particular node, overwriting the node's local transform for the duration of the animation.

You mentioned that the inverse bind matrix is identity for some of these nodes, but the node's local translation / rotation is not. In this case, the skinning will "permanently" deform the mesh, changing it from the bind pose stored in raw mesh data to the default pose.

This probably isn't very common, as the model author could have probably just baked down the default pose and got rid of the skeleton entirely. But in case they thought the skeleton would be useful for some other purpose later, yes, it's valid to ship a glTF in this state.

Upvotes: 1

Related Questions