diff options
Diffstat (limited to 'tests/manual/stereographicsview')
-rw-r--r-- | tests/manual/stereographicsview/CMakeLists.txt | 27 | ||||
-rw-r--r-- | tests/manual/stereographicsview/main.cpp | 26 | ||||
-rw-r--r-- | tests/manual/stereographicsview/mainwindow.cpp | 79 | ||||
-rw-r--r-- | tests/manual/stereographicsview/mainwindow.h | 30 | ||||
-rw-r--r-- | tests/manual/stereographicsview/mainwindow.ui | 101 | ||||
-rw-r--r-- | tests/manual/stereographicsview/mygraphicsview.cpp | 209 | ||||
-rw-r--r-- | tests/manual/stereographicsview/mygraphicsview.h | 47 | ||||
-rw-r--r-- | tests/manual/stereographicsview/stereographicsview.pro | 13 |
8 files changed, 532 insertions, 0 deletions
diff --git a/tests/manual/stereographicsview/CMakeLists.txt b/tests/manual/stereographicsview/CMakeLists.txt new file mode 100644 index 0000000000..6e43c660dd --- /dev/null +++ b/tests/manual/stereographicsview/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## stereographicsview Binary: +##################################################################### + +set(CMAKE_AUTOUIC ON) + +qt_internal_add_manual_test(stereographicsview + GUI + SOURCES + main.cpp + mainwindow.cpp + mainwindow.h + mainwindow.ui + mygraphicsview.h + mygraphicsview.cpp + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate + Qt::OpenGL + Qt::OpenGLWidgets + Qt::Widgets + Qt::WidgetsPrivate +) diff --git a/tests/manual/stereographicsview/main.cpp b/tests/manual/stereographicsview/main.cpp new file mode 100644 index 0000000000..a085f782b3 --- /dev/null +++ b/tests/manual/stereographicsview/main.cpp @@ -0,0 +1,26 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "mainwindow.h" + +#include <QApplication> +#include <QSurfaceFormat> + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + QSurfaceFormat format; + format.setDepthBufferSize(24); + format.setStencilBufferSize(8); + format.setSamples(16); + format.setStereo(true); + QSurfaceFormat::setDefaultFormat(format); + + MainWindow w; + w.show(); + return a.exec(); +} + + +#include "main.moc" diff --git a/tests/manual/stereographicsview/mainwindow.cpp b/tests/manual/stereographicsview/mainwindow.cpp new file mode 100644 index 0000000000..86269b096c --- /dev/null +++ b/tests/manual/stereographicsview/mainwindow.cpp @@ -0,0 +1,79 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "mainwindow.h" +#include "./ui_mainwindow.h" +#include <QPushButton> +#include <QSlider> +#include <QLabel> +#include <QGraphicsEllipseItem> +#include <QRandomGenerator> +#include <QOpenGLWidget> + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + ui->setupUi(this); + + ui->graphicsView->setViewport(new QOpenGLWidget); + ui->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + + QRect rect = ui->graphicsView->rect(); + QGraphicsScene *m_scene = new QGraphicsScene(rect); + ui->graphicsView->setScene(m_scene); + + QSize initialSize(150, 150); + m_ellipse = m_scene->addEllipse( + rect.width() / 2 - initialSize.width() / 2, + rect.height() / 2 - initialSize.height() / 2, + initialSize.width(), + initialSize.height(), + QPen(Qt::magenta, 5), + Qt::blue); + + QPushButton *button = new QPushButton(); + button->setGeometry(QRect(rect.width() / 2 - 75, 100, 150, 50)); + button->setText("Random ellipse color"); + QObject::connect(button, &QPushButton::pressed, [&]() { + m_ellipse->setBrush(QColor::fromRgb(QRandomGenerator::global()->generate())); + m_ellipse->setPen(QPen(QColor::fromRgb(QRandomGenerator::global()->generate()), 5)); + }); + m_scene->addWidget(button); + + m_label = new QLabel(); + m_label->setGeometry(QRect(rect.width() / 2 - 50, rect.height() - 100, 100, 50)); + m_label->setAlignment(Qt::AlignCenter); + m_scene->addWidget(m_label); + + QSlider *slider = new QSlider(Qt::Horizontal); + slider->setGeometry(QRect(rect.width() / 2 - 100, rect.height() - 50, 200, 50)); + slider->setMinimum(10); + slider->setMaximum(300); + slider->setValue(initialSize.width()); + QObject::connect(slider, &QAbstractSlider::valueChanged, [this](int value){ + QRectF rect = m_ellipse->rect(); + rect.setWidth(value); + rect.setHeight(value); + m_ellipse->setRect(rect); + m_label->setText("Ellipse size: " + QString::number(value)); + }); + emit slider->valueChanged(initialSize.width()); + m_scene->addWidget(slider); + + QMenu *screenShotMenu = menuBar()->addMenu("&Screenshot"); + screenShotMenu->addAction("Left buffer", this, [this](){ + ui->graphicsView->saveImage(QOpenGLWidget::LeftBuffer); + }); + + screenShotMenu->addAction("Right buffer", this, [this](){ + ui->graphicsView->saveImage(QOpenGLWidget::RightBuffer); + }); + +} + +MainWindow::~MainWindow() +{ + delete ui; +} + diff --git a/tests/manual/stereographicsview/mainwindow.h b/tests/manual/stereographicsview/mainwindow.h new file mode 100644 index 0000000000..5219aae644 --- /dev/null +++ b/tests/manual/stereographicsview/mainwindow.h @@ -0,0 +1,30 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include <QMainWindow> + +QT_BEGIN_NAMESPACE +namespace Ui { class MainWindow; } +QT_END_NAMESPACE + +class QGraphicsEllipseItem; +class QLabel; + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +private: + QGraphicsEllipseItem *m_ellipse; + QLabel *m_label; + + Ui::MainWindow *ui; +}; +#endif // MAINWINDOW_H diff --git a/tests/manual/stereographicsview/mainwindow.ui b/tests/manual/stereographicsview/mainwindow.ui new file mode 100644 index 0000000000..2ebb6b8caa --- /dev/null +++ b/tests/manual/stereographicsview/mainwindow.ui @@ -0,0 +1,101 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>MainWindow</class> + <widget class="QMainWindow" name="MainWindow"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1120</width> + <height>695</height> + </rect> + </property> + <property name="windowTitle"> + <string>MainWindow</string> + </property> + <widget class="QWidget" name="centralwidget"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="MyGraphicsView" name="graphicsView"> + <property name="sizePolicy"> + <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <property name="sizeAdjustPolicy"> + <enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum> + </property> + </widget> + </item> + <item> + <widget class="QFrame" name="frame"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>QFrame::StyledPanel</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Raised</enum> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>QGraphicsView Stereoscopic Example</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <widget class="QMenuBar" name="menubar"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>1120</width> + <height>21</height> + </rect> + </property> + </widget> + <widget class="QStatusBar" name="statusbar"/> + </widget> + <customwidgets> + <customwidget> + <class>MyGraphicsView</class> + <extends>QGraphicsView</extends> + <header>mygraphicsview.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections/> +</ui> diff --git a/tests/manual/stereographicsview/mygraphicsview.cpp b/tests/manual/stereographicsview/mygraphicsview.cpp new file mode 100644 index 0000000000..933ee00835 --- /dev/null +++ b/tests/manual/stereographicsview/mygraphicsview.cpp @@ -0,0 +1,209 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include "mygraphicsview.h" +#include <QResizeEvent> +#include <QFileDialog> + +Q_OPENGL_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); + +MyGraphicsView::MyGraphicsView(QWidget *parent) : + QGraphicsView(parent), + m_indexBuf(QOpenGLBuffer::IndexBuffer) +{ + +} + +MyGraphicsView::MyGraphicsView(QGraphicsScene *scene, QWidget *parent) : + QGraphicsView(scene, parent) +{ + +} + +void MyGraphicsView::saveImage(QOpenGLWidget::TargetBuffer targetBuffer) +{ + QOpenGLWidget *w = static_cast<QOpenGLWidget*>(viewport()); + Q_ASSERT(w); + + w->makeCurrent(targetBuffer); + draw(targetBuffer); + + QImage img = qt_gl_read_framebuffer(w->size() * w->devicePixelRatio(), true, true); + + if (img.isNull()) { + qFatal("Failed to grab framebuffer"); + } + + const char *fn = + targetBuffer == QOpenGLWidget::LeftBuffer + ? "leftBuffer.png" : "rightBuffer.png"; + + QFileDialog fd(this); + fd.setAcceptMode(QFileDialog::AcceptSave); + fd.setDefaultSuffix("png"); + fd.selectFile(fn); + if (fd.exec() == QDialog::Accepted) + img.save(fd.selectedFiles().first()); +} + +void MyGraphicsView::drawBackground(QPainter *painter, const QRectF &rect) +{ + if (!m_initialized) + init(); + + QOpenGLWidget *w = static_cast<QOpenGLWidget*>(viewport()); + + painter->beginNativePainting(); + + draw(w->currentTargetBuffer()); + + painter->endNativePainting(); + + + m_yaw += 0.5; + if (m_yaw > 360) + m_yaw = 0; +} + +void MyGraphicsView::resizeEvent(QResizeEvent *event) +{ + QGraphicsView::resizeEvent(event); + + resize(event->size().width(), event->size().height()); +} + +void MyGraphicsView::init() +{ + if (m_initialized) + return; + + initializeOpenGLFunctions(); + + initShaders(); + initCube(); + + resize(viewport()->width(), viewport()->height()); + + m_initialized = true; +} + +void MyGraphicsView::initShaders() +{ + static const char *vertexShaderSource = + "#ifdef GL_ES\n" + "// Set default precision to medium\n" + "precision mediump int;\n" + "precision mediump float;\n" + "#endif\n" + "attribute vec4 a_position;\n" + "uniform mat4 u_mvp;\n" + "void main() {\n" + "gl_Position = u_mvp * a_position;\n" + "}\n"; + + static const char *fragmentShaderSource = + "#ifdef GL_ES\n" + "// Set default precision to medium\n" + "precision mediump int;\n" + "precision mediump float;\n" + "#endif\n" + "void main() {\n" + "gl_FragColor = vec4(0.7, 0.1, 0.0, 1.0);\n" + "}\n"; + + if (!m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource)) + close(); + + if (!m_program.addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource)) + close(); + + if (!m_program.link()) + close(); + + if (!m_program.bind()) + close(); +} + +void MyGraphicsView::initCube() +{ + m_arrayBuf.create(); + m_indexBuf.create(); + + QVector3D vertices[] = { + QVector3D(-1.0f, -1.0f, 1.0f), + QVector3D( 1.0f, -1.0f, 1.0f), + QVector3D(-1.0f, 1.0f, 1.0f), + QVector3D( 1.0f, 1.0f, 1.0f), + QVector3D( 1.0f, -1.0f, 1.0f), + QVector3D( 1.0f, -1.0f, -1.0f), + QVector3D( 1.0f, 1.0f, 1.0f), + QVector3D( 1.0f, 1.0f, -1.0f), + QVector3D( 1.0f, -1.0f, -1.0f), + QVector3D(-1.0f, -1.0f, -1.0f), + QVector3D( 1.0f, 1.0f, -1.0f), + QVector3D(-1.0f, 1.0f, -1.0f), + QVector3D(-1.0f, -1.0f, -1.0f), + QVector3D(-1.0f, -1.0f, 1.0f), + QVector3D(-1.0f, 1.0f, -1.0f), + QVector3D(-1.0f, 1.0f, 1.0f), + QVector3D(-1.0f, -1.0f, -1.0f), + QVector3D( 1.0f, -1.0f, -1.0f), + QVector3D(-1.0f, -1.0f, 1.0f), + QVector3D( 1.0f, -1.0f, 1.0f), + QVector3D(-1.0f, 1.0f, 1.0f), + QVector3D( 1.0f, 1.0f, 1.0f), + QVector3D(-1.0f, 1.0f, -1.0f), + QVector3D( 1.0f, 1.0f, -1.0f) + }; + + GLushort indices[] = { + 0, 1, 2, 3, 3, + 4, 4, 5, 6, 7, 7, + 8, 8, 9, 10, 11, 11, + 12, 12, 13, 14, 15, 15, + 16, 16, 17, 18, 19, 19, + 20, 20, 21, 22, 23 + }; + + + m_arrayBuf.bind(); + m_arrayBuf.allocate(vertices, 24 * sizeof(QVector3D)); + + m_indexBuf.bind(); + m_indexBuf.allocate(indices, 34 * sizeof(GLushort)); +} + +void MyGraphicsView::draw(QOpenGLWidget::TargetBuffer targetBuffer) +{ + glClearColor(0.0f, 0.7f, 0.0f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + m_program.bind(); + m_arrayBuf.bind(); + m_indexBuf.bind(); + + QMatrix4x4 matrix; + matrix.translate(targetBuffer == QOpenGLWidget::LeftBuffer ? -2.0 : 2.0, + 0.0, + -10.0); + matrix.scale(2.0); + matrix.rotate(QQuaternion::fromEulerAngles(10, m_yaw, 0)); + m_program.setUniformValue("u_mvp", m_projection * matrix); + + int vertexLocation = m_program.attributeLocation("a_position"); + m_program.enableAttributeArray(vertexLocation); + m_program.setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, sizeof(QVector3D)); + + glDrawElements(GL_TRIANGLE_STRIP, 34, GL_UNSIGNED_SHORT, nullptr); +} + +void MyGraphicsView::resize(int w, int h) +{ + qreal aspect = qreal(w) / qreal(h ? h : 1); + const qreal zNear = 0.0, zFar = 100.0, fov = 45.0; + m_projection.setToIdentity(); + m_projection.perspective(fov, aspect, zNear, zFar); + + if (m_initialized) + glViewport(0, 0, w, h); +} diff --git a/tests/manual/stereographicsview/mygraphicsview.h b/tests/manual/stereographicsview/mygraphicsview.h new file mode 100644 index 0000000000..57cf902d5d --- /dev/null +++ b/tests/manual/stereographicsview/mygraphicsview.h @@ -0,0 +1,47 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#ifndef MYGRAPHICSVIEW_H +#define MYGRAPHICSVIEW_H + +#include <QOpenGLFunctions> +#include <QGraphicsView> +#include <QOpenGLShaderProgram> +#include <QOpenGLBuffer> +#include <QMatrix4x4> +#include <QOpenGLWidget> + +class MyGraphicsView : public QGraphicsView, protected QOpenGLFunctions +{ +public: + MyGraphicsView(QWidget *parent = nullptr); + MyGraphicsView(QGraphicsScene *scene, QWidget *parent = nullptr); + + void saveImage(QOpenGLWidget::TargetBuffer targetBuffer); + +protected: + void drawBackground(QPainter *painter, const QRectF &rect) override; + + void resizeEvent(QResizeEvent *event) override; + +private: + void init(); + void initShaders(); + void initCube(); + + void draw(QOpenGLWidget::TargetBuffer targetBuffer); + + void resize(int w, int h); + + + bool m_initialized = false; + + QOpenGLShaderProgram m_program; + QMatrix4x4 m_projection; + QOpenGLBuffer m_arrayBuf; + QOpenGLBuffer m_indexBuf; + + qreal m_yaw = 0; +}; + +#endif // MYGRAPHICSVIEW_H diff --git a/tests/manual/stereographicsview/stereographicsview.pro b/tests/manual/stereographicsview/stereographicsview.pro new file mode 100644 index 0000000000..597166367c --- /dev/null +++ b/tests/manual/stereographicsview/stereographicsview.pro @@ -0,0 +1,13 @@ +QT += widgets widgets-private gui-private core-private + +TARGET = stereographicsview +TEMPLATE = app + +SOURCES += main.cpp \ + mainwindow.cpp \ + mainwindow.h \ + mainwindow.ui \ + mygraphicsview.h \ + mygraphicsview.cpp \ + +HEADERS += openglwidget.h |