【问题标题】:3D animation with bones and their matrices带有骨骼及其矩阵的 3D 动画
【发布时间】:2014-07-19 22:21:40
【问题描述】:

我真的要求这是最后的手段。我已经2天没能解决这个问题了。因此,如果有人对 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 命令都返回一个根据骨骼索引排序的 Matrix[] 数组。所以要得到 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;

好吧,当我尝试上述解决方案时,我得到的结果好坏参半。对于某些骨骼,它会在动画的中间部分正确移动。但老实说没什么好。有人可以解释这里发生了什么吗?如何获得手掌中骨头的位置?我在这里真的很黑暗。 2 个月前我才知道矩阵是什么,这周才知道有骨骼的动画。

【问题讨论】:

  • 看起来你需要第 i 个世界变换。我不太相信+1 索引,但您可以尝试一下。
  • @NicoSchertler 是的,我再次查看了该部分,我将删除 +1。 “看来你需要第i个世界变换了。” - 什么是“我”?
  • 索引为 i 的变换 ;)

标签: c# animation matrix 3d xna


【解决方案1】:

好的,所以这个错误很令人沮丧,所以我从编码中休息了大约一周。两天前我又开始工作了。尝试了许多随机的东西....查看矩阵的值寻找模式,我终于明白了。 这是一张手部动画的图像,所有骨骼都用大的白色球体完美突出。它也完美地跟随动画! 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 绳索。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 不需要修改文件。已经有足够的信息可用。无论如何,您只是在建议 OP 的要求。追踪某块骨头,正是他想要达到的目的。您帖子的其余部分并没有真正添加有价值的信息。所以我建议在它被否决之前删除这个答案。你甚至说你对动画数学知之甚少。我希望,这听起来不太不礼貌。此评论无意冒犯您。
    • XNA 无法追踪对象在世界空间中的位置?我承认我从未使用过 XNA,但我很难相信要在任何游戏开发环境中检索任何动画模型的任何子对象的位置,您将不得不浏览一堆变换矩阵。我觉得他找错了树。
    • 好吧,我的错,我应该提前调查 XNA 是什么。我没想到两个月前了解矩阵是什么的人会尝试在没有原生世界空间坐标系的框架上编写动画。而且我确实知道如何将矩阵相乘并从坐标空间进行变换。我只是不熟悉 XNA 框架极其基本的行为。
    • @ThisHandleNotInUse 好吧,我很高兴收到了回复。好吧,这是进入游戏内容之前的最后一步。我的动画正在运行,我还能够将动画单独加载到某些骨骼上。所以我可以将多个动画加载到一个模型上。这也不是我在 3D 游戏中做的第一件事。我使用过 SAT 碰撞、AABB 碰撞、高度贴图碰撞、照明、HLSL 着色器、UV 贴图瓷砖纹理、剔除等。我在那里有更多绝望的情况,我也会在这里成功!
    • @ThisHandleNotInUse 终于搞定了。
    猜你喜欢
    • 2017-05-05
    • 2017-04-10
    • 2015-07-21
    • 2015-05-25
    • 2020-09-27
    • 2012-10-17
    • 1970-01-01
    • 1970-01-01
    • 2014-10-16
    相关资源
    最近更新 更多