3aeb21ee2fd4a91bc4137e24e607c625234d2d69
[profile/ivi/qtbase.git] / examples / opengl / cube / mainwidget.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
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
19 **     distribution.
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.
23 **
24 **
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."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41 #include "mainwidget.h"
42
43 #include "geometryengine.h"
44
45 #include <QtOpenGL/QGLShaderProgram>
46
47 #include <QBasicTimer>
48 #include <QMouseEvent>
49 #include <QDebug>
50
51 #include <math.h>
52 #include <locale.h>
53
54 MainWidget::MainWidget(QWidget *parent) :
55     QGLWidget(parent),
56     timer(new QBasicTimer),
57     program(new QGLShaderProgram),
58     geometries(new GeometryEngine)
59 {
60 }
61
62 MainWidget::~MainWidget()
63 {
64     delete timer; timer = 0;
65     delete program; program = 0;
66     delete geometries; geometries = 0;
67
68     deleteTexture(texture);
69 }
70
71 //! [0]
72 void MainWidget::mousePressEvent(QMouseEvent *e)
73 {
74     // Saving mouse press position
75     mousePressPosition = QVector2D(e->localPos());
76 }
77
78 void MainWidget::mouseReleaseEvent(QMouseEvent *e)
79 {
80     // Mouse release position - mouse press position
81     QVector2D diff = QVector2D(e->localPos()) - mousePressPosition;
82
83     // Rotation axis is perpendicular to the mouse position difference 
84     // vector
85     QVector3D n = QVector3D(diff.y(), diff.x(), 0.0).normalized();
86
87     // Accelerate angular speed relative to the length of the mouse sweep
88     qreal acc = diff.length() / 100.0;
89
90     // Calculate new rotation axis as weighted sum
91     rotationAxis = (rotationAxis * angularSpeed + n * acc).normalized();
92
93     // Increase angular speed
94     angularSpeed += acc;
95 }
96 //! [0]
97
98 //! [1]
99 void MainWidget::timerEvent(QTimerEvent *e)
100 {
101     Q_UNUSED(e);
102
103     // Decrease angular speed (friction)
104     angularSpeed *= 0.99;
105
106     // Stop rotation when speed goes below threshold
107     if (angularSpeed < 0.01)
108         angularSpeed = 0.0;
109     else {
110         // Update rotation
111         rotation = QQuaternion::fromAxisAndAngle(rotationAxis, angularSpeed) * rotation;
112
113         // Update scene
114         updateGL();
115     }
116 }
117 //! [1]
118
119 void MainWidget::initializeGL()
120 {
121     initializeGLFunctions();
122
123     qglClearColor(Qt::black);
124
125     qDebug() << "Initializing shaders...";
126     initShaders();
127
128     qDebug() << "Initializing textures...";
129     initTextures();
130
131 //! [2]
132     // Enable depth buffer
133     glEnable(GL_DEPTH_TEST);
134
135     // Enable back face culling
136     glEnable(GL_CULL_FACE);
137 //! [2]
138
139     qDebug() << "Initializing geometries...";
140     geometries->init();
141
142     // using QBasicTimer because its faster that QTimer
143     timer->start(12, this);
144 }
145
146 //! [3]
147 void MainWidget::initShaders()
148 {
149     // Overriding system locale until shaders are compiled
150     setlocale(LC_NUMERIC, "C");
151
152     // Compiling vertex shader
153     if (!program->addShaderFromSourceFile(QGLShader::Vertex, ":/vshader.glsl"))
154         close();
155
156     // Compiling fragment shader
157     if (!program->addShaderFromSourceFile(QGLShader::Fragment, ":/fshader.glsl"))
158         close();
159
160     // Linking shader pipeline
161     if (!program->link())
162         close();
163
164     // Binding shader pipeline for use
165     if (!program->bind())
166         close();
167
168     // Restore system locale
169     setlocale(LC_ALL, "");
170 }
171 //! [3]
172
173 //! [4]
174 void MainWidget::initTextures()
175 {
176     // Loading cube.png to texture unit 0
177     glActiveTexture(GL_TEXTURE0);
178     glEnable(GL_TEXTURE_2D);
179     texture = bindTexture(QImage(":/cube.png"));
180
181     // Set nearest filtering mode for texture minification
182     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
183
184     // Set bilinear filtering mode for texture magnification
185     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
186
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);
191 }
192 //! [4]
193
194 //! [5]
195 void MainWidget::resizeGL(int w, int h)
196 {
197     // Set OpenGL viewport to cover whole widget
198     glViewport(0, 0, w, h);
199
200     // Calculate aspect ratio
201     qreal aspect = (qreal)w / ((qreal)h?h:1);
202
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;
205
206     // Reset projection
207     projection.setToIdentity();
208
209     // Set perspective projection
210     projection.perspective(fov, aspect, zNear, zFar);
211 }
212 //! [5]
213
214 void MainWidget::paintGL()
215 {
216     // Clear color and depth buffer
217     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
218
219 //! [6]
220     // Calculate model view transformation
221     QMatrix4x4 matrix;
222     matrix.translate(0.0, 0.0, -5.0);
223     matrix.rotate(rotation);
224
225     // Set modelview-projection matrix
226     program->setUniformValue("mvp_matrix", projection * matrix);
227 //! [6]
228
229     // Using texture unit 0 which contains cube.png
230     program->setUniformValue("texture", 0);
231
232     // Draw cube geometry
233     geometries->drawCubeGeometry(program);
234 }