From 806024f4f9ee7fb74f8f595fb103139ca3fc1f30 Mon Sep 17 00:00:00 2001 From: Anakin Date: Sun, 13 Nov 2016 15:46:52 +0100 Subject: [PATCH] faster method for texture handling --- MshViewer/Header/Object.h | 3 +- MshViewer/Source/Object.cpp | 35 ++++++++--- MshViewer/Source/OpenGlController.cpp | 89 +++++++++++++++------------ 3 files changed, 75 insertions(+), 52 deletions(-) diff --git a/MshViewer/Header/Object.h b/MshViewer/Header/Object.h index c4157ea..4eece53 100644 --- a/MshViewer/Header/Object.h +++ b/MshViewer/Header/Object.h @@ -21,7 +21,7 @@ struct ChunkHeader { }; struct Segment { - std::string texture = ""; + std::uint32_t textureIndex = 0; float* vertex = nullptr; float* uv = nullptr; std::uint32_t* mesh = nullptr; @@ -65,5 +65,6 @@ private: public: std::vector getModels() const; + std::vector getTextureList() const; }; diff --git a/MshViewer/Source/Object.cpp b/MshViewer/Source/Object.cpp index 330d007..85336eb 100644 --- a/MshViewer/Source/Object.cpp +++ b/MshViewer/Source/Object.cpp @@ -393,15 +393,7 @@ void Object::analyseSegmChunks(Modl * dataDestination, std::list& if (!strcmp("MATI", (*it)->name)) { fsMesh.seekg((*it)->position); - std::uint32_t tempIndex; - fsMesh.read(reinterpret_cast(&tempIndex), sizeof(tempIndex)); - if (vTextures.size() <= tempIndex) - { - std::cout << "warning texture index <" << tempIndex << "> unknown" << std::endl; - tempData->texture = ""; - continue; - } - tempData->texture = vTextures[tempIndex]; + fsMesh.read(reinterpret_cast(&tempData->textureIndex), sizeof(tempData->textureIndex)); continue; } @@ -471,7 +463,25 @@ void Object::analyseClthChunks(Modl * dataDestination, std::list& char* buffer = new char[(*it)->size]; *buffer = { 0 }; fsMesh.read(buffer, (*it)->size); - tempData->texture = buffer; + + bool tempFound(false); + + for (unsigned int index = 0; index < vTextures.size(); index++) + { + if (!strcmp(buffer, vTextures[index].c_str())) + { + tempData->textureIndex = index; + tempFound = true; + break; + } + } + + if (!tempFound) + { + vTextures.push_back(std::string(buffer)); + tempData->textureIndex = vTextures.size() - 1; + } + delete buffer; continue; } @@ -540,6 +550,11 @@ std::vector Object::getModels() const return vModls; } +std::vector Object::getTextureList() const +{ + return vTextures; +} + ///////////////////////////////////////////////////////////////////////// // public functions diff --git a/MshViewer/Source/OpenGlController.cpp b/MshViewer/Source/OpenGlController.cpp index 7cc1fef..9750e26 100644 --- a/MshViewer/Source/OpenGlController.cpp +++ b/MshViewer/Source/OpenGlController.cpp @@ -302,7 +302,6 @@ void OpenGLController::updateScene() glUniform1i(gluiSamplerID, 0); int instanceOffset(0); - int textureIndex(0); for (unsigned int modelIndex = 0; modelIndex < vModels.size(); modelIndex++) { @@ -316,16 +315,18 @@ void OpenGLController::updateScene() for (auto& segIt : vModels[modelIndex]->segmLst) { // give texture to the shader + std::uint32_t tempTexIndex = segIt->textureIndex >= vTextures.size() ? vTextures.size() - 1 : segIt->textureIndex; + glTexImage2D( GL_TEXTURE_2D, 0, - vTextures[textureIndex]->alpha ? GL_RGBA : GL_RGB, - vTextures[textureIndex]->width, - vTextures[textureIndex]->height, + vTextures[tempTexIndex]->alpha ? GL_RGBA : GL_RGB, + vTextures[tempTexIndex]->width, + vTextures[tempTexIndex]->height, 0, - vTextures[textureIndex]->alpha ? GL_BGRA : GL_BGR, + vTextures[tempTexIndex]->alpha ? GL_BGRA : GL_BGR, GL_UNSIGNED_BYTE, - vTextures[textureIndex]->data->data() + vTextures[tempTexIndex]->data->data() ); glGenerateMipmap(GL_TEXTURE_2D); @@ -335,9 +336,8 @@ void OpenGLController::updateScene() glDrawArrays(GL_TRIANGLES, instanceOffset, segIt->meshSize); - // recalulate counter + // increase the offset instanceOffset += segIt->meshSize; - textureIndex++; } } @@ -350,11 +350,14 @@ void OpenGLController::loadMsh(const char * path) // clean up old stuff first deleteVectors(); + std::vector tempTexList; + // get all models try { Object obj(path); vModels = obj.getModels(); + tempTexList = obj.getTextureList(); } catch (std::invalid_argument e) { @@ -407,42 +410,46 @@ void OpenGLController::loadMsh(const char * path) glBindBuffer(GL_ARRAY_BUFFER, 0); - // get textures - for (auto& modIt : vModels) + // get textures path + std::string tempPath = path; + + while (tempPath.back() != '/' && tempPath.back() != '\\') + tempPath.pop_back(); + + // load all textures; + for (auto& texIt : tempTexList) { - // we don't need textures from null, bones, shadowMesh and hidden things, since they are not displayed - if (modIt->type == null || modIt->type == bone || modIt->type == shadowMesh || modIt->renderFlags == 1) - continue; - for (auto& segIt : modIt->segmLst) + textureData* tempData = new textureData; + + try { - textureData* tempData = new textureData; - try - { - if (segIt->texture == "") - throw std::invalid_argument("no texture name"); + TextureTGA tempTex(std::string(tempPath + texIt).c_str()); - std::string tempPath = path; - - while (tempPath.back() != '/' && tempPath.back() != '\\') - tempPath.pop_back(); - - TextureTGA tempTex(std::string(tempPath + segIt->texture).c_str()); - - tempData->alpha = tempTex.hasAlpha(); - tempData->width = tempTex.getWidth(); - tempData->height = tempTex.getHeight(); - tempData->data = new std::vector(tempTex.getData()); - } - catch (std::invalid_argument e) - { - GLubyte solidColor[4] = { 0, 0, 255, 255 }; - tempData->alpha = true; - tempData->width = 1; - tempData->height = 1; - tempData->data = new std::vector({ 0, 0, 255, 255 }); - } - - vTextures.push_back(tempData); + tempData->alpha = tempTex.hasAlpha(); + tempData->width = tempTex.getWidth(); + tempData->height = tempTex.getHeight(); + tempData->data = new std::vector(tempTex.getData()); } + catch (std::invalid_argument e) + { + GLubyte solidColor[4] = { 0, 0, 255, 255 }; + tempData->alpha = true; + tempData->width = 1; + tempData->height = 1; + tempData->data = new std::vector({ 0, 0, 255, 255 }); + } + + vTextures.push_back(tempData); } + + // add a solid default color at the end (maybe there is an invalid index later) + textureData* tempData = new textureData; + GLubyte solidColor[4] = { 0, 0, 255, 255 }; + tempData->alpha = true; + tempData->width = 1; + tempData->height = 1; + tempData->data = new std::vector({ 0, 0, 255, 255 }); + vTextures.push_back(tempData); + + tempTexList.clear(); }