1

我正在研究一个 3D 渲染设置(所有数学都是使用 GLM for OpenGL 完成的),并且一切正常,除了我希望我的转换如何工作。我为每个实体创建一个矩阵,如下所示:

matrix = mat4(1);
vec3 scale = GetWorldScale();
vec3 pos = GetWorldPosition(); // Returns pos + parent->pos
quat rot = GetWorldRotationQuat(); // Returns parent->rot * rot

matrix = glm::translate(matrix, pos);
matrix *= mat4_cast(rot);
matrix = glm::scale(matrix, scale);

right = matrix[0].xyz;
up = matrix[1].xyz;
direction = matrix[2].xyz;

使用它,它通常可以正常工作,除了我不确定如何根据喜好调整它的一部分。也就是说,使用它,X 轴上的平移被翻转(例如,左为正,Z 轴上为正,但我对此的判别较小),并且 Y 轴上的旋转被翻转。

为此目的查看其他代码,似乎许多人否定了我用于方向的内容(用于相机)。我也这样做了,并且平移是正确的,但是所有旋转轴都与首选轴相反(尽管无论方向是否否定,X 上的旋转都是相同的)。

我不太确定我应该做些什么来帮助纠正这个问题,除了可能在使用前否定 X 轴平移和 Y 轴旋转,但我觉得这不是最好的方法。想法?

4

1 回答 1

0

我相信问题来自于你混合了变换的顺序,尤其是平移和旋转。这些变换(缩放、平移和旋转)中的每一个都定义了如何将一个坐标系变换到另一个坐标系。

让我们来看一个例子:你有一个子对象 c 和它的父对象 p。它们每个都有平移 t、旋转 r 和尺度 s。为简单起见,每个都是 4x4 矩阵。目前你做

matrix = p.t * c.t * p.r * c.r * p.s * c.s

所以想象一下被这个矩阵(长度为 1 的 xyz 轴)转换的孩子的局部坐标系。点是从右乘的,所以我们必须从右到左读。首先,坐标系由子缩放,然后由父缩放。然后它被孩子旋转。然后由家长。现在应用孩子的翻译。这意味着子平移应用在旋转坐标系中。由于您已经应用了孩子父母的旋转,它被旋转到父母的坐标系中。因此,孩子的坐标被解释为就好像它们是父坐标一样。

所以你应该做什么:在你的方法中,计算对象矩阵m = c.t * c.r * c.s。然后你的对象的世界矩阵被定义为wm = pm * m,其中父矩阵pm是父的世界矩阵。这样你就会得到一个世界矩阵:

c.wm = (c.pm) * (c.o) = (p.t * p.r * p.s) * (c.t * c.r * c.s)

这意味着孩子的平移是在孩子的坐标系中,而父母的平移是在父母的坐标系中。

于 2013-06-12T19:03:47.197 回答