2

我有一个简单的模型,我在搅拌机中制作了一个简单的骨架结构。这是它的外观:

图像

这是搅拌机中的层次结构:

图像

如您所见,它有两根骨头:一根在矩形框的中间(“骨头”),它是完全静止的。另一个从中间点到顶部的骨骼(“Bone.001”)旋转。

我使用 AssImpNet 导入了网格,并从动画节点通道中提取了旋转、缩放和位置键。当我将这些变换应用于网格时,我得到了这个结果(按骨骼重量着色):

图像

动作/动画似乎可以正确播放,所以我相信这部分可以正常工作。现在这是我的理解开始崩溃的地方,但我相信我缺少的关键部分是计算“反向绑定姿势”(我已经看到了一些名称),并将其应用于我的骨骼转换也输入我的着色器。但到目前为止,我还不能准确地找到我需要从 AssImp 的格式中提取的内容,并将它们相乘以获得正确的最终转换。我只找到了关于遍历节点树和从每个父节点“撤消”转换或其他内容的模糊解释。

这是我尝试过的,似乎不起作用:

i thought that, for the base bone ("Bone"), i would need:
- the global inverse transform
- the node transform of the node with name "Bone"
- the rotation/position/scale keys from the animation channel with name "Bone"
- the bone offset from Meshes.Bones.OffsetMatrix from the bone named "Bone"

然后按顺序将它们相乘。

similarly for "Bone.001":
- the global inverse transform
- the node transform of the node with name "Bone"
- the rotation/position/scale keys from the animation channel with name "Bone"
- the node transform of the node with name "Bone.001"
- the rotation/position/scale keys from the animation channel with name "Bone.001"
- the bone offset from Meshes.Bones.OffsetMatrix from the bone named "Bone.001"

我尝试实现这一点(现在对索引进行硬编码只是为了让事情正常运行),请注意它使用的是 C#/AssImpNet,因此命名约定与 C++/AssImp 有点不同:

        // "Bone"
        public Matrix4 Bone0Transform(double time)
        {
            var bone0 = MathUtils.ConvertMatrix(Scene.RootNode.Children[1].Children[0].Transform);

            var frame0 = GetTransformedFrame(1, TimeToFrame(1, time));

            var global = MathUtils.ConvertMatrix(Scene.RootNode.Transform).Inverted();

            var offset0 = MathUtils.ConvertMatrix(Scene.Meshes[0].Bones[0].OffsetMatrix);

            var total = global * bone0 * frame0 * offset0;

            return total;
        }

        // "Bone.001"
        public Matrix4 Bone1Transform(double time)
        {
            var bone0 = MathUtils.ConvertMatrix(Scene.RootNode.Children[1].Children[0].Transform);

            var bone1 = MathUtils.ConvertMatrix(Scene.RootNode.Children[1].Children[0].Children[0].Transform);

            var frame0 = GetTransformedFrame(1, TimeToFrame(1, time));
            var frame1 = GetTransformedFrame(2, TimeToFrame(2, time));

            var global = MathUtils.ConvertMatrix(Scene.RootNode.Transform).Inverted();

            var offset1 = MathUtils.ConvertMatrix(Scene.Meshes[0].Bones[1].OffsetMatrix);

            var total = global * bone0 * frame0 * bone1 * frame1 * offset1;

            return total;
        }

GetTransformedFrame 返回一个 Matrix4,它结合了与当前时间相对应的帧的缩放、旋转和位置键,并且它自己给出了您可以在 gif 中看到的结果,其中框为红色/绿色。

所有这一切给我的是一个明显不正确的结果: 图像

所以我的问题是:我对如何计算最终骨骼转换的理解是否错误?如果是这样,正确的做法是什么?

4

0 回答 0