Home Download Gallery Documentation Developer

# The overpainting example

Mixing OpenGL (3D) and QPainter (2D) drawing in the same viewer.

A semi-transparent eounded square is painted in 2D using a QPainter on top of a classical 3D OpenGL rendering. Useful to add 2D objects (annotations, menus, head-up display) to your viewers.

Inspired from the Qt's overpainting example. Note that this functionnality is only available with Qt 4.

## viewer.h

    #include <QGLViewer/qglviewer.h>

    class QPaintEvent;
    class QPainter;

    class Viewer : public QGLViewer {
    public:
      Viewer(QWidget *parent = 0);

    protected:
      virtual void draw();
      virtual void init();
      void drawOverpaint(QPainter *painter);

      virtual void paintGL() { update(); };
      virtual void paintEvent(QPaintEvent *event);
      // Could be overloaded to defer final initializations
      // virtual void showEvent(QShowEvent *event);

      virtual QString helpString() const;
    };

## main.cpp

    #include "viewer.h"
    #include <qapplication.h>

    int main(int argc, char **argv) {
      QApplication application(argc, argv);
      Viewer viewer;

      viewer.setWindowTitle("overpainting");

      viewer.show();
      return application.exec();
    }

## viewer.cpp

    #include "viewer.h"

    #include <QGL>
    #include <QPainter>

    using namespace std;

    #ifndef GL_MULTISAMPLE
    #define GL_MULTISAMPLE 0x809D
    #endif

    Viewer::Viewer(QWidget *parent)
        : QGLViewer(QGLFormat(QGL::SampleBuffers), parent) {
      setAttribute(Qt::WA_NoSystemBackground);
    }

    void Viewer::drawOverpaint(QPainter *painter) {
      painter->save();
      painter->translate(width() / 2, height() / 2);
      QRadialGradient radialGrad(QPointF(-40, -40), 100);
      radialGrad.setColorAt(0, QColor(255, 255, 255, 100));
      radialGrad.setColorAt(1, QColor(200, 200, 0, 100));
      painter->setBrush(QBrush(radialGrad));
      painter->drawRoundRect(-100, -100, 200, 200);
      painter->restore();
    }

    // Draws a spiral
    void Viewer::draw() {
      const float nbSteps = 200.0;

      glBegin(GL_QUAD_STRIP);
      for (int i = 0; i < nbSteps; ++i) {
        const float ratio = i / nbSteps;
        const float angle = 21.0 * ratio;
        const float c = cos(angle);
        const float s = sin(angle);
        const float r1 = 1.0 - 0.8f * ratio;
        const float r2 = 0.8f - 0.8f * ratio;
        const float alt = ratio - 0.5f;
        const float nor = 0.5f;
        const float up = sqrt(1.0 - nor * nor);
        glColor3f(1.0 - ratio, 0.2f, ratio);
        glNormal3f(nor * c, up, nor * s);
        glVertex3f(r1 * c, alt, r1 * s);
        glVertex3f(r2 * c, alt + 0.05f, r2 * s);
      }
      glEnd();
    }

    void Viewer::init() {
      restoreStateFromFile();
      help();
    }

    void Viewer::paintEvent(QPaintEvent *event) {
      Q_UNUSED(event)
      QPainter painter;
      painter.begin(this);
      painter.setRenderHint(QPainter::Antialiasing);

      // Save current OpenGL state
      glPushAttrib(GL_ALL_ATTRIB_BITS);
      glMatrixMode(GL_PROJECTION);
      glPushMatrix();
      glMatrixMode(GL_MODELVIEW);
      glPushMatrix();

      // Reset OpenGL parameters
      glShadeModel(GL_SMOOTH);
      glEnable(GL_DEPTH_TEST);
      glEnable(GL_CULL_FACE);
      glEnable(GL_LIGHTING);
      glEnable(GL_LIGHT0);
      glEnable(GL_MULTISAMPLE);
      static GLfloat lightPosition[4] = {1.0, 5.0, 5.0, 1.0};
      glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);
      glClearColor(backgroundColor().redF(), backgroundColor().greenF(),
                   backgroundColor().blueF(), backgroundColor().alphaF());

      // Classical 3D drawing, usually performed by paintGL().
      preDraw();
      draw();
      postDraw();
      // Restore OpenGL state
      glMatrixMode(GL_MODELVIEW);
      glPopMatrix();
      glMatrixMode(GL_PROJECTION);
      glPopMatrix();
      glPopAttrib();

      drawOverpaint(&painter);

      painter.end();
    }

    QString Viewer::helpString() const {
      QString text("<h2>O v e r p a i n t</h2>");
      text += "This example shows how to mix the 2D QPainter drawing with regular "
              "3D in an OpenGL QGLViewer.<br>";
      text += "The <code>paintEvent</code> method is overloaded to interleave the "
              "two drawing codes.";
      return text;
    }

Back to the examples main page.