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 0000000..42c8c51
Binary files /dev/null and b/QtMeshViewer/Resources/cube.png differ
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 0000000..3a2186f
Binary files /dev/null and b/QtMeshViewer/Resources/icon.ico differ
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();
+}