简体   繁体   English

如何在 Qt 5.0.2 OpenGL(QOpenGLWidget) 中放大和缩小图形?

[英]How to zoom in and out of a figure in Qt 5.0.2 OpenGL(QOpenGLWidget)?

I'm trying to make the zoom in and out of, say, two lines at an angle (like a tick(/)).我正在尝试放大和缩小,例如,两条线以一定角度(如刻度(/))。 I have looked through a lot of options on the Internet, but did not find anything useful.我在互联网上浏览了很多选项,但没有发现任何有用的东西。 If you have an example in Qt which shows how to add zoom in and out of a shape, with a wheel, mouse, or you know how to do it, I will be very grateful if you can share it with me.如果您在 Qt 中有一个示例,它显示了如何使用滚轮、鼠标或您知道如何添加放大和缩小形状,如果您能与我分享,我将不胜感激。

I just recently started to learn Qt and OpenGl.我最近才开始学习 Qt 和 OpenGl。 It would be cool if you could tell me how to move by x and y coordinates, ie the usual movement of a figure left, right, up and down.如果您能告诉我如何按 x 和 y 坐标移动,那就太酷了,即图形的通常向左、向右、向上和向下移动。

Here is the code I use, maybe it will be useful for solving my question.这是我使用的代码,也许它对解决我的问题很有用。

This code was taken from one guide, it would be cool if you could point out the mistakes in it (if there are any)此代码取自一个指南,如果您能指出其中的错误(如果有的话)会很酷

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

private:
    Ui::MainWindow *ui;

};
#endif // MAINWINDOW_H

myqopenglwidget.h

#ifndef MYQOPENGLWIDGET_H
#define MYQOPENGLWIDGET_H

#include <QOpenGLFunctions>
#include <QColor>
#include <GL/gl.h>
#include <GL/glu.h>
#include <QTimer>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QQuaternion>
#include <QVector2D>
#include <QVector>
#include <functional>

#define RGB_MIN 1
#define RGB_MAX 255

class MyQOpenGLWidget : public QOpenGLWidget, public QOpenGLFunctions
{
public:
    MyQOpenGLWidget(QWidget *parent = nullptr);

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

private:
    void qColorToRGB(const QColor &C, float &r, float &g, float &b) const;
    float normaliza_0_1(float val, float min, float max) const;

protected:
};

#endif // MYQOPENGLWIDGET_H

myqopenglwidget.cpp


#include "myqopenglwidget.h"
#include <QOpenGLFunctions>
#include <QOpenGLFunctions_4_1_Compatibility>
#include <cmath>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QGLFramebufferObject>
#include <QOpenGLFramebufferObject>
#include <GL/gl.h>
#include <iostream>
#include <vector>
#include <cmath>
#include <iomanip>
#include <fstream>
#include <QGLWidget>
#include <QMouseEvent>

MyQOpenGLWidget::MyQOpenGLWidget(QWidget *parent) : QOpenGLWidget {parent}
{

}

void MyQOpenGLWidget::initializeGL()
{
    float r,g,b,a = normaliza_0_1(255.0f, RGB_MIN, RGB_MAX);
    initializeOpenGLFunctions();
    qColorToRGB(Qt::black,r,g,b);
    glClearColor(r,g,b,a);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHT0);
    glEnable(GL_LIGHTING);
    glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
    glEnable(GL_COLOR_MATERIAL);

}

