#include "..\Header\OpenGlViewer.h" #include ///////////////////////////////////////////////////////////////////////// // Defined values //opengl #define DEFAULT_MAJOR_VERSION 4 #define DEFAULT_MINOR_VERSION 5 #define DEAFAULT_BACKGROUND 0.5000f, 0.8000f, 1.0000f, 0.0000f //piplines #define VERTEX_INDEX_XYZ 0 #define VERTEX_INDEX_UV 1 #define VERTEX_COMPONENTS_XYZ 3 #define VERTEX_COMPONENTS_UV 2 #define VERTEX_SIZE_XYZ (sizeof(float) * VERTEX_COMPONENTS_XYZ) #define VERTEX_SIZE_UV (sizeof(float) * VERTEX_COMPONENTS_UV) #define VERTEX_OFFSET_XYZ 0 #define VERTEX_OFFSET_UV (VERTEX_SIZE_XYZ) ///////////////////////////////////////////////////////////////////////// // public constructor/destructor OpenGlViewer::OpenGlViewer(QWidget *parent) : QOpenGLWidget(parent) { QSurfaceFormat format; format.setRenderableType(QSurfaceFormat::OpenGL); format.setSamples(4); format.setProfile(QSurfaceFormat::CompatibilityProfile); format.setVersion(DEFAULT_MAJOR_VERSION, DEFAULT_MINOR_VERSION); setFormat(format); //TODO: mouse, move, key, drag/drop, scroll, resize } OpenGlViewer::~OpenGlViewer() { m_oglTexture->destroy(); m_vertexArray.destroy(); m_vertexBuffer.destroy(); delete m_program; deleteData(); } ///////////////////////////////////////////////////////////////////////// // private functions void OpenGlViewer::initializeGL() { initializeOpenGLFunctions(); printContextInformation(); // set Background glClearColor(DEAFAULT_BACKGROUND); //TODO: z-order? // draw vertices only from one side glEnable(GL_CULL_FACE); // Create texture m_oglTexture = new QOpenGLTexture(QOpenGLTexture::Target2D); m_oglTexture->setWrapMode(QOpenGLTexture::Repeat); m_oglTexture->setMagnificationFilter(QOpenGLTexture::Linear); m_oglTexture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear); // Create Shader m_program = new QOpenGLShaderProgram(); m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/simple.vert"); m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/simple.frag"); m_program->link(); m_program->bind(); // get Uniform location //TODO: faster to give everything to shader and calculate there? m_uniformMVP = m_program->uniformLocation("MVP"); // Create Vertex Buffer m_vertexBuffer.create(); m_vertexBuffer.bind(); m_vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); // Create Vertex Array Object m_vertexArray.create(); m_vertexArray.bind(); m_program->enableAttributeArray(0); m_program->enableAttributeArray(1); m_program->setAttributeBuffer(VERTEX_INDEX_XYZ, GL_FLOAT, VERTEX_OFFSET_XYZ, VERTEX_COMPONENTS_XYZ, sizeof(Vertex)); m_program->setAttributeBuffer(VERTEX_INDEX_UV, GL_FLOAT, VERTEX_OFFSET_UV, VERTEX_COMPONENTS_UV, sizeof(Vertex)); // unbind everything m_vertexArray.release(); m_vertexBuffer.release(); m_program->release(); } void OpenGlViewer::resizeGL(int w, int h) { //TODO: change perspective } void OpenGlViewer::paintGL() { //TODO: paint here glClear(GL_COLOR_BUFFER_BIT); m_program->bind(); m_vertexArray.bind(); m_oglTexture->bind(); if (m_vModels != nullptr) { int tmp_offset(0); for (unsigned int modelIndex = 0; modelIndex < m_vModels->size(); modelIndex++) { // skip null, bones, shadowMesh, hidden things if (m_vModels->at(modelIndex)->type == null || m_vModels->at(modelIndex)->type == bone || m_vModels->at(modelIndex)->type == shadowMesh || m_vModels->at(modelIndex)->renderFlags == 1) continue; for (auto& segmentIterator : m_vModels->at(modelIndex)->segmList) { // set the texture std::uint32_t tmp_textureIndex = segmentIterator->textureIndex >= m_vTextures.size() ? m_vTextures.size() - 1 : segmentIterator->textureIndex; m_oglTexture->setData(*m_vTextures.at(tmp_textureIndex)); // give the MVP to the shader m_program->setUniformValue(m_uniformMVP, getMVPMatrix(modelIndex)); // calculate the number of vertex unsigned int tmp_vertexCount(0); for (auto&it : segmentIterator->polyIndices) tmp_vertexCount += (it.size() - 2) * 3; glDrawArrays(GL_TRIANGLES, tmp_offset, tmp_vertexCount); // increase the offset tmp_offset += tmp_vertexCount; } } } //glDrawArrays(GL_TRIANGLES, 0, sizeof(sg_vertexes) / sizeof(sg_vertexes[0])); m_oglTexture->release(); m_vertexArray.release(); m_program->release(); } void OpenGlViewer::printContextInformation() { QString glType; QString glVersion; QString glProfile; glType = (context()->isOpenGLES()) ? "OpenGL ES" : "OpenGL"; glVersion = reinterpret_cast(glGetString(GL_VERSION)); #define CASE(c) case QSurfaceFormat::c: glProfile = #c; break switch (format().profile()) { CASE(NoProfile); CASE(CoreProfile); CASE(CompatibilityProfile); } #undef CASE std::cout << glType.toStdString() << " - " << glVersion.toStdString() << " (" << glProfile.toStdString() << ")"; } QMatrix4x4 OpenGlViewer::getMVPMatrix(unsigned int index) const { return QMatrix4x4(); } void OpenGlViewer::deleteData() { if (m_vModels != NULL) { while (!m_vModels->empty()) { // remove the last Model Model* modelVectorElement = m_vModels->back(); m_vModels->pop_back(); while (!modelVectorElement->segmList.empty()) { // remove the last Segment Segment* segmentVectorElement = modelVectorElement->segmList.back(); modelVectorElement->segmList.pop_back(); // delete data from Segment delete[] segmentVectorElement->uv; delete[] segmentVectorElement->vertex; while (!segmentVectorElement->polyIndices.empty()) { // clear the poly vector and remove it from the list segmentVectorElement->polyIndices.back().clear(); segmentVectorElement->polyIndices.pop_back(); } // delete the actual Segment delete segmentVectorElement; } // delete the actual Model delete modelVectorElement; } // delete the Model's Vector delete m_vModels; } while (!m_vTextures.empty()) { // remove the last texture QImage* cursor = m_vTextures.back(); m_vTextures.pop_back(); //delete image delete cursor; //delete the texture delete cursor; } } ///////////////////////////////////////////////////////////////////////// // public functions void OpenGlViewer::setData(std::vector* models, std::vector textures) { m_vModels = models; m_vTextures = textures; }