0
点赞
收藏
分享

微信扫一扫

Qt-OpenGL-06 摄像机类Camare

Sikj_6590 2022-03-30 阅读 102

摄像机这篇,我感觉教程已经写得很清楚,直接上代码,翻译就完了。

camare类
 

#ifndef CAMERA_H
#define CAMERA_H

#include <QVector3D>
#include <qmatrix4x4.h>

// Defines several possible options for camera movement. Used as abstraction to stay away from window-system specific input methods
enum Camera_Movement {
    FORWARD,
    BACKWARD,
    LEFT,
    RIGHT,
    UP,
    DOWN
};

// Default camera values
const float YAW         = -90.0f;
const float PITCH       =  0.0f;
const float SPEED       =  2.5f;
const float SENSITIVITY =  0.005f;
const float ZOOM        =  45.0f;


// An abstract camera class that processes input and calculates the corresponding Euler Angles, Vectors and Matrices for use in OpenGL
class Camera
{
public:
    // camera Attributes
    QVector3D Position;
    QVector3D Front;
    QVector3D Up;
    QVector3D Right;
    QVector3D WorldUp;
    // euler Angles
    float Yaw;
    float Pitch;
    // camera options
    float MovementSpeed;
    float MouseSensitivity;
    float Zoom;

    // constructor with vectors
    Camera(QVector3D position = QVector3D(0.0f, 0.0f, 0.0f), QVector3D up = QVector3D(0.0f, 1.0f, 0.0f), float yaw = YAW, float pitch = PITCH) : Front(QVector3D(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM)
    {
        Position = position;
        WorldUp = up;
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }
    // constructor with scalar values
    Camera(float posX, float posY, float posZ, float upX, float upY, float upZ, float yaw, float pitch) : Front(QVector3D(0.0f, 0.0f, -1.0f)), MovementSpeed(SPEED), MouseSensitivity(SENSITIVITY), Zoom(ZOOM)
    {
        Position = QVector3D(posX, posY, posZ);
        WorldUp = QVector3D(upX, upY, upZ);
        Yaw = yaw;
        Pitch = pitch;
        updateCameraVectors();
    }

    // returns the view matrix calculated using Euler Angles and the LookAt Matrix
    QMatrix4x4 GetViewMatrix()
    {
        QMatrix4x4 view;
        view.lookAt(Position, Position + Front, Up);
        return view;
    }

    // processes input received from any keyboard-like input system. Accepts input parameter in the form of camera defined ENUM (to abstract it from windowing systems)
    void ProcessKeyboard(Camera_Movement direction, float deltaTime)
    {
        float velocity = MovementSpeed * deltaTime;
        if (direction == FORWARD)
            Position += Front * velocity;
        if (direction == BACKWARD)
            Position -= Front * velocity;
        if (direction == LEFT)
            Position -= Right * velocity;
        if (direction == RIGHT)
            Position += Right * velocity;
        if (direction == UP)
            Position += WorldUp * velocity;
        if (direction == DOWN)
            Position -= WorldUp * velocity;
        //updateCameraVectors();
    }

    // processes input received from a mouse input system. Expects the offset value in both the x and y direction.
    void ProcessMouseMovement(float xoffset, float yoffset, bool constrainPitch = true)
    {
        xoffset *= MouseSensitivity;
        yoffset *= MouseSensitivity;

        Yaw   += xoffset;
        Pitch += yoffset;

        // make sure that when pitch is out of bounds, screen doesn't get flipped
        if (constrainPitch)
        {
            if (Pitch > 89.0f)
                Pitch = 89.0f;
            if (Pitch < -89.0f)
                Pitch = -89.0f;
        }

        // update Front, Right and Up Vectors using the updated Euler angles
        updateCameraVectors();
    }

    // processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
    void ProcessMouseScroll(float yoffset)
    {
        Zoom -= (float)yoffset;
        if (Zoom < 1.0f)
            Zoom = 1.0f;
        if (Zoom > 45.0f)
            Zoom = 45.0f; 
    }

private:
    // calculates the front vector from the Camera's (updated) Euler Angles
    void updateCameraVectors()
    {
        // calculate the new Front vector
        QVector3D front;
        front.setX(cos(Yaw) * cos(Pitch));
        front.setY(sin(Pitch));
        front.setZ(sin(Yaw) * cos(Pitch));
        Front =  front.normalized();
        // also re-calculate the Right and Up vector
        Right = QVector3D::crossProduct(Front,WorldUp).normalized();
        Up = QVector3D::crossProduct(Right,Front).normalized();
    }
};
#endif

.h

#ifndef CAMERAWIDGET_H
#define CAMERAWIDGET_H

#include <QWidget>
#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QDebug>
#include <QOpenGLTexture>
#include <QElapsedTimer>

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

namespace Ui {
class CameraWidget;
}

class HelloCamera;

class CameraWidget : public QWidget
{
    Q_OBJECT

public:
    explicit CameraWidget(QWidget *parent = nullptr);
    ~CameraWidget();

private:
    Ui::CameraWidget *ui;
    HelloCamera *m_contentWidget;
};

class HelloCamera : public QOpenGLWidget,protected QOpenGLExtraFunctions
{


public:
    HelloCamera();
    ~HelloCamera();


protected:
    virtual void initializeGL();
    virtual void resizeGL(int w, int h);
    virtual void paintGL();

