【问题标题】:How does zooming, panning and rotating work?缩放、平移和旋转如何工作?
【发布时间】:2010-10-09 17:26:09
【问题描述】:

我正在尝试使用 OpenGL 绘制校园的原始地图。

谁能向我解释一下平移、缩放和旋转通常是如何实现的?

例如,通过平移和缩放,我只是在调整我的视口吗?所以我绘制并绘制了构成我的地图的所有线条,然后当用户单击并拖动它时,它会调整我的视口吗?

对于平移,它会改变我的视口的 x/y 值吗?对于缩放,它会增加/减少我的视口吗?轮换呢?

对于旋转,我是否必须对代表我的校园地图的每条折线进行仿射变换?在大小合适的地图上即时执行此操作会不会很昂贵?

或者,视口是否保持不变而平移/缩放/旋转以其他方式完成?


例如,如果您访问此link,您会看到他通过修改视口来准确描述平移和缩放。

这不正确吗?

【问题讨论】:

    标签: opengl rotation zooming viewport pan


    【解决方案1】:

    它们是通过在绘制场景之前应用一系列 glTranslate、glRotate 命令(表示相机位置和方向)来实现的。 (从技术上讲,您正在旋转整个场景!)

    有一些实用函数,比如 gluLookAt,它可以抽象出一些关于这个的细节。

    为了简单起见,假设您有两个向量表示您的相机:位置和方向。

    gluLookAt 获取位置、目的地和向上向量。

    如果你实现一个向量类,destinaion = position + direction 应该给你一个目标点。

    为了简单起见,您可以假设上向量始终为 (0,1,0)

    然后,在渲染场景中的任何内容之前,加载单位矩阵并调用 gluLookAt

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt( source.x, source.y, source.z, destination.x, destination.y, destination.z, 0, 1, 0 );
    

    然后开始绘制你的对象

    您可以通过稍微向右或向左改变位置来让用户跨越。旋转有点复杂,因为您必须旋转方向矢量。假设您正在旋转的是相机,而不是场景中的某个对象。

    一个问题是,如果你只有一个方向向量“向前”,你如何移动它?左右在哪里?

    在这种情况下,我的方法是只取“方向”和 (0,1,0) 的叉积。

    现在您可以使用以下方式将相机左右移动:

    position = position + right * amount; //amount < 0 moves to the left
    

    您可以使用“方向矢量”向前移动,但 IMO 最好将移动限制在水平面上,因此以与我们获得正确矢量相同的方式获得前向矢量:

    forward = cross( up, right )
    

    老实说,这有点老套。

    正确的做法是使用更“复杂”的数据结构来表示相机的“方向”,而不仅仅是向前的方向。但是,由于您才刚刚开始,所以最好一步一步来。

    【讨论】:

    • 让我补充一点,“视口”(通过 glViewport 设置)决不会进入这个过程。视口决定了您将渲染到窗口的哪个区域(这实际上不是真的,但现在可以这样想)并且通常会跨越整个窗口。
    【解决方案2】:

    所有这些“动作”都可以使用模型-视图矩阵转换函数来实现。您应该阅读有关 glTranslatef(平移)、glScalef(缩放)、glRotatef(旋转)的信息。您还应该阅读一些关于 OpenGL 的基本教程,您可能会发现 this link 很有用。

    【讨论】:

      【解决方案3】:

      通常,每当您在 opengl 中引用 3d 空间中的任何点时,都会应用三个步骤。

      给定一个局部点

      • 本地 -> 世界变换
      • 世界 -> 相机变换
      • 相机 -> 屏幕变换(通常是投影。取决于您使用的是透视还是正交)

      这些变换中的每一个都取您的 3d 点,并乘以一个矩阵。

      当您旋转相机时,它通常会通过将变换矩阵乘以旋转/平移/缩放仿射变换来改变世界 -> 相机变换。由于每帧都会重新渲染所有点,因此新矩阵将应用于您的点,并呈现出旋转的外观。

      【讨论】: