From a30f1b125c510ae049e60eddac0f9ce34f718e47 Mon Sep 17 00:00:00 2001 From: Anakin Date: Sat, 24 Dec 2016 16:03:37 +0100 Subject: [PATCH] added Qt Example, next change it to fit my project --- QtMeshViewer/Form Files/MainWindow.ui | 32 +++++ QtMeshViewer/Header/GeometryEngine.h | 73 ++++++++++ QtMeshViewer/Header/MainWindow.h | 16 +++ QtMeshViewer/Header/OglViewerWidget.h | 50 +++++++ QtMeshViewer/Resources/Resources.qrc | 9 ++ QtMeshViewer/Resources/cube.png | Bin 0 -> 30341 bytes QtMeshViewer/Resources/fshader.glsl | 18 +++ QtMeshViewer/Resources/icon.ico | Bin 0 -> 270398 bytes QtMeshViewer/Resources/vshader.glsl | 24 ++++ QtMeshViewer/Source/GeometryEngine.cpp | 179 ++++++++++++++++++++++++ QtMeshViewer/Source/MainWindow.cpp | 24 ++++ QtMeshViewer/Source/OglViewerWidget.cpp | 157 +++++++++++++++++++++ QtMeshViewer/main.cpp | 12 ++ 13 files changed, 594 insertions(+) create mode 100644 QtMeshViewer/Form Files/MainWindow.ui create mode 100644 QtMeshViewer/Header/GeometryEngine.h create mode 100644 QtMeshViewer/Header/MainWindow.h create mode 100644 QtMeshViewer/Header/OglViewerWidget.h create mode 100644 QtMeshViewer/Resources/Resources.qrc create mode 100644 QtMeshViewer/Resources/cube.png create mode 100644 QtMeshViewer/Resources/fshader.glsl create mode 100644 QtMeshViewer/Resources/icon.ico create mode 100644 QtMeshViewer/Resources/vshader.glsl create mode 100644 QtMeshViewer/Source/GeometryEngine.cpp create mode 100644 QtMeshViewer/Source/MainWindow.cpp create mode 100644 QtMeshViewer/Source/OglViewerWidget.cpp create mode 100644 QtMeshViewer/main.cpp diff --git a/QtMeshViewer/Form Files/MainWindow.ui b/QtMeshViewer/Form Files/MainWindow.ui new file mode 100644 index 0000000..01cc077 --- /dev/null +++ b/QtMeshViewer/Form Files/MainWindow.ui @@ -0,0 +1,32 @@ + + + MainWindowClass + + + + 0 + 0 + 600 + 400 + + + + MainWindow + + + + + TopToolBarArea + + + false + + + + + + + + + + diff --git a/QtMeshViewer/Header/GeometryEngine.h b/QtMeshViewer/Header/GeometryEngine.h new file mode 100644 index 0000000..36f7797 --- /dev/null +++ b/QtMeshViewer/Header/GeometryEngine.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GEOMETRYENGINE_H +#define GEOMETRYENGINE_H + +#include +#include +#include + +class GeometryEngine : protected QOpenGLFunctions +{ +public: + GeometryEngine(); + virtual ~GeometryEngine(); + + void drawCubeGeometry(QOpenGLShaderProgram *program); + +private: + void initCubeGeometry(); + + QOpenGLBuffer arrayBuf; + QOpenGLBuffer indexBuf; +}; + +#endif // GEOMETRYENGINE_H diff --git a/QtMeshViewer/Header/MainWindow.h b/QtMeshViewer/Header/MainWindow.h new file mode 100644 index 0000000..49e2d43 --- /dev/null +++ b/QtMeshViewer/Header/MainWindow.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include "ui_MainWindow.h" + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(QWidget *parent = Q_NULLPTR); + ~MainWindow(); + +private: + Ui::MainWindowClass* ui; +}; diff --git a/QtMeshViewer/Header/OglViewerWidget.h b/QtMeshViewer/Header/OglViewerWidget.h new file mode 100644 index 0000000..7cb8bfc --- /dev/null +++ b/QtMeshViewer/Header/OglViewerWidget.h @@ -0,0 +1,50 @@ +#pragma once + +#include "geometryengine.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +class GeometryEngine; + +class OglViewerWidget : public QOpenGLWidget, protected QOpenGLFunctions +{ + Q_OBJECT + +public: + explicit OglViewerWidget(QWidget *parent = 0); + ~OglViewerWidget(); + +protected: + void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE; + void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE; + + void initializeGL() Q_DECL_OVERRIDE; + void resizeGL(int w, int h) Q_DECL_OVERRIDE; + void paintGL() Q_DECL_OVERRIDE; + + void initShaders(); + void initTextures(); + +private: + QBasicTimer timer; + QOpenGLShaderProgram program; + GeometryEngine *geometries; + + QOpenGLTexture *texture; + + QMatrix4x4 projection; + + QVector2D mousePressPosition; + QVector3D rotationAxis; + qreal angularSpeed; + QQuaternion rotation; +}; + diff --git a/QtMeshViewer/Resources/Resources.qrc b/QtMeshViewer/Resources/Resources.qrc new file mode 100644 index 0000000..bdb879b --- /dev/null +++ b/QtMeshViewer/Resources/Resources.qrc @@ -0,0 +1,9 @@ + + + fshader.glsl + vshader.glsl + + + cube.png + + diff --git a/QtMeshViewer/Resources/cube.png b/QtMeshViewer/Resources/cube.png new file mode 100644 index 0000000000000000000000000000000000000000..42c8c51b3a004d3caaab6d9ab08f3f58d284c9ca GIT binary patch literal 30341 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 literal 0 HcmV?d00001 diff --git a/QtMeshViewer/Resources/fshader.glsl b/QtMeshViewer/Resources/fshader.glsl new file mode 100644 index 0000000..18068cf --- /dev/null +++ b/QtMeshViewer/Resources/fshader.glsl @@ -0,0 +1,18 @@ +#ifdef GL_ES +// Set default precision to medium +precision mediump int; +precision mediump float; +#endif + +uniform sampler2D texture; + +varying vec2 v_texcoord; + +//! [0] +void main() +{ + // Set fragment color from texture + gl_FragColor = texture2D(texture, v_texcoord); +} +//! [0] + diff --git a/QtMeshViewer/Resources/icon.ico b/QtMeshViewer/Resources/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..3a2186f250235aa317c4f2138818e46d07b4a504 GIT binary patch literal 270398 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 SdCG2hh~`7ItgE(C4g7yhEfLZH literal 0 HcmV?d00001 diff --git a/QtMeshViewer/Resources/vshader.glsl b/QtMeshViewer/Resources/vshader.glsl new file mode 100644 index 0000000..cfdc061 --- /dev/null +++ b/QtMeshViewer/Resources/vshader.glsl @@ -0,0 +1,24 @@ +#ifdef GL_ES +// Set default precision to medium +precision mediump int; +precision mediump float; +#endif + +uniform mat4 mvp_matrix; + +attribute vec4 a_position; +attribute vec2 a_texcoord; + +varying vec2 v_texcoord; + +//! [0] +void main() +{ + // Calculate vertex position in screen space + gl_Position = mvp_matrix * a_position; + + // Pass texture coordinate to fragment shader + // Value will be automatically interpolated to fragments inside polygon faces + v_texcoord = a_texcoord; +} +//! [0] diff --git a/QtMeshViewer/Source/GeometryEngine.cpp b/QtMeshViewer/Source/GeometryEngine.cpp new file mode 100644 index 0000000..21e1703 --- /dev/null +++ b/QtMeshViewer/Source/GeometryEngine.cpp @@ -0,0 +1,179 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "..\Header\GeometryEngine.h" + +#include +#include + +struct VertexData +{ + QVector3D position; + QVector2D texCoord; +}; + +//! [0] +GeometryEngine::GeometryEngine() + : indexBuf(QOpenGLBuffer::IndexBuffer) +{ + initializeOpenGLFunctions(); + + // Generate 2 VBOs + arrayBuf.create(); + indexBuf.create(); + + // Initializes cube geometry and transfers it to VBOs + initCubeGeometry(); +} + +GeometryEngine::~GeometryEngine() +{ + arrayBuf.destroy(); + indexBuf.destroy(); +} +//! [0] + +void GeometryEngine::initCubeGeometry() +{ + // For cube we would need only 8 vertices but we have to + // duplicate vertex for each face because texture coordinate + // is different. + VertexData vertices[] = { + // Vertex data for face 0 + {QVector3D(-1.0f, -1.0f, 1.0f), QVector2D(0.0f, 0.0f)}, // v0 + {QVector3D( 1.0f, -1.0f, 1.0f), QVector2D(0.33f, 0.0f)}, // v1 + {QVector3D(-1.0f, 1.0f, 1.0f), QVector2D(0.0f, 0.5f)}, // v2 + {QVector3D( 1.0f, 1.0f, 1.0f), QVector2D(0.33f, 0.5f)}, // v3 + + // Vertex data for face 1 + {QVector3D( 1.0f, -1.0f, 1.0f), QVector2D( 0.0f, 0.5f)}, // v4 + {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.33f, 0.5f)}, // v5 + {QVector3D( 1.0f, 1.0f, 1.0f), QVector2D(0.0f, 1.0f)}, // v6 + {QVector3D( 1.0f, 1.0f, -1.0f), QVector2D(0.33f, 1.0f)}, // v7 + + // Vertex data for face 2 + {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.5f)}, // v8 + {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(1.0f, 0.5f)}, // v9 + {QVector3D( 1.0f, 1.0f, -1.0f), QVector2D(0.66f, 1.0f)}, // v10 + {QVector3D(-1.0f, 1.0f, -1.0f), QVector2D(1.0f, 1.0f)}, // v11 + + // Vertex data for face 3 + {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.0f)}, // v12 + {QVector3D(-1.0f, -1.0f, 1.0f), QVector2D(1.0f, 0.0f)}, // v13 + {QVector3D(-1.0f, 1.0f, -1.0f), QVector2D(0.66f, 0.5f)}, // v14 + {QVector3D(-1.0f, 1.0f, 1.0f), QVector2D(1.0f, 0.5f)}, // v15 + + // Vertex data for face 4 + {QVector3D(-1.0f, -1.0f, -1.0f), QVector2D(0.33f, 0.0f)}, // v16 + {QVector3D( 1.0f, -1.0f, -1.0f), QVector2D(0.66f, 0.0f)}, // v17 + {QVector3D(-1.0f, -1.0f, 1.0f), QVector2D(0.33f, 0.5f)}, // v18 + {QVector3D( 1.0f, -1.0f, 1.0f), QVector2D(0.66f, 0.5f)}, // v19 + + // Vertex data for face 5 + {QVector3D(-1.0f, 1.0f, 1.0f), QVector2D(0.33f, 0.5f)}, // v20 + {QVector3D( 1.0f, 1.0f, 1.0f), QVector2D(0.66f, 0.5f)}, // v21 + {QVector3D(-1.0f, 1.0f, -1.0f), QVector2D(0.33f, 1.0f)}, // v22 + {QVector3D( 1.0f, 1.0f, -1.0f), QVector2D(0.66f, 1.0f)} // v23 + }; + + // Indices for drawing cube faces using triangle strips. + // Triangle strips can be connected by duplicating indices + // between the strips. If connecting strips have opposite + // vertex order then last index of the first strip and first + // index of the second strip needs to be duplicated. If + // connecting strips have same vertex order then only last + // index of the first strip needs to be duplicated. + GLushort indices[] = { + 0, 1, 2, 3, 3, // Face 0 - triangle strip ( v0, v1, v2, v3) + 4, 4, 5, 6, 7, 7, // Face 1 - triangle strip ( v4, v5, v6, v7) + 8, 8, 9, 10, 11, 11, // Face 2 - triangle strip ( v8, v9, v10, v11) + 12, 12, 13, 14, 15, 15, // Face 3 - triangle strip (v12, v13, v14, v15) + 16, 16, 17, 18, 19, 19, // Face 4 - triangle strip (v16, v17, v18, v19) + 20, 20, 21, 22, 23 // Face 5 - triangle strip (v20, v21, v22, v23) + }; + +//! [1] + // Transfer vertex data to VBO 0 + arrayBuf.bind(); + arrayBuf.allocate(vertices, 24 * sizeof(VertexData)); + + // Transfer index data to VBO 1 + indexBuf.bind(); + indexBuf.allocate(indices, 34 * sizeof(GLushort)); +//! [1] +} + +//! [2] +void GeometryEngine::drawCubeGeometry(QOpenGLShaderProgram *program) +{ + // Tell OpenGL which VBOs to use + arrayBuf.bind(); + indexBuf.bind(); + + // Offset for position + quintptr offset = 0; + + // Tell OpenGL programmable pipeline how to locate vertex position data + int vertexLocation = program->attributeLocation("a_position"); + program->enableAttributeArray(vertexLocation); + program->setAttributeBuffer(vertexLocation, GL_FLOAT, offset, 3, sizeof(VertexData)); + + // Offset for texture coordinate + offset += sizeof(QVector3D); + + // Tell OpenGL programmable pipeline how to locate vertex texture coordinate data + int texcoordLocation = program->attributeLocation("a_texcoord"); + program->enableAttributeArray(texcoordLocation); + program->setAttributeBuffer(texcoordLocation, GL_FLOAT, offset, 2, sizeof(VertexData)); + + // Draw cube geometry using indices from VBO 1 + glDrawElements(GL_TRIANGLE_STRIP, 34, GL_UNSIGNED_SHORT, 0); +} +//! [2] diff --git a/QtMeshViewer/Source/MainWindow.cpp b/QtMeshViewer/Source/MainWindow.cpp new file mode 100644 index 0000000..57860fd --- /dev/null +++ b/QtMeshViewer/Source/MainWindow.cpp @@ -0,0 +1,24 @@ +#include "..\Header\MainWindow.h" +#include "..\Header\OglViewerWidget.h" +#include + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindowClass) +{ + ui->setupUi(this); + + QSurfaceFormat format; + format.setDepthBufferSize(24); + QSurfaceFormat::setDefaultFormat(format); + + this->setCentralWidget(new OglViewerWidget(this)); + + ui->statusBar->showMessage("haha vbgf"); +} + + +MainWindow::~MainWindow() +{ + delete ui; +} \ No newline at end of file diff --git a/QtMeshViewer/Source/OglViewerWidget.cpp b/QtMeshViewer/Source/OglViewerWidget.cpp new file mode 100644 index 0000000..e83c85f --- /dev/null +++ b/QtMeshViewer/Source/OglViewerWidget.cpp @@ -0,0 +1,157 @@ +#include "..\Header\OglViewerWidget.h" + +#include +#include + +OglViewerWidget::OglViewerWidget(QWidget *parent) : + QOpenGLWidget(parent), + geometries(0), + texture(0), + angularSpeed(0) +{ +} + +OglViewerWidget::~OglViewerWidget() +{ + // Make sure the context is current when deleting the texture + // and the buffers. + makeCurrent(); + delete texture; + delete geometries; + doneCurrent(); +} + +void OglViewerWidget::mousePressEvent(QMouseEvent *e) +{ + // Save mouse press position + mousePressPosition = QVector2D(e->localPos()); +} + +void OglViewerWidget::mouseReleaseEvent(QMouseEvent *e) +{ + // Mouse release position - mouse press position + QVector2D diff = QVector2D(e->localPos()) - mousePressPosition; + + // Rotation axis is perpendicular to the mouse position difference + // vector + QVector3D n = QVector3D(diff.y(), diff.x(), 0.0).normalized(); + + // Accelerate angular speed relative to the length of the mouse sweep + qreal acc = diff.length() / 100.0; + + // Calculate new rotation axis as weighted sum + rotationAxis = (rotationAxis * angularSpeed + n * acc).normalized(); + + // Increase angular speed + angularSpeed += acc; +} + +void OglViewerWidget::timerEvent(QTimerEvent *) +{ + // Decrease angular speed (friction) + angularSpeed *= 0.99; + + // Stop rotation when speed goes below threshold + if (angularSpeed < 0.01) { + angularSpeed = 0.0; + } else { + // Update rotation + rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angularSpeed) * rotation; + + // Request an update + update(); + } +} + +void OglViewerWidget::initializeGL() +{ + initializeOpenGLFunctions(); + + glClearColor(0, 0, 0, 1); + + initShaders(); + initTextures(); + + // Enable depth buffer + glEnable(GL_DEPTH_TEST); + + // Enable back face culling + glEnable(GL_CULL_FACE); + + geometries = new GeometryEngine; + + // Use QBasicTimer because its faster than QTimer + timer.start(12, this); +} + +void OglViewerWidget::initShaders() +{ + // Compile vertex shader + if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shaders/vshader.glsl")) + close(); + + // Compile fragment shader + if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment, ":/shaders/fshader.glsl")) + close(); + + // Link shader pipeline + if (!program.link()) + close(); + + // Bind shader pipeline for use + if (!program.bind()) + close(); +} + +void OglViewerWidget::initTextures() +{ + // Load cube.png image + texture = new QOpenGLTexture(QImage(":images/cube.png").mirrored()); + + // Set nearest filtering mode for texture minification + texture->setMinificationFilter(QOpenGLTexture::Nearest); + + // Set bilinear filtering mode for texture magnification + texture->setMagnificationFilter(QOpenGLTexture::Linear); + + // Wrap texture coordinates by repeating + // f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2) + texture->setWrapMode(QOpenGLTexture::Repeat); +} + +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 = 3.0, zFar = 7.0, fov = 45.0; + + // Reset projection + projection.setToIdentity(); + + // Set perspective projection + projection.perspective(fov, aspect, zNear, zFar); +} + +void OglViewerWidget::paintGL() +{ + // Clear color and depth buffer + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + texture->bind(); + + // Calculate model view transformation + QMatrix4x4 matrix; + matrix.translate(0.0, 0.0, -5.0); + matrix.rotate(rotation); + + // Set modelview-projection matrix + program.setUniformValue("mvp_matrix", projection * matrix); + + // Use texture unit 0 which contains cube.png + program.setUniformValue("texture", 0); + + // Draw cube geometry + geometries->drawCubeGeometry(&program); +} diff --git a/QtMeshViewer/main.cpp b/QtMeshViewer/main.cpp new file mode 100644 index 0000000..f4ddde4 --- /dev/null +++ b/QtMeshViewer/main.cpp @@ -0,0 +1,12 @@ +#include "Header\MainWindow.h" +#include + + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + MainWindow w; + w.show(); + return a.exec(); +}