diff --git a/QtMeshViewer/Header/FileInterface.h b/QtMeshViewer/Header/FileInterface.h index bcd66f1..0a611e3 100644 --- a/QtMeshViewer/Header/FileInterface.h +++ b/QtMeshViewer/Header/FileInterface.h @@ -3,11 +3,13 @@ #include #include #include -#include #include #include #include +#include #include +#include +#include #include <..\Header\MainWindow.h> @@ -38,6 +40,12 @@ struct Model { std::vector segmList; }; +struct Material { + QString name; + QOpenGLTexture* texture = Q_NULLPTR; + bool transparent = false; +}; + class FileInterface : public QObject { Q_OBJECT @@ -46,7 +54,7 @@ public: explicit FileInterface(QString path, QObject *parent) : QObject(parent) , m_models(new QVector) - , m_textureNames(new QStringList) + , m_materials(new QVector) { //open file m_file.open(path.toStdString().c_str(), std::ios::in | std::ios::binary); @@ -58,6 +66,7 @@ public: if(tmp != NULL) connect(this, SIGNAL(sendMessage(QString, int)), tmp, SLOT(printMessage(QString, int))); + m_filepath = path.left(path.lastIndexOf(QRegExp("/|\\\\"))); }; @@ -67,9 +76,6 @@ public: m_file.close(); //clean up - m_textureNames->clear(); - delete m_textureNames; - for (Model* modelIt : *m_models) { for (Segment* segIt : modelIt->segmList) @@ -89,16 +95,40 @@ public: protected: QVector* m_models; std::fstream m_file; - QStringList* m_textureNames; + QVector* m_materials; BoundingBox m_sceneBbox; + QString m_filepath; virtual void import() = 0; public: virtual QVector* getModels() const { return m_models; }; - virtual QStringList* getTextureNames() const { return m_textureNames; }; + virtual QVector* getMaterials() const { return m_materials; }; virtual BoundingBox getBoundingBox() const { return m_sceneBbox; }; + static Material getDefaultMaterial() { + Material defMaterial; + + QImage img(1, 1, QImage::Format_RGB32); + img.fill(Qt::red); + + QOpenGLTexture* new_texture = new QOpenGLTexture(img.mirrored()); + + // Set nearest filtering mode for texture minification + new_texture->setMinificationFilter(QOpenGLTexture::Nearest); + + // Set bilinear filtering mode for texture magnification + new_texture->setMagnificationFilter(QOpenGLTexture::Linear); + + // Wrap texture coordinates by repeating + // f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2) + new_texture->setWrapMode(QOpenGLTexture::Repeat); + + defMaterial.texture = new_texture; + + return defMaterial; + }; + signals: void sendMessage(QString msg, int severity); }; \ No newline at end of file diff --git a/QtMeshViewer/Header/GeometryEngine.h b/QtMeshViewer/Header/GeometryEngine.h index c96147c..f52fd63 100644 --- a/QtMeshViewer/Header/GeometryEngine.h +++ b/QtMeshViewer/Header/GeometryEngine.h @@ -25,11 +25,10 @@ public: private: QOpenGLBuffer m_arrayBuf; QOpenGLBuffer m_indexBuf; - QVector m_textures; + QVector* m_materials = Q_NULLPTR; QVector m_drawList; BoundingBox m_boundings; - void loadTexture(QString filePath, QString fileName); void clearData(); public slots: @@ -40,6 +39,6 @@ signals: void requestResetView(); void sendMessage(QString message, int severity); void requestUpdate(); - void sendFileInfo(QString name, QStringList textures, int vertices, int triangle); + void sendFileInfo(QString name, QVector* materials, int vertices, int triangle); }; diff --git a/QtMeshViewer/Header/MainWindow.h b/QtMeshViewer/Header/MainWindow.h index 94c74e0..7b8e0ad 100644 --- a/QtMeshViewer/Header/MainWindow.h +++ b/QtMeshViewer/Header/MainWindow.h @@ -5,6 +5,8 @@ #include #include "ui_MainWindow.h" +struct Material; + class MainWindow : public QMainWindow { Q_OBJECT @@ -28,7 +30,7 @@ private: public slots: void printMessage(QString message, int severity); - void setFileInfo(QString name, QStringList textures, int vertices, int triangle); + void setFileInfo(QString name, QVector* materials, int vertices, int triangle); signals: void loadFile(QString); diff --git a/QtMeshViewer/Header/MshFile.h b/QtMeshViewer/Header/MshFile.h index 79a2bb6..f5b017a 100644 --- a/QtMeshViewer/Header/MshFile.h +++ b/QtMeshViewer/Header/MshFile.h @@ -43,6 +43,8 @@ private: void readVertex(Segment* dataDestination, std::streampos position); void readUV(Segment* dataDestination, std::streampos position); + void loadTexture(QOpenGLTexture* destination, QString filepath); + QMatrix4x4 getParentMatrix(std::string parent) const; QQuaternion getParentRotation(std::string parent) const; }; \ No newline at end of file diff --git a/QtMeshViewer/Source/GeometryEngine.cpp b/QtMeshViewer/Source/GeometryEngine.cpp index c65e928..cb398d6 100644 --- a/QtMeshViewer/Source/GeometryEngine.cpp +++ b/QtMeshViewer/Source/GeometryEngine.cpp @@ -2,7 +2,6 @@ #include "..\Header\MshFile.h" #include "..\Header\OglViewerWidget.h" #include "..\Header\MainWindow.h" -#include "..\Header\tga.h" #include #include @@ -26,39 +25,6 @@ GeometryEngine::~GeometryEngine() ///////////////////////////////////////////////////////////////////////// // private functions -void GeometryEngine::loadTexture(QString filePath, QString fileName) -{ - bool loadSuccess(false); - QImage img; - - if (fileName.isEmpty()) - { - loadSuccess = true; - img = QImage(1, 1, QImage::Format_RGB32); - img.fill(Qt::red); - } - else - img = loadTga(filePath + "/" + fileName, loadSuccess); - - if (!loadSuccess) - emit sendMessage("WARNING: texture not found or corrupted: " + QString(fileName), 1); - - // Load image to OglTexture - QOpenGLTexture* new_texture = new QOpenGLTexture(img.mirrored()); - - // Set nearest filtering mode for texture minification - new_texture->setMinificationFilter(QOpenGLTexture::Nearest); - - // Set bilinear filtering mode for texture magnification - new_texture->setMagnificationFilter(QOpenGLTexture::Linear); - - // Wrap texture coordinates by repeating - // f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2) - new_texture->setWrapMode(QOpenGLTexture::Repeat); - - m_textures.push_back(new_texture); -} - void GeometryEngine::clearData() { if (m_arrayBuf.isCreated()) @@ -66,9 +32,13 @@ void GeometryEngine::clearData() if (m_indexBuf.isCreated()) m_indexBuf.destroy(); - for (auto it : m_textures) - delete it; - m_textures.clear(); + if (m_materials != Q_NULLPTR) + { + for (auto it : *m_materials) + delete it.texture; + m_materials->clear(); + delete m_materials; + } m_drawList.clear(); } @@ -90,7 +60,6 @@ void GeometryEngine::loadFile(QString filePath) try { QVector* models; - QStringList* textureNames; QVector vertexData; QVector indexData; @@ -98,10 +67,11 @@ void GeometryEngine::loadFile(QString filePath) MshFile file(filePath, this); models = file.getModels(); - textureNames = file.getTextureNames(); + m_materials = file.getMaterials(); m_boundings = file.getBoundingBox(); // collect data + //TODO: sort transparent faces unsigned int indexOffset(0); unsigned int vertexOffset(0); for (auto& modelIterator : *models) @@ -140,18 +110,12 @@ void GeometryEngine::loadFile(QString filePath) m_indexBuf.bind(); m_indexBuf.allocate(indexData.data(), indexData.size() * sizeof(GLuint)); - emit sendMessage("loading textures..", 0); - - // load the textures - int split = filePath.lastIndexOf(QRegExp("/|\\\\")); - for (auto& it : *textureNames) - loadTexture(filePath.left(split), it); - - loadTexture("", ""); + //pushback a default material + m_materials->push_back(FileInterface::getDefaultMaterial()); emit requestUpdate(); emit sendMessage("done..", 0); - emit sendFileInfo(filePath.right(filePath.size() - split - 1), QStringList(*textureNames), vertexData.size(), indexData.size() / 3); + emit sendFileInfo(filePath.right(filePath.size() - filePath.lastIndexOf(QRegExp("/|\\\\")) - 1), m_materials, vertexData.size(), indexData.size() / 3); } catch (std::invalid_argument e) { @@ -209,10 +173,10 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program) for (auto& it : m_drawList) { // bind the correct texture - if (it.textureIndex < m_textures.size()) - m_textures.at(it.textureIndex)->bind(); + if (it.textureIndex < m_materials->size()) + m_materials->at(it.textureIndex).texture->bind(); else - m_textures.last()->bind(); + m_materials->last().texture->bind(); // Set model matrix program->setUniformValue("m_matrix", it.modelMatrix); diff --git a/QtMeshViewer/Source/MainWindow.cpp b/QtMeshViewer/Source/MainWindow.cpp index 515d677..b6b0d25 100644 --- a/QtMeshViewer/Source/MainWindow.cpp +++ b/QtMeshViewer/Source/MainWindow.cpp @@ -143,12 +143,12 @@ void MainWindow::takeScreenShot() viewer->grab().save(destination); } -void MainWindow::setFileInfo(QString name, QStringList textures, int vertices, int triangle) +void MainWindow::setFileInfo(QString name, QVector* materials, int vertices, int triangle) { m_fileInfo = QByteArray("Filename: "); m_fileInfo += name; m_fileInfo += "\nMaterials: "; - m_fileInfo += QByteArray::number(textures.size()); + m_fileInfo += QByteArray::number(materials->size()); m_fileInfo += "\nVertices: "; m_fileInfo += QByteArray::number(vertices); m_fileInfo += "\nTriangle: "; @@ -156,12 +156,13 @@ void MainWindow::setFileInfo(QString name, QStringList textures, int vertices, i m_fileInfo += ""; int count(0); - for (auto& it : textures) + //TODO: mark not opened textures + for (auto& it : *materials) { m_fileInfo += "Material "; m_fileInfo += QByteArray::number(count++); m_fileInfo += " - "; - m_fileInfo += it; + m_fileInfo += it.name; m_fileInfo += "\n"; } } diff --git a/QtMeshViewer/Source/MshFile.cpp b/QtMeshViewer/Source/MshFile.cpp index c3aa5a1..d7cecfe 100644 --- a/QtMeshViewer/Source/MshFile.cpp +++ b/QtMeshViewer/Source/MshFile.cpp @@ -1,5 +1,5 @@ #include "..\Header\MshFile.h" - +#include "..\Header\tga.h" // helper function to save data from file to any variable type #define F2V(variableName) reinterpret_cast(&variableName) @@ -160,7 +160,7 @@ void MshFile::analyseMsh2Chunks(std::list& chunkList) std::list tmp_matdChunks; loadChunks(tmp_matdChunks, it->position, it->size); - m_textureNames->push_back(""); + m_materials->push_back(Material()); // analyse MATD subchunks analyseMatdChunks(tmp_matdChunks); @@ -218,12 +218,19 @@ void MshFile::analyseMatdChunks(std::list& chunkList) { if (!strcmp("TX0D", it->name)) { + // get the texture name m_file.seekg(it->position); char* buffer = new char[it->size + 1]; *buffer = { 0 }; m_file.read(buffer, it->size); - m_textureNames->back() = buffer; + m_materials->back().name = buffer; delete[] buffer; + + // load the texture + if (m_materials->back().name.isEmpty()) + loadTexture(m_materials->back().texture, ""); + else + loadTexture(m_materials->back().texture, m_filepath + "/" + m_materials->back().name); } } } @@ -514,14 +521,24 @@ void MshFile::analyseClthChunks(Model * dataDestination, std::list // search if it is already known bool tmp_found(false); - - int index = m_textureNames->indexOf(QString::fromStdString(buffer)); - if (index != -1) - new_segment->textureIndex = index; - else + for (unsigned int index = 0; index < m_materials->size(); index++) { - m_textureNames->push_back(QString::fromStdString(buffer)); - new_segment->textureIndex = m_textureNames->size() - 1; + if (m_materials->at(index).name == QString(buffer)) + { + tmp_found = true; + new_segment->textureIndex = index; + break; + } + } + + if(!tmp_found) + { + m_materials->push_back(Material()); + m_materials->back().name = QString(buffer); + + //TODO: load texture; + loadTexture(m_materials->back().texture, m_filepath + "/" + m_materials->back().name); + new_segment->textureIndex = m_materials->size() - 1; } delete[] buffer; @@ -605,6 +622,39 @@ void MshFile::readUV(Segment * dataDestination, std::streampos position) m_file.read(F2V(dataDestination->vertices[i].texCoord[j]), sizeof(float)); } +void MshFile::loadTexture(QOpenGLTexture * destination, QString filepath) +{ + bool loadSuccess(false); + QImage img; + + if (filepath.isEmpty()) + { + loadSuccess = true; + img = QImage(1, 1, QImage::Format_RGB32); + img.fill(Qt::red); + } + else + img = loadTga(filepath, loadSuccess); + + if (!loadSuccess) + emit sendMessage("WARNING: texture not found or corrupted: " + m_materials->back().name, 1); + + // Load image to OglTexture + QOpenGLTexture* new_texture = new QOpenGLTexture(img.mirrored()); + + // Set nearest filtering mode for texture minification + new_texture->setMinificationFilter(QOpenGLTexture::Nearest); + + // Set bilinear filtering mode for texture magnification + new_texture->setMagnificationFilter(QOpenGLTexture::Linear); + + // Wrap texture coordinates by repeating + // f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2) + new_texture->setWrapMode(QOpenGLTexture::Repeat); + + destination = new_texture; +} + QMatrix4x4 MshFile::getParentMatrix(std::string parent) const { QMatrix4x4 matrix; diff --git a/QtMeshViewer/Source/OglViewerWidget.cpp b/QtMeshViewer/Source/OglViewerWidget.cpp index 67678a6..c26efa8 100644 --- a/QtMeshViewer/Source/OglViewerWidget.cpp +++ b/QtMeshViewer/Source/OglViewerWidget.cpp @@ -259,7 +259,7 @@ void OglViewerWidget::setConnections() connect(this, SIGNAL(loadFile(QString)), m_dataEngine, SLOT(loadFile(QString))); connect(m_dataEngine, SIGNAL(sendMessage(QString, int)), parentWidget(), SLOT(printMessage(QString, int))); connect(m_dataEngine, SIGNAL(requestUpdate()), this, SLOT(update())); - connect(m_dataEngine, SIGNAL(sendFileInfo(QString, QStringList, int, int)), parentWidget(), SLOT(setFileInfo(QString, QStringList, int, int))); + connect(m_dataEngine, SIGNAL(sendFileInfo(QString, QVector*, int, int)), parentWidget(), SLOT(setFileInfo(QString, QVector*, int, int))); }