Learn OpenGL In Qt之摄像机类

在这里插入图片描述

竹杖芒鞋轻胜马,谁怕?一蓑烟雨任平生~
公众号: C++学习与探索  |  个人主页: rainInSunny  |  个人专栏: Learn OpenGL In Qt

摄像机类

  根据上一篇的的内容,实现一个摄像机类,头文件如下:

#ifndef CAMERA_H
#define CAMERA_H

#include <QMatrix4x4>
#include <QVector3D>

class Camera
{
public:
    enum Movement
    {
        FORWARD = 0,
        BACKWARD,
        LEFT,
        RIGHT
    };

    Camera(float yaw = 90.0f, float pitch = 0.0f, const QVector3D& position = QVector3D(0.0f, 0.0f, 0.0f),
           const QVector3D& up = QVector3D(0.0f, 1.0f, 0.0f),
           const QVector3D& front = QVector3D(0.0f, 0.0f, 1.0f));
    ~Camera();

    QMatrix4x4 getViewMatrix();
    void processKeyboard(Movement direction, float deltaTime);
    void processMouseMovement(float xoffset, float yoffset, bool constrainPitch = true);
    void processMouseScroll(float yoffset);
    void updateCameraVectors();
    float getZoom() const { return m_zoom; }

private:
    QVector3D m_position;
    QVector3D m_up;
    QVector3D m_front;
    QVector3D m_right;
    QVector3D m_worldUp;

    float m_yaw;
    float m_pitch;
    float m_moveSpeed;
    float m_mouseSensitivity;
    float m_zoom;
};
#endif
  • Movement 枚举表示摄像机移动的四个方向。
  • Camera 构造函数中给出位置向量、上/前/右向量的初始值,以及 yaw、pitch 的初始角度。
  • getViewMatrix 返回摄像机的某一时刻的视图矩阵。
  • processKeyboard 处理摄像机收到的键盘事件,更新位置向量。
  • processMouseMovement 处理摄像机收到的鼠标移动事件,更新偏转角度。
  • processMouseScroll 处理摄像机收到的鼠标滚轮事件,更新缩放比。
  • updateCameraVectors 根据偏转角度对向量进行更新,用于计算视图矩阵。

  通过 Camera 类,可以帮助处理前后左右的位置移动,鼠标进行的视角移动和滚轮的缩放变换,通过更新 Camera 的实时状态就能在 3D 空间自由移动~

自由移动

  在 3D 空间移动的核心就是实时修改视图矩阵,这里的 3D 场景仍然沿用之前坐标系统讲解中的 3D 箱子场景,具体场景的绘制流程就不再赘述了。需要关注的是在绘制函数中,视图矩阵和透视矩阵会根据摄像机类的返回值进行确定,就像下面这样:

QMatrix4x4 view;
QMatrix4x4 projection;
projection.perspective(m_camera->getZoom(), (float)width() / (float)height(), 0.1f, 100.0f);
view = m_camera->getViewMatrix();
m_shaderProgram->setMat4("view", view);
m_shaderProgram->setMat4("projection", projection);

  为了实现在 3D 场景中移动,需要将鼠标键盘事件传递给 Camera 类,实现如下:

void OpenGLCamera_01::keyPressEvent(QKeyEvent *event)
{
    float deltaTime = 0.1f; // 这里先给个固定值
    if (event->key() == Qt::Key_W)
        m_camera->processKeyboard(Camera::FORWARD, deltaTime);
    if (event->key() == Qt::Key_S)
        m_camera->processKeyboard(Camera::BACKWARD, deltaTime);
    if (event->key() == Qt::Key_A)
        m_camera->processKeyboard(Camera::LEFT, deltaTime);
    if (event->key() == Qt::Key_D)
        m_camera->processKeyboard(Camera::RIGHT, deltaTime);
    update();
}

void OpenGLCamera_01::mouseMoveEvent(QMouseEvent *event)
{
    if (m_bfirstMouse)
    {
        m_lastMouseX = event->x();
        m_lastMouseY = event->y();
        m_bfirstMouse = false;
    }

    float xoffset = event->x() - m_lastMouseX;
    float yoffset = m_lastMouseY - event->y();
    m_lastMouseX = event->x();
    m_lastMouseY = event->y();

    m_camera->processMouseMovement(xoffset, yoffset);
    update();
}

void OpenGLCamera_01::wheelEvent(QWheelEvent *event)
{
    float yoffset = event->angleDelta().y() * 0.05;
    m_camera->processMouseScroll(yoffset);
    update();
}

  通过实现 QWidgetkeyPressEventmouseMoveEventwheelEvent,分别将键盘按下、鼠标移动和滚轮滚动事件传递给 Camera 类,Camera 根据预先处理逻辑对视图矩阵进行变换,实现在 3D 场景中的移动。这里的 update 是 Qt 中用于绘制刷新的函数,当视图矩阵发生改变时,我们期望视图进行更新。另外需要注意的是,需要给 OpenGLCamera_01 控件设置 mouseTracking 属性,默认情况下 Qt 控件只会捕捉鼠标按下后的移动事件,如果需要直接捕获鼠标移动事件则需要设置 mouseTracking

实现效果

  如果一切顺利,会得到下面的效果:
在这里插入图片描述
关注公众号:C++学习与探索,有惊喜哦~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值