diff --git a/QtMeshViewer/Form Files/FileInfoWindow.ui b/QtMeshViewer/Form Files/FileInfoWindow.ui index 8c4793be8463ef321c1a1e8cfbddc4e296f2e2a3..c7f45bfefe153f539c107ec81892ff3e223f812a 100644 --- a/QtMeshViewer/Form Files/FileInfoWindow.ui +++ b/QtMeshViewer/Form Files/FileInfoWindow.ui @@ -47,6 +47,9 @@ Triangles: -</string> <property name="alignment"> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> </property> + <property name="textInteractionFlags"> + <set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set> + </property> </widget> </item> </layout> diff --git a/QtMeshViewer/Header/FileInfoWindow.h b/QtMeshViewer/Header/FileInfoWindow.h index a48bad12fc1d26501c4b2df75c2c489ddee6e308..566accf227dd0b9b64868576ddf164351f9c3700 100644 --- a/QtMeshViewer/Header/FileInfoWindow.h +++ b/QtMeshViewer/Header/FileInfoWindow.h @@ -1,6 +1,5 @@ #pragma once #include <QWidget> -#include <QString> #include "ui_FileInfoWindow.h" class FileInfoWindow : public QWidget @@ -8,13 +7,21 @@ class FileInfoWindow : public QWidget Q_OBJECT public: - FileInfoWindow(QWidget *parent = Q_NULLPTR); - ~FileInfoWindow(); + FileInfoWindow(QWidget *parent = Q_NULLPTR) + : QWidget(parent) + , ui(new Ui::FileInfoWindow) + { + ui->setupUi(this); + setWindowFlags(Qt::Tool | Qt::NoDropShadowWindowHint); + ui->scrollArea->widget()->setStyleSheet("background-color: #ffffff"); + }; + + ~FileInfoWindow() { delete ui; }; private: Ui::FileInfoWindow* ui; public: - void setBasicText(QString text); - void setDetailText(QString text); + void setBasicText(QString text) { ui->basic->setText(text); }; + void setDetailText(QString text) { ui->detail->setText(text); }; }; \ No newline at end of file diff --git a/QtMeshViewer/Header/FileInterface.h b/QtMeshViewer/Header/FileInterface.h index 3c040dec8dff74b33817a4f5a0ffd44a1c55e79f..4dbed752ce775c2e23b3d66f76eadb1ce31a1b49 100644 --- a/QtMeshViewer/Header/FileInterface.h +++ b/QtMeshViewer/Header/FileInterface.h @@ -1,17 +1,13 @@ #pragma once +#include <QObject> +#include <QOpenGlTexture> #include <fstream> #include <QVector> #include <QVector2D> -#include <QVector3D> #include <QMatrix4x4> #include <QQuaternion> -#include <QOpenGLFunctions> -#include <QOpenGlTexture> -#include <QObject> -#include <QOpenGLTexture> #include <QRegExp> -#include <..\Header\MainWindow.h> - +#include "MainWindow.h" struct BoundingBox { QQuaternion rotation; diff --git a/QtMeshViewer/Header/GeometryEngine.h b/QtMeshViewer/Header/GeometryEngine.h index 9cd09b29d3449fad3a5980665336845e8b3dc6a3..854241594e2685aebd76738c56bb37885e05943b 100644 --- a/QtMeshViewer/Header/GeometryEngine.h +++ b/QtMeshViewer/Header/GeometryEngine.h @@ -1,11 +1,11 @@ #pragma once -#include "..\Header\FileInterface.h" #include <QObject> #include <QOpenGLFunctions> #include <QOpenGLShaderProgram> #include <QOpenGLBuffer> -#include <QOpenGLTexture> #include <QVector> +#include "FileInterface.h" + struct DrawInformation { unsigned int offset; @@ -22,20 +22,28 @@ public: GeometryEngine(QObject *parent = Q_NULLPTR); virtual ~GeometryEngine(); +// attributes private: QOpenGLBuffer m_arrayBuf; QOpenGLBuffer m_indexBuf; QVector<Material>* m_materials = Q_NULLPTR; - QVector<DrawInformation> m_drawList; - BoundingBox m_boundings; Material* m_defaultMaterial; + BoundingBox m_boundings; + QVector<DrawInformation> m_drawList; +// functions +private: void clearData(); +public: + void drawGeometry(QOpenGLShaderProgram *program, bool wireframe); + +// slots public slots: void loadFile(QString filePath); - void drawGeometry(QOpenGLShaderProgram *program, bool wireframe); + +// signals signals: void requestResetView(); void sendMessage(QString message, int severity); diff --git a/QtMeshViewer/Header/MainWindow.h b/QtMeshViewer/Header/MainWindow.h index bd86804e70541e99bef6808f924b37fb420039a0..eba0e068ad9fee9d54d14c2b7aad16aff226e57a 100644 --- a/QtMeshViewer/Header/MainWindow.h +++ b/QtMeshViewer/Header/MainWindow.h @@ -1,12 +1,11 @@ #pragma once - #include <QtWidgets/QMainWindow> -#include <qwidget.h> +#include <QWidget> +#include "ui_MainWindow.h" +#include "FileInfoWindow.h" #include <QByteArray> -#include <QStringList> #include <QLabel> -#include "ui_MainWindow.h" -#include "..\Header\FileInfoWindow.h" + struct Material; @@ -18,27 +17,32 @@ public: MainWindow(QWidget *parent = Q_NULLPTR); ~MainWindow(); +// attributes private: Ui::MainWindowClass* ui; - int m_curSeverity; - void setupWidgets(); + QByteArray m_fileInfo; QLabel* m_output; + int m_curSeverity; + FileInfoWindow* m_infoWindow; +// functions private: + void setupWidgets(); void openFile(); - void aboutFile(); - void aboutTool(); void takeScreenShot(); + void aboutTool(); protected: virtual void resizeEvent(QResizeEvent * e) Q_DECL_OVERRIDE; +// slots public slots: void printMessage(QString message, int severity); void setFileInfo(QString name, QVector<Material>* materials, int vertices, int triangle); +// signals signals: void loadFile(QString); }; diff --git a/QtMeshViewer/Header/OglViewerWidget.h b/QtMeshViewer/Header/OglViewerWidget.h index 3c84a3b063996afdcf866970ca5594be7fd5279f..ed77ed1c7e511a975acaee8918837a59f2907278 100644 --- a/QtMeshViewer/Header/OglViewerWidget.h +++ b/QtMeshViewer/Header/OglViewerWidget.h @@ -1,14 +1,10 @@ #pragma once - -#include "geometryengine.h" -#include "..\Header\SettingsWindow.h" #include <QOpenGLWidget> #include <QOpenGLFunctions> -#include <QMatrix4x4> -#include <QQuaternion> -#include <QVector2D> -#include <QBasicTimer> #include <QOpenGLShaderProgram> +#include <QMatrix4x4> +#include "GeometryEngine.h" +#include "SettingsWindow.h" class GeometryEngine; @@ -21,21 +17,16 @@ public: explicit OglViewerWidget(QWidget *parent = 0); ~OglViewerWidget(); -signals: - void loadFile(QString); - +// attributes private: - struct { - bool left = false; - bool right = false; - QVector2D position; - } m_mouse; + QOpenGLShaderProgram m_program; + GeometryEngine *m_dataEngine; - struct { - bool x = true; - bool y = true; - bool z = true; - } m_rotDirections; + QVector4D m_backgroundColorOn = { 0.02f, 0.02f, 0.02f, 1.0f }; + QVector4D m_backgroundColorOff = { 0.5f, 0.8f, 1.0f, 1.0f }; + + bool m_wireframe = false; + bool m_lightOn = false; struct { QVector4D position = { 1,1,1,0 }; @@ -46,44 +37,49 @@ private: SettingsWindow* m_settings; - QVector4D m_backgroundColorOn = {0.02f, 0.02f, 0.02f, 1.0f}; - QVector4D m_backgroundColorOff = { 0.5f, 0.8f, 1.0f, 1.0f }; + struct { + bool left = false; + bool right = false; + QVector2D position; + } m_mouse; - QOpenGLShaderProgram m_program; - GeometryEngine *m_dataEngine; + struct { + bool x = true; + bool y = true; + bool z = true; + } m_rotDirections; QMatrix4x4 m_projection; QVector3D m_translation; QQuaternion m_rotation; - bool m_wireframe = false; - bool m_lightOn = false; - double m_zSpeed = 1.0; +// functions +private: + void initShaders(); + void setConnections(); + void resetView(); + void updateLightPosition(); + protected: + void initializeGL() Q_DECL_OVERRIDE; + void resizeGL(int w, int h) Q_DECL_OVERRIDE; + void paintGL() Q_DECL_OVERRIDE; + void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE; void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE; void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE; void wheelEvent(QWheelEvent *e) Q_DECL_OVERRIDE; - void dragEnterEvent(QDragEnterEvent *e) Q_DECL_OVERRIDE; - void dropEvent(QDropEvent * event) Q_DECL_OVERRIDE; + void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; - void initializeGL() Q_DECL_OVERRIDE; - void resizeGL(int w, int h) Q_DECL_OVERRIDE; - void paintGL() Q_DECL_OVERRIDE; - -private: - void initShaders(); - void setConnections(); - void updateLightPosition(); - -private slots: - void resetView(); + void dragEnterEvent(QDragEnterEvent *e) Q_DECL_OVERRIDE; + void dropEvent(QDropEvent * event) Q_DECL_OVERRIDE; +// slots public slots: - void changeDirection(int direction); + void toggleAxis(int axis); void toggleWireframe(); void toggleLight(); void showSettings(); @@ -93,7 +89,9 @@ public slots: void setAttFac(double value); void setAmbCoef(double value); +// signals signals: void sendMessage(QString message, int severity); + void loadFile(QString); }; diff --git a/QtMeshViewer/Header/SettingsWindow.h b/QtMeshViewer/Header/SettingsWindow.h index 30cd5175656e331e134885a64acf288a1241e563..26a596389be0134bf90e0edf6c129dbb0fd58443 100644 --- a/QtMeshViewer/Header/SettingsWindow.h +++ b/QtMeshViewer/Header/SettingsWindow.h @@ -3,6 +3,7 @@ #include "ui_SettingsWindow.h" #include <QVector3D> + class SettingsWindow : public QWidget { Q_OBJECT diff --git a/QtMeshViewer/Header/tga.h b/QtMeshViewer/Header/tga.h index 0c560bdfe6bde14e679f4f08c01aee6b06ccac14..c95e82ccf0321e15ae51f2e39b0d4747deff88b3 100644 --- a/QtMeshViewer/Header/tga.h +++ b/QtMeshViewer/Header/tga.h @@ -3,7 +3,6 @@ #include <QImage> #include <QColor> -#include <iostream> QImage loadTga(QString filePath, bool &success) { @@ -67,7 +66,7 @@ QImage loadTga(QString filePath, bool &success) int valb = vui8Pixels.at(y * ui32Width * ui32BpP / 8 + x * ui32BpP / 8); QColor value(valr, valg, valb); - img.setPixelColor(x, ui32Width - 1 - y, value); + img.setPixel(x, ui32Width - 1 - y, value.rgba()); } } } @@ -97,7 +96,7 @@ QImage loadTga(QString filePath, bool &success) else color.setRgb(qRgb(tempData[2], tempData[1], tempData[0])); - img.setPixelColor(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color); + img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba()); tmp_pixelIndex++; } } @@ -117,7 +116,7 @@ QImage loadTga(QString filePath, bool &success) else color.setRgb(qRgb(tempData[2], tempData[1], tempData[0])); - img.setPixelColor(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color); + img.setPixel(tmp_pixelIndex % ui32Width, ui32Height - 1 - (tmp_pixelIndex / ui32Width), color.rgba()); tmp_pixelIndex++; } } diff --git a/QtMeshViewer/Resources/StyleSheet.txt b/QtMeshViewer/Resources/StyleSheet.txt index b36e3a943e6af98b91f46f249d6e59887ef4fbef..414040a3fbe1737bf4cd6ac62fde0e9c58217dac 100644 --- a/QtMeshViewer/Resources/StyleSheet.txt +++ b/QtMeshViewer/Resources/StyleSheet.txt @@ -1,3 +1,9 @@ +QLabel#output { + color : white; + min-width: 400px; + min-height: 50px; +} + QToolButton { image: url(:/images/toolbar/placeholder.png); border-style: none; diff --git a/QtMeshViewer/Source/FileInfoWindow.cpp b/QtMeshViewer/Source/FileInfoWindow.cpp deleted file mode 100644 index 47e19af9f7985fd8267db31a796b61201565f88f..0000000000000000000000000000000000000000 --- a/QtMeshViewer/Source/FileInfoWindow.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "..\Header\FileInfoWindow.h" -#include <QIcon> - -FileInfoWindow::FileInfoWindow(QWidget *parent) - : QWidget(parent) - , ui(new Ui::FileInfoWindow) -{ - ui->setupUi(this); - - setWindowFlags(Qt::Tool | Qt::NoDropShadowWindowHint); - - ui->scrollArea->widget()->setStyleSheet("background-color: #ffffff"); - -} - -FileInfoWindow::~FileInfoWindow() -{ - delete ui; -} - -void FileInfoWindow::setBasicText(QString text) -{ - ui->basic->setText(text); -} - -void FileInfoWindow::setDetailText(QString text) -{ - ui->detail->setText(text); -} diff --git a/QtMeshViewer/Source/GeometryEngine.cpp b/QtMeshViewer/Source/GeometryEngine.cpp index 65bff184d332e2cacb85c166816b2ed2bfbb5ead..80549ba4bf3b959faf0a5b0c32e1fc181aa8c5b6 100644 --- a/QtMeshViewer/Source/GeometryEngine.cpp +++ b/QtMeshViewer/Source/GeometryEngine.cpp @@ -2,20 +2,18 @@ #include "..\Header\MshFile.h" #include "..\Header\OglViewerWidget.h" #include "..\Header\MainWindow.h" -#include <cmath> #include <QRegExp> ///////////////////////////////////////////////////////////////////////// -// public constructor/destructor +// constructor/destructor GeometryEngine::GeometryEngine(QObject *parent) : QObject(parent) , m_indexBuf(QOpenGLBuffer::IndexBuffer) + , m_defaultMaterial(FileInterface::getDefaultMaterial()) { initializeOpenGLFunctions(); - - m_defaultMaterial = FileInterface::getDefaultMaterial(); } GeometryEngine::~GeometryEngine() @@ -27,7 +25,7 @@ GeometryEngine::~GeometryEngine() ///////////////////////////////////////////////////////////////////////// -// private functions +// functions void GeometryEngine::clearData() { @@ -52,94 +50,12 @@ void GeometryEngine::clearData() m_drawList.clear(); } - -///////////////////////////////////////////////////////////////////////// -// public slots - -void GeometryEngine::loadFile(QString filePath) -{ - // cleanup old stuff and recreate buffers - clearData(); - m_arrayBuf.create(); - m_indexBuf.create(); - - //reset view - emit requestResetView(); - emit sendMessage("loading file..", 0); - - try - { - QVector<Model*>* models; - QVector<VertexData> vertexData; - QVector<GLuint> indexData; - - // open file and get the information - MshFile file(filePath, this); - - models = file.getModels(); - m_materials = file.getMaterials(); - m_boundings = file.getBoundingBox(); - - // collect data - unsigned int indexOffset(0); - unsigned int vertexOffset(0); - for (auto& modelIterator : *models) - { - for (auto& segmentIterator : modelIterator->segmList) - { - // get draw information - DrawInformation new_info; - new_info.offset = indexOffset; - new_info.size = segmentIterator->indices.size(); - new_info.textureIndex = segmentIterator->textureIndex; - new_info.modelMatrix = modelIterator->m4x4Translation; - new_info.modelMatrix.rotate(modelIterator->quadRotation); - - // add offset to indices, no need to do it for the first one (maybe it's very big) - if (vertexOffset != 0) - for (auto& it : segmentIterator->indices) - it += vertexOffset; - - // save data - vertexData += segmentIterator->vertices; - indexData += segmentIterator->indices; - - if (segmentIterator->textureIndex < (unsigned) m_materials->size() && m_materials->at(segmentIterator->textureIndex).transparent) - m_drawList.push_back(new_info); - else - m_drawList.push_front(new_info); - - // update offset - indexOffset += new_info.size; - vertexOffset += segmentIterator->vertices.size(); - } - } - - // Transfer vertex data to VBO 0 - m_arrayBuf.bind(); - m_arrayBuf.allocate(vertexData.data(), vertexData.size() * sizeof(VertexData)); - - // Transfer index data to VBO 1 - m_indexBuf.bind(); - m_indexBuf.allocate(indexData.data(), indexData.size() * sizeof(GLuint)); - - emit requestUpdate(); - emit sendMessage("done..", 0); - emit sendFileInfo(filePath.right(filePath.size() - filePath.lastIndexOf(QRegExp("/|\\\\")) - 1), m_materials, vertexData.size(), indexData.size() / 3); - } - catch (std::invalid_argument e) - { - clearData(); - emit sendMessage(QString(e.what()), 2); - } -} - void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program, bool wireframe) { if (!m_arrayBuf.isCreated() || !m_indexBuf.isCreated()) return; -// Setup + // Setup // Tell OpenGL which VBOs to use m_arrayBuf.bind(); m_indexBuf.bind(); @@ -178,7 +94,7 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program, bool wireframe) program->enableAttributeArray(normLocation); program->setAttributeBuffer(normLocation, GL_FLOAT, offset, 3, sizeof(VertexData)); -// Paint + // Paint for (auto& it : m_drawList) { @@ -188,7 +104,7 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program, bool wireframe) QVector3D specularColor; // bind the correct texture - if (it.textureIndex < (unsigned) m_materials->size() && m_materials->at(it.textureIndex).texture0 != Q_NULLPTR) + if (it.textureIndex < (unsigned)m_materials->size() && m_materials->at(it.textureIndex).texture0 != Q_NULLPTR) { m_materials->at(it.textureIndex).texture0->bind(); tmp_transparent = m_materials->at(it.textureIndex).transparent; @@ -216,12 +132,94 @@ void GeometryEngine::drawGeometry(QOpenGLShaderProgram *program, bool wireframe) program->setUniformValue("materialSpecularColor", specularColor); // Draw cube geometry using indices from VBO 1 - if(wireframe) + if (wireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glDrawElements(GL_TRIANGLES, it.size, GL_UNSIGNED_INT, (void*)(it.offset * sizeof(GLuint))); - + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } } + +///////////////////////////////////////////////////////////////////////// +// slots + +void GeometryEngine::loadFile(QString filePath) +{ + // cleanup old stuff and recreate buffers + clearData(); + m_arrayBuf.create(); + m_indexBuf.create(); + + //reset view + emit requestResetView(); + emit sendMessage("loading file..", 0); + + try + { + QVector<Model*>* models; + QVector<VertexData> vertexData; + QVector<GLuint> indexData; + + // open file and get the information + MshFile file(filePath, this); + + models = file.getModels(); + m_materials = file.getMaterials(); + m_boundings = file.getBoundingBox(); + + // collect data + unsigned int indexOffset(0); + unsigned int vertexOffset(0); + for (auto& modelIterator : *models) + { + for (auto& segmentIterator : modelIterator->segmList) + { + // get draw information + DrawInformation new_info; + new_info.offset = indexOffset; + new_info.size = segmentIterator->indices.size(); + new_info.textureIndex = segmentIterator->textureIndex; + new_info.modelMatrix = modelIterator->m4x4Translation; + new_info.modelMatrix.rotate(modelIterator->quadRotation); + + // add offset to indices, no need to do it for the first one (maybe it's very big) + if (vertexOffset != 0) + for (auto& it : segmentIterator->indices) + it += vertexOffset; + + // save data + vertexData += segmentIterator->vertices; + indexData += segmentIterator->indices; + + if (segmentIterator->textureIndex < (unsigned) m_materials->size() && m_materials->at(segmentIterator->textureIndex).transparent) + m_drawList.push_back(new_info); + else + m_drawList.push_front(new_info); + + // update offset + indexOffset += new_info.size; + vertexOffset += segmentIterator->vertices.size(); + } + } + + // Transfer vertex data to VBO 0 + m_arrayBuf.bind(); + m_arrayBuf.allocate(vertexData.data(), vertexData.size() * sizeof(VertexData)); + + // Transfer index data to VBO 1 + m_indexBuf.bind(); + m_indexBuf.allocate(indexData.data(), indexData.size() * sizeof(GLuint)); + + emit requestUpdate(); + emit sendMessage("done..", 0); + emit sendFileInfo(filePath.right(filePath.size() - filePath.lastIndexOf(QRegExp("/|\\\\")) - 1), m_materials, vertexData.size(), indexData.size() / 3); + } + catch (std::invalid_argument e) + { + clearData(); + emit sendMessage(QString(e.what()), 2); + } +} + diff --git a/QtMeshViewer/Source/MainWindow.cpp b/QtMeshViewer/Source/MainWindow.cpp index 01b1f07d9d2430b33089d5815c0374825e4c1767..d09568e4b7342030f7beaa8942804fa30f80bb55 100644 --- a/QtMeshViewer/Source/MainWindow.cpp +++ b/QtMeshViewer/Source/MainWindow.cpp @@ -1,32 +1,37 @@ #include "..\Header\MainWindow.h" #include "..\Header\OglViewerWidget.h" +#include "..\Header\FileInterface.h" #include <QSurfaceFormat> -#include <QMessageBox> -#include <QFileDialog> -#include <QPalette> -#include <QAction> #include <QSignalMapper> +#include <QToolButton> #include <QFile> -#include <QSizePolicy> -#include <QFont> +#include <QFileDialog> +#include <QMessageBox> +#include <QPalette> #include <QResizeEvent> -#include <QToolButton> -#include "..\Header\FileInterface.h" #define WINDOW_NAME "Mesh Viewer" + +///////////////////////////////////////////////////////////////////////// +// constructor/destructor + MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindowClass) - , m_curSeverity(0) , m_output(new QLabel(this)) + , m_curSeverity(0) , m_infoWindow(new FileInfoWindow(this)) { + // setup window ui->setupUi(this); setWindowTitle(WINDOW_NAME); setWindowIcon(QIcon(":/images/icon.ico")); + printMessage("MeshViewer by Anakin", 0); + + // setup opengl things QSurfaceFormat format; format.setDepthBufferSize(24); format.setMajorVersion(2); @@ -34,12 +39,13 @@ MainWindow::MainWindow(QWidget *parent) format.setProfile(QSurfaceFormat::NoProfile); QSurfaceFormat::setDefaultFormat(format); - setupWidgets(); - - printMessage("MeshViewer by Anakin", 0); + // set default text to file info + m_fileInfo = "Filename: -\nMaterials: -\nVertices: -\nTriangle: -<detail>No file is open"; - m_fileInfo += "Filename: -\nMaterials: -\nVertices: -\nTriangle: -<detail>No file is open"; + // add widgets to the window + setupWidgets(); + // load stylesheet QFile styleSheet(":/files/StyleSheet.txt"); styleSheet.open(QIODevice::ReadOnly); this->setStyleSheet(styleSheet.readAll()); @@ -52,35 +58,37 @@ MainWindow::~MainWindow() delete m_infoWindow; } -void MainWindow::openFile() -{ - QString fileName = QFileDialog::getOpenFileName(this, "Open File", "", "Mesh (*.msh)"); - if(!fileName.isEmpty()) - emit loadFile(fileName); -} + +///////////////////////////////////////////////////////////////////////// +// functions void MainWindow::setupWidgets() { + // Ogl Viewer OglViewerWidget* viewer = new OglViewerWidget(this); setCentralWidget(viewer); connect(viewer, &OglViewerWidget::sendMessage, this, &MainWindow::printMessage); + // open file QToolButton *openFile = new QToolButton(this); openFile->setObjectName("openFile"); openFile->setToolTip("open file"); connect(openFile, &QToolButton::pressed, this, &MainWindow::openFile); ui->mainToolBar->addWidget(openFile); + // screenshot QToolButton *screenshot = new QToolButton(this); screenshot->setObjectName("screenshot"); screenshot->setToolTip("take screenshot"); connect(screenshot, &QToolButton::pressed, this, &MainWindow::takeScreenShot); ui->mainToolBar->addWidget(screenshot); + ////////////////////////////////////////////////// ui->mainToolBar->addSeparator(); QSignalMapper* signalMapper = new QSignalMapper(this); + // X QToolButton *x = new QToolButton(this); x->setObjectName("x"); x->setToolTip("x-direction"); @@ -88,6 +96,7 @@ void MainWindow::setupWidgets() x->setChecked(true); ui->mainToolBar->addWidget(x); + // Y QToolButton *y = new QToolButton(this); y->setObjectName("y"); y->setToolTip("y-direction"); @@ -95,6 +104,7 @@ void MainWindow::setupWidgets() y->setChecked(true); ui->mainToolBar->addWidget(y); + // Z QToolButton *z = new QToolButton(this); z->setObjectName("z"); z->setToolTip("z-direction"); @@ -110,10 +120,12 @@ void MainWindow::setupWidgets() signalMapper->setMapping(y, 2); signalMapper->setMapping(z, 3); - connect(signalMapper, SIGNAL(mapped(int)), viewer, SLOT(changeDirection(int))); + connect(signalMapper, SIGNAL(mapped(int)), viewer, SLOT(toggleAxis(int))); + ////////////////////////////////////////////////// ui->mainToolBar->addSeparator(); + // wireframe QToolButton *wireframe = new QToolButton(this); wireframe->setObjectName("wireframe"); wireframe->setToolTip("wireframe"); @@ -122,6 +134,7 @@ void MainWindow::setupWidgets() connect(wireframe, &QToolButton::pressed, viewer, &OglViewerWidget::toggleWireframe); ui->mainToolBar->addWidget(wireframe); + // light QToolButton *light = new QToolButton(this); light->setObjectName("light"); light->setToolTip("toggle light"); @@ -130,48 +143,52 @@ void MainWindow::setupWidgets() connect(light, &QToolButton::pressed, viewer, &OglViewerWidget::toggleLight); ui->mainToolBar->addWidget(light); + // settings QToolButton *settings = new QToolButton(this); settings->setObjectName("settings"); settings->setToolTip("settings"); connect(settings, &QToolButton::pressed, viewer, &OglViewerWidget::showSettings); ui->mainToolBar->addWidget(settings); + ////////////////////////////////////////////////// ui->mainToolBar->addSeparator(); + // fileinfo QToolButton *fileInfo = new QToolButton(this); fileInfo->setObjectName("fileInfo"); fileInfo->setToolTip("file info"); - connect(fileInfo, &QToolButton::pressed, this, &MainWindow::aboutFile); + connect(fileInfo, &QToolButton::pressed, m_infoWindow, &FileInfoWindow::show); ui->mainToolBar->addWidget(fileInfo); + // help QToolButton *help = new QToolButton(this); help->setObjectName("help"); help->setToolTip("help"); connect(help, &QToolButton::pressed, this, &MainWindow::aboutTool); ui->mainToolBar->addWidget(help); + // output on screen m_output->setObjectName("output"); - m_output->setStyleSheet("QLabel#output{color : white; min-width: 400px; min-height: 50px;}"); m_output->setAlignment(Qt::AlignTop); - m_output->setText("Name: -\nMaterials: -\nVertice: -\nTriangle: -"); + m_output->setText(m_fileInfo.left(m_fileInfo.indexOf("<detail>"))); m_output->raise(); } -void MainWindow::aboutFile() +void MainWindow::openFile() { - /*QMessageBox* dialog = new QMessageBox(QMessageBox::NoIcon, - WINDOW_NAME, - QString(m_fileInfo.left(m_fileInfo.indexOf("<detail>"))), - QMessageBox::StandardButton::Close, - this, - Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint); + QString fileName = QFileDialog::getOpenFileName(this, "Open File", "", "Mesh (*.msh)"); + if(!fileName.isEmpty()) + emit loadFile(fileName); +} - dialog->setStyleSheet("QLabel{min-width: 200px;}"); - dialog->setDetailedText(QString(m_fileInfo.right(m_fileInfo.size() - m_fileInfo.indexOf("<detail>") - 8))); - dialog->exec(); - delete dialog;*/ - m_infoWindow->show(); +void MainWindow::takeScreenShot() +{ + QString destination = QFileDialog::getSaveFileName(this, "Save as...", "", "PNG (*.png);; BMP (*.bmp);;TIFF (*.tiff, *.tif);;JPEG (*.jpg *jpeg)"); + + OglViewerWidget* viewer = dynamic_cast<OglViewerWidget*>(centralWidget()); + if (!destination.isEmpty() && viewer != NULL) + viewer->grab().save(destination); } void MainWindow::aboutTool() @@ -193,22 +210,48 @@ void MainWindow::aboutTool() delete dialog; } -void MainWindow::takeScreenShot() +void MainWindow::resizeEvent(QResizeEvent * e) { - QString destination = QFileDialog::getSaveFileName(this, "Save as...", "", "PNG (*.png);; BMP (*.bmp);;TIFF (*.tiff, *.tif);;JPEG (*.jpg *jpeg)"); - - OglViewerWidget* viewer = dynamic_cast<OglViewerWidget*>(centralWidget()); - if (!destination.isEmpty() && viewer != NULL) - viewer->grab().save(destination); + m_output->move(40, e->size().height() - 80); } -void MainWindow::resizeEvent(QResizeEvent * e) + +///////////////////////////////////////////////////////////////////////// +// slots + +void MainWindow::printMessage(QString message, int severity) { - m_output->move(40, e->size().height() - 80); + if (!ui->statusBar->currentMessage().isEmpty() && 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); } void MainWindow::setFileInfo(QString name, QVector<Material>* materials, int vertices, int triangle) { + // save basic file information m_fileInfo = QByteArray("Filename: "); m_fileInfo += name; m_fileInfo += "\nMaterials: "; @@ -219,6 +262,7 @@ void MainWindow::setFileInfo(QString name, QVector<Material>* materials, int ver m_fileInfo += QByteArray::number(triangle); m_fileInfo += "<detail>"; + // add detailed information for (auto& it : *materials) { m_fileInfo += it.name; @@ -307,39 +351,11 @@ void MainWindow::setFileInfo(QString name, QVector<Material>* materials, int ver m_fileInfo += "-----------------------------------------------------------------\n"; } + // print basic information on screen m_output->setText(m_fileInfo.left(m_fileInfo.indexOf("<detail>"))); + // print basic and detailed information on info window m_infoWindow->setBasicText(QString(m_fileInfo.left(m_fileInfo.indexOf("<detail>")))); m_infoWindow->setDetailText(QString(m_fileInfo.right(m_fileInfo.size() - m_fileInfo.indexOf("<detail>") - 8))); } - -void MainWindow::printMessage(QString message, int severity) -{ - if (!ui->statusBar->currentMessage().isEmpty() && 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/OglViewerWidget.cpp b/QtMeshViewer/Source/OglViewerWidget.cpp index b81da8a166dd1ac96a6c82c93f9e35b30546ef25..705d7bec141c1188937cd79142c171feb23a2e7a 100644 --- a/QtMeshViewer/Source/OglViewerWidget.cpp +++ b/QtMeshViewer/Source/OglViewerWidget.cpp @@ -1,23 +1,20 @@ #include "..\Header\OglViewerWidget.h" -#include "..\Header\MainWindow.h" + #include <QMouseEvent> #include <QDropEvent> #include <QMimeData> -#include <math.h> -#include <iostream> #define DEFAULT_Z_DISTANCE -4.0 ///////////////////////////////////////////////////////////////////////// -// public constructor/destructor +// constructor/destructor OglViewerWidget::OglViewerWidget(QWidget *parent) : QOpenGLWidget(parent) , m_dataEngine(0) { setFocus(); - m_translation.setZ(DEFAULT_Z_DISTANCE); setAcceptDrops(true); m_settings = new SettingsWindow(m_backgroundColorOff.toVector3D() * 255, m_backgroundColorOn.toVector3D() * 255, m_light.intensities * 255, true, m_light.ambientCoefficient, m_light.attenuationFactor, 1, this); @@ -42,7 +39,135 @@ OglViewerWidget::~OglViewerWidget() ///////////////////////////////////////////////////////////////////////// -// protected functions +// functions + +void OglViewerWidget::initShaders() +{ + // Compile vertex shader + if (!m_program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vshader.glsl")) + close(); + + // Compile fragment shader + if (!m_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fshader.glsl")) + close(); + + // Link shader pipeline + if (!m_program.link()) + close(); + + // Bind shader pipeline for use + if (!m_program.bind()) + close(); +} + +void OglViewerWidget::setConnections() +{ + connect(m_dataEngine, &GeometryEngine::requestResetView, this, &OglViewerWidget::resetView); + connect(parentWidget(), SIGNAL(loadFile(QString)), m_dataEngine, SLOT(loadFile(QString))); + 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, QVector<Material>*, int, int)), parentWidget(), SLOT(setFileInfo(QString, QVector<Material>*, int, int))); +} + +void OglViewerWidget::resetView() +{ + m_rotation = QQuaternion(); + m_translation = { 0.0, 0.0, DEFAULT_Z_DISTANCE }; + m_zSpeed = 1; + update(); +} + +void OglViewerWidget::updateLightPosition() +{ + QMatrix4x4 rotateBack; + rotateBack.rotate(m_rotation.inverted()); + QVector3D cameraPosition = rotateBack * (-m_translation); + + m_light.position.setX(cameraPosition.x()); + m_light.position.setY(cameraPosition.y()); + m_light.position.setZ(cameraPosition.z()); +} + +// OpenGL /////////////////////////////////////////////////////////////// + +void OglViewerWidget::initializeGL() +{ + initializeOpenGLFunctions(); + initShaders(); + + // Enable depth buffer + glEnable(GL_DEPTH_TEST); + + //TODO: make this optional + // Enable back face culling + //glEnable(GL_CULL_FACE); + + // Enable transparency + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + m_dataEngine = new GeometryEngine(this); + setConnections(); +} + +void OglViewerWidget::resizeGL(int w, int h) +{ + // Calculate aspect ratio + qreal aspect = qreal(w) / qreal(h ? h : 1); + + // Set near plane to 3.0, far plane to 7.0, field of view 45 degrees + const qreal zNear = 0.1, zFar = 100.0, fov = 45.0; + + // Reset projection + m_projection.setToIdentity(); + + // Set perspective projection + m_projection.perspective(fov, aspect, zNear, zFar); +} + +void OglViewerWidget::paintGL() +{ + // set background color, last value is dirtybit + if (m_lightOn && m_backgroundColorOn[3] == 1.0) + { + glClearColor(m_backgroundColorOn[0], m_backgroundColorOn[1], m_backgroundColorOn[2], 0.0000f); + m_backgroundColorOn[3] = 0.0; + } + else if (!m_lightOn && m_backgroundColorOff[3] == 1.0) + { + glClearColor(m_backgroundColorOff[0], m_backgroundColorOff[1], m_backgroundColorOff[2], 0.0000f); + m_backgroundColorOff[3] = 0.0; + } + + // Clear color and depth buffer + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // Calculate view transformation + QMatrix4x4 view; + view.translate(m_translation); + view.rotate(m_rotation); + + // Set view-projection matrix + m_program.setUniformValue("vp_matrix", m_projection * view); + + // Set Light values + m_program.setUniformValue("b_light", m_lightOn); + m_program.setUniformValue("light.position", m_light.position); + m_program.setUniformValue("light.intensities", m_light.intensities); + m_program.setUniformValue("light.attenuationFactor", m_light.attenuationFactor); + m_program.setUniformValue("light.ambientCoefficient", m_light.ambientCoefficient); + + // Set camera position + QMatrix4x4 rotateBack; + rotateBack.rotate(m_rotation.inverted()); + m_program.setUniformValue("cameraPosition", rotateBack * (-m_translation)); + + // Draw cube geometry + m_dataEngine->drawGeometry(&m_program, m_wireframe); +} + +// Inputs /////////////////////////////////////////////////////////////// void OglViewerWidget::mousePressEvent(QMouseEvent *e) { @@ -74,11 +199,13 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e) // update the new position m_mouse.position = QVector2D(e->localPos()); - // calculate the rotation axis and rotate + // calculate the rotations depending on the active axis + // XYZ if (m_rotDirections.x && m_rotDirections.y && m_rotDirections.z) { m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(diff.y(), diff.x(), 0.0).normalized(), diff.length() * 0.5) * m_rotation; } + // XY else if (m_rotDirections.x && m_rotDirections.y && !m_rotDirections.z) { @@ -96,18 +223,22 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e) m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll); } + // X else if (m_rotDirections.x && !m_rotDirections.y && !m_rotDirections.z) { m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(0.0, 1.0, 0.0).normalized(), diff.x() * 0.5) * m_rotation; } + // Y else if (!m_rotDirections.x && m_rotDirections.y && !m_rotDirections.z) { m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(1.0, 0.0, 0.0).normalized(), diff.y() * 0.5) * m_rotation; } + // Z else if (!m_rotDirections.x && !m_rotDirections.y && m_rotDirections.z) { m_rotation = QQuaternion::fromAxisAndAngle(QVector3D(0.0, 0.0, 1.0).normalized(), diff.x() * 0.5) * m_rotation; } + // XZ else if (m_rotDirections.x && !m_rotDirections.y && m_rotDirections.z) { float pitch, yaw, roll; @@ -117,6 +248,7 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e) m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll); } + // YZ else if (!m_rotDirections.x && m_rotDirections.y && m_rotDirections.z) { float pitch, yaw, roll; @@ -132,7 +264,6 @@ void OglViewerWidget::mouseMoveEvent(QMouseEvent *e) m_rotation = QQuaternion::fromEulerAngles(pitch, yaw, roll); } - // request an update update(); } @@ -158,20 +289,6 @@ void OglViewerWidget::wheelEvent(QWheelEvent *e) update(); } -void OglViewerWidget::dragEnterEvent(QDragEnterEvent *e) -{ - if (e->mimeData()->hasUrls()) - if(e->mimeData()->urls().size() == 1) - if(e->mimeData()->urls().first().toLocalFile().endsWith(".msh")) - e->acceptProposedAction(); - -} - -void OglViewerWidget::dropEvent(QDropEvent * e) -{ - emit loadFile(e->mimeData()->urls().first().toLocalFile()); -} - void OglViewerWidget::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Space) @@ -200,147 +317,27 @@ void OglViewerWidget::keyPressEvent(QKeyEvent *e) } } -void OglViewerWidget::initializeGL() -{ - initializeOpenGLFunctions(); - - //glClearColor(0.5000f, 0.8000f, 1.0000f, 0.0000f); - - initShaders(); - - // Enable depth buffer - glEnable(GL_DEPTH_TEST); - - // Enable back face culling - //glEnable(GL_CULL_FACE); - - // Enable transparency - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - m_dataEngine = new GeometryEngine(this); - setConnections(); -} - -void OglViewerWidget::resizeGL(int w, int h) -{ - // Calculate aspect ratio - qreal aspect = qreal(w) / qreal(h ? h : 1); - - // Set near plane to 3.0, far plane to 7.0, field of view 45 degrees - const qreal zNear = 0.1, zFar = 100.0, fov = 45.0; - - // Reset projection - m_projection.setToIdentity(); - - // Set perspective projection - m_projection.perspective(fov, aspect, zNear, zFar); -} - -void OglViewerWidget::paintGL() -{ - if (m_lightOn && m_backgroundColorOn[3] == 1.0) - { - glClearColor(m_backgroundColorOn[0], m_backgroundColorOn[1], m_backgroundColorOn[2], 0.0000f); - m_backgroundColorOn[3] = 0.0; - } - else if(!m_lightOn && m_backgroundColorOff[3] == 1.0) - { - glClearColor(m_backgroundColorOff[0], m_backgroundColorOff[1], m_backgroundColorOff[2], 0.0000f); - m_backgroundColorOff[3] = 0.0; - } - - // Clear color and depth buffer - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // Calculate model view transformation - QMatrix4x4 view; - view.translate(m_translation); - view.rotate(m_rotation); - - // Set view-projection matrix - m_program.setUniformValue("vp_matrix", m_projection * view); - - // Set Light values - m_program.setUniformValue("b_light", m_lightOn); - m_program.setUniformValue("light.position", m_light.position); - m_program.setUniformValue("light.intensities", m_light.intensities); - m_program.setUniformValue("light.attenuationFactor", m_light.attenuationFactor); - m_program.setUniformValue("light.ambientCoefficient", m_light.ambientCoefficient); - - // Set camera position - QMatrix4x4 rotateBack; - rotateBack.rotate(m_rotation.inverted()); - m_program.setUniformValue("cameraPosition", rotateBack * (-m_translation)); - - // Draw cube geometry - m_dataEngine->drawGeometry(&m_program, m_wireframe); -} - - -///////////////////////////////////////////////////////////////////////// -// private functions - -void OglViewerWidget::initShaders() -{ - // Compile vertex shader - if (!m_program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vshader.glsl")) - close(); - - // Compile fragment shader - if (!m_program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fshader.glsl")) - close(); - - // Link shader pipeline - if (!m_program.link()) - close(); - - // Bind shader pipeline for use - if (!m_program.bind()) - close(); -} - -void OglViewerWidget::setConnections() -{ - connect(m_dataEngine, &GeometryEngine::requestResetView, this, &OglViewerWidget::resetView); - connect(parentWidget(), SIGNAL(loadFile(QString)), m_dataEngine, SLOT(loadFile(QString))); - 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, QVector<Material>*, int, int)), parentWidget(), SLOT(setFileInfo(QString, QVector<Material>*, int, int))); - -} - -void OglViewerWidget::updateLightPosition() +void OglViewerWidget::dragEnterEvent(QDragEnterEvent *e) { - QMatrix4x4 rotateBack; - rotateBack.rotate(m_rotation.inverted()); - QVector3D cameraPosition = rotateBack * (-m_translation); + if (e->mimeData()->hasUrls()) + if(e->mimeData()->urls().size() == 1) + if(e->mimeData()->urls().first().toLocalFile().endsWith(".msh")) + e->acceptProposedAction(); - m_light.position.setX(cameraPosition.x()); - m_light.position.setY(cameraPosition.y()); - m_light.position.setZ(cameraPosition.z()); } - -///////////////////////////////////////////////////////////////////////// -// private slots - -void OglViewerWidget::resetView() +void OglViewerWidget::dropEvent(QDropEvent * e) { - m_rotation = QQuaternion(); - m_translation = { 0.0, 0.0, DEFAULT_Z_DISTANCE }; - m_zSpeed = 1; - update(); + emit loadFile(e->mimeData()->urls().first().toLocalFile()); } ///////////////////////////////////////////////////////////////////////// // public slots -void OglViewerWidget::changeDirection(int direction) +void OglViewerWidget::toggleAxis(int axis) { - switch (direction) + switch (axis) { case 1: m_rotDirections.x = !m_rotDirections.x; @@ -356,13 +353,13 @@ void OglViewerWidget::changeDirection(int direction) void OglViewerWidget::toggleWireframe() { - m_wireframe = 1 - m_wireframe; + m_wireframe = !m_wireframe; update(); } void OglViewerWidget::toggleLight() { - m_lightOn = 1 - m_lightOn; + m_lightOn = !m_lightOn; if (m_lightOn) { @@ -373,6 +370,7 @@ void OglViewerWidget::toggleLight() { m_backgroundColorOff[3] = 1.0; } + update(); } diff --git a/QtMeshViewer/Source/SettingsWindow.cpp b/QtMeshViewer/Source/SettingsWindow.cpp index de0c0b7ab30fc57d0252ad833ff4f7bda389fa68..f440ccce1da5fbfe4f30fa8cbe76de4473bb1a17 100644 --- a/QtMeshViewer/Source/SettingsWindow.cpp +++ b/QtMeshViewer/Source/SettingsWindow.cpp @@ -1,5 +1,8 @@ #include "..\Header\SettingsWindow.h" -#include <QString> + + +///////////////////////////////////////////////////////////////////////// +// constructor/destructor SettingsWindow::SettingsWindow(QVector3D bgOffColor, QVector3D bgOnColor, QVector3D lightColor, bool autoColor, double ambCoef, double attFac, int lightType, QWidget * parent) : QWidget(parent) @@ -38,6 +41,10 @@ SettingsWindow::~SettingsWindow() delete ui; } + +///////////////////////////////////////////////////////////////////////// +// functions + void SettingsWindow::setupConnections() { // light off @@ -87,8 +94,8 @@ void SettingsWindow::setupConnections() } -//////////////////////////////////////////////////////////////////////////////// -// connection slots +///////////////////////////////////////////////////////////////////////// +// slots void SettingsWindow::autoColorToggled() { diff --git a/QtMeshViewer/main.cpp b/QtMeshViewer/main.cpp index acd59df9eeba54f4dea11d9aba6bb269e33cc54c..a4a0ce04d872145eb4359ada37fa9803e64dbc7c 100644 --- a/QtMeshViewer/main.cpp +++ b/QtMeshViewer/main.cpp @@ -1,8 +1,6 @@ #include "Header\MainWindow.h" #include <QtWidgets/QApplication> -// TODO: add glow/emissive - int main(int argc, char *argv[]) { QApplication a(argc, argv);