• 摄像机


    https://learnopengl-cn.github.io/01%20Getting%20started/09%20Camera/#_8

    https://www.jianshu.com/p/003b1fb8d6d3

    #include "ACamera.h"
    
    #include <QDebug>
    
    ACamera::ACamera(QVector3D position, QVector3D up, float yaw, float pitch) :
        position(position),
        worldUp(up),
        front(-position),
        picth(pitch),
        yaw(yaw),
        movementSpeed(SPEED),
        mouseSensitivity(SENSITIVITY),
        zoom(ZOOM)
    {
        this->updateCameraVectors();
    
        for(uint i = 0; i != 1024; ++i)
            keys[i] = false;
    }
    
    ACamera::~ACamera()
    {
    
    }
    
    // Returns the view matrix calculated using Euler Angles and the LookAt Matrix
    QMatrix4x4 ACamera::getViewMatrix()
    {
        QMatrix4x4 view;
        view.lookAt(this->position, this->position + this->front, this->up);
        return view;
    }
    
    // Processes input received from any keyboard-like input system. Accepts input parameter in the form of ACamera defined ENUM (to abstract it from windowing systems)
    void ACamera::processKeyboard(Camera_Movement direction, float deltaTime)
    {
        float velocity = this->movementSpeed * deltaTime;
        if (direction == FORWARD)
            this->position += this->front * velocity;
        if (direction == BACKWARD)
            this->position -= this->front * velocity;
        if (direction == LEFT)
            this->position += this->right * velocity;
        if (direction == RIGHT)
            this->position -= this->right * velocity;
        if (direction == UP)
            this->position += this->worldUp * velocity;
        if (direction == DOWN)
            this->position -= this->worldUp * velocity;
    }
    
    // Processes input received from a mouse input system. Expects the offset value in both the x and y direction.
    void ACamera::processMouseMovement(float xoffset, float yoffset, bool constraintPitch)
    {
      xoffset *= this->mouseSensitivity;
      yoffset *= this->mouseSensitivity;
    
      this->yaw += xoffset;
      this->picth += yoffset;
    
      if (constraintPitch) {
        if (this->picth > 89.0f)
          this->picth = 89.0f;
        if (this->picth < -89.0f)
          this->picth = -89.0f;
      }
    
      this->updateCameraVectors();
    }
    
    // Processes input received from a mouse scroll-wheel event. Only requires input on the vertical wheel-axis
    void ACamera::processMouseScroll(float yoffset)
    {
      if (this->zoom >= 1.0f && this->zoom <= 45.0f)
        this->zoom -= yoffset;
      if (this->zoom > 45.0f)
        this->zoom = 45.0f;
      if (this->zoom < 1.0f)
          this->zoom = 1.0f;
    }
    
    void ACamera::processInput(float dt)
    {
    
        if (keys[Qt::Key_W])
          processKeyboard(FORWARD, dt);
        if (keys[Qt::Key_S])
          processKeyboard(BACKWARD, dt);
        if (keys[Qt::Key_A])
          processKeyboard(LEFT, dt);
        if (keys[Qt::Key_D])
          processKeyboard(RIGHT, dt);
        if (keys[Qt::Key_E])
          processKeyboard(UP, dt);
        if (keys[Qt::Key_Q])
          processKeyboard(DOWN, dt);
    }
    
    void ACamera::updateCameraVectors()
    {
        // Calculate the new Front vector
        QVector3D front;
        front.setX(cos(this->yaw) * cos(this->picth));
        front.setY(sin(this->picth));
        front.setZ(sin(this->yaw) * cos(this->picth));
        this->front = front.normalized();
        this->right = QVector3D::crossProduct(this->front, this->worldUp).normalized();
        this->up = QVector3D::crossProduct(this->right, this->front).normalized();
    }
    ACamera.cpp
    #ifndef ACAMERA_H
    #define ACAMERA_H
    
    #include <QVector3D>
    #include <QMatrix4x4>
    #include <QKeyEvent>
    
    // 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 = 1.0f;
    const float SENSITIVITY = 0.0001f;
    const float ZOOM = 45.0f;
    
    class ACamera {
    public:
        ACamera(QVector3D position = QVector3D(0.0f, 0.0f, 0.0f), QVector3D up = QVector3D(0.0f, 1.0f, 0.0f),
        float yaw = YAW, float pitch = PITCH);
        ~ACamera();
    
        QMatrix4x4 getViewMatrix();
        void processMouseMovement(float xoffset, float yoffset, bool constraintPitch = true);
        void processMouseScroll(float yoffset);
        void processInput(float dt);
    
        QVector3D position;// 摄像机位置
        QVector3D worldUp; // 上向量
        QVector3D front;// 摄像机方向向量  /
    
        QVector3D up; // 上轴
        QVector3D right; // 右轴
    
        //Eular Angles
        float picth; // 俯仰角
        float yaw; // 偏航角
    
        //Camera options
        float movementSpeed;
        float mouseSensitivity;
        float zoom;
    
        //Keyboard multi-touch
        bool keys[1024];
    private:
        void updateCameraVectors();
        void processKeyboard(Camera_Movement direction, float deltaTime);
    };
    
    #endif // ACAMERA_H
    ACamera.hpp
    #include "aqtfunwidget.h"
    #include <QDebug>
    #include <QTimer>
    
    AQtFunWidget::AQtFunWidget(QWidget *parent)
        : QOpenGLWidget(parent),
          vbo(QOpenGLBuffer::VertexBuffer)
    {
        m_camera = new ACamera(QVector3D(5.0f,0.0f,10.0f));
        m_bLeftPressed = false;
    
        m_pTimer = new QTimer(this);
        connect(m_pTimer,&QTimer::timeout,this,[=]{
           m_nTimeValue += 1;
           update();
        });
        m_pTimer->start(40);
    }
    
    AQtFunWidget::~AQtFunWidget()
    {
        makeCurrent();
    
        vbo.destroy();
        vao.destroy();
    
        delete texture1;
        delete texture2;
    
        doneCurrent();
    }
    
    void AQtFunWidget::initializeGL()
    {
        this->initializeOpenGLFunctions();
    
        bool success = shaderProgram.addShaderFromSourceFile(QOpenGLShader::Vertex,":/shader/textures.vert");
        if (!success){
            qDebug() << "load vert file failded." << shaderProgram.log();
            return;
        }
        success = shaderProgram.addShaderFromSourceFile(QOpenGLShader::Fragment,":/shader/textures.frag");
        if (!success){
            qDebug() << "load fag file failded." << shaderProgram.log();
            return;
        }
    
        success = shaderProgram.link();
        if (!success){
            qDebug() << "shaderProgram link failded." << shaderProgram.log();
        }
    
        //VAO,VBO data
         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
         };
    
         QOpenGLVertexArrayObject::Binder vaobinD(&vao);
    
         vbo.create();
         vbo.bind();
         vbo.allocate(vertices,sizeof(vertices));
    
     // position attribute
         int attr = -1;
         attr = shaderProgram.attributeLocation("aPos");
         shaderProgram.setAttributeBuffer(attr, GL_FLOAT, 0, 3, sizeof(GLfloat) * 5);
         shaderProgram.enableAttributeArray(attr);
         // texture coord attribute
         attr = shaderProgram.attributeLocation("aTexCoord");
         shaderProgram.setAttributeBuffer(attr, GL_FLOAT, sizeof(GLfloat) * 3, 2, sizeof(GLfloat) * 5);
         shaderProgram.enableAttributeArray(attr);
    
         // texture 1
         // ---------
         texture1 = new QOpenGLTexture(QImage(":/image/container.jpg"), QOpenGLTexture::GenerateMipMaps);
         if(!texture1->isCreated()){
             qDebug() << "Failed to load texture";
         }
         // set the texture wrapping parameters
         texture1->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
         texture1->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
         // set texture filtering parameters
         texture1->setMinificationFilter(QOpenGLTexture::Linear);
         texture1->setMagnificationFilter(QOpenGLTexture::Linear);
    
         // texture 2
         // ---------
         texture2 = new QOpenGLTexture(QImage(":/image/awesomeface.png").mirrored(true, true), QOpenGLTexture::GenerateMipMaps);
         if(!texture2->isCreated()){
             qDebug() << "Failed to load texture";
         }
         // set the texture wrapping parameters
         texture2->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::Repeat);
         texture2->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::Repeat);
         // set texture filtering parameters
         texture2->setMinificationFilter(QOpenGLTexture::Linear);
         texture2->setMagnificationFilter(QOpenGLTexture::Linear);
    
         // tell opengl for each sampler to which texture unit it belongs to (only has to be done once)
         shaderProgram.bind();   // don't forget to activate/use the shader before setting uniforms!
         shaderProgram.setUniformValue("texture1", 0);
         shaderProgram.setUniformValue("texture2", 1);
    
         vbo.release();
    
         // configure global opengl state
         // -----------------------------
         glEnable(GL_DEPTH_TEST);
    
    }
    
    void AQtFunWidget::resizeGL(int w, int h)
    {
        glViewport(0,0,w,h);
    }
    
    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 AQtFunWidget::paintGL()
    {
        glClearColor(0.2f,0.3f,0.3f,1.0f);
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    
        m_camera->processInput(1.0f);
    
        glActiveTexture(GL_TEXTURE0);
        texture1->bind();
        glActiveTexture(GL_TEXTURE1);
        texture2->bind();
    
        shaderProgram.bind();
    
        QMatrix4x4 projection;
        projection.perspective(m_camera->zoom,1.0f*width()/height(),0.1f,100.0f);
        shaderProgram.setUniformValue("projection",projection);
    
        shaderProgram.setUniformValue("view",m_camera->getViewMatrix());
    
        // render box 渲染箱子
        {
            QOpenGLVertexArrayObject::Binder vaobind(&vao);
            for (int i = 0; i < 10; i++) {
                QMatrix4x4 model;
                model.translate(cubePositions[i]);
                float angle = m_nTimeValue*(1.0f+i);
                model.rotate(angle,QVector3D(1.0f,0.3f,0.5f));
                shaderProgram.setUniformValue("model",model);
                glDrawArrays(GL_TRIANGLES,0,36);
            }
    
        }
    
        texture1->release();
        texture2->release();
        shaderProgram.release();
    }
    
    void AQtFunWidget::keyPressEvent(QKeyEvent *event)
    {
        int key = event->key();
        if (key >0 && key < 1024){
            m_camera->keys[key] = true;
        }
    }
    
    void AQtFunWidget::keyReleaseEvent(QKeyEvent *event)
    {
        int key = event->key();
        if (key >0 && key < 1024){
            m_camera->keys[key] = false;
        }
    }
    
    void AQtFunWidget::mousePressEvent(QMouseEvent *event)
    {
        if(event->button() == Qt::LeftButton){
            m_bLeftPressed = true;
            m_lastPos = event->pos();
        }
    }
    
    void AQtFunWidget::mouseReleaseEvent(QMouseEvent *event)
    {
        Q_UNUSED(event);
    
        m_bLeftPressed = false;
    }
    
    void AQtFunWidget::mouseMoveEvent(QMouseEvent *event)
    {
        if(m_bLeftPressed){
            int xPos = event->pos().x();
            int yPos = event->pos().y();
    
            int xOffset = m_lastPos.x() - xPos;
            int yOffset = yPos - m_lastPos.y();
            m_camera->processMouseMovement(xOffset,yOffset);
        }
    
    }
    
    void AQtFunWidget::wheelEvent(QWheelEvent *event)
    {
        QPoint offset = event->angleDelta();
        m_camera->processMouseScroll(offset.y()/20.0f);
    }
    Widget.cpp
    #ifndef AQTFUNWIDGET_H
    #define AQTFUNWIDGET_H
    
    #include <QWidget>
    #include <QOpenGLWidget>
    #include <QOpenGLShaderProgram>
    #include <QOpenGLFunctions>
    #include <QOpenGLVertexArrayObject>
    #include <QOpenGLBuffer>
    #include <QOpenGLTexture>
    
    #include "ACamera.h"
    
    class AQtFunWidget : public QOpenGLWidget,protected QOpenGLFunctions
    {
        Q_OBJECT
    
    public:
        AQtFunWidget(QWidget *parent = 0);
        ~AQtFunWidget();
    protected:
        virtual void initializeGL() Q_DECL_OVERRIDE;
        virtual void resizeGL(int w, int h) Q_DECL_OVERRIDE;
        virtual void paintGL() Q_DECL_OVERRIDE;
    
        void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
        void keyReleaseEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
        void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
        void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
        void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
        void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE;
    
    private:
        QOpenGLShaderProgram shaderProgram;
        QOpenGLBuffer vbo;
        QOpenGLVertexArrayObject vao;
        QOpenGLTexture *texture1 = nullptr;
        QOpenGLTexture *texture2 = nullptr;
    
        QTimer* m_pTimer = nullptr;
        int     m_nTimeValue = 0;
    
        // camera
        ACamera *m_camera;
        bool m_bLeftPressed;
        QPoint m_lastPos;
    };
    
    #endif // AQTFUNWIDGET_H
    .hpp
  • 相关阅读:
    WPF : ListBox的几种Template属性
    提问的角度 5W1H,GRETT
    软件=科学+技术+工程, 软件的成败, 软件开发的首要任务
    软件的几个问题
    体会
    "复述一遍"是沟通的好办法
    WCF客户端调用IIS上WebService的安全问题
    C#处理chart
    js获取asp.net服务器端控件的值Demo
    SQL Server的复合索引适当用法
  • 原文地址:https://www.cnblogs.com/xiangtingshen/p/12083359.html
Copyright © 2020-2023  润新知