20
21
** ensure the GNU Lesser General Public License version 2.1 requirements
21
22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23
** In addition, as a special exception, Nokia gives you certain
24
** additional rights. These rights are described in the Nokia Qt LGPL
25
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
28
** GNU General Public License Usage
29
** Alternatively, this file may be used under the terms of the GNU
30
** General Public License version 3.0 as published by the Free Software
31
** Foundation and appearing in the file LICENSE.GPL included in the
32
** packaging of this file. Please review the following information to
33
** ensure the GNU General Public License version 3.0 requirements will be
34
** met: http://www.gnu.org/copyleft/gpl.html.
36
** If you are unsure which license is appropriate for your use, please
37
** contact the sales department at http://www.qtsoftware.com/contact.
24
** In addition, as a special exception, Nokia gives you certain additional
25
** rights. These rights are described in the Nokia Qt LGPL Exception
26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
38
38
** $QT_END_LICENSE$
40
40
****************************************************************************/
42
42
#include "glwidget.h"
43
43
#include <QPainter>
44
#include <QPaintEngine>
46
47
#include "bubble.h"
49
50
const int bubbleNum = 8;
51
inline void CrossProduct(qreal &xOut, qreal &yOut, qreal &zOut, qreal x1, qreal y1, qreal z1, qreal x2, qreal y2, qreal z2)
53
xOut = y1 * z2 - z1 * y2;
54
yOut = z1 * x2 - x1 * z2;
55
zOut = x1 * y2 - y1 * x2;
58
inline void Normalize(qreal &x, qreal &y, qreal &z)
60
qreal l = sqrt(x*x + y*y + z*z);
66
inline void IdentityMatrix(GLfloat *m)
86
// Adjust a 4x4 matrix to apply a scale.
87
inline void ScaleMatrix(GLfloat *m, GLfloat scalex, GLfloat scaley, GLfloat scalez)
89
m[0 * 4 + 0] *= scalex;
90
m[0 * 4 + 1] *= scalex;
91
m[0 * 4 + 2] *= scalex;
92
m[0 * 4 + 3] *= scalex;
93
m[1 * 4 + 0] *= scaley;
94
m[1 * 4 + 1] *= scaley;
95
m[1 * 4 + 2] *= scaley;
96
m[1 * 4 + 3] *= scaley;
97
m[2 * 4 + 0] *= scalez;
98
m[2 * 4 + 1] *= scalez;
99
m[2 * 4 + 2] *= scalez;
100
m[2 * 4 + 3] *= scalez;
103
// Adjust a 4x4 matrix to apply a translation.
104
inline void TranslateMatrix(GLfloat *m, GLfloat translatex, GLfloat translatey, GLfloat translatez)
106
m[3 * 4 + 0] += m[0 * 4 + 0] * translatex + m[1 * 4 + 0] * translatey + m[2 * 4 + 0] * translatez;
107
m[3 * 4 + 1] += m[0 * 4 + 1] * translatex + m[1 * 4 + 1] * translatey + m[2 * 4 + 1] * translatez;
108
m[3 * 4 + 2] += m[0 * 4 + 2] * translatex + m[1 * 4 + 2] * translatey + m[2 * 4 + 2] * translatez;
109
m[3 * 4 + 3] += m[0 * 4 + 3] * translatex + m[1 * 4 + 3] * translatey + m[2 * 4 + 3] * translatez;
113
#define M_PI 3.14159265358979323846
116
// Adjust a 4x4 matrix to apply a rotation.
117
inline void RotateMatrix(GLfloat *m, GLfloat angle, GLfloat vx, GLfloat vy, GLfloat vz)
119
GLfloat len = sqrt(vx * vx + vy * vy + vz * vz);
127
c = cos(angle * M_PI / 180.0);
128
s = sin(angle * M_PI / 180.0);
132
rot[0 * 4 + 0] = vx * vx * ic + c;
133
rot[1 * 4 + 0] = vx * vy * ic - vz * s;
134
rot[2 * 4 + 0] = vx * vz * ic + vy * s;
135
rot[3 * 4 + 0] = 0.0f;
136
rot[0 * 4 + 1] = vy * vx * ic + vz * s;
137
rot[1 * 4 + 1] = vy * vy * ic + c;
138
rot[2 * 4 + 1] = vy * vz * ic - vx * s;
139
rot[3 * 4 + 1] = 0.0f;
140
rot[0 * 4 + 2] = vx * vz * ic - vy * s;
141
rot[1 * 4 + 2] = vy * vz * ic + vx * s;
142
rot[2 * 4 + 2] = vz * vz * ic + c;
143
rot[3 * 4 + 2] = 0.0f;
144
rot[0 * 4 + 3] = 0.0f;
145
rot[1 * 4 + 3] = 0.0f;
146
rot[2 * 4 + 3] = 0.0f;
147
rot[3 * 4 + 3] = 1.0f;
150
for (int i = 0; i < 4; ++i) {
151
for (int j = 0; j < 4; ++j) {
152
temp[j * 4 + i] = 0.0f;
153
for (int k = 0; k < 4; ++k) {
154
temp[j * 4 + i] += m[k * 4 + i] * rot[j * 4 + k];
159
qMemCopy(m, temp, sizeof(temp));
162
52
GLWidget::GLWidget(QWidget *parent)
163
53
: QGLWidget(parent)
170
57
setAttribute(Qt::WA_PaintOnScreen);
171
58
setAttribute(Qt::WA_NoSystemBackground);
210
93
void GLWidget::paintQtLogo()
212
glDisable(GL_TEXTURE_2D);
213
glVertexAttribPointer(vertexAttr1, 3, GL_FLOAT, GL_FALSE, 0, createdVertices);
214
glEnableVertexAttribArray(vertexAttr1);
215
glVertexAttribPointer(normalAttr1, 3, GL_FLOAT, GL_FALSE, 0, createdNormals);
216
glEnableVertexAttribArray(normalAttr1);
217
glDrawArrays(GL_TRIANGLES, 0, m_vertexNumber / 3);
218
glDisableVertexAttribArray(normalAttr1);
219
glDisableVertexAttribArray(vertexAttr1);
95
program1.setAttributeArray(vertexAttr1, vertices.constData());
96
program1.setAttributeArray(normalAttr1, normals.constData());
97
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
98
program1.disableAttributeArray(normalAttr1);
99
program1.disableAttributeArray(vertexAttr1);
222
102
void GLWidget::paintTexturedCube()
224
glEnable(GL_TEXTURE_2D);
225
104
glBindTexture(GL_TEXTURE_2D, m_uiTexture);
226
105
GLfloat afVertices[] = {
227
106
-0.5, 0.5, 0.5, 0.5,-0.5,0.5,-0.5,-0.5,0.5,
239
118
-0.5, -0.5, -0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5,
240
119
0.5, -0.5, 0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 0.5
242
glVertexAttribPointer(vertexAttr2, 3, GL_FLOAT, GL_FALSE, 0, afVertices);
243
glEnableVertexAttribArray(vertexAttr2);
121
program2.setAttributeArray(vertexAttr2, afVertices, 3);
245
123
GLfloat afTexCoord[] = {
246
124
0.0f,0.0f, 1.0f,1.0f, 1.0f,0.0f,
278
155
0,1,0, 0,1,0, 0,1,0,
279
156
0,1,0, 0,1,0, 0,1,0
281
glVertexAttribPointer(normalAttr2, 3, GL_FLOAT, GL_FALSE, 0, afNormals);
282
glEnableVertexAttribArray(normalAttr2);
158
program2.setAttributeArray(normalAttr2, afNormals, 3);
284
glUniform1i(textureUniform2, 0); // use texture unit 0
160
program2.setUniformValue(textureUniform2, 0); // use texture unit 0
286
162
glDrawArrays(GL_TRIANGLES, 0, 36);
288
glDisableVertexAttribArray(vertexAttr2);
289
glDisableVertexAttribArray(normalAttr2);
290
glDisableVertexAttribArray(texCoordAttr2);
293
static void reportCompileErrors(GLuint shader, const char *src)
296
glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
297
bool compiled = (value != 0);
299
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &value);
300
if (!compiled && value > 1) {
301
char *log = new char [value];
303
glGetShaderInfoLog(shader, value, &len, log);
304
qWarning("%s\n", log);
305
qWarning("when compiling:\n%s\n", src);
310
static void reportLinkErrors(GLuint program, const char *vsrc, const char *fsrc)
313
glGetProgramiv(program, GL_LINK_STATUS, &value);
314
bool linked = (value != 0);
316
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &value);
317
if (!linked && value > 1) {
318
char *log = new char [value];
320
glGetProgramInfoLog(program, value, &len, log);
321
qWarning("%s\n", log);
322
qWarning("when linking:\n%s\nwith:\n%s\n", vsrc, fsrc);
164
program2.disableAttributeArray(vertexAttr2);
165
program2.disableAttributeArray(normalAttr2);
166
program2.disableAttributeArray(texCoordAttr2);
327
169
void GLWidget::initializeGL ()
329
171
glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
331
glEnable(GL_TEXTURE_2D);
332
173
glGenTextures(1, &m_uiTexture);
333
174
m_uiTexture = bindTexture(QImage(":/qt.png"));
335
GLuint vshader1 = glCreateShader(GL_VERTEX_SHADER);
336
const char *vsrc1[1] = {
176
QGLShader *vshader1 = new QGLShader(QGLShader::VertexShader, this);
337
178
"attribute highp vec4 vertex;\n"
338
179
"attribute mediump vec3 normal;\n"
339
180
"uniform mediump mat4 matrix;\n"
346
187
" color = vec4(col * 0.2 + col * 0.8 * angle, 1.0);\n"
347
188
" color = clamp(color, 0.0, 1.0);\n"
348
189
" gl_Position = matrix * vertex;\n"
351
glShaderSource(vshader1, 1, vsrc1, 0);
352
glCompileShader(vshader1);
353
reportCompileErrors(vshader1, vsrc1[0]);
191
vshader1->compile(vsrc1);
355
GLuint fshader1 = glCreateShader(GL_FRAGMENT_SHADER);
356
const char *fsrc1[1] = {
193
QGLShader *fshader1 = new QGLShader(QGLShader::FragmentShader, this);
357
195
"varying mediump vec4 color;\n"
358
196
"void main(void)\n"
360
198
" gl_FragColor = color;\n"
363
glShaderSource(fshader1, 1, fsrc1, 0);
364
glCompileShader(fshader1);
365
reportCompileErrors(fshader1, fsrc1[0]);
367
program1 = glCreateProgram();
368
glAttachShader(program1, vshader1);
369
glAttachShader(program1, fshader1);
370
glLinkProgram(program1);
371
reportLinkErrors(program1, vsrc1[0], fsrc1[0]);
373
vertexAttr1 = glGetAttribLocation(program1, "vertex");
374
normalAttr1 = glGetAttribLocation(program1, "normal");
375
matrixUniform1 = glGetUniformLocation(program1, "matrix");
377
GLuint vshader2 = glCreateShader(GL_VERTEX_SHADER);
378
const char *vsrc2[1] = {
200
fshader1->compile(fsrc1);
202
program1.addShader(vshader1);
203
program1.addShader(fshader1);
206
vertexAttr1 = program1.attributeLocation("vertex");
207
normalAttr1 = program1.attributeLocation("normal");
208
matrixUniform1 = program1.uniformLocation("matrix");
210
QGLShader *vshader2 = new QGLShader(QGLShader::VertexShader);
379
212
"attribute highp vec4 vertex;\n"
380
213
"attribute highp vec4 texCoord;\n"
381
214
"attribute mediump vec3 normal;\n"
404
234
" highp vec3 color = texture2D(tex, texc.st).rgb;\n"
405
235
" color = color * 0.2 + color * 0.8 * angle;\n"
406
236
" gl_FragColor = vec4(clamp(color, 0.0, 1.0), 1.0);\n"
409
glShaderSource(fshader2, 1, fsrc2, 0);
410
glCompileShader(fshader2);
411
reportCompileErrors(fshader2, fsrc2[0]);
413
program2 = glCreateProgram();
414
glAttachShader(program2, vshader2);
415
glAttachShader(program2, fshader2);
416
glLinkProgram(program2);
417
reportLinkErrors(program2, vsrc2[0], fsrc2[0]);
419
vertexAttr2 = glGetAttribLocation(program2, "vertex");
420
normalAttr2 = glGetAttribLocation(program2, "normal");
421
texCoordAttr2 = glGetAttribLocation(program2, "texCoord");
422
matrixUniform2 = glGetUniformLocation(program2, "matrix");
423
textureUniform2 = glGetUniformLocation(program2, "tex");
238
fshader2->compile(fsrc2);
240
program2.addShader(vshader2);
241
program2.addShader(fshader2);
244
vertexAttr2 = program2.attributeLocation("vertex");
245
normalAttr2 = program2.attributeLocation("normal");
246
texCoordAttr2 = program2.attributeLocation("texCoord");
247
matrixUniform2 = program2.uniformLocation("matrix");
248
textureUniform2 = program2.uniformLocation("tex");
425
250
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
426
251
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
450
276
glEnable(GL_CULL_FACE);
451
277
glEnable(GL_DEPTH_TEST);
453
GLfloat modelview[16];
454
IdentityMatrix(modelview);
455
RotateMatrix(modelview, m_fAngle, 0.0, 1.0, 0.0);
456
RotateMatrix(modelview, m_fAngle, 1.0, 0.0, 0.0);
457
RotateMatrix(modelview, m_fAngle, 0.0, 0.0, 1.0);
458
ScaleMatrix(modelview, m_fScale, m_fScale, m_fScale);
459
TranslateMatrix(modelview, 0, -0.2, 0);
279
QMatrix4x4 modelview;
280
modelview.rotate(m_fAngle, 0.0f, 1.0f, 0.0f);
281
modelview.rotate(m_fAngle, 1.0f, 0.0f, 0.0f);
282
modelview.rotate(m_fAngle, 0.0f, 0.0f, 1.0f);
283
modelview.scale(m_fScale);
284
modelview.translate(0.0f, -0.2f, 0.0f);
462
glUseProgram(program1);
463
glUniformMatrix4fv(matrixUniform1, 1, GL_FALSE, modelview);
288
program1.setUniformValue(matrixUniform1, modelview);
467
glUseProgram(program2);
468
glUniformMatrix4fv(matrixUniform2, 1, GL_FALSE, modelview);
293
program1.setUniformValue(matrixUniform2, modelview);
469
294
paintTexturedCube();
473
298
glDisable(GL_DEPTH_TEST);
474
299
glDisable(GL_CULL_FACE);
301
painter.endNativePainting();
476
303
if (m_showBubbles)
477
304
foreach (Bubble *bubble, bubbles) {
478
305
bubble->drawBubble(&painter);
563
390
extrude(x8, y8, x5, y5);
566
m_vertexNumber = vertices.size();
567
createdVertices = new GLfloat[m_vertexNumber];
568
createdNormals = new GLfloat[m_vertexNumber];
569
for (int i = 0;i < m_vertexNumber;i++) {
570
createdVertices[i] = vertices.at(i) * 2;
571
createdNormals[i] = normals.at(i);
393
for (int i = 0;i < vertices.size();i++)
577
397
void GLWidget::quad(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4)
581
vertices << x1 << y1 << -0.05f;
582
vertices << x2 << y2 << -0.05f;
583
vertices << x4 << y4 << -0.05f;
585
vertices << x3 << y3 << -0.05f;
586
vertices << x4 << y4 << -0.05f;
587
vertices << x2 << y2 << -0.05f;
589
CrossProduct(nx, ny, nz, x2 - x1, y2 - y1, 0, x4 - x1, y4 - y1, 0);
590
Normalize(nx, ny, nz);
592
normals << nx << ny << nz;
593
normals << nx << ny << nz;
594
normals << nx << ny << nz;
596
normals << nx << ny << nz;
597
normals << nx << ny << nz;
598
normals << nx << ny << nz;
600
vertices << x4 << y4 << 0.05f;
601
vertices << x2 << y2 << 0.05f;
602
vertices << x1 << y1 << 0.05f;
604
vertices << x2 << y2 << 0.05f;
605
vertices << x4 << y4 << 0.05f;
606
vertices << x3 << y3 << 0.05f;
608
CrossProduct(nx, ny, nz, x2 - x4, y2 - y4, 0, x1 - x4, y1 - y4, 0);
609
Normalize(nx, ny, nz);
611
normals << nx << ny << nz;
612
normals << nx << ny << nz;
613
normals << nx << ny << nz;
615
normals << nx << ny << nz;
616
normals << nx << ny << nz;
617
normals << nx << ny << nz;
399
vertices << QVector3D(x1, y1, -0.05f);
400
vertices << QVector3D(x2, y2, -0.05f);
401
vertices << QVector3D(x4, y4, -0.05f);
403
vertices << QVector3D(x3, y3, -0.05f);
404
vertices << QVector3D(x4, y4, -0.05f);
405
vertices << QVector3D(x2, y2, -0.05f);
407
QVector3D n = QVector3D::normal
408
(QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(x4 - x1, y4 - y1, 0.0f));
418
vertices << QVector3D(x4, y4, 0.05f);
419
vertices << QVector3D(x2, y2, 0.05f);
420
vertices << QVector3D(x1, y1, 0.05f);
422
vertices << QVector3D(x2, y2, 0.05f);
423
vertices << QVector3D(x4, y4, 0.05f);
424
vertices << QVector3D(x3, y3, 0.05f);
426
n = QVector3D::normal
427
(QVector3D(x2 - x4, y2 - y4, 0.0f), QVector3D(x1 - x4, y1 - y4, 0.0f));
620
438
void GLWidget::extrude(qreal x1, qreal y1, qreal x2, qreal y2)
624
vertices << x1 << y1 << +0.05f;
625
vertices << x2 << y2 << +0.05f;
626
vertices << x1 << y1 << -0.05f;
628
vertices << x2 << y2 << -0.05f;
629
vertices << x1 << y1 << -0.05f;
630
vertices << x2 << y2 << +0.05f;
632
CrossProduct(nx, ny, nz, x2 - x1, y2 - y1, 0.0f, 0.0f, 0.0f, -0.1f);
633
Normalize(nx, ny, nz);
635
normals << nx << ny << nz;
636
normals << nx << ny << nz;
637
normals << nx << ny << nz;
639
normals << nx << ny << nz;
640
normals << nx << ny << nz;
641
normals << nx << ny << nz;
440
vertices << QVector3D(x1, y1, +0.05f);
441
vertices << QVector3D(x2, y2, +0.05f);
442
vertices << QVector3D(x1, y1, -0.05f);
444
vertices << QVector3D(x2, y2, -0.05f);
445
vertices << QVector3D(x1, y1, -0.05f);
446
vertices << QVector3D(x2, y2, +0.05f);
448
QVector3D n = QVector3D::normal
449
(QVector3D(x2 - x1, y2 - y1, 0.0f), QVector3D(0.0f, 0.0f, -0.1f));