void MyQOpenGLWidget::paintGL()
{
    float r,g,b;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

//x
    glBegin(GL_LINES);
    qColorToRGB(Qt::yellow,r,g,b);
    glColor3f(r,g,b);
    glVertex3f(-1.0f, 0.0f,0.0f);
    glVertex3f(1.0f, 0.0f,0.0f);
    glEnd();
//y
    glBegin(GL_LINES);
    qColorToRGB(Qt::yellow,r,g,b);
    glColor3f(r,g,b);
    glVertex3f(0.0f, -1.0f,0.0f);
    glVertex3f(0.0f, 1.0f,0.0f);
    glEnd();

    glBegin(GL_LINES);
    qColorToRGB(Qt::green,r,g,b);
    glColor3f(r,g,b);
    glVertex3f(0.0f, 0.0f,0.0f);
    glVertex3f(0.835f, 0.69f,0.0f);
    glEnd();


    glBegin(GL_LINES);
    qColorToRGB(Qt::green,r,g,b);
    glColor3f(r,g,b);
    glVertex3f(-0.835f, 0.69f,0.0f);
    glVertex3f(0.0f, 0.0f,0.0f);
    glEnd();

}

void MyQOpenGLWidget::resizeGL(int w, int h)
{
    glViewport(0,0,w,h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

}

void MyQOpenGLWidget::qColorToRGB(const QColor &C, float &r, float &g, float &b) const
{
    r = normaliza_0_1(C.red(),RGB_MIN, RGB_MAX);
    g = normaliza_0_1(C.green(),RGB_MIN, RGB_MAX);
    b = normaliza_0_1(C.blue(),RGB_MIN, RGB_MAX);
}

float MyQOpenGLWidget::normaliza_0_1(float val, float min, float max) const
{
    return (val-min)/(max-min);
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

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

main.cpp

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

If you have an example in Qt which shows how to add zoom in and out of a shape, with a wheel如果您在 Qt 中有一个示例,它显示了如何使用轮子添加放大和缩小形状

My example shows how to zoom with the wheel button and pan with the right button: https://github.com/8Observer8/PanZoom_OpenGL3_Qt6Cpp我的示例显示了如何使用滚轮按钮进行缩放并使用右键进行平移: https://github.com/8Observer8/PanZoom_OpenGL3_Qt6Cpp

在此处输入图像描述

main.cpp主文件

#ifdef _WIN32
#include <windows.h>
extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
#endif

#include "Widget.h"

#include <QtGui/QSurfaceFormat>
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QSurfaceFormat format;
    format.setSamples(8);

    Widget w;
    w.setFormat(format);
    w.show();
    return a.exec();
}

Widget.h小部件.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QtGui/QOpenGLFunctions>
#include <QtGui/QMatrix4x4>
#include <QtGui/QWheelEvent>
#include <QtOpenGLWidgets/QOpenGLWidget>
#include <QtOpenGL/QOpenGLBuffer>
#include <QtOpenGL/QOpenGLShaderProgram>

class Widget : public QOpenGLWidget, QOpenGLFunctions
{
    Q_OBJECT

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

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

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

private:
    QOpenGLShaderProgram m_program;
    QOpenGLBuffer m_vertPosBuffer;
    QMatrix4x4 m_projMatrix;
    QMatrix4x4 m_viewMatrix;
    QMatrix4x4 m_modelMatrix;
    QMatrix4x4 m_mvpMatrix;
    int m_uMvpMatrixLocation;

    bool m_panning = false;
    float m_panX = 0;
    float m_panY = 0;
    float m_prevXForPan;
    float m_prevYForPan;
};
#endif // WIDGET_H

Widget.cpp小部件.cpp

#include "Widget.h"

#include <QtMath>
#include <QtGui/QOffscreenSurface>
#include <QtGui/QOpenGLContext>

Widget::Widget(QWidget *parent)
    : QOpenGLWidget(parent)
{
    setWindowTitle("OpenGL3, Qt6, C++");
    setFixedSize(QSize(400, 400));
}

Widget::~Widget()
{
}

void Widget::initializeGL()
{
    initializeOpenGLFunctions();
    glClearColor(0.86f, 0.87f, 0.84f, 1.f);

    float vertPositions[] = {
        -0.5f, -0.5f, 0.f,
        -0.5f, 0.5f, 0.f,
        0.5f, -0.5f, 0.f,
        0.5f, -0.5f, 0.f,
        -0.5f, 0.5f, 0.f,
        0.5f, 0.5f, 0.f
    };
    m_vertPosBuffer.create();
    m_vertPosBuffer.bind();
    m_vertPosBuffer.allocate(vertPositions, sizeof(vertPositions));

    m_program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Assets/Shaders/default.vert");
    m_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/Assets/Shaders/default.frag");
    m_program.bindAttributeLocation("aPosition", 0);
    m_program.link();

    m_program.setAttributeBuffer(0, GL_FLOAT, 0, 3);
    m_program.enableAttributeArray(0);

    m_projMatrix.perspective(50.f, 1.f, 0.1f, 500.0f);
    m_viewMatrix.lookAt(QVector3D(0.f, 0.f, 20.f), QVector3D(0.f, 0.f, 0.f), QVector3D(0.f, 1.f, 0.f));

    m_modelMatrix.translate(0.f, 0.f);
    m_modelMatrix.rotate(30.f, QVector3D(0.f, 0.f, 1.f));
    m_modelMatrix.scale(7.f, 4.f);

    m_program.bind();

    m_uMvpMatrixLocation = m_program.uniformLocation("uMvpMatrix");

    int uColorLocation = m_program.uniformLocation("uColor");
    QVector3D color(0.34f, 0.73f, 0.73f);
    m_program.setUniformValue(uColorLocation, color);
}

void Widget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT);
    m_program.bind();

    QMatrix4x4 projViewMatrix = m_projMatrix * m_viewMatrix;
    m_mvpMatrix = projViewMatrix * m_modelMatrix;
    m_program.setUniformValue(m_uMvpMatrixLocation, m_mvpMatrix);

    glDrawArrays(GL_TRIANGLES, 0, 6);
}

