QOpenGLWidget Problem
-
Hi,Why does my QOpenGLWidget's drawn model disappear after using update(), but the background color is still displayed.
Here is my code:void OpenGLWidget::initializeGL() { initializeOpenGLFunctions(); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); f = QOpenGLContext::currentContext()->functions(); f->glEnable(GL_DEPTH_TEST); this->initializeShaders(); } void OpenGLWidget::initializeShaders() { this->m_ModelShader = new QOpenGLShaderProgram(this); /*--------m_ModelShader------------*/ if (!m_ModelShader->addShaderFromSourceFile(QOpenGLShader::Vertex, \ ModelvertexShaderPath)) qDebug() << "Failed to load Vert shader:" << m_ModelShader->log(); if (!m_ModelShader->addShaderFromSourceFile(QOpenGLShader::Fragment, \ ModelfragmentShaderPath)) qDebug() << "Failed to load fragment shader:" << m_ModelShader->log(); if (!m_ModelShader->link()) std::cout << "ERROR: failed to link: " << m_ModelShader->log().toStdString(); } void OpenGLWidget::resizeGL(int w, int h) { this->SCR_WIDTH = w; this->SCR_HEIGHT = h; this->SelectProjection(this->operatePro); } void OpenGLWidget::paintGL() { f = QOpenGLContext::currentContext()->functions(); f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); f->glClearColor(0.0f, 0.5f, 0.7f, 1.0f); if (isValid()) switch (RenderModel) { case Model: { makeCurrent(); m_VAO = new QOpenGLVertexArrayObject(this); m_VBO = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); m_EBO = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); this->DrawModelData(); m_ModelShader->bind(); { m_VAO->bind(); m_EBO->bind(); this->setModelShaderMatrix(); f->glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); } m_ModelShader->release(); break; } case Line: { break; } case Points: { break; } } } void OpenGLWidget::DrawModelData() { this->m_ModelShader->bind(); if (!m_VAO->create()) std::cerr << "ERROR: faild to create vertex array object" << std::endl; if (!m_VBO->create()) std::cerr << "ERROR: failed to create vertex buffer object" << std::endl; if (!m_EBO->create()) std::cerr << "ERROR: failed to create index buffer object" << std::endl; m_VAO->bind(); if (!m_VBO->bind()) { std::cerr << "ERROR: failed to bind vertex buffer object" << std::endl; } m_VBO->allocate(&meshes[0], meshes.size() * sizeof(Vertex)); if (!m_EBO->bind()) { std::cerr << "ERROR: failed to bind index buffer object" << std::endl; } m_EBO->allocate(&indices[0], sizeof(unsigned int) * indices.size()); int vertexLocation = m_ModelShader->attributeLocation("aPos"); / int normalLocation = m_ModelShader->attributeLocation("aNormal"); glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Position)); glEnableVertexAttribArray(vertexLocation); glVertexAttribPointer(normalLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal)); glEnableVertexAttribArray(normalLocation); m_VBO->release(); m_EBO->release(); m_VAO->release(); m_ModelShader->release(); } void OpenGLWidget::setModelShaderMatrix() { // DirLight GLint ViewPos = glGetUniformLocation(m_ModelShader->programId(), "viewPos"); GLint lightDir = glGetUniformLocation(m_ModelShader->programId(), "dirLight.direction"); GLint lightAmb = glGetUniformLocation(m_ModelShader->programId(), "dirLight.ambient"); GLint lightDif = glGetUniformLocation(m_ModelShader->programId(), "dirLight.diffuse"); GLint lightSpe = glGetUniformLocation(m_ModelShader->programId(), "dirLight.specular"); // Material变量 GLint materAmb = glGetUniformLocation(m_ModelShader->programId(), "material.ambient"); GLint materDif = glGetUniformLocation(m_ModelShader->programId(), "material.diffuse"); GLint materSpe = glGetUniformLocation(m_ModelShader->programId(), "material.specular"); GLint materShi = glGetUniformLocation(m_ModelShader->programId(), "material.shininess"); GLint alpha = glGetUniformLocation(m_ModelShader->programId(), "alpha"); GLint Model_model = glGetUniformLocation(m_ModelShader->programId(), "model"); GLint Model_view = glGetUniformLocation(m_ModelShader->programId(), "view"); GLint Model_proj = glGetUniformLocation(m_ModelShader->programId(), "projection"); m_ModelShader->setUniformValue(ViewPos, m_Camera->getPosition()); m_ModelShader->setUniformValue(lightAmb, Light_ambient); m_ModelShader->setUniformValue(lightDir, Light_direction); m_ModelShader->setUniformValue(lightDif, Light_diffuse); m_ModelShader->setUniformValue(lightSpe, Light_specular); m_ModelShader->setUniformValue(materAmb, Model_ambient); m_ModelShader->setUniformValue(materDif, Model_diffuse); m_ModelShader->setUniformValue(materSpe, Model_specular); m_ModelShader->setUniformValue(materShi, Model_shininess); m_ModelShader->setUniformValue(alpha, 1.0f); this->m_view = m_Camera->GetViewMatrix(); m_ModelShader->setUniformValue(Model_view, m_view); m_ModelShader->setUniformValue(Model_proj, m_projection); m_scale_rate = max(0.75f / max_len, m_scale_rate); this->m_model.scale(m_scale_rate); this->m_model = m_scale * m_model; this->m_middle = QVector3D(this->bbox.centerPoint.x, this->bbox.centerPoint.y, this->bbox.centerPoint.z); this->m_model.translate(-m_middle); this->m_model = m_move * m_rotate * m_model; m_ModelShader->setUniformValue(Model_model, m_model); }
-
Hi and welcome to devnet,
Your code is incomplete so it's not easy to fully grasp what you are doing.
In any case, why are you allocating your buffer objects possibly on every call of paintGL ?
That is pretty strange. Also you see to have derived from QOpenGLFunctions yet you retrieve the function from the current context although the context will be current when the xxxGL methods are called.
-
Hi and welcome to devnet,
Your code is incomplete so it's not easy to fully grasp what you are doing.
In any case, why are you allocating your buffer objects possibly on every call of paintGL ?
That is pretty strange. Also you see to have derived from QOpenGLFunctions yet you retrieve the function from the current context although the context will be current when the xxxGL methods are called.
@SGaist
Before that my code looked like this,it doesn't allocating buffer objects repeatedly.
But to do that would just show the background and not draw the model.struct Vertex { QVector3D Position; QVector3D Normal; }; OpenGLWidget::OpenGLWidget(QWidget* parent) : QOpenGLWidget(parent) { this->m_Camera = new QCamera(this, QVector3D(0.0f, 0.0f, 3.0f)); this->m_scale.setToIdentity(); this->m_move.setToIdentity(); this->m_model.setToIdentity(); this->m_scale.setToIdentity(); this->m_rotate.rotate(-90.0f, QVector3D(1.0f, 0.0f, 0.0f)); this->m_rotate.rotate(45.0f, QVector3D(0.0f, 0.0f, 1.0f)); this->m_middle.setX(0.0f);this->m_middle.setY(0.0f);this->m_middle.setZ(0.0f); this->m_projection.perspective(45.0f, static_cast<float>(SCR_WIDTH) / static_cast<float>(SCR_HEIGHT), 0.1f, 100.0f); this->m_view.lookAt(QVector3D(2.0f, 0.0f, 2.0f), QVector3D(0.0f, 0.0f, 0.0f), QVector3D(0.0f, 1.0f, 0.0f)); } void OpenGLWidget::initializeGL() { initializeOpenGLFunctions(); glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glEnable(GL_DEPTH_TEST); m_VAO = new QOpenGLVertexArrayObject(this); m_VBO = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer); m_EBO = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer); this->initializeShaders(); } void OpenGLWidget::initializeShaders() { this->m_ModelShader = new QOpenGLShaderProgram(this); /*--------m_ModelShader------------*/ if (!m_ModelShader->addShaderFromSourceFile(QOpenGLShader::Vertex, \ ModelvertexShaderPath)) qDebug() << "Failed to load Vert shader:" << m_ModelShader->log(); if (!m_ModelShader->addShaderFromSourceFile(QOpenGLShader::Fragment, \ ModelfragmentShaderPath)) qDebug() << "Failed to load fragment shader:" << m_ModelShader->log(); if (!m_ModelShader->link()) std::cout << "ERROR: failed to link: " << m_ModelShader->log().toStdString(); } void OpenGLWidget::LoadModel(GeoStruct::TriModel<>* curModel) { this->meshes.clear(); this->meshes.resize(curModel->vertices.size()); #pragma parallel for for (int i = 0; i < curModel->vertices.size(); ++i) { this->meshes[i].Position = QVector3D(curModel->vertices[i].x, curModel->vertices[i].y, curModel->vertices[i].z); this->meshes[i].Normal = QVector3D(curModel->PointNormals[i].x, curModel->PointNormals[i].y, curModel->PointNormals[i].z); } this->indices.resize(curModel->faces.size() * 3); #pragma parallel for for (int i = 0; i < curModel->faces.size(); ++i) { this->indices[3 * i] = curModel->faces[i][0]; this->indices[3 * i + 1] = curModel->faces[i][1]; this->indices[3 * i + 2] = curModel->faces[i][2]; } this->max_len = max(max(curModel->Bounding.a, curModel->Bounding.b), curModel->Bounding.c); this->bbox = curModel->Bounding; this->DrawModelData(); } void OpenGLWidget::DrawModelData() { this->m_ModelShader->bind(); /*--------------------initial------------------*/ if (!m_VAO->create()) std::cerr << "ERROR: faild to create vertex array object" << std::endl; if (!m_VBO->create()) std::cerr << "ERROR: failed to create vertex buffer object" << std::endl; if (!m_EBO->create()) std::cerr << "ERROR: failed to create index buffer object" << std::endl; /*-------------------bind------------------*/ m_VAO->bind(); if (!m_VBO->bind()) { std::cerr << "ERROR: failed to bind vertex buffer object" << std::endl; } m_VBO->allocate(&meshes[0], meshes.size() * sizeof(Vertex)); if (!m_EBO->bind()) { std::cerr << "ERROR: failed to bind index buffer object" << std::endl; } m_EBO->allocate(&indices[0], sizeof(unsigned int) * indices.size()); int vertexLocation = m_ModelShader->attributeLocation("aPos"); int normalLocation = m_ModelShader->attributeLocation("aNormal"); glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Position)); glEnableVertexAttribArray(vertexLocation); glVertexAttribPointer(normalLocation, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal)); glEnableVertexAttribArray(normalLocation); m_VBO->release(); m_EBO->release(); m_VAO->release(); m_ModelShader->release(); } void OpenGLWidget::resizeGL(int w, int h) { this->SCR_WIDTH = w; this->SCR_HEIGHT = h; this->SelectProjection(this->operatePro); } void OpenGLWidget::SelectProjection(Projection ProjectionModel) { switch (ProjectionModel) { case ORTHO: { m_projection.setToIdentity(); float left = -(float)SCR_WIDTH / (float)SCR_WIDTH * 2.0f; float right = (float)SCR_WIDTH / (float)SCR_WIDTH * 2.0f; float bottom = -(float)SCR_HEIGHT / (float)SCR_WIDTH * 2.0f; float top = (float)SCR_HEIGHT / (float)SCR_WIDTH * 2.0f; float nearVal = 0.1f; float farVal = 100.0f; this->m_projection.ortho(left, right, bottom, top, nearVal, farVal); break; } case PERSPECTIVE: { m_projection.setToIdentity(); m_projection.perspective(45.0f, static_cast<float>(SCR_WIDTH) / SCR_HEIGHT, 0.1f, 100.0f); break; } default: { m_projection.setToIdentity(); float left = -(float)SCR_WIDTH / (float)SCR_WIDTH * 2.0f; float right = (float)SCR_WIDTH / (float)SCR_WIDTH * 2.0f; float bottom = -(float)SCR_HEIGHT / (float)SCR_WIDTH * 2.0f; float top = (float)SCR_HEIGHT / (float)SCR_WIDTH * 2.0f; float nearVal = 0.1f; float farVal = 100.0f; this->m_projection.ortho(left, right, bottom, top, nearVal, farVal); break; } } } void OpenGLWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClearColor(0.0f, 0.5f, 0.7f, 1.0f); switch (RenderModel) { case Model: { m_ModelShader->bind(); { m_VAO->bind(); m_EBO->bind(); this->setModelShaderMatrix(); // render glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0); } m_ModelShader->release(); break; } case Line: { break; } case Points: { break; } } }
This is called in QMainWindow :
STLViewer::STLViewer(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); resize(1024, 768); this->pixmap = new QPixmap(file_name); QIcon icon(*pixmap); setWindowIcon(icon); connectSlots(); } void STLViewer::connectSlots() { connect(ui.action_LoadSTL, &QAction::triggered, this, &STLViewer_BasedQT::LoadSTLdoc); } void STLViewer::LoadSTLdoc() { QString qs_FilePath = QFileDialog::getOpenFileName(this, QStringLiteral("ChooseSTL"), "", QStringLiteral(" (*.stl)")); QFileInfo fileinfo = QFileInfo(qs_FilePath); QString FileName = fileinfo.fileName(); QByteArray qba = qs_FilePath.toLocal8Bit(); const char* chFilename = qba.data(); std::string s_FilePath(chFilename); GeoStruct::TriModel<>* CurModel = new GeoStruct::TriModel<>(); bool state = ImportModel(CurModel,s_FilePath); if (state&& CurModel->vertices.size()!=0) { Model_Library.emplace_back(CurModel); ++Model_Index; CurModel->need_normals(); CurModel->computeVolume(); ui.openGLWidget->LoadModel(CurModel); ui.openGLWidget->LoadPoint(CurModel->vertices); ui.openGLWidget->RenderModel = Model; } }
I still can't see what's causing the failure to draw.
-
With the code you posted, there's no way to know what RenderModel is so it might just be a value that does not do anything in your switch statement.
You should start by simplifying your code and strip away all the complexity.
Then start by adding the minimal amount of stuff to actually show something on the widget and only then add the loading of your file.
On a side note, please use a clean style when writing your code. You are mixing TitleCase, camelCase and snake_case is the same code base which makes it quite painful to go through. Same goes for your variable naming.