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.
#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;
};
#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();
}
#include "viewer.h"
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
# include <QGL>
#endif
#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.