void Widget::resizeGL(int w, int h)
{

}

void Widget::mousePressEvent(QMouseEvent *event)
{
    switch(event->button())
    {
        case Qt::LeftButton:
        {
            break;
        }
        case Qt::MiddleButton:
        {
            break;
        }
        case Qt::RightButton:
        {
            if (m_panning)
            {
                return;
            }
            m_panning = true;
            m_prevXForPan = event->position().x();
            m_prevYForPan = event->position().y();
            break;
        }
        default:
        {
            break;
        }
    }
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    if (!m_panning)
    {
        return;
    }

    float x = event->position().x();
    float y = event->position().y();

    float distance = m_viewMatrix.column(3).z();

    m_panX = (m_panX + (x - m_prevXForPan) * qFabs(distance) / 500.f);
    m_panY = (m_panY + (y - m_prevYForPan) * qFabs(distance) / 500.f);

    m_prevXForPan = x;
    m_prevYForPan = y;

    m_viewMatrix.setColumn(3, QVector4D(m_panX, -m_panY, distance, 1.f));

    update();
}

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    Q_UNUSED(event);

    if (!m_panning)
    {
        return;
    }
    m_panning = false;
}

void Widget::wheelEvent(QWheelEvent *event)
{
    float delta = event->angleDelta().y() / 100.f;
    float distance = m_viewMatrix.column(3).z();
    distance += delta;
    m_viewMatrix.setColumn(3, QVector4D(m_panX, -m_panY, distance, 1.f));
    update();
}

Assets/Shader/default.vert资产/着色器/default.vert

#version 130

in vec3 aPosition;
uniform mat4 uMvpMatrix;

void main()
{
    gl_Position = uMvpMatrix * vec4(aPosition, 1.0);
}

Assets/Shader/default.frag资产/着色器/default.frag

#version 130

uniform vec3 uColor;

out vec4 fragColor;

void main()
{
    fragColor = vec4(uColor, 1.0);
}

.pro .pro

QT       += core gui openglwidgets

win32: LIBS += -lopengl32

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    Widget.cpp

HEADERS += \
    Widget.h

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

RESOURCES += \
    Shaders.qrc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM