1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtCore module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
14 ** * Redistributions of source code must retain the above copyright
15 ** notice, this list of conditions and the following disclaimer.
16 ** * Redistributions in binary form must reproduce the above copyright
17 ** notice, this list of conditions and the following disclaimer in
18 ** the documentation and/or other materials provided with the
20 ** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21 ** of its contributors may be used to endorse or promote products derived
22 ** from this software without specific prior written permission.
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
39 ****************************************************************************/
41 #include "mainwidget.h"
43 #include "geometryengine.h"
45 #include <QtOpenGL/QGLShaderProgram>
47 #include <QBasicTimer>
48 #include <QMouseEvent>
54 MainWidget::MainWidget(QWidget *parent) :
56 timer(new QBasicTimer),
57 program(new QGLShaderProgram),
58 geometries(new GeometryEngine)
62 MainWidget::~MainWidget()
64 delete timer; timer = 0;
65 delete program; program = 0;
66 delete geometries; geometries = 0;
68 deleteTexture(texture);
72 void MainWidget::mousePressEvent(QMouseEvent *e)
74 // Saving mouse press position
75 mousePressPosition = QVector2D(e->localPos());
78 void MainWidget::mouseReleaseEvent(QMouseEvent *e)
80 // Mouse release position - mouse press position
81 QVector2D diff = QVector2D(e->localPos()) - mousePressPosition;
83 // Rotation axis is perpendicular to the mouse position difference
85 QVector3D n = QVector3D(diff.y(), diff.x(), 0.0).normalized();
87 // Accelerate angular speed relative to the length of the mouse sweep
88 qreal acc = diff.length() / 100.0;
90 // Calculate new rotation axis as weighted sum
91 rotationAxis = (rotationAxis * angularSpeed + n * acc).normalized();
93 // Increase angular speed
99 void MainWidget::timerEvent(QTimerEvent *e)
103 // Decrease angular speed (friction)
104 angularSpeed *= 0.99;
106 // Stop rotation when speed goes below threshold
107 if (angularSpeed < 0.01)
111 rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angularSpeed) * rotation;
119 void MainWidget::initializeGL()
121 initializeGLFunctions();
123 qglClearColor(Qt::black);
125 qDebug() << "Initializing shaders...";
128 qDebug() << "Initializing textures...";
132 // Enable depth buffer
133 glEnable(GL_DEPTH_TEST);
135 // Enable back face culling
136 glEnable(GL_CULL_FACE);
139 qDebug() << "Initializing geometries...";
142 // using QBasicTimer because its faster that QTimer
143 timer->start(12, this);
147 void MainWidget::initShaders()
149 // Overriding system locale until shaders are compiled
150 setlocale(LC_NUMERIC, "C");
152 // Compiling vertex shader
153 if (!program->addShaderFromSourceFile(QGLShader::Vertex, ":/vshader.glsl"))
156 // Compiling fragment shader
157 if (!program->addShaderFromSourceFile(QGLShader::Fragment, ":/fshader.glsl"))
160 // Linking shader pipeline
161 if (!program->link())
164 // Binding shader pipeline for use
165 if (!program->bind())
168 // Restore system locale
169 setlocale(LC_ALL, "");
174 void MainWidget::initTextures()
176 // Loading cube.png to texture unit 0
177 glActiveTexture(GL_TEXTURE0);
178 glEnable(GL_TEXTURE_2D);
179 texture = bindTexture(QImage(":/cube.png"));
181 // Set nearest filtering mode for texture minification
182 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
184 // Set bilinear filtering mode for texture magnification
185 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
187 // Wrap texture coordinates by repeating
188 // f.ex. texture coordinate (1.1, 1.2) is same as (0.1, 0.2)
189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
190 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
195 void MainWidget::resizeGL(int w, int h)
197 // Set OpenGL viewport to cover whole widget
198 glViewport(0, 0, w, h);
200 // Calculate aspect ratio
201 qreal aspect = (qreal)w / ((qreal)h?h:1);
203 // Set near plane to 3.0, far plane to 7.0, field of view 45 degrees
204 const qreal zNear = 3.0, zFar = 7.0, fov = 45.0;
207 projection.setToIdentity();
209 // Set perspective projection
210 projection.perspective(fov, aspect, zNear, zFar);
214 void MainWidget::paintGL()
216 // Clear color and depth buffer
217 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
220 // Calculate model view transformation
222 matrix.translate(0.0, 0.0, -5.0);
223 matrix.rotate(rotation);
225 // Set modelview-projection matrix
226 program->setUniformValue("mvp_matrix", projection * matrix);
229 // Using texture unit 0 which contains cube.png
230 program->setUniformValue("texture", 0);
232 // Draw cube geometry
233 geometries->drawCubeGeometry(program);