6

我正在尝试为我的 3D 游戏创建一个场景图,其中每个对象的转换都相对于它的父对象。图的每个节点都有一个旋转、缩放和平移向量。

组合相对变换矩阵以获得对象的绝对变换的正确方法是什么?如果您也可以解释您的解决方案,我会很高兴。


这是一个错误的例子:
这实际上是解决方案:

Matrix GetAbsoluteTransformation()
{
    if (!this.IsRoot())
    {
        return this.Transformation * this.Parent.GetAbsoluteTransformation();
    }
    else
    {
        return this.Transformation;
    }
}

在这种情况下,当父节点旋转、缩放或移动时,子节点的变换量相同,这是正确的行为! 但是孩子只会围绕自己的原点旋转,不会围绕父母的原点移动。


应用:

有一个有四个轮子的汽车模型。车轮相对定位在汽车的原点周围。轮子可以像真正的轮子一样旋转。如果我现在旋转汽车,轮子应该始终与它相连。在这种情况下,汽车是根节点,车轮是子节点。

另一个例子是太阳系的模型。行星围绕自己的轴旋转,围绕太阳移动,卫星围绕行星运行。

4

3 回答 3

4

关于你的“怎么做错了”,我不想告诉你,但它没有错;相反,它是不完整的。您需要独立于父子关系来完成这些工作。

这是一个例子:就像你提到的那样,车轮连接在汽车上。如果您平移或旋转汽车,则无需触摸车轮 - 它们相对于汽车位于相同位置。但是,当您尝试在“现实世界”中获取轮子的新位置时,您必须沿着树向下遍历,边走边应用矩阵变换。这一切都有效,对吧?

当您旋转一个对象时,它会围绕其 OWN 原点旋转。因此,一个轮子可能应该围绕它的 y 轴旋转,而一个行星应该围绕它的 z 轴旋转。但是现在如果你需要让一颗行星“围绕太阳”移动,那么你正在做一些完全不同的事情。这必须单独计算。这并不是说使用你已经拥有的一些相同的匹配不会缓解它,(尽管我不能在不自己做数学的情况下肯定地说),但它完全不同。

您正在查看实际更改对象的状态。这就是场景图的美妙之处!如果您没有场景图,则必须计算出所有各种值,一直到主场景,然后进行各种数学运算。在这里,你只需要做一点三角和代数就可以绕着行星移动(你可以谷歌天体力学)并相对于它的恒星移动行星。下次主场景询问行星在哪里时,它会顺着场景图走下去!:-D

于 2011-11-06T21:47:31.903 回答
1

我认为这是正确的行为。

我不认为围绕父母的原点旋转是可以通过简单的矩阵堆栈来完成的。我认为你只能从父母传给孩子。

您可以尝试根据与父级绝对原点的偏移量来设置相对旋转和变换,尽管这比简单地推入矩阵堆栈要多得多。

这是一个类似的问题:从场景图中获取绝对位置和旋转?

于 2011-11-06T21:42:52.937 回答
1

这取决于您使用的是 OpenGL 还是 Direct3D。在 OpenGL 中,变换是从右到左应用的,而在 Direct3D 中,它们是从左到右应用的。它们都是设计变换系统的完全有效的方法,但这意味着你必须以不同的方式思考它们。

我发现在 OpenGL 的系统中最容易思考,但反过来。我没有考虑在从右到左应用变换时对象的顶点如何移动,而是想象对象的坐标系以从左到右的顺序进行变换。每个变换都相对于新的局部坐标系应用,而不是相对于世界。

对于汽车上的车轮,涉及三个变换:汽车在空间中的位置、车轮相对于汽车的原点以及车轮相对于其空档位置的方向。只需按从左到右的顺序应用它们(对于 Direct3D,反之亦然)。要绘制四个轮子,首先应用汽车的变换,然后记住当前的变换,然后依次应用位置和方向的变换,之后再回到记住的汽车变换。

于 2011-11-06T21:47:44.307 回答