From 78221fe762fc21b629eb9a5643364d23680c349d Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 6 Aug 2014 10:25:36 +0200 Subject: Clean up the QOpenGLWindow example 1. Use includes without module prefixes, as is the custom in examples. 2. No inline functions to make it more readable. 3. Pause animation on pressing P and document our signal connection a bit more. Change-Id: I68dc3d4c74b639cf3fec17b63b7f49626db58bdb Reviewed-by: Gunnar Sletta --- examples/opengl/qopenglwindow/main.cpp | 170 ++++++++++++++++++++------------- 1 file changed, 102 insertions(+), 68 deletions(-) (limited to 'examples/opengl/qopenglwindow/main.cpp') diff --git a/examples/opengl/qopenglwindow/main.cpp b/examples/opengl/qopenglwindow/main.cpp index 19ac9e8a152..a67bcbb2e32 100644 --- a/examples/opengl/qopenglwindow/main.cpp +++ b/examples/opengl/qopenglwindow/main.cpp @@ -38,12 +38,13 @@ ** ****************************************************************************/ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #include "background_renderer.h" @@ -65,71 +66,16 @@ class OpenGLWindow : public QOpenGLWindow Q_OBJECT public: - // Use NoPartialUpdate. This means that all the rendering goes directly to - // the window surface, no additional framebuffer object stands in the - // middle. This is fine since we will clear the entire framebuffer on each - // paint. Under the hood this means that the behavior is equivalent to the - // manual makeCurrent - perform OpenGL calls - swapBuffers loop that is - // typical in pure QWindow-based applications. - OpenGLWindow() - : QOpenGLWindow(QOpenGLWindow::NoPartialUpdate) - , m_fragment_toy("background.frag") - , m_text_layout("The triangle and this text is rendered with QPainter") - { - m_view.lookAt(QVector3D(3,1,1), - QVector3D(0,0,0), - QVector3D(0,1,0)); - connect(this, SIGNAL(frameSwapped()), this, SLOT(update())); - - QLinearGradient gradient(QPointF(-1,-1), QPointF(1,1)); - gradient.setColorAt(0, Qt::red); - gradient.setColorAt(1, Qt::green); - - m_brush = QBrush(gradient); - } + OpenGLWindow(); protected: - void paintGL() Q_DECL_OVERRIDE - { - m_fragment_toy.draw(size()); - - QPainter p(this); - p.setWorldTransform(m_window_normalised_matrix.toTransform()); - - QMatrix4x4 mvp = m_projection * m_view * m_model_triangle; - p.setTransform(mvp.toTransform(), true); - - p.fillPath(painterPathForTriangle(), m_brush); - - QTransform text_transform = (m_window_painter_matrix * m_view * m_model_text).toTransform(); - p.setTransform(text_transform, false); - p.setPen(QPen(Qt::white)); - m_text_layout.prepare(text_transform); - qreal x = - (m_text_layout.size().width() / 2); - qreal y = 0; - p.drawStaticText(x, y, m_text_layout); - - m_model_triangle.rotate(-1, 0, 1, 0); - m_model_text.rotate(1, 0, 1, 0); - } - - void resizeGL(int w, int h) Q_DECL_OVERRIDE - { - m_window_normalised_matrix.setToIdentity(); - m_window_normalised_matrix.translate(w / 2.0, h / 2.0); - m_window_normalised_matrix.scale(w / 2.0, -h / 2.0); - - m_window_painter_matrix.setToIdentity(); - m_window_painter_matrix.translate(w / 2.0, h / 2.0); - - m_text_layout.setTextWidth(std::max(w * 0.2, 80.0)); - - m_projection.setToIdentity(); - m_projection.perspective(45.f, qreal(w) / qreal(h), 0.1f, 100.f); - - } + void paintGL() Q_DECL_OVERRIDE; + void resizeGL(int w, int h) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; private: + void setAnimating(bool enabled); + QMatrix4x4 m_window_normalised_matrix; QMatrix4x4 m_window_painter_matrix; QMatrix4x4 m_projection; @@ -140,9 +86,97 @@ private: FragmentToy m_fragment_toy; QStaticText m_text_layout; + bool m_animate; }; -int main (int argc, char **argv) +// Use NoPartialUpdate. This means that all the rendering goes directly to +// the window surface, no additional framebuffer object stands in the +// middle. This is fine since we will clear the entire framebuffer on each +// paint. Under the hood this means that the behavior is equivalent to the +// manual makeCurrent - perform OpenGL calls - swapBuffers loop that is +// typical in pure QWindow-based applications. +OpenGLWindow::OpenGLWindow() + : QOpenGLWindow(QOpenGLWindow::NoPartialUpdate) + , m_fragment_toy("background.frag") + , m_text_layout("The triangle and this text is rendered with QPainter") + , m_animate(true) +{ + m_view.lookAt(QVector3D(3,1,1), + QVector3D(0,0,0), + QVector3D(0,1,0)); + + QLinearGradient gradient(QPointF(-1,-1), QPointF(1,1)); + gradient.setColorAt(0, Qt::red); + gradient.setColorAt(1, Qt::green); + + m_brush = QBrush(gradient); + + setAnimating(m_animate); +} + +void OpenGLWindow::paintGL() +{ + m_fragment_toy.draw(size()); + + QPainter p(this); + p.setWorldTransform(m_window_normalised_matrix.toTransform()); + + QMatrix4x4 mvp = m_projection * m_view * m_model_triangle; + p.setTransform(mvp.toTransform(), true); + + p.fillPath(painterPathForTriangle(), m_brush); + + QTransform text_transform = (m_window_painter_matrix * m_view * m_model_text).toTransform(); + p.setTransform(text_transform, false); + p.setPen(QPen(Qt::white)); + m_text_layout.prepare(text_transform); + qreal x = - (m_text_layout.size().width() / 2); + qreal y = 0; + p.drawStaticText(x, y, m_text_layout); + + m_model_triangle.rotate(-1, 0, 1, 0); + m_model_text.rotate(1, 0, 1, 0); +} + +void OpenGLWindow::resizeGL(int w, int h) +{ + m_window_normalised_matrix.setToIdentity(); + m_window_normalised_matrix.translate(w / 2.0, h / 2.0); + m_window_normalised_matrix.scale(w / 2.0, -h / 2.0); + + m_window_painter_matrix.setToIdentity(); + m_window_painter_matrix.translate(w / 2.0, h / 2.0); + + m_text_layout.setTextWidth(std::max(w * 0.2, 80.0)); + + m_projection.setToIdentity(); + m_projection.perspective(45.f, qreal(w) / qreal(h), 0.1f, 100.f); +} + +void OpenGLWindow::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_P) { // pause + m_animate = !m_animate; + setAnimating(m_animate); + } +} + +void OpenGLWindow::setAnimating(bool enabled) +{ + if (enabled) { + // Animate continuously, throttled by the blocking swapBuffers() call the + // QOpenGLWindow internally executes after each paint. Once that is done + // (frameSwapped signal is emitted), we schedule a new update. This + // obviously assumes that the swap interval (see + // QSurfaceFormat::setSwapInterval()) is non-zero. + connect(this, SIGNAL(frameSwapped()), this, SLOT(update())); + update(); + } else { + disconnect(this, SIGNAL(frameSwapped()), this, SLOT(update())); + } +} + +int main(int argc, char **argv) { QGuiApplication app(argc, argv); -- cgit v1.2.3