From b6ef34f9884b5591ca5a0397b2b28aae1d015aa0 Mon Sep 17 00:00:00 2001 From: Anakin Date: Wed, 14 Dec 2016 17:20:20 +0100 Subject: [PATCH] still trying to fix the problem --- MeshViewerQt/Header/OpenGlViewer.h | 18 ++-- MeshViewerQt/Header/Texture.h | 22 ++++ MeshViewerQt/Resources/TextureShader.frag | 4 +- MeshViewerQt/Resources/TextureShader.vert | 2 +- MeshViewerQt/Source/MainWindow.cpp | 101 +++++++++--------- MeshViewerQt/Source/OpenGlViewer.cpp | 73 +++++++------ MeshViewerQt/Source/Texture.cpp | 119 ++++++++++++++++++++++ 7 files changed, 255 insertions(+), 84 deletions(-) create mode 100644 MeshViewerQt/Header/Texture.h create mode 100644 MeshViewerQt/Source/Texture.cpp diff --git a/MeshViewerQt/Header/OpenGlViewer.h b/MeshViewerQt/Header/OpenGlViewer.h index fe260b5..8f91453 100644 --- a/MeshViewerQt/Header/OpenGlViewer.h +++ b/MeshViewerQt/Header/OpenGlViewer.h @@ -4,8 +4,7 @@ #include #include #include -#include -#include +#include "..\Header\Texture.h" #include "..\Header\FileInterface.h" struct Vertex { @@ -13,6 +12,13 @@ struct Vertex { GLfloat uv[2]; }; +struct TextureData { + bool alpha; + std::uint32_t width; + std::uint32_t height; + std::vector* data; +}; + class OpenGlViewer : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT @@ -24,14 +30,14 @@ public: private: // OpenGL ====================================== int m_uniformMVP; - QOpenGLTexture* m_oglTexture; - QOpenGLBuffer m_vertexBuffer; + GLuint m_oglTexture; + GLuint m_vertexBuffer; QOpenGLVertexArrayObject m_vertexArray; QOpenGLShaderProgram* m_program = nullptr; // Data ======================================== std::vector* m_vModels = nullptr; - std::vector* m_vTextures = nullptr; + std::vector* m_vTextures = nullptr; BoundingBox m_sceneBoundings; // Transformation ============================== @@ -57,5 +63,5 @@ private: void deleteData(); public: - void setData(std::vector* models, std::vector* textures, BoundingBox bbox); + void setData(std::vector* models, std::vector* textures, BoundingBox bbox); }; diff --git a/MeshViewerQt/Header/Texture.h b/MeshViewerQt/Header/Texture.h new file mode 100644 index 0000000..cd56653 --- /dev/null +++ b/MeshViewerQt/Header/Texture.h @@ -0,0 +1,22 @@ +#pragma once +#include + + +class TextureTGA +{ +public: + TextureTGA(const char* filePath); + ~TextureTGA(); + +private: + std::vector* vui8Pixels; + std::uint32_t ui32BpP; + std::uint32_t ui32Width; + std::uint32_t ui32Height; + +public: + std::vector* getData() const; + bool hasAlpha() const; + std::uint32_t getWidth() const; + std::uint32_t getHeight() const; +}; diff --git a/MeshViewerQt/Resources/TextureShader.frag b/MeshViewerQt/Resources/TextureShader.frag index a3e3320..3c9924a 100644 --- a/MeshViewerQt/Resources/TextureShader.frag +++ b/MeshViewerQt/Resources/TextureShader.frag @@ -1,4 +1,4 @@ -#version 450 +#version 330 // Input in vec2 UV; @@ -8,5 +8,5 @@ out vec4 color; void main() { - color = texture(textureSampler, UV).rgb; + color = {255,0,0};//texture(textureSampler, UV).rgb; } \ No newline at end of file diff --git a/MeshViewerQt/Resources/TextureShader.vert b/MeshViewerQt/Resources/TextureShader.vert index f1c181e..b8865eb 100644 --- a/MeshViewerQt/Resources/TextureShader.vert +++ b/MeshViewerQt/Resources/TextureShader.vert @@ -1,4 +1,4 @@ -#version 450 +#version 330 // Input vertex data, different for all executions of this shader layout(location = 0) in vec3 vertexPosition; diff --git a/MeshViewerQt/Source/MainWindow.cpp b/MeshViewerQt/Source/MainWindow.cpp index 2c9b205..2148647 100644 --- a/MeshViewerQt/Source/MainWindow.cpp +++ b/MeshViewerQt/Source/MainWindow.cpp @@ -44,58 +44,22 @@ void MainWindow::setupWindow() void MainWindow::import(const char * path) { + // variables + std::vector* tmp_models = nullptr; + std::vector* tmp_textures = new std::vector; + std::vector tmp_texNames; + BoundingBox tmp_bbox; + + // model file try { MshFile file(path); - - // Models - std::vector* tmp_models = file.getModels(); - - // Textures - std::vector tmp_texNames = file.getTextureNames(); - std::vector* tmp_textures = new std::vector; - - std::string tmp_path = path; - - while (tmp_path.back() != '/' && tmp_path.back() != '\\') - tmp_path.pop_back(); - - for (auto& it : tmp_texNames) - { - QImage* tmp_image = new QImage; - - std::string test = tmp_path + it; - QString test2 = "D:\\workspaces\\Visual Studio 2015\\Projects\\OpenGL\\Release\\Msh\\texture32R.tga"; - - if (tmp_image->load(test2)) - tmp_textures->push_back(tmp_image); - else - { - delete tmp_image; - tmp_image = new QImage(1, 1, QImage::Format_RGB32); - tmp_image->fill(Qt::red); - tmp_textures->push_back(tmp_image); - } - } - - // add a solid default color at the end (maybe there is an invalid index later) - QImage* tmp_image = new QImage(1, 1, QImage::Format_RGB16); - tmp_image->fill(Qt::red); - tmp_textures->push_back(tmp_image); - - tmp_texNames.clear(); - - // Bounding Box - BoundingBox tmp_bbox = file.getBoundingBox(); - - OpenGlViewer* tmp_viewer = dynamic_cast(centralWidget()); - - tmp_viewer->setData(tmp_models, tmp_textures, tmp_bbox); - + tmp_models = file.getModels(); + tmp_texNames = file.getTextureNames(); + tmp_bbox = file.getBoundingBox(); } catch (std::invalid_argument e) { - //TODO: QMessageBox msg(this); msg.addButton(QMessageBox::Ok); msg.setText(QString::fromStdString(e.what())); @@ -103,7 +67,52 @@ void MainWindow::import(const char * path) msg.setWindowTitle("Open File Error"); msg.exec(); + return; } + + // parth to texture + std::string tmp_path = path; + while (tmp_path.back() != '/' && tmp_path.back() != '\\') + tmp_path.pop_back(); + + // load all textures + for (auto& texIt : tmp_texNames) + { + TextureData* new_data = new TextureData; + try + { + TextureTGA tmp_texFile(std::string(tmp_path + texIt).c_str()); + + new_data->alpha = tmp_texFile.hasAlpha(); + new_data->width = tmp_texFile.getWidth(); + new_data->height = tmp_texFile.getHeight(); + new_data->data = tmp_texFile.getData(); + } + catch (std::invalid_argument e) + { + new_data->alpha = true; + new_data->width = 1; + new_data->height = 1; + new_data->data = new std::vector({ 0, 0, 255, 255 }); + } + + tmp_textures->push_back(new_data); + } + + // add a solid default color at the end (maybe there is an invalid index later) + TextureData* new_data = new TextureData; + new_data->alpha = true; + new_data->width = 1; + new_data->height = 1; + new_data->data = new std::vector({ 0, 0, 255, 255 }); + tmp_textures->push_back(new_data); + + // clean up texture name list + tmp_texNames.clear(); + + // give the data to the viewer + OpenGlViewer* tmp_viewer = dynamic_cast(centralWidget()); + tmp_viewer->setData(tmp_models, tmp_textures, tmp_bbox); } diff --git a/MeshViewerQt/Source/OpenGlViewer.cpp b/MeshViewerQt/Source/OpenGlViewer.cpp index 2a5202c..ba14af0 100644 --- a/MeshViewerQt/Source/OpenGlViewer.cpp +++ b/MeshViewerQt/Source/OpenGlViewer.cpp @@ -35,7 +35,7 @@ OpenGlViewer::OpenGlViewer(QWidget *parent) QSurfaceFormat format; format.setRenderableType(QSurfaceFormat::OpenGL); format.setSamples(4); - format.setProfile(QSurfaceFormat::CompatibilityProfile); + format.setProfile(QSurfaceFormat::CoreProfile); format.setVersion(DEFAULT_MAJOR_VERSION, DEFAULT_MINOR_VERSION); setFormat(format); @@ -44,9 +44,9 @@ OpenGlViewer::OpenGlViewer(QWidget *parent) OpenGlViewer::~OpenGlViewer() { - m_oglTexture->destroy(); + glDeleteTextures(1, &m_oglTexture); + glDeleteBuffers(1, &m_vertexBuffer); m_vertexArray.destroy(); - m_vertexBuffer.destroy(); delete m_program; deleteData(); @@ -70,10 +70,12 @@ void OpenGlViewer::initializeGL() 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); + glGenTextures(1, &m_oglTexture); + glBindTexture(GL_TEXTURE_2D, m_oglTexture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Create Shader m_program = new QOpenGLShaderProgram(); @@ -87,9 +89,8 @@ void OpenGlViewer::initializeGL() m_uniformMVP = m_program->uniformLocation("MVP"); // Create Vertex Buffer - m_vertexBuffer.create(); - m_vertexBuffer.bind(); - m_vertexBuffer.setUsagePattern(QOpenGLBuffer::StaticDraw); + glGenBuffers(1, &m_vertexBuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer); // Create Vertex Array Object m_vertexArray.create(); @@ -101,7 +102,7 @@ void OpenGlViewer::initializeGL() // unbind everything m_vertexArray.release(); - m_vertexBuffer.release(); + glBindBuffer(GL_ARRAY_BUFFER, 0); m_program->release(); } @@ -112,8 +113,11 @@ void OpenGlViewer::paintGL() glClear(GL_COLOR_BUFFER_BIT); m_program->bind(); - m_vertexArray.bind(); - m_oglTexture->bind(); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, m_oglTexture); + m_program->setUniformValue("textureSampler", 0); + if (m_vModels != nullptr) { @@ -133,15 +137,19 @@ void OpenGlViewer::paintGL() // set the texture std::uint32_t tmp_textureIndex = segmentIterator->textureIndex >= m_vTextures->size() ? m_vTextures->size() - 1 : segmentIterator->textureIndex; - if (m_oglTexture->isCreated()) - { - m_oglTexture->destroy(); - m_oglTexture->create(); - m_oglTexture->setSize(m_vTextures->at(tmp_textureIndex)->width(), m_vTextures->at(tmp_textureIndex)->height()); - m_oglTexture->setData(*m_vTextures->at(tmp_textureIndex)); - } + glTexImage2D( + GL_TEXTURE_2D, + 0, + m_vTextures->at(tmp_textureIndex)->alpha ? GL_RGBA : GL_RGB, + m_vTextures->at(tmp_textureIndex)->width, + m_vTextures->at(tmp_textureIndex)->height, + 0, + m_vTextures->at(tmp_textureIndex)->alpha ? GL_BGRA : GL_BGR, + GL_UNSIGNED_BYTE, + m_vTextures->at(tmp_textureIndex)->data->data() + ); - + glGenerateMipmap(GL_TEXTURE_2D); // give the MVP to the shader m_program->setUniformValue(m_uniformMVP, getMVPMatrix(modelIndex)); @@ -159,9 +167,9 @@ void OpenGlViewer::paintGL() } } - m_oglTexture->release(); - m_vertexArray.release(); m_program->release(); + + this->frameSwapped(); } void OpenGlViewer::printContextInformation() @@ -270,9 +278,12 @@ void OpenGlViewer::deleteData() while (!m_vTextures->empty()) { // remove the last texture - QImage* cursor = m_vTextures->back(); + TextureData* cursor = m_vTextures->back(); m_vTextures->pop_back(); + cursor->data->clear(); + delete cursor->data; + //delete image delete cursor; } @@ -285,7 +296,7 @@ void OpenGlViewer::deleteData() ///////////////////////////////////////////////////////////////////////// // public functions -void OpenGlViewer::setData(std::vector* models, std::vector* textures, BoundingBox bbox) +void OpenGlViewer::setData(std::vector* models, std::vector* textures, BoundingBox bbox) { // new Data, so clean up the old things deleteData(); @@ -348,10 +359,14 @@ void OpenGlViewer::setData(std::vector* models, std::vector* te } } - - m_vertexBuffer.bind(); - m_vertexBuffer.allocate(tmp_bufferData.data(), sizeof(Vertex) * tmp_bufferData.size()); - m_vertexBuffer.release(); + glBindBuffer(GL_ARRAY_BUFFER, m_vertexBuffer); + glBufferData( + GL_ARRAY_BUFFER, + sizeof(Vertex) * tmp_bufferData.size(), + tmp_bufferData.data(), + GL_STATIC_DRAW + ); + glBindBuffer(GL_ARRAY_BUFFER, 0); tmp_bufferData.clear(); } diff --git a/MeshViewerQt/Source/Texture.cpp b/MeshViewerQt/Source/Texture.cpp new file mode 100644 index 0000000..9ed6ff3 --- /dev/null +++ b/MeshViewerQt/Source/Texture.cpp @@ -0,0 +1,119 @@ +#include "Texture.h" +#include + +TextureTGA::TextureTGA(const char * filePath) +{ + // open the file + std::fstream fsPicture(filePath, std::ios::in | std::ios::binary); + + if (!fsPicture.is_open()) + throw std::invalid_argument(std::string("file not found: ") += filePath); + + // read in the header + std::uint8_t ui8x18Header[19] = { 0 }; + fsPicture.read(reinterpret_cast(&ui8x18Header), sizeof(ui8x18Header)-1); + + //get variables + vui8Pixels = new std::vector; + bool bCompressed; + std::uint32_t ui32IDLength; + std::uint32_t ui32PicType; + std::uint32_t ui32PaletteLength; + std::uint32_t ui32Size; + + // extract all information from header + ui32IDLength = ui8x18Header[0]; + ui32PicType = ui8x18Header[2]; + ui32PaletteLength = ui8x18Header[6] * 0x100 + ui8x18Header[5]; + ui32Width = ui8x18Header[13] * 0x100 + ui8x18Header[12]; + ui32Height = ui8x18Header[15] * 0x100 + ui8x18Header[14]; + ui32BpP = ui8x18Header[16]; + + // calculate some more information + ui32Size = ui32Width * ui32Height * ui32BpP/8; + bCompressed = ui32PicType == 9 || ui32PicType == 10; + vui8Pixels->resize(ui32Size); + + // jump to the data block + fsPicture.seekg(ui32IDLength + ui32PaletteLength, std::ios_base::cur); + + // If not compressed 24 or 32 bit + if (ui32PicType == 2 && (ui32BpP == 24 || ui32BpP == 32)) + { + fsPicture.read(reinterpret_cast(vui8Pixels->data()), ui32Size); + } + // else if compressed 24 or 32 bit + else if (ui32PicType == 10 && (ui32BpP == 24 || ui32BpP == 32)) // compressed + { + std::uint8_t tempChunkHeader; + std::uint8_t tempData[5]; + unsigned int tempByteIndex = 0; + + do { + fsPicture.read(reinterpret_cast(&tempChunkHeader), sizeof(tempChunkHeader)); + + if (tempChunkHeader >> 7) // repeat count + { + // just use the first 7 bits + tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1); + + fsPicture.read(reinterpret_cast(&tempData), ui32BpP/8); + + for (int i = 0; i <= tempChunkHeader; i++) + { + vui8Pixels->at(tempByteIndex++) = tempData[0]; + vui8Pixels->at(tempByteIndex++) = tempData[1]; + vui8Pixels->at(tempByteIndex++) = tempData[2]; + if(ui32BpP == 32) vui8Pixels->at(tempByteIndex++) = tempData[3]; + } + } + else // data count + { + // just use the first 7 bits + tempChunkHeader = (uint8_t(tempChunkHeader << 1) >> 1); + + for (int i = 0; i <= tempChunkHeader; i++) + { + fsPicture.read(reinterpret_cast(&tempData), ui32BpP/8); + + vui8Pixels->at(tempByteIndex++) = tempData[0]; + vui8Pixels->at(tempByteIndex++) = tempData[1]; + vui8Pixels->at(tempByteIndex++) = tempData[2]; + if (ui32BpP == 32) vui8Pixels->at(tempByteIndex++) = tempData[3]; + } + } + } while (tempByteIndex < ui32Size); + } + // not useable format + else + { + fsPicture.close(); + throw std::invalid_argument("Invaild File Format! Required 24 or 31 Bit Image."); + } + + fsPicture.close(); +} + +TextureTGA::~TextureTGA() +{ +} + +std::vector* TextureTGA::getData() const +{ + return vui8Pixels; +} + +bool TextureTGA::hasAlpha() const +{ + return ui32BpP == 32; +} + +std::uint32_t TextureTGA::getWidth() const +{ + return ui32Width; +} + +std::uint32_t TextureTGA::getHeight() const +{ + return ui32Height; +}