Qt produces OpenGl ES error
-
I made a small graphics engine to render objects and it uses paintGL function of QOpenGLWidget. However some 3D models cause error at the very first draw call d_ptr->f.DrawElements(mode, count, type, indices) as bad memory access. During the loading of these objects there is not any single GL error, buffers are all created fine. In addition if I trigger my model importing function from QT mousePressEvent callback everything works fine. It only happens if the model loading function is triggered from a menu bar item with QAction. Also these code and the same models run fine in Android,IOS and some windows platforms while have problem with some other Windows platforms and OSx. I suspect it is something to do with the GL context.
Here is my MainWindow and QOpenGLWidget for your reference.
// MainGlWidget.cpp #include <QtWidgets> #include <QtOpenGL> #include "MainGlWidget.h" #include "iostream" #include "Common.h" #ifdef __APPLE__ #include <unistd.h> #endif // /*#include "Common.h" #include "UltimateDesign.h"*/ MainGlWidget::MainGlWidget(QWidget *parent) : QOpenGLWidget(parent) { xRot = 0; yRot = 0; zRot = 0; } MainGlWidget::~MainGlWidget() { } QSize MainGlWidget::minimumSizeHint() const { return QSize(50, 50); } QSize MainGlWidget::sizeHint() const { return QSize(400, 400); } static void qNormalizeAngle(int &angle) { while (angle < 0) angle += 360 * 16; while (angle > 360) angle -= 360 * 16; } void MainGlWidget::setXRotation(int angle) { qNormalizeAngle(angle); if (angle != xRot) { xRot = angle; emit xRotationChanged(angle); } } void MainGlWidget::setYRotation(int angle) { qNormalizeAngle(angle); if (angle != yRot) { yRot = angle; emit yRotationChanged(angle); } } void MainGlWidget::setZRotation(int angle) { qNormalizeAngle(angle); if (angle != zRot) { zRot = angle; emit zRotationChanged(angle); } } void MainGlWidget::importFile(std::string file) { // When a QAction triggeres this function, for some models I have the mentioned problem makeCurrent(); application->importFile(file); } void MainGlWidget::initializeGL() { CHECK_GL(glEnable(GL_DEPTH_TEST)); CHECK_GL(glEnable(GL_CULL_FACE)); //CHECK_GL(glCullFace(GL_CULL_FACE)); //glCullFace(GL_BACK); CHECK_GL(glShadeModel(GL_SMOOTH)); CHECK_GL(glEnable(GL_LIGHTING)); CHECK_GL(glEnable(GL_LIGHT0)); CHECK_GL(glClearColor(0.4, 0.4, 0.4, 1)); CHECK_GL(glEnable(GL_BLEND)); CHECK_GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); CHECK_GL(glDepthMask(GL_TRUE)); #ifdef WIN32 //glViewport(0, 0, 1280, 960); #endif application->init((QOpenGLWidget*)this); application->setScreenDimentions(width(),height()); #ifdef WIN32 CreateThread( NULL, // default security attributes 0, // use default stack size timer, // thread function name (void*) this, // argument to thread function 0, // use default creation flags NULL); // returns the thread identifier #elif __linux__ || __APPLE__ pthread_t thread; pthread_create(&thread, NULL, timer, (void*) this); #endif } void MainGlWidget::paintGL() { GLint m_viewport[4]; glGetIntegerv( GL_VIEWPORT, m_viewport ); CHECK_GL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); application->render("cam1"); } void MainGlWidget::resizeGL(int width, int height) { std::cout << "width" << width << std::endl; std::cout << "height" << height << std::endl; size[0] = width; size[1] = height; #ifndef DRONE int side = qMin(size[0], size[1]); glViewport((size[0]-side)/2,(size[1]-side)/2, side, side); #endif update(); } void MainGlWidget::mousePressEvent(QMouseEvent *event) { lastPos = event->pos(); if (event->buttons() & Qt::LeftButton) { application->mouseClickWithLeft(lastPos.x(),lastPos.y()); }else if (event->buttons() & Qt::RightButton) { application->mouseClickWithRight(lastPos.x(),lastPos.y()); } } void MainGlWidget::mouseMoveEvent(QMouseEvent *event) { //if I import the model in this call back function then it works fine with all models. // application->importFile(file); int dx = event->x() - lastPos.x(); int dy = event->y() - lastPos.y(); lastPos = event->pos(); if (event->buttons() & Qt::LeftButton) { setXRotation(xRot + dy); setYRotation(yRot + dx); application->mouseDragWithLeft(dx,dy); } else if (event->buttons() & Qt::RightButton) { setXRotation(xRot + 8 * dy); setZRotation(zRot + 8 * dx); application->mouseDragWithRight(dx,dy); }else if (event->buttons() &Qt::MiddleButton) { setXRotation(xRot + 8 * dy); setZRotation(zRot + 8 * dx); application->mouseDragWithMiddle(dx,dy); } } void MainGlWidget::draw() { } #ifdef WIN32 DWORD WINAPI timer(LPVOID lpParam) { MainGlWidget* glwidget = (MainGlWidget*)lpParam; while (true) { glwidget->update(); Sleep(10); } } #elif __linux__ || __APPLE__ void *timer(void *lpParam) { MainGlWidget* glwidget = (MainGlWidget*)lpParam; while (true) { std::cout<<"loop "<<pthread_self(); glwidget->update(); usleep(16000); } } #endif //======================================================================= //MainWindow.cpp void MainWindowMVM::createActions() { importAct = new QAction( tr("&Import Model"), this); importAct->setShortcuts(QKeySequence::Open); importAct->setStatusTip(tr("Please open a model")); connect(importAct, SIGNAL(triggered()), this, SLOT(import())); } void MainWindowMVM::createMenus() { fileMenu=menuBar()->addMenu(tr("&File")); fileMenu->addAction(importAct); } void MainWindowMVM::import() { QString fileName = QFileDialog::getOpenFileName(this); std::string file = fileName.toUtf8().constData(); ui->MainScreen->importFile(file); //MainScreen keeps the instance of MainGlWidget class above. }