OpenGL and QT, crash at glDrawElements



  • Hi guys,
    I am new here and new to OpenGL ;)

    So I was trying to make something to appear on my screen, but unfortunately it always crashes at glDrawElements.
    I am glad if somebody could help. Here is the code:

    //Initialization 
    void Mesh::initialize()
    {
        this->initializeOpenGLFunctions();
    
        vao = new QOpenGLVertexArrayObject();
        vbo = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
        ebo = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
    
        vao->create();
        vbo->create();
        ebo->create();
    
        vao->bind();
    
            vbo->bind();
            vbo->setUsagePattern(QOpenGLBuffer::StaticDraw);
            vbo->allocate(vertices.data(),vertices.size() * sizeof(Vertex)); 
    
    
            ebo->bind(); 
            ebo->setUsagePattern(QOpenGLBuffer::StaticDraw);
            ebo->allocate(indices.data(),indices.size()*sizeof(GLuint)); 
    
    
            //Vertex position
    
            program->enableAttributeArray(0);
            program->setAttributeBuffer(0,GL_FLOAT,0,sizeof(Vertex));
    
            program->enableAttributeArray(1); 
            program->setAttributeBuffer(1,GL_FLOAT,offsetof(Vertex,Normal),3,sizeof(Vertex)); 
    
            glEnableVertexAttribArray(2);
            program->setAttributeBuffer(2,GL_FLOAT,offsetof(Vertex,TextCoords),2,sizeof(Vertex));
    
        vao->release();
    
    }
    

    It always crashes here:

    void Mesh::DrawMesh()
    {
        vao->bind();
        qDebug() << vertices.size();
        glDrawElements(GL_TRIANGLES, indices.size(),GL_UNSIGNED_INT,0);
        vao->release();
    }
    

    Note: When I call vao->isCreated() it returns false even tough I made sure (100%) that initialize() is called BEFORE DrawMesh.

    Here is my Vertex struct:

    struct Vertex
    {
        QVector3D Position;
        QVector3D Normal;
        QVector2D TextCoords;
    };
    

    This is my vertex shader:

    #version 330 core
    
    layout(location=0) in vec3 position;
    layout(location=1) in vec3 normal;
    layout(location=2) in vec2 textCoords;
    
    uniform mat4 MVP;
    
    out vec4 color;
    
    void main(void)
    {
        gl_Position= MVP*vec4(position,1);
        color = vec4(1,1,1,1);
    }
    
    

    Can somebody help me? I'm really stuck here. Also I don't know if I can pass an array of QVector3D like that to the graphicscard...

    Thank you really for your help. ;)


  • Moderators

    Hi, welcome to the Qt forum! Seems like you forgot to create an OpenGL context and make it current, see: http://doc.qt.io/qt-5/qopenglfunctions.html#details

    Edit: There is also a minimal example: http://doc.qt.io/qt-5/qtgui-openglwindow-example.html



  • @Wieland Thanks for the reply Wieland.
    Inside paintGL I loop through a list of meshes and call the DrawMesh() method on all of them. I use a QOpenGLWidget for that.
    So is manually creating a context still the recommended way to go?
    Thanks you ;)


  • Moderators

    @DaOnlyOwner said:

    void Mesh::initialize()

    That should be void Mesh::initializeGL(), in other words override void QOpenGLWidget::initializeGL(). Otherwise the function won't automatically use the correct OpenGL context. May I please see your Mesh header file?



  • @Wieland Of course,

    class Mesh : public QOpenGLFunctions_3_3_Core
    {
    public:
        Mesh(const Mesh& mesh)
        {
            this->vertices = mesh.vertices;
            this->indices = mesh.indices;
            this->program = mesh.program;
            initialize();
        }
    
        Mesh(){}
        ~Mesh()
        {
    
            vao->destroy();
            vbo->destroy();
            ebo->destroy();
    
        }
    
        QVector<Vertex> vertices;
        QVector<GLuint> indices;
        QOpenGLShaderProgram* program;
    
        Mesh(const QVector<Vertex> &vertices, const QVector<GLuint> &indices, QOpenGLShaderProgram* program);
        void DrawMesh();
    
    private:
    
        QOpenGLVertexArrayObject* vao;
        QOpenGLBuffer* vbo;
        QOpenGLBuffer* ebo;
    
        void initialize();
    
    };
    

    The code of my QOpenGLWidget:

    void RenderingWindow::initializeGL()
    {
        this->initializeOpenGLFunctions();    
        program->create();
        program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/testvert.vert" );
        program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/testfrag.frag");
        program->link();
    
        Camera::instance().LookAt(0,0,5, 0,0,0 ,0,1,0);
    }
    
    void RenderingWindow::resizeGL(int w, int h)
    {
        Camera::instance().Perspective(60,w/h,0,10000);
    }
    
    void RenderingWindow::paintGL()
    {
        program->bind();
            program->setUniformValue("MVP",Camera::instance().GetMVP());
            model.Draw();
        program->release();
    }
    
    void RenderingWindow::LoadModel()
    {
        QString filename = QFileDialog::getOpenFileName(this,"Choose Model file",QString(),"Model files (*.fbx *.obj)");
        model.LoadModel(*this, filename, program);
    }
    
    

    model.Draw() goes through all the meshes currently attached to this model and draws them.


  • Moderators

    Mesh(const Mesh& mesh) calls void Mesh::initialize(). Who calls Mesh(const Mesh& mesh)? The constructor must be called from within the correct OpenGL context.



  • @Wieland I think it's called when storing the Meshes inside a QVector. So the constructor is called somewhere in LoadModel().


  • Moderators

    Ok. Then call makeCurrent() in void RenderingWindow::LoadModel().



  • @Wieland somehow It's still not working.
    The reason why I have to call initialize() inside the copyConstructor is, that you can't copy QOpenGLVertexArrayObject..


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.