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.
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.