c++qtopenglqglwidget

QOpenGLWidget draw object


I already asked a question about QOpenglWidget here. In my last problem I just called the shaderid the wrong way. Now I am trying to load my vertices from a object. I've written a loader which loads the vertices, texture coordinates, normals and indices. I have already written this code in native openGL and checked the output. the vertices etc are matching with the ones in my Qt code.

The only problem is that I am unable to make the method paintGL() draw my object, which should be a simple cube.

--Main.cpp

    #include <QApplication>
#include <QLabel>
#include <QSurfaceFormat>

#ifndef QT_NO_OPENGL
#include "mainwidget.h"
#endif

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QSurfaceFormat format;
    format.setDepthBufferSize(24);
    QSurfaceFormat::setDefaultFormat(format);

    app.setApplicationName("MainWidget");

#ifndef QT_NO_OPENGL
    MainWidget widget;
    widget.resize(800, 600);
    widget.show();
#else
    QLabel note("OpenGL Support required");
    note.show();
#endif
    return app.exec();
}

--MainWidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QVector2D>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QVector3D>
#include <QOpenGLVertexArrayObject>
#include <QVector>
#include "geometryengine.h"


class GeometryEngine;
class MainWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT
public:
    MainWidget(QWidget *parent = 0);
    ~MainWidget();
protected:
    void initializeGL()Q_DECL_OVERRIDE;
    void resizeGL(int w, int h)Q_DECL_OVERRIDE;
    void paintGL()Q_DECL_OVERRIDE;

    void initShaders();
private:
    QOpenGLShaderProgram program;
    GeometryEngine *geometries;

};

#endif // MAINWIDGET_H

--MainWidget.cpp

#include "mainwidget.h"
#include <iostream>


extern QVector<QVector3D> m_vertices;
extern QVector<QVector2D> m_uvs;
extern QVector<QVector3D> m_normals;

extern QVector<QVector3D> m_indexed_vertices;
extern QVector<QVector2D> m_indexed_uvs;
extern QVector<QVector3D> m_indexed_normals;
extern QVector<unsigned short> m_indices;

MainWidget::MainWidget(QWidget *parent):QOpenGLWidget(parent), geometries(0){

}

MainWidget::~MainWidget(){
    makeCurrent();
    delete geometries;
    doneCurrent();
}

void MainWidget::initializeGL(){
    initializeOpenGLFunctions();
    glClearColor(0, 0, 0.4f, 0);
    glEnable(GL_DEPTH_TEST);
    initShaders();

    geometries = new GeometryEngine;
    for(auto i : m_indexed_vertices){
            std::cout<<i.x()<<" "<<i.y()<<" "<<i.z()<<std::endl;
            //std::cout << i << " " << std::endl;
        }
}

void MainWidget::resizeGL(int w, int h){

}

void MainWidget::paintGL(){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    /*for(auto i : m_indices){
            //std::cout<<i.x()<<" "<<i.y()<<" "<<i.z()<<std::endl;
            std::cout << i << " " << std::endl;
        }*/
    geometries->drawGeometry(&program, m_indices);
}


void MainWidget::initShaders(){
    // Compile vertex shader
    if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex, "vertex.vert"))
        close();

    // Compile fragment shader
    if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment, "fragment.frag"))
        close();

    // Link shader pipeline
    if (!program.link())
        close();

    // Bind shader pipeline for use
    if (!program.bind())
        close();
}

--GeometryEngine.h

#ifndef GEOMETRYENGINE_H
#define GEOMETRYENGINE_H
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include "mainwidget.h"


class GeometryEngine : protected QOpenGLFunctions
{
public:
    GeometryEngine();
    virtual ~GeometryEngine();

    void drawGeometry(QOpenGLShaderProgram *program, QVector<unsigned short> indices);


private:
    void initGeometry(const char *path, QVector<QVector3D> &vert, QVector<QVector2D> &uv, QVector<QVector3D> &norm,QVector<unsigned short> &indices, QVector<QVector3D> &indexed_vertices,
    QVector<QVector2D> &indexed_uvs,
    QVector<QVector3D> &indexed_normals);

    QOpenGLBuffer arrayBuf;
    QOpenGLBuffer indexBuf;
    QOpenGLVertexArrayObject vertexArrayID;

};

#endif // GEOMETRYENGINE_H

--GeometryEngine.cpp

#include "geometryengine.h"
#include "mainwidget.h"
#include "loadobj.h"
#include <QVector>
#include <QVector2D>
#include <QVector3D>
#include <string>
#include <iostream>


QVector<QVector3D> m_vertices;
QVector<QVector2D> m_uvs;
QVector<QVector3D> m_normals;

QVector<QVector3D> m_indexed_vertices;
QVector<QVector2D> m_indexed_uvs;
QVector<QVector3D> m_indexed_normals;
QVector<unsigned short> m_indices;

GeometryEngine::GeometryEngine() : indexBuf(QOpenGLBuffer::IndexBuffer)
{


    initializeOpenGLFunctions();
    vertexArrayID.create();
    vertexArrayID.bind();
    //generate vbos
    arrayBuf.create();
    indexBuf.create();


    initGeometry("cube.obj", m_vertices, m_uvs, m_normals, m_indices, m_indexed_vertices, m_indexed_uvs, m_indexed_normals);

}

GeometryEngine::~GeometryEngine(){
    arrayBuf.destroy();
    indexBuf.destroy();
    vertexArrayID.destroy();
}
void GeometryEngine::initGeometry(const char *path,QVector<QVector3D> &vertices, QVector<QVector2D> &uvs, QVector<QVector3D> &normals, QVector<unsigned short> &indices,  QVector<QVector3D> &indexed_vertices, QVector<QVector2D> &indexed_uvs, QVector<QVector3D> &indexed_normals ){
    bool res = loadObj(path, vertices, uvs, normals);
    vboIndexer(vertices, uvs, normals, indices, indexed_vertices, indexed_uvs, indexed_normals );
    /*for(auto i : indices){
            //std::cout<<i.x()<<" "<<i.y()<<" "<<i.z()<<std::endl;
            std::cout << i << " " << std::endl;
        }*/
    arrayBuf.bind();
    arrayBuf.allocate(&indexed_vertices, indexed_vertices.size() * sizeof(QVector3D));

    indexBuf.bind();
    indexBuf.allocate(&indices, indices.size() * sizeof(unsigned short));

}

void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program, QVector<unsigned short> indices){
    arrayBuf.bind();
    indexBuf.bind();

    int vertexLocation = program->attributeLocation("vertex");
    program->enableAttributeArray(vertexLocation);
    program->setAttributeBuffer(vertexLocation, GL_FLOAT, 0, 3, sizeof(GLfloat));

    //glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_SHORT, 0);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    glDisableVertexAttribArray(0);
}

--vertex.vert

#version 330

layout(location = 0) in vec3 vertex;

void main(){
    gl_Position = vec4(vertex, 1.0);
}

--fragment.frag

#version 330

out vec3 color;
void main(){
    color = vec3(1,0,0);
}

I don't know whether I messed up some of the QOpenGL code or if it's because of the fact that I have stored my vertices in a QVector and not in an array. As a lead I used the cube example from Qt as you can see in the code similarity.


Solution

  • ok problem solved.

    native openGL is able to paint data from Vectors and QopenGLWidget is only able to paint if the data is stored in an array. even if the array contains Qvector3D data.

    correct me if im wrong.. cause this looks a bit fishy to me.