diff options
Diffstat (limited to 'tests/manual/qopenglwidget/dockedopenglwidget/mainwidget.cpp')
-rw-r--r-- | tests/manual/qopenglwidget/dockedopenglwidget/mainwidget.cpp | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/tests/manual/qopenglwidget/dockedopenglwidget/mainwidget.cpp b/tests/manual/qopenglwidget/dockedopenglwidget/mainwidget.cpp new file mode 100644 index 0000000000..b9dc4c5fe2 --- /dev/null +++ b/tests/manual/qopenglwidget/dockedopenglwidget/mainwidget.cpp @@ -0,0 +1,161 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "mainwidget.h" +#include <QMouseEvent> +#include <cmath> + +MainWidget::~MainWidget() +{ + cleanup(); +} + +void MainWidget::cleanup() +{ + makeCurrent(); + delete texture; + texture = nullptr; + delete geometries; + geometries = nullptr; + delete program; + program = nullptr; + doneCurrent(); + + QObject::disconnect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &MainWidget::cleanup); +} + +void MainWidget::mousePressEvent(QMouseEvent *e) +{ + // Save mouse press position + mousePressPosition = QVector2D(e->position()); +} + +void MainWidget::mouseReleaseEvent(QMouseEvent *e) +{ + // Mouse release position - mouse press position + QVector2D diff = QVector2D(e->position()) - mousePressPosition; + + // Rotation axis is perpendicular to the mouse position difference + // vector + QVector3D n = QVector3D(diff.y(), diff.x(), 0.0).normalized(); + + // Accelerate angular speed relative to the length of the mouse sweep + qreal acc = diff.length() / 100.0; + + // Calculate new rotation axis as weighted sum + rotationAxis = (rotationAxis * angularSpeed + n * acc).normalized(); + + // Increase angular speed + angularSpeed += acc; +} + +void MainWidget::timerEvent(QTimerEvent *) +{ + // Decrease angular speed (friction) + angularSpeed *= 0.99; + + // Stop rotation when speed goes below threshold + if (angularSpeed < 0.01) { + angularSpeed = 0.0; + } else { + // Update rotation + rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angularSpeed) * rotation; + + // Request an update + update(); + } +} + +void MainWidget::initializeGL() +{ + initializeOpenGLFunctions(); + + glClearColor(0, 0, 0, 1); + + initShaders(); + initTextures(); + + glEnable(GL_DEPTH_TEST); + + glEnable(GL_CULL_FACE); + + geometries = new GeometryEngine; + + // Use QBasicTimer because its faster than QTimer + timer.start(12, this); + + connect(context(), &QOpenGLContext::aboutToBeDestroyed, this, &MainWidget::cleanup); +} + +void MainWidget::initShaders() +{ + program = new QOpenGLShaderProgram; + // Compile vertex shader + if (!program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/vshader.glsl")) + close(); + + // Compile fragment shader + if (!program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/fshader.glsl")) + close(); + + // Link shader pipeline + if (!program->link()) + close(); + + // Bind shader pipeline for use + if (!program->bind()) + close(); +} + +void MainWidget::initTextures() +{ + // Load cube.png image + texture = new QOpenGLTexture(QImage(":/cube.png").mirrored()); + + // Set nearest filtering mode for texture minification + texture->setMinificationFilter(QOpenGLTexture::Nearest); + + // Set bilinear filtering mode for texture magnification + texture->setMagnificationFilter(QOpenGLTexture::Linear); + + // Wrap texture coordinates by repeating + // f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2) + texture->setWrapMode(QOpenGLTexture::Repeat); +} + +void MainWidget::resizeGL(int w, int h) +{ + // Calculate aspect ratio + qreal aspect = qreal(w) / qreal(h ? h : 1); + + // Set near plane to 3.0, far plane to 7.0, field of view 45 degrees + const qreal zNear = 3.0, zFar = 7.0, fov = 45.0; + + // Reset projection + projection.setToIdentity(); + + // Set perspective projection + projection.perspective(fov, aspect, zNear, zFar); +} + +void MainWidget::paintGL() +{ + // Clear color and depth buffer + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + texture->bind(); + + // Calculate model view transformation + QMatrix4x4 matrix; + matrix.translate(0.0, 0.0, -5.0); + matrix.rotate(rotation); + + // Set modelview-projection matrix + program->setUniformValue("mvp_matrix", projection * matrix); + + // Use texture unit 0 which contains cube.png + program->setUniformValue("texture", 0); + + // Draw cube geometry + geometries->drawCubeGeometry(program); +} |