Qt5与现代OpenGL学习(十一)OpenGL Widget鼠标控制直线旋转

glwidget.h

cpp 复制代码
#ifndef GLWIDGET_H
#define GLWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QMatrix4x4>
#include <QMouseEvent>
#include <QVector3D>

class GLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT
public:
    explicit GLWidget(QWidget *parent = nullptr);
    ~GLWidget() override;

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

    // 鼠标事件处理
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void wheelEvent(QWheelEvent *event) override;

private:
    void initShaders();
    QVector3D getArcballVector(int x, int y);

    QOpenGLShaderProgram shaderProgram;
    QMatrix4x4 projection;
    QMatrix4x4 view;
    QMatrix4x4 model;

    // 旋转控制变量
    QPoint lastMousePos;
    QQuaternion rotation;
    QQuaternion lastRotation;
    float zoomFactor = 1.0f;



     float pointSize = 550.0f; // 控制点的大小



};

#endif // GLWIDGET_H

glwidget.cpp

cpp 复制代码
#include "glwidget.h"
#include <QMouseEvent>
#include <QWheelEvent>
#include <QtMath>
#include <QTimer>

GLWidget::GLWidget(QWidget *parent) : QOpenGLWidget(parent)
{
    setFocusPolicy(Qt::StrongFocus);
}

GLWidget::~GLWidget()
{
    makeCurrent();
    doneCurrent();
}

void GLWidget::initializeGL()
{
    initializeOpenGLFunctions();
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glEnable(GL_DEPTH_TEST);
    initShaders();
}

void GLWidget::resizeGL(int w, int h)
{
    glViewport(0, 0, w, h);
    projection.setToIdentity();
    projection.perspective(45.0f, (float)w/(float)h, 0.1f, 100.0f);
    view.setToIdentity();
    view.translate(0.0f, 0.0f, -5.0f);
}

void GLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    model.setToIdentity();
    model.scale(zoomFactor);
    model.rotate(rotation);

    QMatrix4x4 mvp = projection * view * model;

    shaderProgram.bind();
    shaderProgram.setUniformValue("mvpMatrix", mvp);







    GLfloat vertices[] = {
        -0.2f, 0.3f, 0.5f,  // p1
        1.0f, 1.0f, 1.0f     // p2
    };

    GLfloat colors[] = {
        1.0f, 0.0f, 0.0f,
        1.0f, 0.0f, 0.0f
    };

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, colors);
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);

    glDrawArrays(GL_LINES, 0, 2);


















    // 绘制绿色原点(0,0,0)
        GLfloat pointVertex[] = {0.0f, 0.0f, 0.0f};
        GLfloat pointColor[] = {0.0f, 1.0f, 0.0f};

        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, pointVertex);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, pointColor);


        glDrawArrays(GL_POINTS, 0, 1);







        GLfloat vertices1[] = {
            -0.2f, 0.3f, 0.5f,  // p1
            -1.0f, -1.0f, -1.0f     // p2
        };

        GLfloat colors1[] = {
            1.0f, 1.0f, 0.0f,
            1.0f, 1.0f, 0.0f
        };

        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices1);
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, colors1);
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
        glDrawArrays(GL_LINES, 0, 2);




    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    shaderProgram.release();















}

void GLWidget::mousePressEvent(QMouseEvent *event)
{
    lastMousePos = event->pos();
    lastRotation = rotation;
}

void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
    if (event->buttons() & Qt::LeftButton) {
        // 获取当前和之前的鼠标位置对应的球面坐标
        QVector3D va = getArcballVector(lastMousePos.x(), lastMousePos.y());
        QVector3D vb = getArcballVector(event->x(), event->y());

        // 计算旋转轴和角度
        float angle = qAcos(qMin(1.0f, QVector3D::dotProduct(va, vb))) * 180.0f / M_PI;
        QVector3D axis = QVector3D::crossProduct(va, vb).normalized();

        // 更新旋转
        rotation = QQuaternion::fromAxisAndAngle(axis, angle) * lastRotation;
        update();
    }
}

void GLWidget::wheelEvent(QWheelEvent *event)
{
    float delta = event->angleDelta().y() / 120.0f;
    zoomFactor *= (1.0f + delta * 0.1f);
    zoomFactor = qBound(0.1f, zoomFactor, 2.0f);
    update();
}

QVector3D GLWidget::getArcballVector(int x, int y)
{
    // 将鼠标坐标映射到[-1, 1]范围
    float mx = (float)x / width() * 2.0f - 1.0f;
    float my = 1.0f - (float)y / height() * 2.0f;

    float length = mx * mx + my * my;
    if (length <= 1.0f) {
        return QVector3D(mx, my, qSqrt(1.0f - length));
    } else {
        // 如果超出单位球,归一化到球面
        return QVector3D(mx, my, 0.0f).normalized();
    }
}

void GLWidget::initShaders()
{
    const char *vertexShaderSource =
        "#version 330 core\n"
        "layout(location = 0) in vec3 position;\n"
        "layout(location = 1) in vec3 color;\n"
        "uniform mat4 mvpMatrix;\n"
        "out vec3 fragColor;\n"
        "void main() {\n"
        "   gl_Position = mvpMatrix * vec4(position, 1.0);\n"
        "   fragColor = color;\n"
        "}\n";

    const char *fragmentShaderSource =
        "#version 330 core\n"
        "in vec3 fragColor;\n"
        "out vec4 outColor;\n"
        "void main() {\n"
        "   outColor = vec4(fragColor, 1.0);\n"
        "}\n";

    shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
    shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
    shaderProgram.link();
}

在mainwindow.ui中,添加OpenGLWidget,并提升为:GLWidget

相关推荐
lyw2056193 分钟前
微服务八股(自用)
java·开发语言
dot to one4 分钟前
Qt 中 QWidget涉及的常用核心属性介绍
开发语言·c++·qt
液态不合群11 分钟前
理解 C# 中的各类指针
java·开发语言·c#
charlie11451419120 分钟前
内核深入学习3——分析ARM32和ARM64体系架构下的Linux内存区域示意图与页表的建立流程
linux·学习·架构·内存管理
橙子1991101621 分钟前
Kotlin 中的作用域函数
android·开发语言·kotlin
zimoyin21 分钟前
Kotlin 懒初始化值
android·开发语言·kotlin
threelab33 分钟前
03.three官方示例+编辑器+AI快速学习webgl_animation_multiple
人工智能·学习·编辑器
threelab37 分钟前
18.three官方示例+编辑器+AI快速学习webgl_buffergeometry_points_interleaved
学习·编辑器·webgl
码农新猿类39 分钟前
初入OpenCV
qt·opencv·计算机视觉
黄雪超1 小时前
JVM——方法内联之去虚化
java·开发语言·jvm