    void keyPressEvent(QKeyEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void wheelEvent(QWheelEvent *event);
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);


private:
    Shader *m_shader;
    QOpenGLTexture *m_combine_texture1;
    QOpenGLTexture *m_combine_texture2;
    QElapsedTimer m_time;

    Camera m_camera;
    float m_lastX ;
    float m_lastY ;
    float m_deltaTime = 0.0f;
    float m_lastFrame = 0.0f;
    bool m_firstMouse = true;
    bool m_isMousePress = false;
};



#endif // CAMERAWIDGET_H

cpp

#include "camerawidget.h"
#include "ui_camerawidget.h"

#include <QKeyEvent>
#include <QMouseEvent>
#include <QWheelEvent>

CameraWidget::CameraWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::CameraWidget)
{
    ui->setupUi(this);
    m_contentWidget = new HelloCamera();
    ui->verticalLayout->addWidget(m_contentWidget);
}

CameraWidget::~CameraWidget()
{
    delete ui;
}


HelloCamera::HelloCamera()
{
    m_camera.Position = QVector3D(0.0f,0.0f,3.0f);
    m_lastX = width()/2;
    m_lastY = height()/2;
    setFocusPolicy(Qt::StrongFocus);
}

HelloCamera::~HelloCamera()
{

}

static GLuint VBO, VAO = 0;

// world space positions of our cubes
static QVector3D cubePositions[] = {
    QVector3D( 0.0f,  0.0f,  0.0f),
    QVector3D( 2.0f,  5.0f, -15.0f),
    QVector3D(-1.5f, -2.2f, -2.5f),
    QVector3D(-3.8f, -2.0f, -12.3f),
    QVector3D( 2.4f, -0.4f, -3.5f),
    QVector3D(-1.7f,  3.0f, -7.5f),
    QVector3D( 1.3f, -2.0f, -2.5f),
    QVector3D( 1.5f,  2.0f, -2.5f),
    QVector3D( 1.5f,  0.2f, -1.5f),
    QVector3D(-1.3f,  1.0f, -1.5f)
};

void HelloCamera::initializeGL()
{
    this->initializeOpenGLFunctions();
    glEnable(GL_DEPTH_TEST);

    float vertices[] = {
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
        0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };



    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    // texture coord attribute
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);


    m_shader = new Shader(":/shader/res/shaders/getting_started/7.4.camera.vs"
    ,":/shader/res/shaders/getting_started/7.4.camera.fs");


    //垂直镜像mirrored
    m_combine_texture1 = new QOpenGLTexture(QImage(":/texture/res/textures/container.jpg").mirrored());
    if(!m_combine_texture1->isCreated()){
        qDebug() << "Failed to load texture";
    }
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    m_combine_texture1->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    m_combine_texture1->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);

    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    m_combine_texture1->setMinificationFilter(QOpenGLTexture::Linear);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    m_combine_texture1->setMagnificationFilter(QOpenGLTexture::Linear);


    m_combine_texture2 = new QOpenGLTexture(QImage(":/texture/res/textures/awesomeface.png").mirrored());
    if(!m_combine_texture2->isCreated()){
        qDebug() << "Failed to load texture";
    }
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    m_combine_texture2->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    m_combine_texture2->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);

    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    m_combine_texture2->setMinificationFilter(QOpenGLTexture::Linear);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    m_combine_texture2->setMagnificationFilter(QOpenGLTexture::Linear);

    //设置纹理单元编号
    m_shader->use();
    m_shader->m_shaderProgram.setUniformValue(m_shader->m_shaderProgram.uniformLocation("texture1"), 0);
    m_shader->m_shaderProgram.setUniformValue(m_shader->m_shaderProgram.uniformLocation("texture2"), 1);

    m_time.start();
}

