1

I'm trying right now to do a text/graphical overlay of the QOpenGLWidget I've created. As you can see I've got the 3D down pretty tight but the 2D overlay using the QPainter is not working properly. Using the QPainter's drawRect function I expect to see a rectangle. Instead I'm getting four arrows.

QOpenGLWidget with arrows instead of a rectangle

The pertinent code is as follows:

main.cpp

QApplication a(argc, argv);

QSurfaceFormat format;
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile);
QSurfaceFormat::setDefaultFormat(format);

HSIOpenGLQuadViewWidget qvwidget;
qvwidget.setFormat(format);
qvwidget.init();
qvwidget.addPoint(QVector3D(-1,  1,  1), Qt::red);
qvwidget.addPoint(QVector3D( 1,  1,  1), Qt::red);
qvwidget.addPoint(QVector3D( 1, -1,  1), Qt::red);
qvwidget.addPoint(QVector3D(-1, -1,  1), Qt::red);
qvwidget.addPoint(QVector3D( 0,  0,  0), Qt::red);
qvwidget.addPoint(QVector3D(-1,  1, -1), Qt::red);
qvwidget.addPoint(QVector3D( 1,  1, -1), Qt::red);
qvwidget.addPoint(QVector3D( 1, -1, -1), Qt::red);
qvwidget.addPoint(QVector3D(-1, -1, -1), Qt::red);
qvwidget.generateSphere(0.5);
qvwidget.show();

return a.exec();

MyQOpenGLWidget.cpp

void HSIOpenGLQuadViewWidget::initializeGL()
{
// Required by Qt
initializeOpenGLFunctions();

// Creates a 24 bit depth mask
glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width(), height());

// Sets the OpenGL screen clear color
glClearColor(0, 0, 0, 0);

glEnable(GL_POLYGON_SMOOTH);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);

// Enables face culling
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);

glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
glColorMaterial(GL_FRONT, GL_SPECULAR);

// Somewhere in the initialization part of your program…
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);

glShadeModel(GL_SMOOTH);

// Create light components
//GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat ambientLight[] = { 2.0f, 2.0f, 2.0f, 1.0f };
GLfloat diffuseLight[] = { 0.8f, 0.8f, 0.8f, 1.0f };
GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
GLfloat position[] = { 0.0f, -10.0f, 0.0f, 1.0f };

// Assign created components to GL_LIGHT0
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
glLightfv(GL_LIGHT0, GL_POSITION, position);

//glDisable(GL_DEPTH_TEST);
glEnable(GL_PROGRAM_POINT_SIZE);
glPointSize(5);
}

void HSIOpenGLQuadViewWidget::paintGL()
{
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

// Set the depth test and clear the depth field
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glClearDepth(1.0);
glDepthFunc(GL_LEQUAL);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

drawPoints();

drawSphere();

glPopMatrix();

QPainter painter(this);

QRect rect = this->rect();

float top = rect.y() + (rect.height() * 0.8);
float height = rect.height() * 0.15;
float left = rect.x() + (rect.width() * 0.8);
float width = rect.width() * 0.15;

QPen pen;
pen.setColor(Qt::red);
pen.setWidth(10);
painter.setPen(pen);
painter.setBrush(QBrush(Qt::red));
painter.drawRect(left, top, width, height);

QString textYaw = QString("  Yaw : ") + QString::number(100) + QString("\n");
QString textPitch = QString("Pitch : ") + QString::number(200) + QString("\n");
QString textRoll = QString(" Roll : ") + QString::number(300) + QString("\n");

painter.drawText(left, top + 10, textYaw);
painter.drawText(left, top + 25, textPitch);
painter.drawText(left, top + 40, textRoll);
}

So, the question is, what would be causing the QOpenGLWidget to draw the four arrows instead of a solid red rectangle? Anybody have a clue? Thanks.

soulsabr
  • 895
  • 4
  • 16

1 Answers1

1

See this answer. You need to start a painter first, then inform it about native painting, push the state, do the native painting using GL calls, pop the state, end native painting, and finally draw using the painter.

Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • I've tried it both ways. With or without the begin/endNativePainter() I get the same results. – soulsabr Aug 26 '16 at 17:31
  • 1
    Your context preinitialization is wrecking it. See the other answer's details and comments. Do it in piecemeal fashion: get something very simple working first - e.g. no OpenGL calls at all, just the painter, then start adding simple draw calls one by one and see where it breaks. It clearly doesn't work because the painter is expecting a different state for the context than the one it finds itself in. – Kuba hasn't forgotten Monica Aug 26 '16 at 17:56
  • kuba ober I'll give this a shot. Seriously can't believe I didn't even think of doing that. :) Even if it doesn't work it is still a silly rookie mistake. – soulsabr Aug 26 '16 at 18:22
  • 1
    For some reason removing the lines 'glEnable(GL_CULL_FACE)' and 'glCullFace(GL_BACK)' solved the issue. Moving this to the start of the gl command and turning it off after the commands solves the problem. So, chalk this up to another rookie mistake. Thanks! EDIT: I also tried just turning on front face culling and that worked, too. It may just be me but that makes no sense. Oh well. – soulsabr Aug 26 '16 at 18:28