骨骼及其矩阵的3D动画

本文关键字:3D 动画 | 更新日期: 2023-09-27 18:13:54

我真的是迫不得已才问这个问题。我已经两天没能解决这个问题了。所以,如果有人知道一些关于3D,矩阵和动画的事情,我会非常感谢你的输入。

我已经下载了这个项目,并将其实现到我自己的项目:http://xbox.create.msdn.com/en-US/education/catalog/sample/skinned_model。在我的游戏中,角色在施放咒语时移动他的手。我已经成功制作了这个动画并导入到项目中。但我需要在他的手掌中生成粒子,这些粒子根据动画移动。我所需要的是动画应用后他手掌的3D位置

动画中手的图片:http://s18.postimg.org/qkaipufa1/hands.png

如果你看一下蒙皮模型示例项目:Class: AnimationPlayer.cs,你会注意到它处理矩阵3次:

    public void Update(TimeSpan time, bool relativeToCurrentTime,
                       Matrix rootTransform)
    {
        UpdateBoneTransforms(time, relativeToCurrentTime);
        UpdateWorldTransforms(rootTransform);
        UpdateSkinTransforms();
    }

并允许我们在每个步骤之后访问它们:

        /// Gets the current bone transform matrices, relative to their parent bones.
    /// </summary>
    public Matrix[] GetBoneTransforms()
    {
        return boneTransforms;
    }

    /// <summary>
    /// Gets the current bone transform matrices, in absolute format.
    /// </summary>
    public Matrix[] GetWorldTransforms()
    {
        return worldTransforms;
    }

    /// <summary>
    /// Gets the current bone transform matrices,
    /// relative to the skinning bind pose.
    /// </summary>
    public Matrix[] GetSkinTransforms()
    {
        return skinTransforms;
    }

我还应该提一下,我知道手掌骨的索引和它所有父母的索引:

10 - 11的父母,根骨

11 - 12的父母

12 - 13的父母

13 - 14的父母

14 - 15的父母

15 - 16的父母

16 -手掌骨

据我所知,这个项目是我上面列出的所有GetXXXXXXXX命令返回一个矩阵[]数组,根据骨骼的索引排序。为了得到Bone 10的变换。我相信代码看起来像:

Matrix[] M = animtionplayer.GetSkinTransforms();
Matrix transform = M[10];

好的,现在是我不明白的部分。我不知道我需要使用3个GetXXXXXXXXX函数中的哪一个来获得手掌位置。

我认为着色器计算骨骼位置的方法是将它们乘以它们的每个父骨骼。所以:

Matrix[] M = animtionplayer.GetBoneTransforms();
Matrix transform = M[10];
transform = transform * M[11];
transform = transform * M[12];
transform = transform * M[13];
transform = transform * M[14];
transform = transform * M[15];
transform = transform * M[16];
//maybe apply the world position of the model? 
transform = transform * MyWorld;

然后可能得到一个vector3位置

Vector3 HandPosition = transform.Up;

当我尝试上面的解决方案时,我得到了不同的结果。对于某些骨骼,它会在动画的中间部分正确移动。但老实说,没什么好东西。有人能解释一下这是怎么回事吗?我怎么知道骨头在手掌里的位置?我真是一头雾水。我两个月前才知道矩阵是什么,这周才知道带骨头的动画。

骨骼及其矩阵的3D动画

好吧,所以这个bug是非常令人沮丧,所以我休息了大约一个星期的编码。两天前我又开始做了。尝试许多随机的事情....通过观察矩阵的值来寻找模式,我终于找到了。这是一张手被动画的图片,所有的骨头都用白色的大球体完美地突出显示。它也完美地遵循了动画!http://s27.postimg.org/f48i7ae4x/2014_07_30_18_H14_M20_S.jpg

代码:

Matrix[] BoneTransforms = animtionPlayer.GetWorldTransforms();
for (int i = 0; i < BoneTransforms.Length; i++)
{
    Vector3 v3 = new Vector3(BoneTransforms[i].M41, BoneTransforms[i].M42, BoneTransforms[i].M43);
    v3 = Vector3.Transform(v3, GetWorld(Position, Rotation, Scale));//GetWorld is the models world matrix: position, rotation and scale.
    Game1.DrawMarker(v3); //v3 is the position of the current Bone.
}

我只是通过观察特定矩阵的所有值来编写代码。我了解到M41, M42, M43是特定骨骼的X, Y, Z线。

重新打开你的网格设计器,在他的手中放一个关于粒子效果应该在哪里的空,将空放置在"手掌"骨骼上,并跟踪空在局部坐标中所面对的方向,这样你就可以在正确的方向上面对粒子,重新制作动画并重新导入它。我承认我不熟悉你正在使用的"网格剥皮"-但我可以想象它支持像空的骨头的子对象,因为它们经常被用于这样的目的。你想太多了。如果你不能用X-box套件做到这一点,我不知道。

"变换矩阵"不一定是骨骼的位置-所以我对这些函数返回的内容感到困惑。它们可能只是返回它用来计算这些骨头加权的顶点位置的矩阵。没有一个函数可以返回掌骨的"世界位置",并简单地跟踪动画到空掌骨或掌骨的世界位置?我很困惑你需要用变换矩阵做什么。如果你使用的库是好的,几乎肯定会有一种方法来获得骨骼的世界坐标,在这种情况下,在手掌外添加"跟踪骨骼"将让你跟踪动画或对象到该骨骼,甚至直接父级它们。