带骨骼和矩阵的3D动画

3
我真的是最后一招了。我已经两天没能解决这个问题了。所以,如果有人对3D、矩阵和动画有一定的了解,我会非常感激您的意见。
我已经下载了这个项目并将其实现到我的项目中:http://xbox.create.msdn.com/en-US/education/catalog/sample/skinned_model。 我的游戏角色在施法时会挥舞手臂。我已经成功地制作了这个动画并将其导入到了项目中。但我需要在他双手的掌心产生根据动画移动的粒子。我只需要在应用动画后双手掌心的3D位置。 动画期间手部图片: http://s18.postimg.org/qkaipufa1/hands.png 如果您查看样本项目中的蒙皮模型:类: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命令都会返回一个按照骨骼索引排序的Matrix[]数组。因此,要获取Bone 10的Transform,我认为代码将如下所示:
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 HandPosition = transform.Up;

当我尝试上述解决方案时,我得到了混合的结果。对于某些骨骼来说,在动画的中间部分移动是正确的。但是,实际上并没有什么好的效果。有人能解释一下这里发生了什么吗?如何获得手掌骨骼的位置?我真的很茫然。我只在两个月前学会了矩阵是什么,而且这周才开始学习带骨骼的动画。


看起来你需要第ith个世界变换。我不是很确定这个+1索引,但你可以尝试一下。 - Nico Schertler
@NicoSchertler 是的,我又看了一遍那个部分,我会去掉+1。 “看起来你需要第ith个世界变换。” - “ith”是什么意思? - Nathan
转换索引为 i ;) - Nico Schertler
2个回答

2

好的,这个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坐标。


0
重新打开你的网格设计器,在手掌骨骼附近放置一个空物体,作为粒子效果的位置,将该空物体与“手掌”骨骼进行父子关联,并记录空物体在本地坐标系中面向的方向,以便正确面向粒子,重新烘焙动画并重新导入。我承认我不熟悉你正在使用的“网格蒙皮工具”,但我想它支持像空物体这样的骨骼子对象,因为它们经常用于此类目的。你正在过度思考。如果你不能用X-box套件完成这个任务,我就不知道了。
“变换矩阵”不一定是骨骼的位置,所以我对这些函数返回什么感到困惑。它们可能只返回用于计算加权到这些骨骼上的顶点位置的矩阵。是否有一种方法可以返回手掌骨骼的“世界位置”,并直接跟踪动画到空物体或手掌骨骼的世界位置?我对你需要使用变换矩阵感到困惑。如果你正在使用的库很好,几乎肯定会有一种方法来获取骨骼的世界坐标,这样添加一个位于手掌外部的“跟踪骨骼”就可以让你跟踪动画或对象到该骨骼,甚至直接将它们作为子对象。

不需要修改文件。已经有足够的信息可用。无论如何,您只是提供OP要求的建议。跟踪特定骨骼正是他想要实现的。您发表的其余内容并没有真正增加有价值的信息。因此,在它被投票下降之前,我建议删除此答案。您甚至表示自己对动画数学不了解。希望这听起来不太无礼。本评论不是要冒犯您。 - Nico Schertler
XNA 没有跟踪物体在世界空间中位置的方法?我承认我从未使用过 XNA,但我很难相信,在任何游戏开发环境中,要检索任何动画模型的任何子对象的位置,都必须浏览一堆变换矩阵。我觉得他可能在错误的方向上努力。 - ThisHandleNotInUse
好的,我的错,我应该提前调查一下XNA是什么。我没有想到一个两个月前才学习了矩阵的人会尝试在没有本地世界空间坐标系的框架上编写动画。我确实知道如何相乘矩阵和从坐标空间进行变换。我只是对XNA框架的极其基本的行为不熟悉。 - ThisHandleNotInUse
@ThisHandleNotInUse 恩,我很高兴收到了回复。这是进入游戏内容前的最后一步之一。我的动画已经在工作了,我也能够将动画分别加载到特定的骨骼上。因此,我可以将多个动画加载到一个模型上。这也不是我在3D游戏中做的第一件事情。我已经处理过SAT碰撞、AABB碰撞、高度图碰撞、照明、HLSL着色器、UV贴图纹理、裁剪等等。我在那里遇到了更多绝望的情况,但我会成功的! - Nathan
@ThisHandleNotInUse 终于搞定了。 - Nathan
@nate142 现在你让我写D3D11的东西,每30分钟就要撞墙。干得好;-) 我的相机上的XMMatrixLookAtLH函数在尝试进行平移时返回一个充满NaN的视图矩阵——有什么想法吗? - ThisHandleNotInUse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接