【OpenGL】--- OpenGL中实现摄像机自由移动与缩放

在使用Qt和OpenGL开发图形应用程序时,实现摄像机的自由移动和缩放是一个常见的需求。在本篇博客中,我们将介绍如何创建一个摄像机类,以实现用户可以通过键盘和鼠标交互来控制场景中的摄像机。

创建摄像机类

首先,我们创建一个 Camera 类,该类封装了摄像机的位置、方向、上向量等信息。摄像机类还提供了用于更新摄像机状态的方法,例如处理键盘输入、鼠标移动和滚轮滚动。

camera.h:

// camera.h
#ifndef CAMERA_H
#define CAMERA_H

#include 
#include 

class Camera
{
public:
    Camera();

    void setPosition(const QVector3D& position);
    void setDirection(const QVector3D& direction);
    void setUpVector(const QVector3D& up);

    QVector3D getPosition() const;
    QVector3D getDirection() const;
    QVector3D getUpVector() const;

    QMatrix4x4 getViewMatrix() const;
    void processKeyboard(int key);
    void processMouseMovement(float xOffset, float yOffset);
    void processMouseScroll(float yOffset);

private:
    QVector3D position;
    QVector3D front;
    QVector3D up;
    QVector3D right;
    QVector3D worldUp;

    float yaw;
    float pitch;

    float movementSpeed;
    float mouseSensitivity;
    float zoom;

    void updateCameraVectors();
};

#endif // CAMERA_H

 camera.cpp:

// camera.cpp
#include "camera.h"

#include 

Camera::Camera()
    : position(QVector3D(0.0f, 0.0f, 3.0f)),
      front(QVector3D(0.0f, 0.0f, -1.0f)),
      up(QVector3D(0.0f, 1.0f, 0.0f)),
      worldUp(QVector3D(0.0f, 1.0f, 0.0f)),
      yaw(-90.0f),
      pitch(0.0f),
      movementSpeed(2.5f),
      mouseSensitivity(0.1f),
      zoom(45.0f)
{
    updateCameraVectors();
}

void Camera::setPosition(const QVector3D& position)
{
    this->position = position;
}

void Camera::setDirection(const QVector3D& direction)
{
    this->front = direction.normalized();
    updateCameraVectors();
}

void Camera::setUpVector(const QVector3D& up)
{
    this->up = up.normalized();
    updateCameraVectors();
}

QVector3D Camera::getPosition() const
{
    return position;
}

QVector3D Camera::getDirection() const
{
    return front;
}

QVector3D Camera::getUpVector() const
{
    return up;
}

QMatrix4x4 Camera::getViewMatrix() const
{
    QMatrix4x4 view;
    view.lookAt(position, position + front, up);
    return view;
}

void Camera::processKeyboard(int key)
{
    float velocity = movementSpeed * 0.1f;
    if (key == Qt::Key_W)
        position += front * velocity;
    if (key == Qt::Key_S)
        position -= front * velocity;
    if (key == Qt::Key_A)
        position -= right * velocity;
    if (key == Qt::Key_D)
        position += right * velocity;
}

void Camera::processMouseMovement(float xOffset, float yOffset)
{
    xOffset *= mouseSensitivity;
    yOffset *= mouseSensitivity;

    yaw += xOffset;
    pitch += yOffset;

    // Constrain the pitch to avoid flipping
    if (pitch > 89.0f)
        pitch = 89.0f;
    if (pitch < -89.0f)
        pitch = -89.0f;

    updateCameraVectors();
}

void Camera::processMouseScroll(float yOffset)
{
    if (zoom >= 1.0f && zoom <= 45.0f)
        zoom -= yOffset;
    if (zoom <= 1.0f)
        zoom = 1.0f;
    if (zoom >= 45.0f)
        zoom = 45.0f;
}

void Camera::updateCameraVectors()
{
    QVector3D newFront;
    newFront.setX(qCos(qDegreesToRadians(yaw)) * qCos(qDegreesToRadians(pitch)));
    newFront.setY(qSin(qDegreesToRadians(pitch)));
    newFront.setZ(qSin(qDegreesToRadians(yaw)) * qCos(qDegreesToRadians(pitch)));
    front = newFront.normalized();

    right = QVector3D::crossProduct(front, worldUp).normalized();
    up = QVector3D::crossProduct(right, front).normalized();
}

在OpenGL小部件中使用摄像机

在你的OpenGL小部件中,你可以创建一个 Camera 对象,并在渲染循环中根据用户输入更新摄像机的状态。以下是一个简单的OpenGL小部件示例:

myopenglwidget.h:

// myopenglwidget.h
#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H

#include 
#include 
#include 
#include "camera.h"

class MyOpenGLWidget : public QOpenGLWidget
{
    Q_OBJECT

public:
    MyOpenGLWidget(QWidget *parent = nullptr);

protected:
    void initializeGL() override;
    void resizeGL(int w, int h) override;
    void paintGL() override;
    void keyPressEvent(QKeyEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void wheelEvent(QWheelEvent *event) override;

private:
    // 成员变量省略...

    Camera camera;
    QOpenGLShaderProgram shaderProgram;
    QOpenGLTexture *texture;
};

#endif // MYOPENGLWIDGET_H

myopenglwidget.cpp: 

// myopenglwidget.cpp
#include "myopenglwidget.h"
#include 
#include 

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent)
    : QOpenGLWidget(parent)
{
    // 初始化摄像机位置等信息
    camera.setPosition(QVector3D(0.0f, 0.0f, 3.0f));

    // 其他初始化...
}

void MyOpenGLWidget::initializeGL()
{
    // OpenGL 初始化...

    // 加载纹理、着色器等...
}

void MyOpenGLWidget::resizeGL(int w, int h)
{
    // 视口设置...
}

void MyOpenGLWidget::paintGL()
{
    // 渲染循环...
}

void MyOpenGLWidget::keyPressEvent(QKeyEvent *event)
{
    // 键盘事件处理...
}

void MyOpenGLWidget::mouseMoveEvent(QMouseEvent *event)
{
    // 鼠标移动事件处理...
}

void MyOpenGLWidget::wheelEvent(QWheelEvent *event)
{
    // 鼠标滚轮事件处理...
}

结语

通过使用 Camera 类,我们能够轻松实现在OpenGL场景中控制摄像机的功能。这为创建交互式的三维图形应用程序提供了基础,用户可以通过键盘和鼠标与场景进行交互。此方法还可以进一步扩展,以支持更多摄像机特性和用户控制。希望这篇博客能够帮助你更好地理解在Qt和OpenGL中使用摄像机的方法。

你可能感兴趣的:(OpenGL,计算机视觉,图形渲染)