0 上一个章节我们将多个立方体随机放置在了三维空间中,并让立方体在各自的位置上自转。本章我们将:
(1)创建摄像机矩阵,并调整视角让摄像机围绕着世界坐标原点匀速旋转。
(2)创造一个FPS游戏(First-person shooting game)摄像机风格的视角,使用键盘的WSAD键控制摄像机的前后左右移动。
(3)使用鼠标滑动来控制摄像机的俯仰角和偏航角,使用鼠标滚轮来控制摄像机的投影视口角度。
(资料图片)
(4)将摄像机抽象成camera类。
1 创建摄像机矩阵,并调整视角让摄像机围绕着世界坐标中心匀速旋转。
1.0 创建一个观察矩阵,定义好摄像机在世界坐标上的位置向量和目标向量,由于我们的摄像机风格是FPS的风格,所以我将摄像机初始向上的向量设置为世界坐标系的y轴正方向。由此可以计算出摄像机的三轴向量。将摄像机三个轴的向量值和摄像机位置向量代入到旋转和位移矩阵中,即可得到观察矩阵。
1.1 上述的观察矩阵的生成过程比较麻烦,向量的构造也很复杂。好在glm库有包装好的lookAt()接口供我们直接调用。
1.2 编译运行程序,可以得到一个摆放在我们正前方3个单位的多个立方体,此时的摄像机位于世界坐标z轴正方向的3个单位处,镜头朝向正对着坐标原点。
1.3 我们可以修改摄像机的位置,让其绕着世界坐标的y轴方向,沿着半径为10个单位的圆周进行旋转,在旋转的过程中摄像机的朝向始终对准着世界坐标原点。
2 创造一个FPS游戏(First-person shooting game)摄像机风格的视角,使用键盘的WSAD键控制摄像机的前后左右移动。
2.0 将摄像机的位置和朝向等三个向量设置为全局变量。并设置好观察矩阵。
2.1 在键盘按键回调函数里面设置好WSAD按键的触发响应方式。我们先设置好摄像机的移动速度。当触发W和S时,摄像机的位置向量将沿着摄像机的朝向做出改变。当触发A和D时,我们需要先把摄像机朝前和朝上的向量进行叉乘得到朝右的向量,此时摄像机的位置向量才能沿着朝右的向量方向做出改变。
2.2 按照前面设置的键盘响应来控制摄像机会有一个问题,那就是我们每次回调函数的触发时机是跟本机的CUP处理速度相关的,CUP频率越高,触发的间隔就会越密,这会导致我们的程序在不同的机器上摄像机移动的速度会不统一。为了解决这个问题。我们需设置一个记录每帧时间间隔的deltaTime。使用这个间隔时间来控制每帧中摄像机的移动速度。
2.3 编译运行程序,我们可以通过触发键盘的WSAD按键来控制摄像机位置。
3 使用鼠标滑动来控制摄像机的俯仰角和偏航角,使用鼠标滚轮来控制摄像机的视口角度。
3.0 下图是航空领域用到的表示飞机飞行姿态的参数。其中飞机绕x轴旋转的角度为俯仰角(pitch)、绕y轴的旋转角度为偏航角(yaw)、绕z轴的旋转角度为滚转角(roll)。
3.1 在全局变量位置处设置好摄像机姿态参数、鼠标滑动时在xy方向上产生的偏移量以及摄像机的投影视口夹角。
3.2 在创建窗口时设置好鼠标滑动和滚轮转动的回调。
3.3 实现鼠标滑动的回调。其中需要注意的是摄像机的俯仰角和偏航角根据鼠标在xy方向上的偏移产生。鼠标的滑动转换为摄像机状态时同样需要设置一个鼠标灵敏度。摄像机的朝向则同时由俯仰角和偏航角根据三角关系获得。为了不产生万向节死锁等问题,我们将俯仰角限制在正负89°之间。
3.4 设置鼠标滚轮回调函数,通过滚轮的滚动量修改摄像机投影视口角度的大小。由于我们是FPS风格的摄像机,所以我们将角度限制在1到80°之间。
3.5 编译运行程序,此时我们可以通过鼠标的移动和滚轮滑动来控制摄像机的朝向。
4 将摄像机抽象成camera类。
4.0 我们将散乱在各处的关于摄像机的代码抽象出来整合成一个摄像机类进行调用。
4.1 类具体实现都被封装到接口中。