void HelloCamera::resizeGL(int w, int h)
{
    this->glViewport(0,0,w,h);
}

void HelloCamera::paintGL()
{
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    float currentFrame = (float)m_time.elapsed()/100;
    m_deltaTime = currentFrame - m_lastFrame;
    m_lastFrame = currentFrame;

    //激活纹理单元0
    glActiveTexture(GL_TEXTURE0);
    m_combine_texture1->bind();
    glActiveTexture(GL_TEXTURE1);
    m_combine_texture2->bind();


    // render container
    m_shader->use();
    QMatrix4x4 view = m_camera.GetViewMatrix();
    QMatrix4x4 projection;

    view.translate(QVector3D(0.0f, 0.0f, -3.0f));
    projection.perspective(m_camera.Zoom,(float)width() / (float)height(), 0.1f, 100.0f);

    for (unsigned int i = 0; i < 10; i++)
    {
        QMatrix4x4 model;
        model.translate(cubePositions[i]);
        float angle;
        if(i % 3 == 0)
        {
            angle  = (float)m_time.elapsed()/10;
        }else
        {
            angle = i * 20.0f;
        }
        model.rotate(angle, QVector3D(1.0f, 0.3f, 0.5f));
        m_shader->m_shaderProgram.setUniformValue("model",model);
        m_shader->m_shaderProgram.setUniformValue("view",view);
        m_shader->m_shaderProgram.setUniformValue("projection",projection);
        glDrawArrays(GL_TRIANGLES, 0, 36);
    }

    update();
}

void HelloCamera::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_A)
    {
        m_camera.ProcessKeyboard(Camera_Movement::LEFT,m_deltaTime);
    }else if(event->key() == Qt::Key_D)
    {
        m_camera.ProcessKeyboard(Camera_Movement::RIGHT,m_deltaTime);
    }
    else if(event->key() == Qt::Key_W)
    {
        m_camera.ProcessKeyboard(Camera_Movement::FORWARD,m_deltaTime);
    }
    else if(event->key() == Qt::Key_S)
    {
        m_camera.ProcessKeyboard(Camera_Movement::BACKWARD,m_deltaTime);
    }
    else if(event->key() == Qt::Key_E)
    {
        m_camera.ProcessKeyboard(Camera_Movement::UP,m_deltaTime);
    }
    else if(event->key() == Qt::Key_Q)
    {
        m_camera.ProcessKeyboard(Camera_Movement::DOWN,m_deltaTime);
    }
}

void HelloCamera::mouseMoveEvent(QMouseEvent *event)
{
    float xpos = static_cast<float>(event->pos().x());
    float ypos = static_cast<float>(event->pos().y());
    if(!m_isMousePress)
        return;

    if (m_firstMouse)
    {
        m_lastX = xpos;
        m_lastY = ypos;
        m_firstMouse = false;
    }

    float xoffset = xpos - m_lastX;
    float yoffset = m_lastY - ypos; // reversed since y-coordinates go from bottom to top

    m_lastX = xpos;
    m_lastY = ypos;

    m_camera.ProcessMouseMovement(xoffset, yoffset);
}

void HelloCamera::wheelEvent(QWheelEvent *event)
{
    m_camera.ProcessMouseScroll((float)event->angleDelta().y()/60.0f);
}

void HelloCamera::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
        m_isMousePress = true;
}

void HelloCamera::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
     m_isMousePress = false;
     m_firstMouse = true;
    }

}
举报

相关推荐

0 条评论