Qt5与现代OpenGL学习(十二)在OpenGL Widge内,用button按钮画直线,不需要提升类(二)

在这里插入图片描述
glwidget.h

#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; // 控制点的大小
     void drawLine();



};

#endif // GLWIDGET_H


glwidget.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);









   drawLine();





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


}


void GLWidget::drawLine()
{

    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);

}

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.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_clicked();

private:
    Ui::MainWindow *ui;

    class GLWidget *glWidget;



};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QVBoxLayout>
#include "glwidget.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);








}

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


void MainWindow::on_pushButton_clicked()
{



    // 手动创建OpenGL Widget并添加到containerWidget中
            glWidget = new GLWidget(ui->containerWidget);
            QVBoxLayout *layout = new QVBoxLayout(ui->containerWidget);
            layout->setContentsMargins(0, 0, 0, 0);
            layout->addWidget(glWidget);
            ui->containerWidget->setLayout(layout);


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向日葵xyz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值