GLTF 动画导致网格扭曲

发布于 2025-01-10 16:42:16 字数 2362 浏览 2 评论 0原文

我已经下载了 GLTF 示例 Fox https://github。 com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/Fox 并试图通过 SharpGLTF 使动画正常工作。

到目前为止,当传入联合 worldTransform * inverseBindMatrix 时看起来很好 输入图片这里的描述

但是当尝试动画的第一帧看起来都扭曲了 输入图片此处描述

这是计算骨骼变换的代码。我希望有人知道可能出了什么问题,我已经尝试让它工作 3 天了,但不知道该去哪里了。

private void UpdateBone (Node node, Matrix4x4 parentTransformation) {
    Skin skin = skeleton.skin;
    (Node joint, System.Numerics.Matrix4x4 inverseBindMatrix) = skin.GetJoint(0);
    
    for (var i = 0; i < skin.JointsCount; i++) {
        (joint, inverseBindMatrix) = skin.GetJoint(i);
        if (joint.Name == node.Name) break;
    }

    
    Matrix4x4 scale = Matrix4x4.Identity;
    Matrix4x4 rotation = Matrix4x4.Identity;
    Matrix4x4 translation = Matrix4x4.Identity;
    IEnumerable<AnimationChannel> jointChannels = currentAnimation.logicalAnimation.FindChannels(joint);
    foreach (var jointChannel in jointChannels) {
        if (jointChannel.GetTranslationSampler() is { } translationSampler) {
            translation = Matrix4x4.Translation(Vector3.FromSystemVector(translationSampler.GetLinearKeys().First().Value));
        }

        if (jointChannel.GetRotationSampler() is { } rotationSampler) {
            rotation = Matrix4x4.RotationQuaternion((Quaternion) rotationSampler.GetLinearKeys().First().Value);
        }

        if (jointChannel.GetScaleSampler() is { } scaleSampler) {
            scale = Matrix4x4.Scaling(Vector3.FromSystemVector(scaleSampler.GetLinearKeys().First().Value));
        }
    }

    Matrix4x4 localTransformation = translation * rotation * scale;
    Matrix4x4 globalTransformation = parentTransformation * localTransformation;
    skeletonState.BoneTransformations[node.LogicalIndex] = Matrix4x4.Identity;
    
    foreach (var child in node.VisualChildren) {
        if (child is null || !child.IsSkinJoint) continue;
        
        UpdateBone(child, globalTransformation);
    }
}

I've downloaded the GLTF sample Fox https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/Fox
and been trying to get the animations working through SharpGLTF.

So far it looks fine when pass in the joint worldTransform * inverseBindMatrix
enter image description here

But when trying the first frame of the animation looks all distorted
enter image description here

Here is the code that calculates the bone transformations. I hope anyone knows what might be wrong, I've been trying to get it to work for 3 days and don't know where to look anymore.

private void UpdateBone (Node node, Matrix4x4 parentTransformation) {
    Skin skin = skeleton.skin;
    (Node joint, System.Numerics.Matrix4x4 inverseBindMatrix) = skin.GetJoint(0);
    
    for (var i = 0; i < skin.JointsCount; i++) {
        (joint, inverseBindMatrix) = skin.GetJoint(i);
        if (joint.Name == node.Name) break;
    }

    
    Matrix4x4 scale = Matrix4x4.Identity;
    Matrix4x4 rotation = Matrix4x4.Identity;
    Matrix4x4 translation = Matrix4x4.Identity;
    IEnumerable<AnimationChannel> jointChannels = currentAnimation.logicalAnimation.FindChannels(joint);
    foreach (var jointChannel in jointChannels) {
        if (jointChannel.GetTranslationSampler() is { } translationSampler) {
            translation = Matrix4x4.Translation(Vector3.FromSystemVector(translationSampler.GetLinearKeys().First().Value));
        }

        if (jointChannel.GetRotationSampler() is { } rotationSampler) {
            rotation = Matrix4x4.RotationQuaternion((Quaternion) rotationSampler.GetLinearKeys().First().Value);
        }

        if (jointChannel.GetScaleSampler() is { } scaleSampler) {
            scale = Matrix4x4.Scaling(Vector3.FromSystemVector(scaleSampler.GetLinearKeys().First().Value));
        }
    }

    Matrix4x4 localTransformation = translation * rotation * scale;
    Matrix4x4 globalTransformation = parentTransformation * localTransformation;
    skeletonState.BoneTransformations[node.LogicalIndex] = Matrix4x4.Identity;
    
    foreach (var child in node.VisualChildren) {
        if (child is null || !child.IsSkinJoint) continue;
        
        UpdateBone(child, globalTransformation);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

颜漓半夏 2025-01-17 16:42:16

显然没有必要在 SharpGLTF 中自己编写动画。以下是 VPenades 关于 SharpGLTF Discord 的有用信息

node.GetLocalTransform(动画, 时间);和
node.GetWorldTransform(动画, 时间);取决于你是哪一个
需要的是那些为您提供所需的动画变换的
更新你的骨骼,你不需要所有的代码。

但是这些调用相当慢,它们的存在是为了方便,但快速的方法是使用node.GetCurveSamplers一次,然后重用它来获取矩阵

Apparently there is no need to compose the animations myself in SharpGLTF. Here is the helpful message from VPenades on the SharpGLTF Discord

node.GetLocalTransform(Animation, Time); and
node.GetWorldTransform(Animation, Time); depending on which one you
need, are the ones that give you the animated transforms you need to
update your bones, you don't need all that code.

but these calls are fairly slow, they're there for convenience, but the fast way is to use node.GetCurveSamplers once, and reuse it to get the matrices

你的他你的她 2025-01-17 16:42:16

看来正确的矩阵运算是:
m0i * m0 * bindm * m

其中 m0i 是 m0 矩阵的逆矩阵,m0 是从树中收集的矩阵(未应用动画),bindm 是绑定矩阵,m 是从应用了动画的树中收集的 slerped 矩阵。

(但我实际上使用 ri * m0i * m0 * bindm * m * resize,其中 ri 和 resize 可以正确调整模型大小)

It seems that correct matrix operation is:
m0i * m0 * bindm * m

where m0i is inverse of m0 matrix, m0 is the matrix collected from the tree (without animations applied), bindm is the bind matrix, and m is the slerped matrix collected from the tree with animations applied.

(but I'm actually using ri * m0i * m0 * bindm * m * resize, where ri and resize are there to resize the model correctly)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文