跳至内容

OpenGL 编程/现代 OpenGL 教程导航

来自维基教科书,开放世界中的开放书籍

键盘输入

[编辑 | 编辑源代码]
  • glutKeyboardFunc
  • glutSpecialFunc
  • glutSpecialUpFunc
  • glutGetModifiers() == GLUT_ACTIVE_SHIFT 或 GLUT_ACTIVE_CTRL 或 GLUT_ACTIVE_ALT

注意:当按下键并保持按住时,GLUT 的 special() 回调函数会反复调用。

坐标系

[编辑 | 编辑源代码]

有几种方法可以定位 (X,Y,Z) 轴三元组。

右手定则
  • Z 轴向上 : 在 Blender 中使用,这意味着 (X,Y) 是地面,而 Z 是海拔高度
  • Y 轴向上 : 在 OpenGL 中使用,这意味着 (X,Y) 像一面墙,所以 Y 是海拔高度,而 Z 是距离该墙更近或更远
  • 右手系 / 左手系 : OpenGL 和 Blender 使用右手坐标系,这意味着你可以用右手来表示它,拇指指向 X 轴,食指指向 Y 轴,中指指向 Z 轴。左手坐标系(如 DirectX 使用)可以用左手类似地表示。

在 OpenGL 中使用 Blender 的 Z 轴向上坐标系可能很诱人,但会导致问题

  • .obj 文件通常是 Y 轴向上,在加载它们时需要更改(或在从 Blender 导出它们时)
  • 相机是 Y 轴向上,因此如果你使用 Z 轴向上坐标系,默认情况下相机位于 (0,0,0) 处,并且它面向下方。当旋转相机时,这会非常令人困惑,因为例如,如果你的相机正在注视地平线朝向 Y 轴,并且你在 Z 轴上旋转以向左或向右看,你实际上是在 Y 轴上旋转视图(横滚)。当变换相机时,你必须想象你是从脚上拍摄视频。
  • 其他引擎,如 Irrlicht 和 Ogre,也使用 Y 轴向上

因此,我们将在本书中坚持使用 Y 轴向上。

定位相机

[编辑 | 编辑源代码]

OpenGL 中没有内置的相机概念。我们必须略作欺骗才能实现它。

我们的技术如下:与其思考如何在固定世界中移动相机,不如思考如何在相机周围移动整个世界。

例如,在 X 轴上移动相机 3 个单位与在 X 轴上移动整个世界 -3 个单位相同。对所有其他轴和旋转也是如此。

在使用相机时请牢记这一点。最终结果会感觉非常直观,但如果你在使用相机时忘记了我们最初的欺骗行为,你将得到错误的变换。

相机控制

[编辑 | 编辑源代码]

我们将从一个直观的实现开始

  • 左右旋转相机 Y 轴
  • 上下移动前后
  • Page Up/Page Down 旋转相机 X 轴
/* code here */

为了向前/向后移动,我们使用 glm::translate。有两种形式

  • glm::translate(transformation_matrix, glm::vec3(dx, dy, dz)): 应用 transformation_matrix,然后在新坐标系中移动 (dx,dy,dz)
  • glm::translate(glm::mat4(1), glm::vec3(dx, dy, dz)) * transformation_matrix: 应用 transformation_matrix,然后在旧坐标系中移动 (dx,dy,dz)(即移动之前的坐标系)
  • 在相机平移的情况下,不要忘记我们正在欺骗并移动整个世界,而不是相机;因此,上述含义对于 world2camera 矩阵是相反的。

例如,如果你的现有 transformation_matrix 将你的相机向右旋转 90°,然后沿 Z 轴平移

  • 使用第一种形式,你将平移相机的新左侧(沿世界 Z 轴),
  • 而使用第二种形式,你将平移相机向前(沿世界 X 轴)。

这种实现存在可用性问题:当相机弯曲时左右旋转相机时,我们不习惯在这个弯曲的轴上旋转我们的整个身体。相反,我们习惯于在世界直线 Y 轴上旋转头部。因此,我们需要将世界 Y 轴平移到相机的局部坐标

      glm::vec3 y_axis_world = glm::mat3(transforms[MODE_CAMERA]) * glm::vec3(0.0, 1.0, 0.0);
      transforms[MODE_CAMERA] = glm::rotate(glm::mat4(1.0), -delta_rotY, y_axis_world) * transforms[MODE_CAMERA];

最后,让我们实现侧移

/* code here */

< OpenGL 编程

浏览和下载 完整代码
华夏公益教科书