From a2f5324a3c8b309a1bf6f6d1060e3993fae4b705 Mon Sep 17 00:00:00 2001 From: Anakin Date: Wed, 4 Jan 2017 14:35:27 +0100 Subject: [PATCH] sendMessage via signal plot from file to window, add severity to messages (black, yellow, red), add about text, removed unused texture from resource --- QtMeshViewer/Header/FileInterface.h | 22 ++++++++-- QtMeshViewer/Header/GeometryEngine.h | 5 ++- QtMeshViewer/Header/MainWindow.h | 4 ++ QtMeshViewer/Header/MshFile.h | 2 +- QtMeshViewer/Header/OglViewerWidget.h | 1 + QtMeshViewer/Resources/Resources.qrc | 4 +- QtMeshViewer/Resources/about.txt | 24 +++++++++++ QtMeshViewer/Resources/cube.png | Bin 30341 -> 0 bytes QtMeshViewer/Source/GeometryEngine.cpp | 20 ++++++--- QtMeshViewer/Source/MainWindow.cpp | 54 +++++++++++++++++++++--- QtMeshViewer/Source/MshFile.cpp | 18 ++++---- QtMeshViewer/Source/OglViewerWidget.cpp | 16 ++++--- 12 files changed, 133 insertions(+), 37 deletions(-) create mode 100644 QtMeshViewer/Resources/about.txt delete mode 100644 QtMeshViewer/Resources/cube.png diff --git a/QtMeshViewer/Header/FileInterface.h b/QtMeshViewer/Header/FileInterface.h index 7db28b8..83cbcf0 100644 --- a/QtMeshViewer/Header/FileInterface.h +++ b/QtMeshViewer/Header/FileInterface.h @@ -6,6 +6,8 @@ #include #include #include +#include +#include <..\Header\MainWindow.h> struct BoundingBox { @@ -34,18 +36,27 @@ struct Model { std::vector segmList; }; -class FileInterface +class FileInterface : public QObject { + Q_OBJECT + public: - explicit FileInterface(const char* path) - : m_models(new QVector) + explicit FileInterface(const char* path, QObject *parent) + : QObject(parent) + , m_models(new QVector) , m_textureNames(new QVector) { //open file m_file.open(path, std::ios::in | std::ios::binary); if (!m_file.is_open()) - throw std::invalid_argument(std::string("file not found: ") += path); + throw std::invalid_argument(std::string("ERROR: file not found: ") += path); + + MainWindow* tmp = dynamic_cast(parent->parent()->parent()); + if(tmp != NULL) + connect(this, SIGNAL(sendMessage(QString, int)), tmp, SLOT(showMessage(QString, int))); + + }; virtual ~FileInterface() @@ -85,4 +96,7 @@ public: virtual QVector* getModels() const { return m_models; }; virtual QVector* getTextureNames() const { return m_textureNames; }; virtual BoundingBox getBoundingBox() const { return m_sceneBbox; }; + +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 979cfb1..db265b8 100644 --- a/QtMeshViewer/Header/GeometryEngine.h +++ b/QtMeshViewer/Header/GeometryEngine.h @@ -19,7 +19,7 @@ class GeometryEngine : public QObject, protected QOpenGLFunctions Q_OBJECT public: - GeometryEngine(); + GeometryEngine(QObject *parent = Q_NULLPTR); virtual ~GeometryEngine(); private: @@ -38,6 +38,7 @@ public slots: signals: void requestResetView(); - + void sendMessage(QString message, int severity); + void requestUpdate(); }; diff --git a/QtMeshViewer/Header/MainWindow.h b/QtMeshViewer/Header/MainWindow.h index d13c3c7..10eb092 100644 --- a/QtMeshViewer/Header/MainWindow.h +++ b/QtMeshViewer/Header/MainWindow.h @@ -13,12 +13,16 @@ public: private: Ui::MainWindowClass* ui; + int m_curSeverity; private slots: void openFile(); void aboutFile(); void aboutTool(); +public slots: + void showMessage(QString message, int severity); + signals: void loadFile(const char*); }; diff --git a/QtMeshViewer/Header/MshFile.h b/QtMeshViewer/Header/MshFile.h index 7dc1744..cef8dc0 100644 --- a/QtMeshViewer/Header/MshFile.h +++ b/QtMeshViewer/Header/MshFile.h @@ -20,7 +20,7 @@ enum ModelTyp { class MshFile : public FileInterface { public: - explicit MshFile(const char* path); + explicit MshFile(const char* path, QObject *parent = Q_NULLPTR); virtual ~MshFile(); private: diff --git a/QtMeshViewer/Header/OglViewerWidget.h b/QtMeshViewer/Header/OglViewerWidget.h index b10ffea..9d9508f 100644 --- a/QtMeshViewer/Header/OglViewerWidget.h +++ b/QtMeshViewer/Header/OglViewerWidget.h @@ -53,6 +53,7 @@ protected: private: void initShaders(); + void setConnections(); private slots: void resetView(); diff --git a/QtMeshViewer/Resources/Resources.qrc b/QtMeshViewer/Resources/Resources.qrc index b54819d..020bab0 100644 --- a/QtMeshViewer/Resources/Resources.qrc +++ b/QtMeshViewer/Resources/Resources.qrc @@ -4,7 +4,9 @@ vshader.glsl - cube.png icon.ico + + about.txt + diff --git a/QtMeshViewer/Resources/about.txt b/QtMeshViewer/Resources/about.txt new file mode 100644 index 0000000..b6f2fa1 --- /dev/null +++ b/QtMeshViewer/Resources/about.txt @@ -0,0 +1,24 @@ +This is a viewer for .msh files made by Anakin. +questions, bug reports, requests: http://www.gametoast.com/viewtopic.php?f=29&t=32624 +source code: https://git.rwth-aachen.de/carstenf/OpenGL/tree/master/QtMeshViewer + +=============================================================== +Controll: +left mouse - rotate +right mouse - move +scroll - zoom +space - reset view +esc - close + +tipp: hold the left mouse and do round movement to rotate the object in z-direction + +=============================================================== +Known bugs: +RLE compressed tga files are not supported, +Most msh files that were not exported through ZETools are not displayed correctly + +=============================================================== +Credits: +ANDEWEGET +opengl.org +forum.qt.io diff --git a/QtMeshViewer/Resources/cube.png b/QtMeshViewer/Resources/cube.png deleted file mode 100644 index 42c8c51b3a004d3caaab6d9ab08f3f58d284c9ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30341 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 diff --git a/QtMeshViewer/Source/GeometryEngine.cpp b/QtMeshViewer/Source/GeometryEngine.cpp index 9813904..c2bb6e1 100644 --- a/QtMeshViewer/Source/GeometryEngine.cpp +++ b/QtMeshViewer/Source/GeometryEngine.cpp @@ -1,13 +1,16 @@ #include "..\Header\GeometryEngine.h" #include "..\Header\MshFile.h" +#include "..\Header\OglViewerWidget.h" +#include "..\Header\MainWindow.h" #include ///////////////////////////////////////////////////////////////////////// // public constructor/destructor -GeometryEngine::GeometryEngine() - : m_indexBuf(QOpenGLBuffer::IndexBuffer) +GeometryEngine::GeometryEngine(QObject *parent) + : QObject(parent) + , m_indexBuf(QOpenGLBuffer::IndexBuffer) { initializeOpenGLFunctions(); } @@ -30,6 +33,7 @@ void GeometryEngine::loadFile(const char* filePath) //reset view emit requestResetView(); + emit sendMessage("loading file..", 0); try { @@ -41,7 +45,8 @@ void GeometryEngine::loadFile(const char* filePath) QVector indexData; // open file and get the information - MshFile file(filePath); + MshFile file(filePath, this); + models = file.getModels(); textureNames = file.getTextureNames(); m_boundings = file.getBoundingBox(); @@ -91,18 +96,18 @@ void GeometryEngine::loadFile(const char* filePath) while (path.back() != '/' && path.back() != '\\') path.pop_back(); + emit sendMessage("loading textures..", 0); // load the textures for(auto& it : *textureNames) loadTexture(std::string(path + it).c_str()); + emit requestUpdate(); + emit sendMessage("done..", 0); } catch (std::invalid_argument e) { - //TODO: make a cool message box - auto msg = e.what(); + emit sendMessage(QString(e.what()), 2); } - - } void GeometryEngine::loadTexture(const char* filePath) @@ -201,3 +206,4 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program) glDrawElements(GL_TRIANGLES, it.size, GL_UNSIGNED_INT, (void*)(it.offset * sizeof(GLuint))); } } + diff --git a/QtMeshViewer/Source/MainWindow.cpp b/QtMeshViewer/Source/MainWindow.cpp index e8a1455..d908ed3 100644 --- a/QtMeshViewer/Source/MainWindow.cpp +++ b/QtMeshViewer/Source/MainWindow.cpp @@ -3,22 +3,23 @@ #include #include #include +#include +#include #define WINDOW_NAME "Mesh Viewer" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindowClass) + , m_curSeverity(0) { ui->setupUi(this); setWindowTitle(WINDOW_NAME); setWindowIcon(QIcon(":/images/icon.ico")); - ui->statusBar->showMessage("pre-alpha"); - ui->mainToolBar->addAction("Open File", this, &MainWindow::openFile); - ui->mainToolBar->addAction("About File", this, &MainWindow::aboutFile); + ui->mainToolBar->addAction("File Info", this, &MainWindow::aboutFile); ui->mainToolBar->addAction("Help", this, &MainWindow::aboutTool); QSurfaceFormat format; @@ -26,6 +27,8 @@ MainWindow::MainWindow(QWidget *parent) QSurfaceFormat::setDefaultFormat(format); setCentralWidget(new OglViewerWidget(this)); + + ui->statusBar->showMessage("MeshViewer by Anakin", 0); } MainWindow::~MainWindow() @@ -53,12 +56,49 @@ void MainWindow::aboutFile() void MainWindow::aboutTool() { - QMessageBox* dialog = new QMessageBox(QMessageBox::Question, + QFile file(":/files/about.txt"); + file.open(QIODevice::ReadOnly); + QMessageBox* dialog = new QMessageBox( + QMessageBox::Question, WINDOW_NAME, - "This is the Pre-Alpha version of my Mesh Viewer\nCheck the detailed information", + QString(file.readAll()), QMessageBox::StandardButton::Close, this, - Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint); - dialog->setDetailedText("left mouse - rotate\nright mouse - move\nscroll - zoom\nspace - reset view\nesc - close"); + Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint + ); + + //dialog->setDetailedText(QString(file.readAll())); + file.close(); + dialog->exec(); +} + +void MainWindow::showMessage(QString message, int severity) +{ + if (severity < m_curSeverity) + return; + + m_curSeverity = severity; + int time(0); + QPalette palette; + + switch (severity) + { + case 1: + time = 3000; + palette.setColor(QPalette::WindowText, Qt::darkYellow); + break; + case 2: + time = 3000; + palette.setColor(QPalette::WindowText, Qt::red); + break; + case 0: + default: + time = 2000; + palette.setColor(QPalette::WindowText, Qt::black); + break; + } + + ui->statusBar->setPalette(palette); + ui->statusBar->showMessage(message, time); } \ No newline at end of file diff --git a/QtMeshViewer/Source/MshFile.cpp b/QtMeshViewer/Source/MshFile.cpp index 49c41d9..1dbd23c 100644 --- a/QtMeshViewer/Source/MshFile.cpp +++ b/QtMeshViewer/Source/MshFile.cpp @@ -1,5 +1,4 @@ #include "..\Header\MshFile.h" -#include // helper function to save data from file to any variable type @@ -9,8 +8,8 @@ ///////////////////////////////////////////////////////////////////////// // public constructor/destructor -MshFile::MshFile(const char * path) - : FileInterface(path) +MshFile::MshFile(const char * path, QObject * parent) + : FileInterface(path, parent) { import(); } @@ -89,8 +88,7 @@ void MshFile::loadChunks(std::list& destination, std::streampos st // out of file. Maybe a size information is corrupted if (!m_file.good()) { - //TODO: different way for output - std::cout << "WARNING: corrupted file. Trying to continue" << std::endl; + emit sendMessage("WARNING: corrupted file. Trying to continue..", 1); m_file.clear(); break; } @@ -579,15 +577,15 @@ void MshFile::readUV(Segment * dataDestination, std::streampos position) if (tmp_size < dataDestination->vertices.size()) { - //TODO: warning - std::cout << "WARNING: too less UVs " << tmp_size << " < " << dataDestination->vertices.size() << std::endl; + emit sendMessage("WARNING: too less UVs " + QString::number(tmp_size) + " < " + QString::number(dataDestination->vertices.size()),1); - //TODO: fill backward with default UVs + for (unsigned int i = dataDestination->vertices.size(); i != tmp_size; i--) + for (unsigned int j = 0; j < 2; j++) + dataDestination->vertices[i - 1].texCoord[j] = 0; } else if (tmp_size > dataDestination->vertices.size()) { - //TODO: warning - std::cout << "WARNING: too many UVs " << tmp_size << " > " << dataDestination->vertices.size() << std::endl; + emit sendMessage("WARNING: too many UVs " + QString::number(tmp_size) + " > " + QString::number(dataDestination->vertices.size()), 1); tmp_size = dataDestination->vertices.size(); } diff --git a/QtMeshViewer/Source/OglViewerWidget.cpp b/QtMeshViewer/Source/OglViewerWidget.cpp index 2fe6d84..adc9085 100644 --- a/QtMeshViewer/Source/OglViewerWidget.cpp +++ b/QtMeshViewer/Source/OglViewerWidget.cpp @@ -133,11 +133,8 @@ void OglViewerWidget::initializeGL() // Enable back face culling glEnable(GL_CULL_FACE); - m_dataEngine = new GeometryEngine; - connect(m_dataEngine, &GeometryEngine::requestResetView, this, &OglViewerWidget::resetView); - connect(parentWidget(), SIGNAL(loadFile(const char*)), m_dataEngine, SLOT(loadFile(const char*))); - connect(this, SIGNAL(loadFile(const char*)), m_dataEngine, SLOT(loadFile(const char*))); - + m_dataEngine = new GeometryEngine(this); + setConnections(); } void OglViewerWidget::resizeGL(int w, int h) @@ -195,6 +192,15 @@ void OglViewerWidget::initShaders() close(); } +void OglViewerWidget::setConnections() +{ + connect(m_dataEngine, &GeometryEngine::requestResetView, this, &OglViewerWidget::resetView); + connect(parentWidget(), SIGNAL(loadFile(const char*)), m_dataEngine, SLOT(loadFile(const char*))); + connect(this, SIGNAL(loadFile(const char*)), m_dataEngine, SLOT(loadFile(const char*))); + connect(m_dataEngine, SIGNAL(sendMessage(QString, int)), parentWidget(), SLOT(showMessage(QString, int))); + connect(m_dataEngine, SIGNAL(requestUpdate()), this, SLOT(update())); +} + ///////////////////////////////////////////////////////////////////////// // private slots