0

我试图理解NEHEs 教程中的第 9 课,这是关于在 3d 空间中移动位图的。

这里最有趣的是通过 3d 空间在一个简单的四边形上移动 2d 位图纹理,并使其始终面向屏幕(查看器)。所以位图看起来是 3d 的,但无论它在 3d 空间中的哪个位置,它始终是 2d 面向观察者的。

在第 9 课中,生成了一个绕圈移动的星星列表,看起来非常好。为了避免从侧面看到星星,编码人员正在做一些棘手的编码,以使星星始终面向观察者。

代码如下:(在循环中为每个星调用以下代码)

glLoadIdentity();
glTranslatef(0.0f,0.0f,zoom);
glRotatef(tilt,1.0f,0.0f,0.0f);
glRotatef(star[loop].angle,0.0f,1.0f,0.0f);
glTranslatef(star[loop].dist,0.0f,0.0f);
glRotatef(-star[loop].angle,0.0f,1.0f,0.0f);
glRotatef(-tilt,1.0f,0.0f,0.0f);

在上面的线条之后,开始绘制星星。如果您检查最后两行,您会看到第 3 行和第 4 行的转换刚刚被取消(如撤消)。最后的这两行让我们有可能让星星一直面向观众。但我不知道为什么这是有效的。

我认为这来自于我对 OpenGL 如何真正进行转换的误解。对我来说,最后两行就像撤销之前所做的一样,这对我来说没有意义。但它的工作。

因此,当我调用 glTranslatef 时,我知道视图的当前矩阵乘以 glTranslatef 提供的平移值。换句话说,“glTranslatef(0.0f,0.0f,zoom);” 如果缩放为负数,则会将我要绘制星星的位置移动到场景中。好的。

但究竟是什么被移到了这里?观看者是“离开”了还是有某种对象坐标系通过 glTranslatef 移动到场景中?这里发生了什么事?

然后glRotatef,这里旋转的是什么?又是一个坐标系,观众本身?

在现实世界中。我会将星星放置在 3d 空间中的某个位置,然后在围绕我的世界原点的世界空间中旋转它,然后在星星移动到原点并再次从边缘开始时进行移动,然后我会为明星本身,所以它面向观众。我想这是在这里完成的。但是我如何首先围绕世界原点旋转,然后围绕恒星本身旋转?对我来说,opengl 似乎正在世界坐标系统和对象坐标系统之间切换,这并没有像你看到的那样真正发生。

我不需要添加其余的代码,因为它非常标准。简单的 GL 初始化 3d 绘图,旋转的东西,然后使用混合使用星形纹理进行简单的 QUADS 绘图。就是这样。

有人可以解释一下我在这里误解了什么吗?

4

3 回答 3

4

考虑 gl 矩阵堆栈的另一种方法是从你的绘图调用向后走。在您的情况下,由于您的 draw 是最后一行,让我们加强代码:

1) 首先,星形相对于原点绕 X 轴旋转 -tilt。

2) 星星相对于原点绕 Y 轴旋转 -star[loop].angle。

3) 星星由star[loop].dist 沿X 轴移动。

4) 星星相对于原点围绕 Y 轴旋转了 star[loop].angle。由于第 3 步,恒星不再位于原点,因此该旋转既移动了恒星的中心,又将其局部旋转。

5) 星星相对于原点绕 X 轴倾斜旋转。(同注4)

6) 星星通过缩放单位沿 Z 轴向下移动。

这里的诀窍是很难输入文字,但试着描绘出动作的顺序。虽然第 2 步和第 4 步看起来像是相互颠倒,但它们之间的移动改变了旋转的性质。关键短语是旋转是围绕原点定义的。移动星星会改变旋转的效果。

当您想就地旋转某些东西时,这导致典型的使用堆叠矩阵。首先将其移动到原点,然后旋转它,然后将其移回原点。你在这里所拥有的几乎是相同的概念。

我发现用两只手来可视化矩阵很有用。一只手代表原点,第二只手(通常是右手,如果你在像 OpenGL 这样的右手坐标系中)代表对象。我像 XYZ 轴一样张开手指,以便可以在本地和原点周围可视化旋转。像这样开始,围绕原点的旋转顺序和线性移动应该更容易描绘。

您问的第二个问题与相机矩阵在典型 OpenGL 设置中的行为有关。首先,了解屏幕空间坐标(类似地,设备坐标)的概念。这是实际显示的空间。X 和 Y 是屏幕的矢量,Z 是深度。该空间通常在 -1 到 1 的范围内。将对象向下移动 Z 有效地将对象移开。

相机(或透视矩阵)通常负责将“世界”空间转换为该屏幕空间。该矩阵定义了“查看者”,但最终它只是另一个矩阵。矩阵总是“最后”应用,所以如果你像我之前描述的那样向上读取变换,相机通常在最顶部,就像你看到的那样。在这种情况下,您可以将最后一次变换(通过缩放转换)视为一个非常简单的相机矩阵,它将相机向后移动缩放单位。

祝你好运。:)

于 2011-03-04T23:13:52.767 回答
1

中间的 glTranslatef受到旋转的影响:它将星星沿 x' 轴移动到距离 dist,此时轴 x' 相对于原始 x 轴旋转了(倾斜 + 角度)。

在opengl中,您有对象坐标乘以(一堆)投影矩阵。所以你正在移动物体。如果要“移动相机”,则必须乘以相机位置和轴的逆矩阵:

ProjectedCoords = CameraMatrix^-1。对象矩阵。对象坐标

于 2011-03-04T22:55:46.823 回答
0

我也发现这很令人困惑,但我只是玩弄了一些 NeHe 代码来更好地理解 glTranslatef() 和 glRotatef()。

我目前的理解是 glRotatef() 实际上旋转坐标系,这样 glRotatef(90.0f, 0.0f, 0.0f, 1.0f) 将导致 x 轴位于 y 轴之前的位置。旋转后,glTranslatef(1.0f, 0.0f, 0.0f) 将在屏幕上向上移动一个对象。

因此,glTranslatef() 根据坐标系的当前旋转移动对象。因此,glTranslatef 和 glRotatef 的顺序在教程 9 中很重要。

用技术术语来说,我的描述可能并不完美,但它对我有用。

于 2011-03-22T11:02:37.583 回答