我有一个简单的模型,它具有在Blender中制作的简单骨骼结构。外观如下:
这是搅拌器中的层次结构:
如您所见,它有两根骨头:一根在矩形框(“骨头”)的中间,完全固定。从中点一直延伸到顶部的另一个骨骼(“ 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中看到的结果,该框的颜色为红色/绿色。
这给了我一个明显不正确的结果:
所以我的问题是:我对如何计算最终骨骼变形的理解是否错误?如果是这样,正确的做法是什么?