移动相机需要用到键盘按键,按键事件的引入需要包含头文件
#include <Qt3DInput\qkeyevent.h>
并实现QWidget中定义的虚函数keyPressEvent
我们首先在MyGlWindow中重写这个虚函数。
在MyGlWindow.h加入
void keyPressEvent(QKeyEvent*);
在MyGlWindow.cpp中定义:
1 void MyGlWindow::keyPressEvent(QKeyEvent * e) 2 { 3 switch (e->key()) 4 { 5 case Qt::Key::Key_W: 6 camera.moveForward(); 7 break; 8 case Qt::Key::Key_S: 9 camera.moveBackward(); 10 break; 11 case Qt::Key::Key_A: 12 camera.strafeLeft(); 13 break; 14 case Qt::Key::Key_D: 15 camera.strafeRight(); 16 break; 17 case Qt::Key::Key_Q: 18 camera.moveUp(); 19 break; 20 case Qt::Key::Key_E: 21 camera.moveDown(); 22 break; 23 24 default: 25 break; 26 } 27 repaint(); 28 }
代码很简单,从中我们可以看到按下W 和 S键会分别前进、后退,按下A和D键会分别向左向右平移,按下Q和E键会分别向上向下平移。
但是目前我们还没有在Camera类中实现这6个移动的函数。
下面就来实现这些函数:
在Camera.h中添加成员:
1 void moveForward(); 2 void moveBackward(); 3 void strafeLeft(); 4 void strafeRight(); 5 void moveUp(); 6 void moveDown(); 7 8 float moveSpeed = 0.1f;
在Camera.cpp中定义这些方法:
1 void Camera::moveForward() 2 { 3 position += viewDirection * moveSpeed; 4 } 5 6 void Camera::moveBackward() 7 { 8 position -= viewDirection * moveSpeed; 9 } 10 11 void Camera::strafeLeft() 12 { 13 glm::vec3 pitchAxis = glm::cross(viewDirection, UP); 14 position += pitchAxis * moveSpeed; 15 } 16 17 void Camera::strafeRight() 18 { 19 glm::vec3 pitchAxis = glm::cross(viewDirection, UP); 20 position -= pitchAxis * moveSpeed; 21 22 } 23 24 void Camera::moveUp() 25 { 26 position += UP * moveSpeed; 27 } 28 29 void Camera::moveDown() 30 { 31 position -= UP * moveSpeed; 32 }
编译运行,我们发现相机可以前进后退上下左右平移了。
PS:
这里的上下并不是依照相机的局部坐标的上下,而是世界坐标的上下。要改成局部坐标的上下有些麻烦。
我做了一些尝试,定义一个新的成员cameraUp,用来表示相机的上方,每次旋转过后都重新使用向量差乘来重新计算cameraUp。这样确实可以按照相机的上下移动,但是带来了一些其他问题,相机在世界中不再是“正”的了,经过几次旋转,会累积一些偏差,导致相机倾斜。这里需要解决这个问题可能需要用到四元数,但是暂时不再深究了。