author | Eckhart Koeppen <eckhart.koppen@nokia.com> |
Wed, 21 Apr 2010 20:15:53 +0300 | |
branch | RCL_3 |
changeset 13 | c0432d11811c |
parent 4 | 3b1da2848fc7 |
permissions | -rw-r--r-- |
0 | 1 |
/**************************************************************************** |
2 |
** |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
3 |
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
0 | 4 |
** All rights reserved. |
5 |
** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 |
** |
|
7 |
** This file is part of the demonstration applications of the Qt Toolkit. |
|
8 |
** |
|
9 |
** $QT_BEGIN_LICENSE:LGPL$ |
|
10 |
** No Commercial Usage |
|
11 |
** This file contains pre-release code and may not be distributed. |
|
12 |
** You may use this file in accordance with the terms and conditions |
|
13 |
** contained in the Technology Preview License Agreement accompanying |
|
14 |
** this package. |
|
15 |
** |
|
16 |
** GNU Lesser General Public License Usage |
|
17 |
** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 |
** General Public License version 2.1 as published by the Free Software |
|
19 |
** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 |
** packaging of this file. Please review the following information to |
|
21 |
** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 |
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 |
** |
|
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. |
|
27 |
** |
|
28 |
** If you have questions regarding the use of this file, please contact |
|
29 |
** Nokia at qt-info@nokia.com. |
|
30 |
** |
|
31 |
** |
|
32 |
** |
|
33 |
** |
|
34 |
** |
|
35 |
** |
|
36 |
** |
|
37 |
** |
|
38 |
** $QT_END_LICENSE$ |
|
39 |
** |
|
40 |
****************************************************************************/ |
|
41 |
||
42 |
#include <QDebug> |
|
43 |
#include "scene.h" |
|
44 |
#include <QtGui/qmatrix4x4.h> |
|
45 |
#include <QtGui/qvector3d.h> |
|
46 |
||
47 |
#include "3rdparty/fbm.h" |
|
48 |
||
49 |
void checkGLErrors(const QString& prefix) |
|
50 |
{ |
|
51 |
switch (glGetError()) { |
|
52 |
case GL_NO_ERROR: |
|
53 |
//qDebug() << prefix << tr("No error."); |
|
54 |
break; |
|
55 |
case GL_INVALID_ENUM: |
|
56 |
qDebug() << prefix << QObject::tr("Invalid enum."); |
|
57 |
break; |
|
58 |
case GL_INVALID_VALUE: |
|
59 |
qDebug() << prefix << QObject::tr("Invalid value."); |
|
60 |
break; |
|
61 |
case GL_INVALID_OPERATION: |
|
62 |
qDebug() << prefix << QObject::tr("Invalid operation."); |
|
63 |
break; |
|
64 |
case GL_STACK_OVERFLOW: |
|
65 |
qDebug() << prefix << QObject::tr("Stack overflow."); |
|
66 |
break; |
|
67 |
case GL_STACK_UNDERFLOW: |
|
68 |
qDebug() << prefix << QObject::tr("Stack underflow."); |
|
69 |
break; |
|
70 |
case GL_OUT_OF_MEMORY: |
|
71 |
qDebug() << prefix << QObject::tr("Out of memory."); |
|
72 |
break; |
|
73 |
default: |
|
74 |
qDebug() << prefix << QObject::tr("Unknown error."); |
|
75 |
break; |
|
76 |
} |
|
77 |
} |
|
78 |
||
79 |
//============================================================================// |
|
80 |
// ColorEdit // |
|
81 |
//============================================================================// |
|
82 |
||
83 |
ColorEdit::ColorEdit(QRgb initialColor, int id) |
|
84 |
: m_color(initialColor), m_id(id) |
|
85 |
{ |
|
86 |
QHBoxLayout *layout = new QHBoxLayout; |
|
87 |
setLayout(layout); |
|
88 |
layout->setContentsMargins(0, 0, 0, 0); |
|
89 |
||
90 |
m_lineEdit = new QLineEdit(QString::number(m_color, 16)); |
|
91 |
layout->addWidget(m_lineEdit); |
|
92 |
||
93 |
m_button = new QFrame; |
|
94 |
QPalette palette = m_button->palette(); |
|
95 |
palette.setColor(QPalette::Window, QColor(m_color)); |
|
96 |
m_button->setPalette(palette); |
|
97 |
m_button->setAutoFillBackground(true); |
|
98 |
m_button->setMinimumSize(32, 0); |
|
99 |
m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); |
|
100 |
m_button->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); |
|
101 |
layout->addWidget(m_button); |
|
102 |
||
103 |
connect(m_lineEdit, SIGNAL(editingFinished()), this, SLOT(editDone())); |
|
104 |
} |
|
105 |
||
106 |
void ColorEdit::editDone() |
|
107 |
{ |
|
108 |
bool ok; |
|
109 |
QRgb newColor = m_lineEdit->text().toUInt(&ok, 16); |
|
110 |
if (ok) |
|
111 |
setColor(newColor); |
|
112 |
} |
|
113 |
||
114 |
void ColorEdit::mousePressEvent(QMouseEvent *event) |
|
115 |
{ |
|
116 |
if (event->button() == Qt::LeftButton) { |
|
117 |
QColor color(m_color); |
|
118 |
QColorDialog dialog(color, 0); |
|
119 |
dialog.setOption(QColorDialog::ShowAlphaChannel, true); |
|
120 |
// The ifdef block is a workaround for the beta, TODO: remove when bug 238525 is fixed |
|
121 |
#ifdef Q_WS_MAC |
|
122 |
dialog.setOption(QColorDialog::DontUseNativeDialog, true); |
|
123 |
#endif |
|
124 |
dialog.move(280, 120); |
|
125 |
if (dialog.exec() == QDialog::Rejected) |
|
126 |
return; |
|
127 |
QRgb newColor = dialog.selectedColor().rgba(); |
|
128 |
if (newColor == m_color) |
|
129 |
return; |
|
130 |
setColor(newColor); |
|
131 |
} |
|
132 |
} |
|
133 |
||
134 |
void ColorEdit::setColor(QRgb color) |
|
135 |
{ |
|
136 |
m_color = color; |
|
137 |
m_lineEdit->setText(QString::number(m_color, 16)); // "Clean up" text |
|
138 |
QPalette palette = m_button->palette(); |
|
139 |
palette.setColor(QPalette::Window, QColor(m_color)); |
|
140 |
m_button->setPalette(palette); |
|
141 |
emit colorChanged(m_color, m_id); |
|
142 |
} |
|
143 |
||
144 |
//============================================================================// |
|
145 |
// FloatEdit // |
|
146 |
//============================================================================// |
|
147 |
||
148 |
FloatEdit::FloatEdit(float initialValue, int id) |
|
149 |
: m_value(initialValue), m_id(id) |
|
150 |
{ |
|
151 |
QHBoxLayout *layout = new QHBoxLayout; |
|
152 |
setLayout(layout); |
|
153 |
layout->setContentsMargins(0, 0, 0, 0); |
|
154 |
||
155 |
m_lineEdit = new QLineEdit(QString::number(m_value)); |
|
156 |
layout->addWidget(m_lineEdit); |
|
157 |
||
158 |
connect(m_lineEdit, SIGNAL(editingFinished()), this, SLOT(editDone())); |
|
159 |
} |
|
160 |
||
161 |
void FloatEdit::editDone() |
|
162 |
{ |
|
163 |
bool ok; |
|
164 |
float newValue = m_lineEdit->text().toFloat(&ok); |
|
165 |
if (ok) { |
|
166 |
m_value = newValue; |
|
167 |
m_lineEdit->setText(QString::number(m_value)); // "Clean up" text |
|
168 |
emit valueChanged(m_value, m_id); |
|
169 |
} |
|
170 |
} |
|
171 |
||
172 |
//============================================================================// |
|
173 |
// TwoSidedGraphicsWidget // |
|
174 |
//============================================================================// |
|
175 |
||
176 |
TwoSidedGraphicsWidget::TwoSidedGraphicsWidget(QGraphicsScene *scene) |
|
177 |
: QObject(scene) |
|
178 |
, m_current(0) |
|
179 |
, m_angle(0) |
|
180 |
, m_delta(0) |
|
181 |
{ |
|
182 |
for (int i = 0; i < 2; ++i) |
|
183 |
m_proxyWidgets[i] = 0; |
|
184 |
} |
|
185 |
||
186 |
void TwoSidedGraphicsWidget::setWidget(int index, QWidget *widget) |
|
187 |
{ |
|
188 |
if (index < 0 || index >= 2) |
|
189 |
{ |
|
190 |
qWarning("TwoSidedGraphicsWidget::setWidget: Index out of bounds, index == %d", index); |
|
191 |
return; |
|
192 |
} |
|
193 |
||
194 |
GraphicsWidget *proxy = new GraphicsWidget; |
|
195 |
proxy->setWidget(widget); |
|
196 |
||
197 |
if (m_proxyWidgets[index]) |
|
198 |
delete m_proxyWidgets[index]; |
|
199 |
m_proxyWidgets[index] = proxy; |
|
200 |
||
201 |
proxy->setCacheMode(QGraphicsItem::ItemCoordinateCache); |
|
202 |
proxy->setZValue(1e30); // Make sure the dialog is drawn on top of all other (OpenGL) items |
|
203 |
||
204 |
if (index != m_current) |
|
205 |
proxy->setVisible(false); |
|
206 |
||
207 |
qobject_cast<QGraphicsScene *>(parent())->addItem(proxy); |
|
208 |
} |
|
209 |
||
210 |
QWidget *TwoSidedGraphicsWidget::widget(int index) |
|
211 |
{ |
|
212 |
if (index < 0 || index >= 2) |
|
213 |
{ |
|
214 |
qWarning("TwoSidedGraphicsWidget::widget: Index out of bounds, index == %d", index); |
|
215 |
return 0; |
|
216 |
} |
|
217 |
return m_proxyWidgets[index]->widget(); |
|
218 |
} |
|
219 |
||
220 |
void TwoSidedGraphicsWidget::flip() |
|
221 |
{ |
|
222 |
m_delta = (m_current == 0 ? 9 : -9); |
|
223 |
animateFlip(); |
|
224 |
} |
|
225 |
||
226 |
void TwoSidedGraphicsWidget::animateFlip() |
|
227 |
{ |
|
228 |
m_angle += m_delta; |
|
229 |
if (m_angle == 90) { |
|
230 |
int old = m_current; |
|
231 |
m_current ^= 1; |
|
232 |
m_proxyWidgets[old]->setVisible(false); |
|
233 |
m_proxyWidgets[m_current]->setVisible(true); |
|
234 |
m_proxyWidgets[m_current]->setGeometry(m_proxyWidgets[old]->geometry()); |
|
235 |
} |
|
236 |
||
237 |
QRectF r = m_proxyWidgets[m_current]->boundingRect(); |
|
238 |
m_proxyWidgets[m_current]->setTransform(QTransform() |
|
239 |
.translate(r.width() / 2, r.height() / 2) |
|
240 |
.rotate(m_angle - 180 * m_current, Qt::YAxis) |
|
241 |
.translate(-r.width() / 2, -r.height() / 2)); |
|
242 |
||
243 |
if ((m_current == 0 && m_angle > 0) || (m_current == 1 && m_angle < 180)) |
|
244 |
QTimer::singleShot(25, this, SLOT(animateFlip())); |
|
245 |
} |
|
246 |
||
247 |
QVariant GraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value) |
|
248 |
{ |
|
249 |
if (change == ItemPositionChange && scene()) { |
|
250 |
QRectF rect = boundingRect(); |
|
251 |
QPointF pos = value.toPointF(); |
|
252 |
QRectF sceneRect = scene()->sceneRect(); |
|
253 |
if (pos.x() + rect.left() < sceneRect.left()) |
|
254 |
pos.setX(sceneRect.left() - rect.left()); |
|
255 |
else if (pos.x() + rect.right() >= sceneRect.right()) |
|
256 |
pos.setX(sceneRect.right() - rect.right()); |
|
257 |
if (pos.y() + rect.top() < sceneRect.top()) |
|
258 |
pos.setY(sceneRect.top() - rect.top()); |
|
259 |
else if (pos.y() + rect.bottom() >= sceneRect.bottom()) |
|
260 |
pos.setY(sceneRect.bottom() - rect.bottom()); |
|
261 |
return pos; |
|
262 |
} |
|
263 |
return QGraphicsProxyWidget::itemChange(change, value); |
|
264 |
} |
|
265 |
||
266 |
void GraphicsWidget::resizeEvent(QGraphicsSceneResizeEvent *event) |
|
267 |
{ |
|
268 |
setCacheMode(QGraphicsItem::NoCache); |
|
269 |
setCacheMode(QGraphicsItem::ItemCoordinateCache); |
|
270 |
QGraphicsProxyWidget::resizeEvent(event); |
|
271 |
} |
|
272 |
||
273 |
void GraphicsWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) |
|
274 |
{ |
|
275 |
painter->setRenderHint(QPainter::Antialiasing, false); |
|
276 |
QGraphicsProxyWidget::paint(painter, option, widget); |
|
277 |
//painter->setRenderHint(QPainter::Antialiasing, true); |
|
278 |
} |
|
279 |
||
280 |
//============================================================================// |
|
281 |
// RenderOptionsDialog // |
|
282 |
//============================================================================// |
|
283 |
||
284 |
RenderOptionsDialog::RenderOptionsDialog() |
|
285 |
: QDialog(0, Qt::CustomizeWindowHint | Qt::WindowTitleHint) |
|
286 |
{ |
|
287 |
setWindowOpacity(0.75); |
|
288 |
setWindowTitle(tr("Options (double click to flip)")); |
|
289 |
QGridLayout *layout = new QGridLayout; |
|
290 |
setLayout(layout); |
|
291 |
layout->setColumnStretch(1, 1); |
|
292 |
||
293 |
int row = 0; |
|
294 |
||
295 |
QCheckBox *check = new QCheckBox(tr("Dynamic cube map")); |
|
296 |
check->setCheckState(Qt::Unchecked); |
|
297 |
// Dynamic cube maps are only enabled when multi-texturing and render to texture are available. |
|
298 |
check->setEnabled(glActiveTexture && glGenFramebuffersEXT); |
|
299 |
connect(check, SIGNAL(stateChanged(int)), this, SIGNAL(dynamicCubemapToggled(int))); |
|
300 |
layout->addWidget(check, 0, 0, 1, 2); |
|
301 |
++row; |
|
302 |
||
303 |
QPalette palette; |
|
304 |
||
305 |
// Load all .par files |
|
306 |
// .par files have a simple syntax for specifying user adjustable uniform variables. |
|
307 |
QSet<QByteArray> uniforms; |
|
308 |
QList<QString> filter = QStringList("*.par"); |
|
309 |
QList<QFileInfo> files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable); |
|
310 |
||
311 |
foreach (QFileInfo fileInfo, files) { |
|
312 |
QFile file(fileInfo.absoluteFilePath()); |
|
313 |
if (file.open(QIODevice::ReadOnly)) { |
|
314 |
while (!file.atEnd()) { |
|
315 |
QList<QByteArray> tokens = file.readLine().simplified().split(' '); |
|
316 |
QList<QByteArray>::const_iterator it = tokens.begin(); |
|
317 |
if (it == tokens.end()) |
|
318 |
continue; |
|
319 |
QByteArray type = *it; |
|
320 |
if (++it == tokens.end()) |
|
321 |
continue; |
|
322 |
QByteArray name = *it; |
|
323 |
bool singleElement = (tokens.size() == 3); // type, name and one value |
|
324 |
char counter[10] = "000000000"; |
|
325 |
int counterPos = 8; // position of last digit |
|
326 |
while (++it != tokens.end()) { |
|
327 |
m_parameterNames << name; |
|
328 |
if (!singleElement) { |
|
329 |
m_parameterNames.back() += "["; |
|
330 |
m_parameterNames.back() += counter + counterPos; |
|
331 |
m_parameterNames.back() += "]"; |
|
332 |
int j = 8; // position of last digit |
|
333 |
++counter[j]; |
|
334 |
while (j > 0 && counter[j] > '9') { |
|
335 |
counter[j] = '0'; |
|
336 |
++counter[--j]; |
|
337 |
} |
|
338 |
if (j < counterPos) |
|
339 |
counterPos = j; |
|
340 |
} |
|
341 |
||
342 |
if (type == "color") { |
|
343 |
layout->addWidget(new QLabel(m_parameterNames.back())); |
|
344 |
bool ok; |
|
345 |
ColorEdit *colorEdit = new ColorEdit(it->toUInt(&ok, 16), m_parameterNames.size() - 1); |
|
346 |
m_parameterEdits << colorEdit; |
|
347 |
layout->addWidget(colorEdit); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
348 |
connect(colorEdit, SIGNAL(colorChanged(QRgb,int)), this, SLOT(setColorParameter(QRgb,int))); |
0 | 349 |
++row; |
350 |
} else if (type == "float") { |
|
351 |
layout->addWidget(new QLabel(m_parameterNames.back())); |
|
352 |
bool ok; |
|
353 |
FloatEdit *floatEdit = new FloatEdit(it->toFloat(&ok), m_parameterNames.size() - 1); |
|
354 |
m_parameterEdits << floatEdit; |
|
355 |
layout->addWidget(floatEdit); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
356 |
connect(floatEdit, SIGNAL(valueChanged(float,int)), this, SLOT(setFloatParameter(float,int))); |
0 | 357 |
++row; |
358 |
} |
|
359 |
} |
|
360 |
} |
|
361 |
file.close(); |
|
362 |
} |
|
363 |
} |
|
364 |
||
365 |
layout->addWidget(new QLabel(tr("Texture:"))); |
|
366 |
m_textureCombo = new QComboBox; |
|
367 |
connect(m_textureCombo, SIGNAL(currentIndexChanged(int)), this, SIGNAL(textureChanged(int))); |
|
368 |
layout->addWidget(m_textureCombo); |
|
369 |
++row; |
|
370 |
||
371 |
layout->addWidget(new QLabel(tr("Shader:"))); |
|
372 |
m_shaderCombo = new QComboBox; |
|
373 |
connect(m_shaderCombo, SIGNAL(currentIndexChanged(int)), this, SIGNAL(shaderChanged(int))); |
|
374 |
layout->addWidget(m_shaderCombo); |
|
375 |
++row; |
|
376 |
||
377 |
layout->setRowStretch(row, 1); |
|
378 |
} |
|
379 |
||
380 |
int RenderOptionsDialog::addTexture(const QString &name) |
|
381 |
{ |
|
382 |
m_textureCombo->addItem(name); |
|
383 |
return m_textureCombo->count() - 1; |
|
384 |
} |
|
385 |
||
386 |
int RenderOptionsDialog::addShader(const QString &name) |
|
387 |
{ |
|
388 |
m_shaderCombo->addItem(name); |
|
389 |
return m_shaderCombo->count() - 1; |
|
390 |
} |
|
391 |
||
392 |
void RenderOptionsDialog::emitParameterChanged() |
|
393 |
{ |
|
394 |
foreach (ParameterEdit *edit, m_parameterEdits) |
|
395 |
edit->emitChange(); |
|
396 |
} |
|
397 |
||
398 |
void RenderOptionsDialog::setColorParameter(QRgb color, int id) |
|
399 |
{ |
|
400 |
emit colorParameterChanged(m_parameterNames[id], color); |
|
401 |
} |
|
402 |
||
403 |
void RenderOptionsDialog::setFloatParameter(float value, int id) |
|
404 |
{ |
|
405 |
emit floatParameterChanged(m_parameterNames[id], value); |
|
406 |
} |
|
407 |
||
408 |
void RenderOptionsDialog::mouseDoubleClickEvent(QMouseEvent *event) |
|
409 |
{ |
|
410 |
if (event->button() == Qt::LeftButton) |
|
411 |
emit doubleClicked(); |
|
412 |
} |
|
413 |
||
414 |
//============================================================================// |
|
415 |
// ItemDialog // |
|
416 |
//============================================================================// |
|
417 |
||
418 |
ItemDialog::ItemDialog() |
|
419 |
: QDialog(0, Qt::CustomizeWindowHint | Qt::WindowTitleHint) |
|
420 |
{ |
|
421 |
setWindowTitle(tr("Items (double click to flip)")); |
|
422 |
setWindowOpacity(0.75); |
|
423 |
resize(160, 100); |
|
424 |
||
425 |
QVBoxLayout *layout = new QVBoxLayout; |
|
426 |
setLayout(layout); |
|
427 |
QPushButton *button; |
|
428 |
||
429 |
button = new QPushButton(tr("Add Qt box")); |
|
430 |
layout->addWidget(button); |
|
431 |
connect(button, SIGNAL(clicked()), this, SLOT(triggerNewQtBox())); |
|
432 |
||
433 |
button = new QPushButton(tr("Add circle")); |
|
434 |
layout->addWidget(button); |
|
435 |
connect(button, SIGNAL(clicked()), this, SLOT(triggerNewCircleItem())); |
|
436 |
||
437 |
button = new QPushButton(tr("Add square")); |
|
438 |
layout->addWidget(button); |
|
439 |
connect(button, SIGNAL(clicked()), this, SLOT(triggerNewSquareItem())); |
|
440 |
||
441 |
layout->addStretch(1); |
|
442 |
} |
|
443 |
||
444 |
void ItemDialog::triggerNewQtBox() |
|
445 |
{ |
|
446 |
emit newItemTriggered(QtBoxItem); |
|
447 |
} |
|
448 |
||
449 |
void ItemDialog::triggerNewCircleItem() |
|
450 |
{ |
|
451 |
emit newItemTriggered(CircleItem); |
|
452 |
} |
|
453 |
||
454 |
void ItemDialog::triggerNewSquareItem() |
|
455 |
{ |
|
456 |
emit newItemTriggered(SquareItem); |
|
457 |
} |
|
458 |
||
459 |
void ItemDialog::mouseDoubleClickEvent(QMouseEvent *event) |
|
460 |
{ |
|
461 |
if (event->button() == Qt::LeftButton) |
|
462 |
emit doubleClicked(); |
|
463 |
} |
|
464 |
||
465 |
//============================================================================// |
|
466 |
// Scene // |
|
467 |
//============================================================================// |
|
468 |
||
469 |
const static char environmentShaderText[] = |
|
470 |
"uniform samplerCube env;" |
|
471 |
"void main() {" |
|
472 |
"gl_FragColor = textureCube(env, gl_TexCoord[1].xyz);" |
|
473 |
"}"; |
|
474 |
||
475 |
Scene::Scene(int width, int height, int maxTextureSize) |
|
476 |
: m_distExp(600) |
|
477 |
, m_frame(0) |
|
478 |
, m_maxTextureSize(maxTextureSize) |
|
479 |
, m_currentShader(0) |
|
480 |
, m_currentTexture(0) |
|
481 |
, m_dynamicCubemap(false) |
|
482 |
, m_updateAllCubemaps(true) |
|
483 |
, m_box(0) |
|
484 |
, m_vertexShader(0) |
|
485 |
, m_environmentShader(0) |
|
486 |
, m_environmentProgram(0) |
|
487 |
{ |
|
488 |
setSceneRect(0, 0, width, height); |
|
489 |
||
490 |
m_trackBalls[0] = TrackBall(0.05f, QVector3D(0, 1, 0), TrackBall::Sphere); |
|
491 |
m_trackBalls[1] = TrackBall(0.005f, QVector3D(0, 0, 1), TrackBall::Sphere); |
|
492 |
m_trackBalls[2] = TrackBall(0.0f, QVector3D(0, 1, 0), TrackBall::Plane); |
|
493 |
||
494 |
m_renderOptions = new RenderOptionsDialog; |
|
495 |
m_renderOptions->move(20, 120); |
|
496 |
m_renderOptions->resize(m_renderOptions->sizeHint()); |
|
497 |
||
498 |
connect(m_renderOptions, SIGNAL(dynamicCubemapToggled(int)), this, SLOT(toggleDynamicCubemap(int))); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
499 |
connect(m_renderOptions, SIGNAL(colorParameterChanged(QString,QRgb)), this, SLOT(setColorParameter(QString,QRgb))); |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
500 |
connect(m_renderOptions, SIGNAL(floatParameterChanged(QString,float)), this, SLOT(setFloatParameter(QString,float))); |
0 | 501 |
connect(m_renderOptions, SIGNAL(textureChanged(int)), this, SLOT(setTexture(int))); |
502 |
connect(m_renderOptions, SIGNAL(shaderChanged(int)), this, SLOT(setShader(int))); |
|
503 |
||
504 |
m_itemDialog = new ItemDialog; |
|
505 |
connect(m_itemDialog, SIGNAL(newItemTriggered(ItemDialog::ItemType)), this, SLOT(newItem(ItemDialog::ItemType))); |
|
506 |
||
507 |
TwoSidedGraphicsWidget *twoSided = new TwoSidedGraphicsWidget(this); |
|
508 |
twoSided->setWidget(0, m_renderOptions); |
|
509 |
twoSided->setWidget(1, m_itemDialog); |
|
510 |
||
511 |
connect(m_renderOptions, SIGNAL(doubleClicked()), twoSided, SLOT(flip())); |
|
512 |
connect(m_itemDialog, SIGNAL(doubleClicked()), twoSided, SLOT(flip())); |
|
513 |
||
514 |
addItem(new QtBox(64, width - 64, height - 64)); |
|
515 |
addItem(new QtBox(64, width - 64, 64)); |
|
516 |
addItem(new QtBox(64, 64, height - 64)); |
|
517 |
addItem(new QtBox(64, 64, 64)); |
|
518 |
||
519 |
initGL(); |
|
520 |
||
521 |
m_timer = new QTimer(this); |
|
522 |
m_timer->setInterval(20); |
|
523 |
connect(m_timer, SIGNAL(timeout()), this, SLOT(update())); |
|
524 |
m_timer->start(); |
|
525 |
||
526 |
m_time.start(); |
|
527 |
} |
|
528 |
||
529 |
Scene::~Scene() |
|
530 |
{ |
|
531 |
if (m_box) |
|
532 |
delete m_box; |
|
533 |
foreach (GLTexture *texture, m_textures) |
|
534 |
if (texture) delete texture; |
|
535 |
if (m_mainCubemap) |
|
536 |
delete m_mainCubemap; |
|
537 |
foreach (QGLShaderProgram *program, m_programs) |
|
538 |
if (program) delete program; |
|
539 |
if (m_vertexShader) |
|
540 |
delete m_vertexShader; |
|
541 |
foreach (QGLShader *shader, m_fragmentShaders) |
|
542 |
if (shader) delete shader; |
|
543 |
foreach (GLRenderTargetCube *rt, m_cubemaps) |
|
544 |
if (rt) delete rt; |
|
545 |
if (m_environmentShader) |
|
546 |
delete m_environmentShader; |
|
547 |
if (m_environmentProgram) |
|
548 |
delete m_environmentProgram; |
|
549 |
} |
|
550 |
||
551 |
void Scene::initGL() |
|
552 |
{ |
|
553 |
m_box = new GLRoundedBox(0.25f, 1.0f, 10); |
|
554 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
555 |
m_vertexShader = new QGLShader(QGLShader::Vertex); |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
556 |
m_vertexShader->compileSourceFile(QLatin1String(":/res/boxes/basic.vsh")); |
0 | 557 |
|
558 |
QStringList list; |
|
559 |
list << ":/res/boxes/cubemap_posx.jpg" << ":/res/boxes/cubemap_negx.jpg" << ":/res/boxes/cubemap_posy.jpg" |
|
560 |
<< ":/res/boxes/cubemap_negy.jpg" << ":/res/boxes/cubemap_posz.jpg" << ":/res/boxes/cubemap_negz.jpg"; |
|
561 |
m_environment = new GLTextureCube(list, qMin(1024, m_maxTextureSize)); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
562 |
m_environmentShader = new QGLShader(QGLShader::Fragment); |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
563 |
m_environmentShader->compileSourceCode(environmentShaderText); |
0 | 564 |
m_environmentProgram = new QGLShaderProgram; |
565 |
m_environmentProgram->addShader(m_vertexShader); |
|
566 |
m_environmentProgram->addShader(m_environmentShader); |
|
567 |
m_environmentProgram->link(); |
|
568 |
||
569 |
const int NOISE_SIZE = 128; // for a different size, B and BM in fbm.c must also be changed |
|
570 |
m_noise = new GLTexture3D(NOISE_SIZE, NOISE_SIZE, NOISE_SIZE); |
|
571 |
QRgb *data = new QRgb[NOISE_SIZE * NOISE_SIZE * NOISE_SIZE]; |
|
572 |
memset(data, 0, NOISE_SIZE * NOISE_SIZE * NOISE_SIZE * sizeof(QRgb)); |
|
573 |
QRgb *p = data; |
|
574 |
float pos[3]; |
|
575 |
for (int k = 0; k < NOISE_SIZE; ++k) { |
|
576 |
pos[2] = k * (0x20 / (float)NOISE_SIZE); |
|
577 |
for (int j = 0; j < NOISE_SIZE; ++j) { |
|
578 |
for (int i = 0; i < NOISE_SIZE; ++i) { |
|
579 |
for (int byte = 0; byte < 4; ++byte) { |
|
580 |
pos[0] = (i + (byte & 1) * 16) * (0x20 / (float)NOISE_SIZE); |
|
581 |
pos[1] = (j + (byte & 2) * 8) * (0x20 / (float)NOISE_SIZE); |
|
582 |
*p |= (int)(128.0f * (noise3(pos) + 1.0f)) << (byte * 8); |
|
583 |
} |
|
584 |
++p; |
|
585 |
} |
|
586 |
} |
|
587 |
} |
|
588 |
m_noise->load(NOISE_SIZE, NOISE_SIZE, NOISE_SIZE, data); |
|
589 |
delete[] data; |
|
590 |
||
591 |
m_mainCubemap = new GLRenderTargetCube(512); |
|
592 |
||
593 |
QStringList filter; |
|
594 |
QList<QFileInfo> files; |
|
595 |
||
596 |
// Load all .png files as textures |
|
597 |
m_currentTexture = 0; |
|
598 |
filter = QStringList("*.png"); |
|
599 |
files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable); |
|
600 |
||
601 |
foreach (QFileInfo file, files) { |
|
602 |
GLTexture *texture = new GLTexture2D(file.absoluteFilePath(), qMin(256, m_maxTextureSize), qMin(256, m_maxTextureSize)); |
|
603 |
if (texture->failed()) { |
|
604 |
delete texture; |
|
605 |
continue; |
|
606 |
} |
|
607 |
m_textures << texture; |
|
608 |
m_renderOptions->addTexture(file.baseName()); |
|
609 |
} |
|
610 |
||
611 |
if (m_textures.size() == 0) |
|
612 |
m_textures << new GLTexture2D(qMin(64, m_maxTextureSize), qMin(64, m_maxTextureSize)); |
|
613 |
||
614 |
// Load all .fsh files as fragment shaders |
|
615 |
m_currentShader = 0; |
|
616 |
filter = QStringList("*.fsh"); |
|
617 |
files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable); |
|
618 |
foreach (QFileInfo file, files) { |
|
619 |
QGLShaderProgram *program = new QGLShaderProgram; |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
620 |
QGLShader* shader = new QGLShader(QGLShader::Fragment); |
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
621 |
shader->compileSourceFile(file.absoluteFilePath()); |
0 | 622 |
// The program does not take ownership over the shaders, so store them in a vector so they can be deleted afterwards. |
623 |
program->addShader(m_vertexShader); |
|
624 |
program->addShader(shader); |
|
625 |
if (!program->link()) { |
|
626 |
qWarning("Failed to compile and link shader program"); |
|
627 |
qWarning("Vertex shader log:"); |
|
628 |
qWarning() << m_vertexShader->log(); |
|
629 |
qWarning() << "Fragment shader log ( file =" << file.absoluteFilePath() << "):"; |
|
630 |
qWarning() << shader->log(); |
|
631 |
qWarning("Shader program log:"); |
|
632 |
qWarning() << program->log(); |
|
633 |
||
634 |
delete shader; |
|
635 |
delete program; |
|
636 |
continue; |
|
637 |
} |
|
638 |
||
639 |
m_fragmentShaders << shader; |
|
640 |
m_programs << program; |
|
641 |
m_renderOptions->addShader(file.baseName()); |
|
642 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
643 |
program->bind(); |
0 | 644 |
m_cubemaps << ((program->uniformLocation("env") != -1) ? new GLRenderTargetCube(qMin(256, m_maxTextureSize)) : 0); |
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
645 |
program->release(); |
0 | 646 |
} |
647 |
||
648 |
if (m_programs.size() == 0) |
|
649 |
m_programs << new QGLShaderProgram; |
|
650 |
||
651 |
m_renderOptions->emitParameterChanged(); |
|
652 |
} |
|
653 |
||
654 |
static void loadMatrix(const QMatrix4x4& m) |
|
655 |
{ |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
656 |
// static to prevent glLoadMatrixf to fail on certain drivers |
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
657 |
static GLfloat mat[16]; |
0 | 658 |
const qreal *data = m.constData(); |
659 |
for (int index = 0; index < 16; ++index) |
|
660 |
mat[index] = data[index]; |
|
661 |
glLoadMatrixf(mat); |
|
662 |
} |
|
663 |
||
664 |
static void multMatrix(const QMatrix4x4& m) |
|
665 |
{ |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
666 |
// static to prevent glMultMatrixf to fail on certain drivers |
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
3
diff
changeset
|
667 |
static GLfloat mat[16]; |
0 | 668 |
const qreal *data = m.constData(); |
669 |
for (int index = 0; index < 16; ++index) |
|
670 |
mat[index] = data[index]; |
|
671 |
glMultMatrixf(mat); |
|
672 |
} |
|
673 |
||
674 |
// If one of the boxes should not be rendered, set excludeBox to its index. |
|
675 |
// If the main box should not be rendered, set excludeBox to -1. |
|
676 |
void Scene::renderBoxes(const QMatrix4x4 &view, int excludeBox) |
|
677 |
{ |
|
678 |
QMatrix4x4 invView = view.inverted(); |
|
679 |
||
680 |
// If multi-texturing is supported, use three saplers. |
|
681 |
if (glActiveTexture) { |
|
682 |
glActiveTexture(GL_TEXTURE0); |
|
683 |
m_textures[m_currentTexture]->bind(); |
|
684 |
glActiveTexture(GL_TEXTURE2); |
|
685 |
m_noise->bind(); |
|
686 |
glActiveTexture(GL_TEXTURE1); |
|
687 |
} else { |
|
688 |
m_textures[m_currentTexture]->bind(); |
|
689 |
} |
|
690 |
||
691 |
glDisable(GL_LIGHTING); |
|
692 |
glDisable(GL_CULL_FACE); |
|
693 |
||
694 |
QMatrix4x4 viewRotation(view); |
|
695 |
viewRotation(3, 0) = viewRotation(3, 1) = viewRotation(3, 2) = 0.0f; |
|
696 |
viewRotation(0, 3) = viewRotation(1, 3) = viewRotation(2, 3) = 0.0f; |
|
697 |
viewRotation(3, 3) = 1.0f; |
|
698 |
loadMatrix(viewRotation); |
|
699 |
glScalef(20.0f, 20.0f, 20.0f); |
|
700 |
||
701 |
// Don't render the environment if the environment texture can't be set for the correct sampler. |
|
702 |
if (glActiveTexture) { |
|
703 |
m_environment->bind(); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
704 |
m_environmentProgram->bind(); |
0 | 705 |
m_environmentProgram->setUniformValue("tex", GLint(0)); |
706 |
m_environmentProgram->setUniformValue("env", GLint(1)); |
|
707 |
m_environmentProgram->setUniformValue("noise", GLint(2)); |
|
708 |
m_box->draw(); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
709 |
m_environmentProgram->release(); |
0 | 710 |
m_environment->unbind(); |
711 |
} |
|
712 |
||
713 |
loadMatrix(view); |
|
714 |
||
715 |
glEnable(GL_CULL_FACE); |
|
716 |
glEnable(GL_LIGHTING); |
|
717 |
||
718 |
for (int i = 0; i < m_programs.size(); ++i) { |
|
719 |
if (i == excludeBox) |
|
720 |
continue; |
|
721 |
||
722 |
glPushMatrix(); |
|
723 |
QMatrix4x4 m; |
|
724 |
m.rotate(m_trackBalls[1].rotation()); |
|
725 |
multMatrix(m); |
|
726 |
||
727 |
glRotatef(360.0f * i / m_programs.size(), 0.0f, 0.0f, 1.0f); |
|
728 |
glTranslatef(2.0f, 0.0f, 0.0f); |
|
729 |
glScalef(0.3f, 0.6f, 0.6f); |
|
730 |
||
731 |
if (glActiveTexture) { |
|
732 |
if (m_dynamicCubemap && m_cubemaps[i]) |
|
733 |
m_cubemaps[i]->bind(); |
|
734 |
else |
|
735 |
m_environment->bind(); |
|
736 |
} |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
737 |
m_programs[i]->bind(); |
0 | 738 |
m_programs[i]->setUniformValue("tex", GLint(0)); |
739 |
m_programs[i]->setUniformValue("env", GLint(1)); |
|
740 |
m_programs[i]->setUniformValue("noise", GLint(2)); |
|
741 |
m_programs[i]->setUniformValue("view", view); |
|
742 |
m_programs[i]->setUniformValue("invView", invView); |
|
743 |
m_box->draw(); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
744 |
m_programs[i]->release(); |
0 | 745 |
|
746 |
if (glActiveTexture) { |
|
747 |
if (m_dynamicCubemap && m_cubemaps[i]) |
|
748 |
m_cubemaps[i]->unbind(); |
|
749 |
else |
|
750 |
m_environment->unbind(); |
|
751 |
} |
|
752 |
glPopMatrix(); |
|
753 |
} |
|
754 |
||
755 |
if (-1 != excludeBox) { |
|
756 |
QMatrix4x4 m; |
|
757 |
m.rotate(m_trackBalls[0].rotation()); |
|
758 |
multMatrix(m); |
|
759 |
||
760 |
if (glActiveTexture) { |
|
761 |
if (m_dynamicCubemap) |
|
762 |
m_mainCubemap->bind(); |
|
763 |
else |
|
764 |
m_environment->bind(); |
|
765 |
} |
|
766 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
767 |
m_programs[m_currentShader]->bind(); |
0 | 768 |
m_programs[m_currentShader]->setUniformValue("tex", GLint(0)); |
769 |
m_programs[m_currentShader]->setUniformValue("env", GLint(1)); |
|
770 |
m_programs[m_currentShader]->setUniformValue("noise", GLint(2)); |
|
771 |
m_programs[m_currentShader]->setUniformValue("view", view); |
|
772 |
m_programs[m_currentShader]->setUniformValue("invView", invView); |
|
773 |
m_box->draw(); |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
774 |
m_programs[m_currentShader]->release(); |
0 | 775 |
|
776 |
if (glActiveTexture) { |
|
777 |
if (m_dynamicCubemap) |
|
778 |
m_mainCubemap->unbind(); |
|
779 |
else |
|
780 |
m_environment->unbind(); |
|
781 |
} |
|
782 |
} |
|
783 |
||
784 |
if (glActiveTexture) { |
|
785 |
glActiveTexture(GL_TEXTURE2); |
|
786 |
m_noise->unbind(); |
|
787 |
glActiveTexture(GL_TEXTURE0); |
|
788 |
} |
|
789 |
m_textures[m_currentTexture]->unbind(); |
|
790 |
} |
|
791 |
||
792 |
void Scene::setStates() |
|
793 |
{ |
|
794 |
//glClearColor(0.25f, 0.25f, 0.5f, 1.0f); |
|
795 |
||
796 |
glEnable(GL_DEPTH_TEST); |
|
797 |
glEnable(GL_CULL_FACE); |
|
798 |
glEnable(GL_LIGHTING); |
|
799 |
//glEnable(GL_COLOR_MATERIAL); |
|
800 |
glEnable(GL_TEXTURE_2D); |
|
801 |
glEnable(GL_NORMALIZE); |
|
802 |
||
803 |
glMatrixMode(GL_PROJECTION); |
|
804 |
glPushMatrix(); |
|
805 |
glLoadIdentity(); |
|
806 |
||
807 |
glMatrixMode(GL_MODELVIEW); |
|
808 |
glPushMatrix(); |
|
809 |
glLoadIdentity(); |
|
810 |
||
811 |
setLights(); |
|
812 |
||
813 |
float materialSpecular[] = {0.5f, 0.5f, 0.5f, 1.0f}; |
|
814 |
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, materialSpecular); |
|
815 |
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 32.0f); |
|
816 |
} |
|
817 |
||
818 |
void Scene::setLights() |
|
819 |
{ |
|
820 |
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); |
|
821 |
//float lightColour[] = {1.0f, 1.0f, 1.0f, 1.0f}; |
|
822 |
float lightDir[] = {0.0f, 0.0f, 1.0f, 0.0f}; |
|
823 |
//glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColour); |
|
824 |
//glLightfv(GL_LIGHT0, GL_SPECULAR, lightColour); |
|
825 |
glLightfv(GL_LIGHT0, GL_POSITION, lightDir); |
|
826 |
glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, 1.0f); |
|
827 |
glEnable(GL_LIGHT0); |
|
828 |
} |
|
829 |
||
830 |
void Scene::defaultStates() |
|
831 |
{ |
|
832 |
//glClearColor(0.0f, 0.0f, 0.0f, 0.0f); |
|
833 |
||
834 |
glDisable(GL_DEPTH_TEST); |
|
835 |
glDisable(GL_CULL_FACE); |
|
836 |
glDisable(GL_LIGHTING); |
|
837 |
//glDisable(GL_COLOR_MATERIAL); |
|
838 |
glDisable(GL_TEXTURE_2D); |
|
839 |
glDisable(GL_LIGHT0); |
|
840 |
glDisable(GL_NORMALIZE); |
|
841 |
||
842 |
glMatrixMode(GL_MODELVIEW); |
|
843 |
glPopMatrix(); |
|
844 |
||
845 |
glMatrixMode(GL_PROJECTION); |
|
846 |
glPopMatrix(); |
|
847 |
||
848 |
glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, 0.0f); |
|
849 |
float defaultMaterialSpecular[] = {0.0f, 0.0f, 0.0f, 1.0f}; |
|
850 |
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, defaultMaterialSpecular); |
|
851 |
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f); |
|
852 |
} |
|
853 |
||
854 |
void Scene::renderCubemaps() |
|
855 |
{ |
|
856 |
// To speed things up, only update the cubemaps for the small cubes every N frames. |
|
857 |
const int N = (m_updateAllCubemaps ? 1 : 3); |
|
858 |
||
859 |
QMatrix4x4 mat; |
|
860 |
GLRenderTargetCube::getProjectionMatrix(mat, 0.1f, 100.0f); |
|
861 |
||
862 |
glMatrixMode(GL_PROJECTION); |
|
863 |
glPushMatrix(); |
|
864 |
loadMatrix(mat); |
|
865 |
||
866 |
glMatrixMode(GL_MODELVIEW); |
|
867 |
glPushMatrix(); |
|
868 |
||
869 |
QVector3D center; |
|
870 |
||
871 |
for (int i = m_frame % N; i < m_cubemaps.size(); i += N) { |
|
872 |
if (0 == m_cubemaps[i]) |
|
873 |
continue; |
|
874 |
||
875 |
float angle = 2.0f * PI * i / m_cubemaps.size(); |
|
876 |
||
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
877 |
center = m_trackBalls[1].rotation().rotatedVector(QVector3D(cos(angle), sin(angle), 0.0f)); |
0 | 878 |
|
879 |
for (int face = 0; face < 6; ++face) { |
|
880 |
m_cubemaps[i]->begin(face); |
|
881 |
||
882 |
GLRenderTargetCube::getViewMatrix(mat, face); |
|
883 |
QVector4D v = QVector4D(-center.x(), -center.y(), -center.z(), 1.0); |
|
884 |
mat.setColumn(3, mat * v); |
|
885 |
||
886 |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
|
887 |
renderBoxes(mat, i); |
|
888 |
||
889 |
m_cubemaps[i]->end(); |
|
890 |
} |
|
891 |
} |
|
892 |
||
893 |
for (int face = 0; face < 6; ++face) { |
|
894 |
m_mainCubemap->begin(face); |
|
895 |
GLRenderTargetCube::getViewMatrix(mat, face); |
|
896 |
||
897 |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
|
898 |
renderBoxes(mat, -1); |
|
899 |
||
900 |
m_mainCubemap->end(); |
|
901 |
} |
|
902 |
||
903 |
glPopMatrix(); |
|
904 |
||
905 |
glMatrixMode(GL_PROJECTION); |
|
906 |
glPopMatrix(); |
|
907 |
||
908 |
m_updateAllCubemaps = false; |
|
909 |
} |
|
910 |
||
911 |
void Scene::drawBackground(QPainter *painter, const QRectF &) |
|
912 |
{ |
|
913 |
float width = float(painter->device()->width()); |
|
914 |
float height = float(painter->device()->height()); |
|
915 |
||
916 |
painter->beginNativePainting(); |
|
917 |
setStates(); |
|
918 |
||
919 |
if (m_dynamicCubemap) |
|
920 |
renderCubemaps(); |
|
921 |
||
922 |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
|
923 |
||
924 |
glMatrixMode(GL_PROJECTION); |
|
925 |
gluPerspective(60.0, width / height, 0.01, 15.0); |
|
926 |
||
927 |
glMatrixMode(GL_MODELVIEW); |
|
928 |
||
929 |
QMatrix4x4 view; |
|
930 |
view.rotate(m_trackBalls[2].rotation()); |
|
931 |
view(2, 3) -= 2.0f * exp(m_distExp / 1200.0f); |
|
932 |
renderBoxes(view); |
|
933 |
||
934 |
defaultStates(); |
|
935 |
++m_frame; |
|
936 |
||
937 |
painter->endNativePainting(); |
|
938 |
} |
|
939 |
||
940 |
QPointF Scene::pixelPosToViewPos(const QPointF& p) |
|
941 |
{ |
|
942 |
return QPointF(2.0 * float(p.x()) / width() - 1.0, |
|
943 |
1.0 - 2.0 * float(p.y()) / height()); |
|
944 |
} |
|
945 |
||
946 |
void Scene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) |
|
947 |
{ |
|
948 |
QGraphicsScene::mouseMoveEvent(event); |
|
949 |
if (event->isAccepted()) |
|
950 |
return; |
|
951 |
||
952 |
if (event->buttons() & Qt::LeftButton) { |
|
953 |
m_trackBalls[0].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); |
|
954 |
event->accept(); |
|
955 |
} else { |
|
956 |
m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); |
|
957 |
} |
|
958 |
||
959 |
if (event->buttons() & Qt::RightButton) { |
|
960 |
m_trackBalls[1].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); |
|
961 |
event->accept(); |
|
962 |
} else { |
|
963 |
m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); |
|
964 |
} |
|
965 |
||
966 |
if (event->buttons() & Qt::MidButton) { |
|
967 |
m_trackBalls[2].move(pixelPosToViewPos(event->scenePos()), QQuaternion()); |
|
968 |
event->accept(); |
|
969 |
} else { |
|
970 |
m_trackBalls[2].release(pixelPosToViewPos(event->scenePos()), QQuaternion()); |
|
971 |
} |
|
972 |
} |
|
973 |
||
974 |
void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event) |
|
975 |
{ |
|
976 |
QGraphicsScene::mousePressEvent(event); |
|
977 |
if (event->isAccepted()) |
|
978 |
return; |
|
979 |
||
980 |
if (event->buttons() & Qt::LeftButton) { |
|
981 |
m_trackBalls[0].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); |
|
982 |
event->accept(); |
|
983 |
} |
|
984 |
||
985 |
if (event->buttons() & Qt::RightButton) { |
|
986 |
m_trackBalls[1].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); |
|
987 |
event->accept(); |
|
988 |
} |
|
989 |
||
990 |
if (event->buttons() & Qt::MidButton) { |
|
991 |
m_trackBalls[2].push(pixelPosToViewPos(event->scenePos()), QQuaternion()); |
|
992 |
event->accept(); |
|
993 |
} |
|
994 |
} |
|
995 |
||
996 |
void Scene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) |
|
997 |
{ |
|
998 |
QGraphicsScene::mouseReleaseEvent(event); |
|
999 |
if (event->isAccepted()) |
|
1000 |
return; |
|
1001 |
||
1002 |
if (event->button() == Qt::LeftButton) { |
|
1003 |
m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); |
|
1004 |
event->accept(); |
|
1005 |
} |
|
1006 |
||
1007 |
if (event->button() == Qt::RightButton) { |
|
1008 |
m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); |
|
1009 |
event->accept(); |
|
1010 |
} |
|
1011 |
||
1012 |
if (event->button() == Qt::MidButton) { |
|
1013 |
m_trackBalls[2].release(pixelPosToViewPos(event->scenePos()), QQuaternion()); |
|
1014 |
event->accept(); |
|
1015 |
} |
|
1016 |
} |
|
1017 |
||
1018 |
void Scene::wheelEvent(QGraphicsSceneWheelEvent * event) |
|
1019 |
{ |
|
1020 |
QGraphicsScene::wheelEvent(event); |
|
1021 |
if (!event->isAccepted()) { |
|
1022 |
m_distExp += event->delta(); |
|
1023 |
if (m_distExp < -8 * 120) |
|
1024 |
m_distExp = -8 * 120; |
|
1025 |
if (m_distExp > 10 * 120) |
|
1026 |
m_distExp = 10 * 120; |
|
1027 |
event->accept(); |
|
1028 |
} |
|
1029 |
} |
|
1030 |
||
1031 |
void Scene::setShader(int index) |
|
1032 |
{ |
|
1033 |
if (index >= 0 && index < m_fragmentShaders.size()) |
|
1034 |
m_currentShader = index; |
|
1035 |
} |
|
1036 |
||
1037 |
void Scene::setTexture(int index) |
|
1038 |
{ |
|
1039 |
if (index >= 0 && index < m_textures.size()) |
|
1040 |
m_currentTexture = index; |
|
1041 |
} |
|
1042 |
||
1043 |
void Scene::toggleDynamicCubemap(int state) |
|
1044 |
{ |
|
1045 |
if ((m_dynamicCubemap = (state == Qt::Checked))) |
|
1046 |
m_updateAllCubemaps = true; |
|
1047 |
} |
|
1048 |
||
1049 |
void Scene::setColorParameter(const QString &name, QRgb color) |
|
1050 |
{ |
|
1051 |
// set the color in all programs |
|
1052 |
foreach (QGLShaderProgram *program, m_programs) { |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
1053 |
program->bind(); |
0 | 1054 |
program->setUniformValue(program->uniformLocation(name), QColor(color)); |
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
1055 |
program->release(); |
0 | 1056 |
} |
1057 |
} |
|
1058 |
||
1059 |
void Scene::setFloatParameter(const QString &name, float value) |
|
1060 |
{ |
|
1061 |
// set the color in all programs |
|
1062 |
foreach (QGLShaderProgram *program, m_programs) { |
|
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
1063 |
program->bind(); |
0 | 1064 |
program->setUniformValue(program->uniformLocation(name), value); |
3
41300fa6a67c
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
1065 |
program->release(); |
0 | 1066 |
} |
1067 |
} |
|
1068 |
||
1069 |
void Scene::newItem(ItemDialog::ItemType type) |
|
1070 |
{ |
|
1071 |
QSize size = sceneRect().size().toSize(); |
|
1072 |
switch (type) { |
|
1073 |
case ItemDialog::QtBoxItem: |
|
1074 |
addItem(new QtBox(64, rand() % (size.width() - 64) + 32, rand() % (size.height() - 64) + 32)); |
|
1075 |
break; |
|
1076 |
case ItemDialog::CircleItem: |
|
1077 |
addItem(new CircleItem(64, rand() % (size.width() - 64) + 32, rand() % (size.height() - 64) + 32)); |
|
1078 |
break; |
|
1079 |
case ItemDialog::SquareItem: |
|
1080 |
addItem(new SquareItem(64, rand() % (size.width() - 64) + 32, rand() % (size.height() - 64) + 32)); |
|
1081 |
break; |
|
1082 |
default: |
|
1083 |
break; |
|
1084 |
} |
|
1085 |
} |