summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorRhys Weatherley <rhys.weatherley@nokia.com>2010-02-26 10:54:01 +1000
committerRhys Weatherley <rhys.weatherley@nokia.com>2010-02-26 14:23:14 +1000
commit8a3b2bf5795fe62626f20062727ea1649994b110 (patch)
treeafa9c117e1f5f5c53a1799c32f03d16f03c336d6 /examples
parente6ae07b804a2ca4dfe11504c9aa95507fcbd5f0d (diff)
Bezier patch subdivision example.
Diffstat (limited to 'examples')
-rw-r--r--examples/opencl/bezierpatch/beziermainwindow.cpp73
-rw-r--r--examples/opencl/bezierpatch/beziermainwindow.h70
-rw-r--r--examples/opencl/bezierpatch/beziermainwindow.ui113
-rw-r--r--examples/opencl/bezierpatch/bezierpatch.cl74
-rw-r--r--examples/opencl/bezierpatch/bezierpatch.pro24
-rw-r--r--examples/opencl/bezierpatch/bezierpatch.qrc6
-rw-r--r--examples/opencl/bezierpatch/bezierwidget.cpp449
-rw-r--r--examples/opencl/bezierpatch/bezierwidget.h122
-rw-r--r--examples/opencl/bezierpatch/main.cpp51
-rw-r--r--examples/opencl/bezierpatch/qglcamera.cpp1025
-rw-r--r--examples/opencl/bezierpatch/qglcamera.h166
-rw-r--r--examples/opencl/bezierpatch/qtlogo.pngbin0 -> 14201 bytes
-rw-r--r--examples/opencl/opencl.pro2
13 files changed, 2174 insertions, 1 deletions
diff --git a/examples/opencl/bezierpatch/beziermainwindow.cpp b/examples/opencl/bezierpatch/beziermainwindow.cpp
new file mode 100644
index 0000000..e6f1ee1
--- /dev/null
+++ b/examples/opencl/bezierpatch/beziermainwindow.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "beziermainwindow.h"
+
+BezierMainWindow::BezierMainWindow(QWidget *parent)
+ : QWidget(parent)
+{
+ setupUi(this);
+
+ useOpenCL->setChecked(true);
+ localWorkSize8x8->setChecked(true);
+
+ connect(useOpenCL, SIGNAL(toggled(bool)),
+ bezierWidget, SLOT(setUseOpenCL(bool)));
+ connect(useOpenCL, SIGNAL(toggled(bool)),
+ localWorkSize, SLOT(setEnabled(bool)));
+
+ connect(localWorkSizeDefault, SIGNAL(toggled(bool)),
+ this, SLOT(selectLocalWorkSizeDefault(bool)));
+ connect(localWorkSize1x1, SIGNAL(toggled(bool)),
+ this, SLOT(selectLocalWorkSize1x1(bool)));
+ connect(localWorkSize1x8, SIGNAL(toggled(bool)),
+ this, SLOT(selectLocalWorkSize1x8(bool)));
+ connect(localWorkSize8x1, SIGNAL(toggled(bool)),
+ this, SLOT(selectLocalWorkSize8x1(bool)));
+ connect(localWorkSize8x8, SIGNAL(toggled(bool)),
+ this, SLOT(selectLocalWorkSize8x8(bool)));
+ connect(localWorkSize16x16, SIGNAL(toggled(bool)),
+ this, SLOT(selectLocalWorkSize16x16(bool)));
+}
+
+BezierMainWindow::~BezierMainWindow()
+{
+}
diff --git a/examples/opencl/bezierpatch/beziermainwindow.h b/examples/opencl/bezierpatch/beziermainwindow.h
new file mode 100644
index 0000000..96ebe0d
--- /dev/null
+++ b/examples/opencl/bezierpatch/beziermainwindow.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BEZIERMAINWINDOW_H
+#define BEZIERMAINWINDOW_H
+
+#include <QtGui/qwidget.h>
+#include "ui_beziermainwindow.h"
+
+class BezierMainWindow : public QWidget, public Ui_BezierMainWindow
+{
+ Q_OBJECT
+public:
+ BezierMainWindow(QWidget *parent = 0);
+ ~BezierMainWindow();
+
+private slots:
+ void selectLocalWorkSizeDefault(bool checked)
+ { if (checked) bezierWidget->setLocalWorkSize(0, 0); }
+ void selectLocalWorkSize1x1(bool checked)
+ { if (checked) bezierWidget->setLocalWorkSize(1, 1); }
+ void selectLocalWorkSize1x8(bool checked)
+ { if (checked) bezierWidget->setLocalWorkSize(1, 8); }
+ void selectLocalWorkSize8x1(bool checked)
+ { if (checked) bezierWidget->setLocalWorkSize(8, 1); }
+ void selectLocalWorkSize8x8(bool checked)
+ { if (checked) bezierWidget->setLocalWorkSize(8, 8); }
+ void selectLocalWorkSize16x16(bool checked)
+ { if (checked) bezierWidget->setLocalWorkSize(16, 16); }
+};
+
+#endif
diff --git a/examples/opencl/bezierpatch/beziermainwindow.ui b/examples/opencl/bezierpatch/beziermainwindow.ui
new file mode 100644
index 0000000..fba7a3c
--- /dev/null
+++ b/examples/opencl/bezierpatch/beziermainwindow.ui
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BezierMainWindow</class>
+ <widget class="QWidget" name="BezierMainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>619</width>
+ <height>405</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>BezierMainWindow</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="BezierWidget" name="bezierWidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QCheckBox" name="useOpenCL">
+ <property name="text">
+ <string>Use OpenCL</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="localWorkSize">
+ <property name="title">
+ <string>Local Work Size</string>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QRadioButton" name="localWorkSizeDefault">
+ <property name="text">
+ <string>Default</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="localWorkSize1x1">
+ <property name="text">
+ <string>1x1</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="localWorkSize1x8">
+ <property name="text">
+ <string>1x8</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="localWorkSize8x1">
+ <property name="text">
+ <string>8x1</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="localWorkSize8x8">
+ <property name="text">
+ <string>8x8</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="localWorkSize16x16">
+ <property name="text">
+ <string>16x16</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>BezierWidget</class>
+ <extends>QWidget</extends>
+ <header>bezierwidget.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/examples/opencl/bezierpatch/bezierpatch.cl b/examples/opencl/bezierpatch/bezierpatch.cl
new file mode 100644
index 0000000..7bca1a6
--- /dev/null
+++ b/examples/opencl/bezierpatch/bezierpatch.cl
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// Evaluate a Bezier patch at a (s, t) determined by the global work item.
+__kernel void evaluateBezier
+ (__global __write_only float4 *positions,
+ __global __write_only float2 *texCoords,
+ float16 matrixX, float16 matrixY, float16 matrixZ,
+ int size)
+{
+ float s = ((float)(get_global_id(0))) / (size - 1);
+ float s2 = s * s;
+ float t = ((float)(get_global_id(1))) / (size - 1);
+ float t2 = t * t;
+ float4 S = (float4)(s2 * s, s2, s, 1);
+ float4 T = (float4)(t2 * t, t2, t, 1);
+
+ // Calculate the position of the item at (s, t).
+ float4 smx = (float4)(dot(S, matrixX.lo.lo),
+ dot(S, matrixX.lo.hi),
+ dot(S, matrixX.hi.lo),
+ dot(S, matrixX.hi.hi));
+ float4 smy = (float4)(dot(S, matrixY.lo.lo),
+ dot(S, matrixY.lo.hi),
+ dot(S, matrixY.hi.lo),
+ dot(S, matrixY.hi.hi));
+ float4 smz = (float4)(dot(S, matrixZ.lo.lo),
+ dot(S, matrixZ.lo.hi),
+ dot(S, matrixZ.hi.lo),
+ dot(S, matrixZ.hi.hi));
+
+ // Output the results.
+ int offset = get_global_id(0) + get_global_id(1) * size;
+ positions[offset] = (float4)(dot(smx, T), dot(smy, T), dot(smz, T), 1);
+ texCoords[offset] = (float2)(s, t);
+}
diff --git a/examples/opencl/bezierpatch/bezierpatch.pro b/examples/opencl/bezierpatch/bezierpatch.pro
new file mode 100644
index 0000000..ca56dae
--- /dev/null
+++ b/examples/opencl/bezierpatch/bezierpatch.pro
@@ -0,0 +1,24 @@
+TEMPLATE = app
+TARGET = bezierpatch
+DEPENDPATH += .
+INCLUDEPATH += .
+QT += opengl
+
+VPATH += ../../../demos/mandelbrot
+INCLUDEPATH += ../../../demos/mandelbrot
+
+# Input
+SOURCES += main.cpp \
+ beziermainwindow.cpp \
+ bezierwidget.cpp \
+ qglcamera.cpp \
+ framerate.cpp
+HEADERS += bezierwidget.h \
+ beziermainwindow.h \
+ qglcamera.h \
+ framerate.h
+RESOURCES += bezierpatch.qrc
+FORMS += beziermainwindow.ui
+
+LIBS += -L../../../lib -L../../../bin
+include(../../../src/opencl/opencl_dep.pri)
diff --git a/examples/opencl/bezierpatch/bezierpatch.qrc b/examples/opencl/bezierpatch/bezierpatch.qrc
new file mode 100644
index 0000000..a55ea7f
--- /dev/null
+++ b/examples/opencl/bezierpatch/bezierpatch.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>bezierpatch.cl</file>
+ <file>qtlogo.png</file>
+</qresource>
+</RCC>
diff --git a/examples/opencl/bezierpatch/bezierwidget.cpp b/examples/opencl/bezierpatch/bezierwidget.cpp
new file mode 100644
index 0000000..96a1d80
--- /dev/null
+++ b/examples/opencl/bezierpatch/bezierwidget.cpp
@@ -0,0 +1,449 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "bezierwidget.h"
+#include <QtCore/qtimer.h>
+#include <QtCore/qdatetime.h>
+#include <QtGui/qpainter.h>
+#if QT_VERSION >= 0x040700
+#define USE_VBOS 1
+#include <QtOpenGL/qglbuffer.h>
+#endif
+
+/*
+ The Bezier patch equation is:
+
+ x(s, t) = S . M . Gx . transpose(M) . transpose(T)
+ y(s, t) = S . M . Gy . transpose(M) . transpose(T)
+ z(s, t) = S . M . Gz . transpose(M) . transpose(T)
+
+ where:
+
+ S = [s^3 s^2 s 1]
+ T = [t^3 t^2 t 1]
+ M = |-1 3 -3 1|
+ | 3 -6 3 0]
+ |-3 3 0 0|
+ | 1 0 0 0|
+ Gx = | x11 x12 x13 x14 | i.e. x components of the control points
+ | x21 x22 x23 x24 |
+ | x31 x32 x33 x34 |
+ | x41 x42 x43 x44 |
+ Gy, Gz are similar
+
+ Note: transpose(M) = M
+
+ From "Computer Graphics: Principles and Practice", Foley, van Dam,
+ et al, Second Edition, Addison Wesley, 1996.
+*/
+
+BezierWidget::BezierWidget(QWidget *parent)
+ : QGLWidget(parent)
+ , useOpenCL(true)
+ , matrixM(-1, 3, -3, 1,
+ 3, -6, 3, 0,
+ -3, 3, 0, 0,
+ 1, 0, 0, 0)
+ , positions(0)
+ , texCoords(0)
+ , indices(0)
+ , numVertices(0)
+ , numIndices(0)
+#ifdef QT_OPENGL_ES
+ // We need a value that is a multiple of 16, but less than
+ // sqrt(65535 / 6) = 104.5 because we cannot use more than
+ // 65535 indices under OpenGL/ES.
+ , subdivisionSize(96)
+#else
+ , subdivisionSize(512)
+#endif
+ , lastSubdivisionSize(-1)
+ , textureId(0)
+ , vertexBuffer(0)
+ , indexBuffer(0)
+{
+ setAutoFillBackground(false);
+
+ // Patch is in the X-Z plane from x = 0, z = 0, to x = 3, z = 3.
+ // The height of the patch at each control point is adjusted in Y.
+ cp[0] = QVector3D(0, 0, 0);
+ cp[1] = QVector3D(1, 1, 0);
+ cp[2] = QVector3D(2, -1, 0);
+ cp[3] = QVector3D(3, 0, 0);
+ cp[4] = QVector3D(0, 0, 1);
+ cp[5] = QVector3D(1, 1, 1);
+ cp[6] = QVector3D(2, -1, 1);
+ cp[7] = QVector3D(3, 0, 1);
+ cp[8] = QVector3D(0, 0, 2);
+ cp[9] = QVector3D(1, 1, 2);
+ cp[10] = QVector3D(2, -1, 2);
+ cp[11] = QVector3D(3, 0, 2);
+ cp[12] = QVector3D(0, 0, 3);
+ cp[13] = QVector3D(1, 1, 3);
+ cp[14] = QVector3D(2, -1, 3);
+ cp[15] = QVector3D(3, 0, 3);
+
+ camera.setCenter(QVector3D(1.5f, 0.0f, 1.5f));
+ camera.setEye(QVector3D(-6.0f, 5.0f, 6.0f));
+
+ if (!context.create())
+ qFatal("Could not create OpenCL context");
+
+ program = context.buildProgramFromSourceFile(QLatin1String(":/bezierpatch.cl"));
+ evaluateBezier = program.createKernel("evaluateBezier");
+ evaluateBezier.setLocalWorkSize(8, 8);
+
+ QTimer *timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(animate()));
+ timer->start(0);
+
+ qsrand(QDateTime::currentDateTime().toTime_t());
+}
+
+BezierWidget::~BezierWidget()
+{
+}
+
+void BezierWidget::resizeGL(int width, int height)
+{
+ glViewport(0, 0, width, height);
+}
+
+void BezierWidget::initializeGL()
+{
+ glEnable(GL_DEPTH_TEST);
+
+ textureImage = QImage(QLatin1String(":/qtlogo.png"));
+ textureId = bindTexture(textureImage);
+}
+
+#if !defined(QT_OPENGL_ES_2)
+
+static void setGLMatrix(GLenum type, const QMatrix4x4& m)
+{
+ glMatrixMode(type);
+ if (sizeof(qreal) == sizeof(GLfloat)) {
+ glLoadMatrixf(reinterpret_cast<const GLfloat *>(m.constData()));
+ } else {
+ GLfloat mat[16];
+ const qreal *data = m.constData();
+ for (int index = 0; index < 16; ++index)
+ mat[index] = data[index];
+ glLoadMatrixf(mat);
+ }
+}
+
+#endif
+
+void BezierWidget::paintGL()
+{
+#if !defined(QT_OPENGL_ES_2)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ if (useOpenCL)
+ computeVerticesCL();
+ else
+ computeVerticesNative();
+
+ QMatrix4x4 proj = camera.projectionMatrix(qreal(width()) / height());
+ QMatrix4x4 mv = camera.modelViewMatrix();
+
+ setGLMatrix(GL_PROJECTION, proj);
+ setGLMatrix(GL_MODELVIEW, mv);
+
+#ifdef USE_VBOS
+ if (vertexBuffer) {
+ vertexBuffer->bind();
+ glVertexPointer(4, GL_FLOAT, 0, 0);
+ glTexCoordPointer(2, GL_FLOAT, 0, (void *)(sizeof(GLfloat) * 4 * numVertices));
+ vertexBuffer->release();
+ } else {
+ glVertexPointer(4, GL_FLOAT, 0, positions);
+ glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+ }
+#else
+ glVertexPointer(4, GL_FLOAT, 0, positions);
+ glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+#endif
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ glEnable(GL_TEXTURE_2D);
+
+#ifdef USE_VBOS
+ if (indexBuffer) {
+ indexBuffer->bind();
+ glDrawElements(GL_TRIANGLES, numIndices, IndexTypeEnum, 0);
+ indexBuffer->release();
+ } else {
+ glDrawElements(GL_TRIANGLES, numIndices, IndexTypeEnum, indices);
+ }
+#else
+ glDrawElements(GL_TRIANGLES, numIndices, IndexTypeEnum, indices);
+#endif
+
+ glDisable(GL_TEXTURE_2D);
+#endif
+
+ qreal fps = frameRate.fps();
+ if (fps > 0.0f) {
+ QPainter painter(this);
+ QString str = QString::number(numIndices / 3) + QLatin1String(" triangles, ");
+ str += QString::number(fps) + QLatin1String(" fps");
+ painter.setPen(Qt::white);
+ painter.drawText(rect(), str);
+ }
+}
+
+void BezierWidget::setUseOpenCL(bool value)
+{
+ useOpenCL = value;
+ frameRate.start();
+}
+
+void BezierWidget::setLocalWorkSize(int x, int y)
+{
+ evaluateBezier.setLocalWorkSize(x, y);
+ frameRate.start();
+}
+
+static inline qreal clamp(qreal value, qreal lower, qreal upper)
+{
+ if (value < lower)
+ return lower;
+ else if (value > upper)
+ return upper;
+ else
+ return value;
+}
+
+void BezierWidget::animate()
+{
+ // Move several of the non-corner control points up or down.
+ static int mapPoints[12] = {1, 2, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14};
+ for (int move = 0; move < 4; ++move) {
+ int index = mapPoints[qrand() % 12];
+ qreal amt = (qrand() & 1) ? 0.2f : -0.2f;
+ qreal y = clamp(cp[index].y() + amt, -3.0f, 3.0f);
+ cp[index].setY(y);
+ }
+ frameRate.newFrame();
+ updateGL();
+}
+
+void BezierWidget::computeMatrices()
+{
+ QMatrix4x4 xm(cp[0].x(), cp[1].x(), cp[2].x(), cp[3].x(),
+ cp[4].x(), cp[5].x(), cp[6].x(), cp[7].x(),
+ cp[8].x(), cp[9].x(), cp[10].x(), cp[11].x(),
+ cp[12].x(), cp[13].x(), cp[14].x(), cp[15].x());
+ QMatrix4x4 ym(cp[0].y(), cp[1].y(), cp[2].y(), cp[3].y(),
+ cp[4].y(), cp[5].y(), cp[6].y(), cp[7].y(),
+ cp[8].y(), cp[9].y(), cp[10].y(), cp[11].y(),
+ cp[12].y(), cp[13].y(), cp[14].y(), cp[15].y());
+ QMatrix4x4 zm(cp[0].z(), cp[1].z(), cp[2].z(), cp[3].z(),
+ cp[4].z(), cp[5].z(), cp[6].z(), cp[7].z(),
+ cp[8].z(), cp[9].z(), cp[10].z(), cp[11].z(),
+ cp[12].z(), cp[13].z(), cp[14].z(), cp[15].z());
+
+ matrixX = matrixM * xm * matrixM;
+ matrixY = matrixM * ym * matrixM;
+ matrixZ = matrixM * zm * matrixM;
+}
+
+void BezierWidget::computeVerticesNative()
+{
+ computeMatrices();
+ allocVertices();
+
+#ifdef USE_VBOS
+ QVector4D *posns;
+ QVector2D *texcs;
+ if (vertexBuffer) {
+ vertexBuffer->bind();
+ void *mapped = vertexBuffer->map(QGLBuffer::WriteOnly);
+ posns = (QVector4D *)mapped;
+ texcs = (QVector2D *)(((uchar *)mapped) +
+ numVertices * sizeof(GLfloat) * 4);
+ } else {
+ posns = positions;
+ texcs = texCoords;
+ }
+#else
+ posns = positions;
+ texcs = texCoords;
+#endif
+
+ for (int sint = 0; sint < subdivisionSize; ++sint) {
+ qreal s = qreal(sint) / (subdivisionSize - 1);
+ QVector4D svec = QVector4D(s * s * s, s * s, s, 1);
+ for (int tint = 0; tint < subdivisionSize; ++tint) {
+ qreal t = qreal(tint) / (subdivisionSize - 1);
+ QVector4D tvec = QVector4D(t * t * t, t * t, t, 1);
+ qreal x = QVector4D::dotProduct(svec * matrixX, tvec);
+ qreal y = QVector4D::dotProduct(svec * matrixY, tvec);
+ qreal z = QVector4D::dotProduct(svec * matrixZ, tvec);
+ int offset = sint + tint * subdivisionSize;
+ posns[offset] = QVector4D(x, y, z, 1);
+ texcs[offset] = QVector2D(s, t);
+ }
+ }
+
+#ifdef USE_VBOS
+ if (vertexBuffer) {
+ vertexBuffer->unmap();
+ vertexBuffer->release();
+ }
+#endif
+}
+
+void BezierWidget::computeVerticesCL()
+{
+ computeMatrices();
+ allocVertices();
+
+ evaluateBezier.setGlobalWorkSize(subdivisionSize, subdivisionSize);
+ evaluateBezier(positionBuffer, texCoordBuffer,
+ matrixX, matrixY, matrixZ, subdivisionSize);
+
+#ifdef USE_VBOS
+ if (vertexBuffer) {
+ // Read the results directly into the vertex buffer.
+ vertexBuffer->bind();
+ GLfloat *mapped = (GLfloat *)vertexBuffer->map(QGLBuffer::WriteOnly);
+ GLfloat *posns = mapped;
+ GLfloat *texcs = mapped + numVertices * 4;
+ positionBuffer.read(posns, numVertices * sizeof(GLfloat) * 4);
+ texCoordBuffer.read(texcs, numVertices * sizeof(GLfloat) * 2);
+ vertexBuffer->unmap();
+ vertexBuffer->release();
+ } else {
+ positionBuffer.read(positions, numVertices * sizeof(GLfloat) * 4);
+ texCoordBuffer.read(texCoords, numVertices * sizeof(GLfloat) * 2);
+ }
+#else
+ positionBuffer.read(positions, numVertices * sizeof(GLfloat) * 4);
+ texCoordBuffer.read(texCoords, numVertices * sizeof(GLfloat) * 2);
+#endif
+}
+
+void BezierWidget::allocVertices()
+{
+ if (subdivisionSize == lastSubdivisionSize)
+ return;
+ lastSubdivisionSize = subdivisionSize;
+
+ // Expand the vertex and index arrays.
+ int num = subdivisionSize * subdivisionSize;
+ if (num > numVertices) {
+ positions = (QVector4D *)qRealloc(positions, num * sizeof(GLfloat) * 4);
+ texCoords = (QVector2D *)qRealloc(texCoords, num * sizeof(GLfloat) * 2);
+
+ int maxIndices = num * 6;
+ indices = (IndexType *)qRealloc(indices, maxIndices * sizeof(IndexType));
+ }
+ numVertices = num;
+#ifdef USE_VBOS
+ // Create a vertex buffer in the server.
+ if (!vertexBuffer) {
+ vertexBuffer = new QGLBuffer(QGLBuffer::VertexBuffer);
+ vertexBuffer->setUsagePattern(QGLBuffer::DynamicDraw);
+ if (!vertexBuffer->create()) {
+ delete vertexBuffer;
+ vertexBuffer = 0;
+ }
+ }
+ if (vertexBuffer) {
+ vertexBuffer->bind();
+ vertexBuffer->allocate(sizeof(GLfloat) * 6 * num);
+ if (!vertexBuffer->map(QGLBuffer::WriteOnly)) {
+ // No point using a vertex buffer if we cannot map it.
+ vertexBuffer->unmap();
+ vertexBuffer->release();
+ delete vertexBuffer;
+ vertexBuffer = 0;
+ } else {
+ vertexBuffer->unmap();
+ vertexBuffer->release();
+ }
+ }
+#endif
+
+ // Generate a new index array for drawing the triangles.
+ numIndices = 0;
+ for (int sint = 0; sint < (subdivisionSize - 1); ++sint) {
+ for (int tint = 0; tint < (subdivisionSize - 1); ++tint) {
+ int corner1 = sint + tint * subdivisionSize;
+ int corner2 = sint + (tint + 1) * subdivisionSize;
+ int corner3 = (sint + 1) + (tint + 1) * subdivisionSize;
+ int corner4 = (sint + 1) + tint * subdivisionSize;
+ indices[numIndices++] = corner1;
+ indices[numIndices++] = corner2;
+ indices[numIndices++] = corner3;
+ indices[numIndices++] = corner1;
+ indices[numIndices++] = corner3;
+ indices[numIndices++] = corner4;
+ }
+ }
+#ifdef USE_VBOS
+ // Upload the indices into a server-side buffer.
+ if (!indexBuffer) {
+ indexBuffer = new QGLBuffer(QGLBuffer::IndexBuffer);
+ if (!indexBuffer->create()) {
+ delete indexBuffer;
+ indexBuffer = 0;
+ }
+ }
+ if (indexBuffer) {
+ indexBuffer->bind();
+ indexBuffer->allocate(indices, sizeof(IndexType) * numIndices);
+ indexBuffer->release();
+ }
+#endif
+
+ // Allocate OpenCL buffers of the right size.
+ positionBuffer = context.createBufferDevice
+ (num * sizeof(GLfloat) * 4, QCL::WriteOnly);
+ texCoordBuffer = context.createBufferDevice
+ (num * sizeof(GLfloat) * 2, QCL::WriteOnly);
+}
diff --git a/examples/opencl/bezierpatch/bezierwidget.h b/examples/opencl/bezierpatch/bezierwidget.h
new file mode 100644
index 0000000..e8836dc
--- /dev/null
+++ b/examples/opencl/bezierpatch/bezierwidget.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef BEZIERWIDGET_H
+#define BEZIERWIDGET_H
+
+#include <QtOpenGL/qgl.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include "qclcontext.h"
+#include "qglcamera.h"
+#include "framerate.h"
+
+class QGLBuffer;
+
+class BezierWidget : public QGLWidget
+{
+ Q_OBJECT
+public:
+ BezierWidget(QWidget *parent = 0);
+ ~BezierWidget();
+
+protected:
+ void resizeGL(int width, int height);
+ void initializeGL();
+ void paintGL();
+
+public slots:
+ void setUseOpenCL(bool value);
+ void setLocalWorkSize(int x, int y);
+
+private slots:
+ void animate();
+
+private:
+ bool useOpenCL;
+
+ QCLContext context;
+
+ QCLProgram program;
+ QCLKernel evaluateBezier;
+ QCLBuffer positionBuffer;
+ QCLBuffer texCoordBuffer;
+
+ QGLCamera camera;
+ FrameRate frameRate;
+
+ QMatrix4x4 matrixM;
+ QMatrix4x4 matrixX;
+ QMatrix4x4 matrixY;
+ QMatrix4x4 matrixZ;
+ QVector3D cp[16];
+
+ QVector4D *positions;
+ QVector2D *texCoords;
+#ifdef QT_OPENGL_ES
+ typedef ushort IndexType;
+ static const GLenum IndexTypeEnum = GL_UNSIGNED_SHORT;
+#else
+ typedef uint IndexType;
+ static const GLenum IndexTypeEnum = GL_UNSIGNED_INT;
+#endif
+ IndexType *indices;
+ int numVertices;
+ int numIndices;
+ int subdivisionSize;
+ int lastSubdivisionSize;
+
+ QImage textureImage;
+ GLuint textureId;
+
+ QGLBuffer *vertexBuffer;
+ QGLBuffer *indexBuffer;
+
+ void computeMatrices();
+ void computeVerticesNative();
+ void computeVerticesCL();
+
+ void allocVertices();
+};
+
+#endif
diff --git a/examples/opencl/bezierpatch/main.cpp b/examples/opencl/bezierpatch/main.cpp
new file mode 100644
index 0000000..46d2a40
--- /dev/null
+++ b/examples/opencl/bezierpatch/main.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include "beziermainwindow.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ BezierMainWindow w;
+ w.show();
+ return app.exec();
+}
diff --git a/examples/opencl/bezierpatch/qglcamera.cpp b/examples/opencl/bezierpatch/qglcamera.cpp
new file mode 100644
index 0000000..ddadeb0
--- /dev/null
+++ b/examples/opencl/bezierpatch/qglcamera.cpp
@@ -0,0 +1,1025 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglcamera.h"
+#include <QtGui/qquaternion.h>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QGLCamera
+ \brief The QGLCamera class defines the projection to apply to simulate a camera's position, orientation, and optics.
+ \since 4.7
+ \ingroup qt3d
+ \ingroup qt3d::viewing
+
+ \section1 Modelview and projection transformations
+
+ A QGLCamera instance is applied to the scene in two phases:
+ modelview transformation and projection transformation.
+
+ During the modelview transformation, the eye(), center(), and
+ upVector() are used to generate a 4x4 transformation matrix that
+ reflects the viewer's current position and orientation.
+
+ During the projection transformation, the projectionType(),
+ nearPlane(), farPlane(), fieldOfView(), and viewSize() are used
+ to define a viewing volume as a 4x4 transformation matrix.
+
+ The modelview transformation matrix is returned by modelViewMatrix().
+ The projection transformation matrix is returned by projectionMatrix().
+
+ \section1 Positioning and orienting the view
+
+ The viewer position and orientation are defined by eye(), center(),
+ and upVector(). The location of the viewer in world co-ordinates is
+ given by eye(), the viewer is looking at the object of interest located
+ at center(), and the upVector() specifies the direction that should
+ be considered "up" with respect to the viewer.
+
+ The vector from the eye() to the center() is called the "view vector",
+ and the cross-product of the view vector and upVector() is called
+ the "side vector". The view vector specifies the direction the
+ viewer is looking, and the side vector points off to the right of
+ the viewer.
+
+ It is recommended that the view vector and upVector() be at right angles
+ to each other, but this is not required as long as the angle between
+ them is close to 90 degrees.
+
+ The most common use of view and up vectors that are not at right angles
+ is to simulate a human eye at a specific height above the ground looking
+ down at a lower object or up at a higher object. In this case, the
+ the view vector will not be true horizontal, but the upVector() indicating
+ the human's upright stance will be true vertical.
+
+ \section1 Zooming the camera image
+
+ There are two ways to zoom the image seen through the camera: either
+ the camera eye() position can be moved closer to the object of interest,
+ or the field of view of the camera lens can be changed to make it appear
+ as though the object is moving closer.
+
+ Changing the eye() position changes the lighting calculation in the
+ scene because the viewer is in a different position, changing the
+ angle of light reflection on the object's surface.
+
+ The setFieldOfView() function can be used to simulate the effect of a
+ camera lens. The smaller the fieldOfView(), the closer the object
+ will appear. The lighting calculation will be the same as for the
+ unzoomed scene.
+
+ If fieldOfView() is zero, then a standard perspective frustum of
+ viewSize() is used to define the viewing volume. The viewSize()
+ can be adjusted with setViewSize() to zoom the view. A smaller
+ viewSize() will make the the object appear closer.
+
+ The fieldOfView() or viewSize() is applied as part of the
+ projectionMatrix().
+
+ \section1 Rotating the viewer or object of interest
+
+ Rotating a viewer in 3D space is a very delicate process. It is very
+ easy to construct the rotation incorrectly and end up in a "gimbal lock"
+ state where further rotations are impossible in certain directions.
+
+ To help alleviate this problem, QGLCamera uses a quaternion-based
+ approach to generate rotations. A quaternion is a compact representation
+ of a rotation in 3D space. Rotations can be combined through quaternion
+ multiplication. More information on quaternions can be found in the
+ documentation for QQuaternion.
+
+ Before rotating the view, you should first decide the type
+ of rotation you want to perform:
+
+ \list
+ \i Tilting or panning a fixed eye to reveal the scene in different
+ directions and orientations. This is equivalent to mounting a camera
+ on a fixed tripod and then adjusting the direction of view and
+ orientation with the tripod controls.
+ \i Rotating a moving viewer about the object of interest. This is
+ equivalent to moving the viewer around the object at a fixed distance,
+ but with the viewer always pointing at the object.
+ \endlist
+
+ In the QGLCamera class, the first type of rotation is performed with
+ rotateEye() and the second with rotateCenter(). Each of these functions
+ take a quaternion argument that defines the type of rotation to perform.
+
+ The tilt(), pan(), and roll() functions return values that can help with
+ constructing the rotation quaternions to pass to rotateEye() and
+ rotateCenter(). Tilt and pan are also known as "pitch" and "yaw" in
+ flight dynamics.
+
+ Three axes of rotation are used to compute the quaternions. The tilt()
+ quaternion is computed with respect to the side vector, the pan()
+ quaterion is computed with respect to the upVector(), and the roll()
+ quaternion is computed with respect to the view vector.
+
+ The following example tilts the direction the eye() is pointing
+ by 5 degrees, and then pans by 45 degrees:
+
+ \code
+ camera.rotateEye(camera.tilt(5));
+ camera.rotateEye(camera.pan(45));
+ \endcode
+
+ The next example performs the two rotations in a single fluid step
+ (note that the rotation to be performed first is multiplied last):
+
+ \code
+ camera.rotateEye(camera.pan(45) * camera.tilt(5));
+ \endcode
+
+ These two examples will not produce the same visual result, even though
+ it looks like they might. In the first example, the upVector() is tilted
+ before the pan() quaternion is computed. In the second example, the pan()
+ quaternion is computed using the original upVector().
+
+ This difference in behavior is useful in different situations. Some
+ applications may wish to perform all rotations relative to the original
+ viewer orientation, and other applications may wish to perform rotations
+ relative to the current viewer orientation. These application types
+ correspond to the second and first examples above.
+
+ \section1 Moving the viewer or object of interest
+
+ The simplest way to move the viewer or object of interest is to call
+ setEye() or setCenter() respectively and supply a new position in
+ world co-ordinates. However, this can lead to non-intuitive movements
+ if the viewer orientation is not aligned with the world co-ordinate axes.
+
+ For example, subtracting 3 from the eye() x co-ordinate will appear to
+ move the eye left 3 units if the viewer orientation is aligned with the
+ world co-ordinate axes. But it will not appear to move the eye left 3
+ units in any other orientation.
+
+ The translation() function can be used to construct a translation
+ vector that is aligned with the viewer's current orientation.
+ Movement in the x direction will move along the side vector, movement in
+ the y direction will move along upVector(), and movement in the z
+ direction will move along the view vector.
+
+ The translation() function is useful when implementing operations such
+ as "step left", "jump up", and so on where the movement should be
+ interpreted relative to the viewer's current orientation, not the
+ world co-ordinate axes,
+
+ In other words, the following two lines of code are not equivalent
+ unless the view is oriented with the world co-ordinate axes:
+
+ \code
+ camera.translateEye(camera.translation(x, y, z));
+
+ camera.translateEye(QVector3D(x, y, z));
+ \endcode
+
+ The following example translates the eye() position while
+ keeping the object of interest at the original center():
+
+ \code
+ camera.translateEye(camera.translation(x, y, z));
+ \endcode
+
+ The following example translates the object of interest at
+ center() while keeping the eye() position fixed:
+
+ \code
+ camera.translateCenter(camera.translation(x, y, z));
+ \endcode
+
+ The following example translates both the eye() and the center()
+ by the same amount, which will maintain the original view vector.
+
+ \code
+ QVector3D vector = camera.translation(x, y, z);
+ camera.translateEye(vector);
+ camera.translateCenter(vector);
+ \endcode
+
+ It is important that the translation vector for center() be computed
+ before eye() is translated if both eye() and center() must move by the
+ same amount. The following code translates center() in the viewer
+ orientation after the eye() is translated:
+
+ \code
+ camera.translateEye(camera.translation(x, y, z));
+ camera.translateCenter(camera.translation(x, y, z));
+ \endcode
+
+ Translating both eye() and center() by the same amount can be used
+ to simulate sliding a viewer past a scene while always looking in the
+ same direction (for example, filming a scene from a moving vehicle).
+ An alternative is to fix the viewer and move the scene itself:
+ the negation of the translation() vector can be applied to the
+ scene's modelview transformation.
+
+ \section1 Motion tracking
+
+ Viewing of 3D scenes can be enhanced if there is some way to track
+ the motion of the viewer or the orientation of the display device.
+
+ Applications can use setMotionAdjustment() to alter the position
+ of the camera to account for the viewer's motion. This indicates
+ the viewer's position relative to the center of the screen.
+ The motionAdjustment() vector is used to determine by how much
+ the camera position should be adjusted. The distance of the viewer
+ from the screen is ignored.
+
+ On handheld devices that use accelerometers to determine the
+ orientation of the device, the down vector due to gravity
+ can be adjusted to serve as a motion tracking vector.
+
+ The output of motion tracking hardware can be very noisy,
+ with minor fluctuations due to viewer twitch movements or
+ environmental factors. The application is responsible for
+ cleaning up the signal and removing these fluctuations before
+ setMotionAdjustment() is called.
+*/
+
+class QGLCameraPrivate
+{
+public:
+ QGLCameraPrivate();
+
+ QGLCamera::ProjectionType projectionType;
+ qreal fieldOfView;
+ qreal nearPlane;
+ qreal farPlane;
+ QSizeF viewSize;
+ QSizeF minViewSize;
+ int screenRotation;
+ QVector3D eye;
+ QVector3D upVector;
+ QVector3D center;
+ QVector3D viewVector;
+ qreal eyeSeparation;
+ QVector3D motionAdjustment;
+ QQuaternion motionQuaternion;
+};
+
+QGLCameraPrivate::QGLCameraPrivate()
+ : projectionType(QGLCamera::Perspective),
+ fieldOfView(0.0f),
+ nearPlane(5.0f),
+ farPlane(1000.0f),
+ viewSize(2.0f, 2.0f),
+ minViewSize(0.0001f, 0.0001f),
+ screenRotation(0),
+ eye(0.0f, 0.0f, 10.0f),
+ upVector(0.0f, 1.0f, 0.0f),
+ center(0.0f, 0.0f, 0.0f),
+ viewVector(0.0f, 0.0f, -10.0f),
+ eyeSeparation(0.0f),
+ motionAdjustment(0.0f, 0.0f, 1.0f)
+{
+}
+
+/*!
+ Constructs a QGLCamera with the default properties and
+ attaches it to \a parent.
+*/
+QGLCamera::QGLCamera(QObject *parent)
+ : QObject(parent), d_ptr(new QGLCameraPrivate)
+{
+}
+
+/*!
+ Destroys this QGLCamera object.
+*/
+QGLCamera::~QGLCamera()
+{
+ delete d_ptr;
+}
+
+/*!
+ \enum QGLCamera::ProjectionType
+ This enum defines the type of view projection to use for a QGLCamera.
+
+ \value Perspective Use a perspective view.
+ \value Orthographic Use an ortographic view.
+*/
+
+/*!
+ \property QGLCamera::projectionType
+ \brief the projection type for this camera. The default is Perspective.
+*/
+QGLCamera::ProjectionType QGLCamera::projectionType() const
+{
+ Q_D(const QGLCamera);
+ return d->projectionType;
+}
+
+void QGLCamera::setProjectionType(QGLCamera::ProjectionType value)
+{
+ Q_D(QGLCamera);
+ if (d->projectionType != value) {
+ d->projectionType = value;
+ emit projectionChanged();
+ }
+}
+
+/*!
+ \property QGLCamera::fieldOfView
+ \brief the field of view in degrees for a perspective projection.
+
+ The default value is zero, which indicates a standard perspective
+ frustum view volume of viewSize() in size. If the value is not
+ zero, then viewSize() is ignored.
+
+ This value is ignored if projectionType() is Orthographic.
+
+ \sa viewSize()
+*/
+qreal QGLCamera::fieldOfView() const
+{
+ Q_D(const QGLCamera);
+ return d->fieldOfView;
+}
+
+void QGLCamera::setFieldOfView(qreal angle)
+{
+ Q_D(QGLCamera);
+ if (d->fieldOfView != angle) {
+ d->fieldOfView = angle;
+ emit projectionChanged();
+ }
+}
+
+/*!
+ \property QGLCamera::nearPlane
+ \brief the distance from the eye to the near clipping plane.
+ The default value is 5.
+
+ \sa farPlane()
+*/
+qreal QGLCamera::nearPlane() const
+{
+ Q_D(const QGLCamera);
+ return d->nearPlane;
+}
+
+void QGLCamera::setNearPlane(qreal value)
+{
+ Q_D(QGLCamera);
+ if (d->nearPlane != value) {
+ d->nearPlane = value;
+ emit projectionChanged();
+ }
+}
+
+/*!
+ \property QGLCamera::farPlane
+ \brief the distance from the eye to the far clipping plane.
+ The default value is 1000.
+
+ \sa nearPlane()
+*/
+qreal QGLCamera::farPlane() const
+{
+ Q_D(const QGLCamera);
+ return d->farPlane;
+}
+
+void QGLCamera::setFarPlane(qreal value)
+{
+ Q_D(QGLCamera);
+ if (d->farPlane != value) {
+ d->farPlane = value;
+ emit projectionChanged();
+ }
+}
+
+/*!
+ \property QGLCamera::viewSize
+ \brief the size of the front of the projection viewing volume.
+ The viewing volume is assumed to be centered on the origin.
+
+ The default value is (2, 2), which indicates a viewing volume front
+ from (-1, -1) to (1, 1).
+
+ If the width or height of the viewing volume is negative, then the
+ co-ordinates will be swapped. For example, a size of (2, -2) will
+ flip the vertical axis upside down for a viewing volume from
+ (-1, 1) to (1, -1).
+
+ The view size will be further adjusted by the window's aspect ratio
+ when projectionMatrix() is called. For best results, the width and
+ height of the view size should be the same to define an ideal square
+ viewing volume, which is then extended to the final viewing volume
+ width and height based on the window's aspect ratio.
+
+ \sa projectionMatrix(), minViewSize()
+*/
+QSizeF QGLCamera::viewSize() const
+{
+ Q_D(const QGLCamera);
+ return d->viewSize;
+}
+
+void QGLCamera::setViewSize(const QSizeF& size)
+{
+ Q_D(QGLCamera);
+ QSizeF sz(size);
+ if (sz.width() < d->minViewSize.width())
+ sz.setWidth(d->minViewSize.width());
+ if (sz.height() < d->minViewSize.height())
+ sz.setHeight(d->minViewSize.height());
+ if (d->viewSize != sz) {
+ d->viewSize = sz;
+ emit projectionChanged();
+ }
+}
+
+/*!
+ \property QGLCamera::minViewSize
+ \brief the minimum size of the front of the projection viewing volume.
+
+ The minimum view size is used to clamp viewSize() when zooming
+ the camera closer to an object to prevent it "passing through"
+ the object and causing the scale factor to become infinite.
+
+ The default value is (0.0001, 0.0001).
+
+ \sa projectionMatrix(), viewSize()
+*/
+QSizeF QGLCamera::minViewSize() const
+{
+ Q_D(const QGLCamera);
+ return d->minViewSize;
+}
+
+void QGLCamera::setMinViewSize(const QSizeF& size)
+{
+ Q_D(QGLCamera);
+ if (d->viewSize != size) {
+ d->viewSize = size;
+ emit projectionChanged();
+ }
+}
+
+/*!
+ \property QGLCamera::screenRotation
+ \brief the screen rotation angle in degrees. The default
+ value is 0. If this value is 90 or 270, then the view
+ will be flipped width for height. The only supported values
+ are 0, 90, 180, and 270. The screen is rotated around the
+ positive z axis.
+
+ This setting is intended for simple screen rotations on handheld
+ devices that can be held in either portrait or landscape orientations.
+ The entire screen image is rotated so that it can be viewed in a
+ different device orientation.
+
+ Use rotateEye() or rotateCenter() for more complex rotations
+ that are not aligned with 0, 90, 180, or 270 degrees.
+*/
+int QGLCamera::screenRotation() const
+{
+ Q_D(const QGLCamera);
+ return d->screenRotation;
+}
+
+void QGLCamera::setScreenRotation(int angle)
+{
+ Q_D(QGLCamera);
+ if (d->screenRotation != angle) {
+ d->screenRotation = angle;
+ emit projectionChanged();
+ }
+}
+
+/*!
+ \property QGLCamera::xEye
+ \brief the x position of the viewer's eye. The default value is 0.
+
+ \sa eye(), translateEye(), upVector(), center(), eyeSeparation()
+ \sa motionAdjustment()
+*/
+qreal QGLCamera::xEye() const
+{
+ Q_D(QGLCamera);
+ return d->eye.x();
+}
+
+void QGLCamera::setXEye(qreal value)
+{
+ Q_D(QGLCamera);
+ d->eye.setX(value);
+ emit viewChanged();
+}
+
+/*!
+ \property QGLCamera::yEye
+ \brief the y position of the viewer's eye. The default value is 0.
+
+ \sa eye(), translateEye(), upVector(), center(), eyeSeparation()
+ \sa motionAdjustment()
+*/
+qreal QGLCamera::yEye() const
+{
+ Q_D(QGLCamera);
+ return d->eye.y();
+}
+
+void QGLCamera::setYEye(qreal value)
+{
+ Q_D(QGLCamera);
+ d->eye.setY(value);
+ emit viewChanged();
+}
+
+/*!
+ \property QGLCamera::zEye
+ \brief the z position of the viewer's eye. The default value is 10.
+
+ \sa eye(), translateEye(), upVector(), center(), eyeSeparation()
+ \sa motionAdjustment()
+*/
+qreal QGLCamera::zEye() const
+{
+ Q_D(QGLCamera);
+ return d->eye.z();
+}
+
+void QGLCamera::setZEye(qreal value)
+{
+ Q_D(QGLCamera);
+ d->eye.setZ(value);
+ emit viewChanged();
+}
+
+/*!
+ \property QGLCamera::eye
+ \brief the position of the viewer's eye. The default value is (0, 0, 10).
+
+ \sa translateEye(), upVector(), center(), eyeSeparation()
+ \sa motionAdjustment()
+*/
+QVector3D QGLCamera::eye() const
+{
+ Q_D(const QGLCamera);
+ return d->eye;
+}
+
+void QGLCamera::setEye(const QVector3D& vertex)
+{
+ Q_D(QGLCamera);
+ if (d->eye != vertex) {
+ d->eye = vertex;
+ d->viewVector = d->center - d->eye;
+ emit viewChanged();
+ }
+}
+
+/*!
+ Adjusts the position of the viewer's eye by the components of \a vector.
+ The final position is eye() + \a vector.
+
+ \sa eye(), setEye(), translateCenter()
+*/
+void QGLCamera::translateEye(const QVector3D& vector)
+{
+ Q_D(QGLCamera);
+ d->eye += vector;
+ d->viewVector = d->center - d->eye;
+ emit viewChanged();
+}
+
+/*!
+ \property QGLCamera::upVector
+ \brief the up vector for the viewer. The default value is (0, 1, 0).
+
+ \sa eye(), center()
+*/
+QVector3D QGLCamera::upVector() const
+{
+ Q_D(const QGLCamera);
+ return d->upVector;
+}
+
+void QGLCamera::setUpVector(const QVector3D& vector)
+{
+ Q_D(QGLCamera);
+ if (d->upVector != vector) {
+ d->upVector = vector;
+ emit viewChanged();
+ }
+}
+
+/*!
+ \property QGLCamera::xCentre
+ \brief the x position of the center of the view visible from the viewer's
+ position. The default value is 0.
+
+ \sa eye(), translateEye(), upVector(), center(), eyeSeparation()
+ \sa motionAdjustment()
+*/
+qreal QGLCamera::xCentre() const
+{
+ Q_D(QGLCamera);
+ return d->center.x();
+}
+
+void QGLCamera::setXCentre(qreal value)
+{
+ Q_D(QGLCamera);
+ d->center.setX(value);
+ emit viewChanged();
+}
+
+/*!
+ \property QGLCamera::yCentre
+ \brief the y position of the center of the view visible from the
+ viewer's position. The default value is 0.
+
+ \sa eye(), translateEye(), upVector(), center(), eyeSeparation()
+ \sa motionAdjustment()
+*/
+qreal QGLCamera::yCentre() const
+{
+ Q_D(QGLCamera);
+ return d->center.y();
+}
+
+void QGLCamera::setYCentre(qreal value)
+{
+ Q_D(QGLCamera);
+ d->center.setY(value);
+ emit viewChanged();
+}
+
+/*!
+ \property QGLCamera::zCentre
+ \brief the z position of the center of the view visible from the
+ viewer's position. The default value is 0.
+
+ \sa eye(), translateEye(), upVector(), center(), eyeSeparation()
+ \sa motionAdjustment()
+*/
+qreal QGLCamera::zCentre() const
+{
+ Q_D(QGLCamera);
+ return d->center.z();
+}
+
+void QGLCamera::setZCentre(qreal value)
+{
+ Q_D(QGLCamera);
+ d->center.setZ(value);
+ emit viewChanged();
+}
+
+/*!
+ \property QGLCamera::center
+ \brief the center of the view visible from the viewer's position.
+ The default value is (0, 0, 0).
+
+ \sa translateCenter(), eye(), upVector()
+*/
+QVector3D QGLCamera::center() const
+{
+ Q_D(const QGLCamera);
+ return d->center;
+}
+
+void QGLCamera::setCenter(const QVector3D& vertex)
+{
+ Q_D(QGLCamera);
+ if (d->center != vertex) {
+ d->center = vertex;
+ d->viewVector = d->center - d->eye;
+ emit viewChanged();
+ }
+}
+
+/*!
+ Adjusts the center of the view by the components of \a vector.
+ The final position is center() + \a vector.
+
+ \sa center(), setCenter(), translateEye()
+*/
+void QGLCamera::translateCenter(const QVector3D& vector)
+{
+ Q_D(QGLCamera);
+ d->center += vector;
+ d->viewVector = d->center - d->eye;
+ emit viewChanged();
+}
+
+/*!
+ \property QGLCamera::eyeSeparation
+ \brief the separation between the eyes when stereo viewing is in use,
+ with eye() specifying the mid-point between the eyes. The default
+ value is 0.
+
+ \sa eye()
+*/
+qreal QGLCamera::eyeSeparation() const
+{
+ Q_D(const QGLCamera);
+ return d->eyeSeparation;
+}
+
+void QGLCamera::setEyeSeparation(qreal value)
+{
+ Q_D(QGLCamera);
+ if (d->eyeSeparation != value) {
+ d->eyeSeparation = value;
+ emit viewChanged();
+ }
+}
+
+/*!
+ \property QGLCamera::motionAdjustment
+ \brief the adjustment vector to apply to the eye() for user motion.
+
+ This property is typically used to implement motion tracking.
+ It is interpreted as a vector from the center of the screen to the
+ current position of the viewer. The angle between the motion
+ adjustment vector and the screen center is used to adjust the
+ position of the eye() when apply() is called.
+
+ The default value is (0, 0, 1), which indicates a viewer
+ directly in front of the center of the screen.
+
+ The units for the vector are unspecified. They could be
+ meters, centimeters, or the force due to gravity in various
+ directions from an accelerometer. The angle defined
+ by the vector is used to perform the adjustment, not its
+ magnitude.
+
+ The output of motion tracking hardware can be very noisy,
+ with minor fluctuations due to viewer twitch movements or
+ environmental factors. The application is responsible for
+ cleaning up the signal and removing these fluctuations before
+ altering this property.
+
+ \sa eye(), apply()
+*/
+
+QVector3D QGLCamera::motionAdjustment() const
+{
+ Q_D(const QGLCamera);
+ return d->motionAdjustment;
+}
+
+void QGLCamera::setMotionAdjustment(const QVector3D& vector)
+{
+ Q_D(QGLCamera);
+ if (d->motionAdjustment != vector) {
+ d->motionAdjustment = vector;
+ if (vector.x() == 0.0f && vector.y() == 0.0f) {
+ // If the vector is centered, then don't perform any rotations.
+ d->motionQuaternion = QQuaternion();
+ } else {
+ // Determine the pan and tilt angles from the vector.
+ QVector3D view = -vector.normalized();
+ if (view.z() < 0.0f)
+ view = -view;
+ qreal xangle = asin(view.x()) * 180.0f / M_PI;
+ qreal yangle = asin(-view.y()) * 180.0f / M_PI;
+
+ // Construct the pan and tilt quaternions.
+ if (qFuzzyIsNull(xangle))
+ d->motionQuaternion = tilt(yangle);
+ else if (qFuzzyIsNull(yangle))
+ d->motionQuaternion = pan(xangle);
+ else
+ d->motionQuaternion = tilt(yangle) * pan(xangle);
+ }
+ emit viewChanged();
+ }
+}
+
+/*!
+ Returns the quaternion corresponding to tilting the view up or
+ down by \a angle degrees. The returned quaternion can be applied to
+ the eye() position with rotateEye() or to the center() position with
+ rotateCenter().
+
+ \sa pan(), roll(), rotateEye(), rotateCenter()
+*/
+QQuaternion QGLCamera::tilt(qreal angle) const
+{
+ Q_D(const QGLCamera);
+ QVector3D side = QVector3D::crossProduct(d->viewVector, d->upVector);
+ return QQuaternion::fromAxisAndAngle(side, angle);
+}
+
+/*!
+ Returns the quaternion corresponding to panning the view left or
+ right by \a angle degrees. The returned quaternion can be applied to
+ the eye() position with rotateEye() or to the center() position with
+ rotateCenter().
+
+ \sa tilt(), roll(), rotateEye(), rotateCenter()
+*/
+QQuaternion QGLCamera::pan(qreal angle) const
+{
+ Q_D(const QGLCamera);
+ return QQuaternion::fromAxisAndAngle(d->upVector, angle);
+}
+
+/*!
+ Returns the quaternion corresponding to rolling the view left or
+ right by \a angle degrees. The returned quaternion can be applied to
+ the eye() position with rotateEye() or to the center() position with
+ rotateCenter().
+
+ \sa tilt(), pan(), rotateEye(), rotateCenter()
+*/
+QQuaternion QGLCamera::roll(qreal angle) const
+{
+ Q_D(const QGLCamera);
+ return QQuaternion::fromAxisAndAngle(d->viewVector, angle);
+}
+
+/*!
+ Rotates the orientation of the eye() according to the quaternion \a q.
+ The eye() will remain in the same position, but the upVector() and
+ center() may be altered by the rotation.
+
+ \sa rotateCenter(), tilt(), pan(), roll()
+*/
+void QGLCamera::rotateEye(const QQuaternion& q)
+{
+ Q_D(QGLCamera);
+ d->upVector = q.rotatedVector(d->upVector);
+ d->viewVector = q.rotatedVector(d->viewVector);
+ d->center = d->eye + d->viewVector;
+ emit viewChanged();
+}
+
+/*!
+ Rotates the position and orientation of the eye() around center()
+ according to the quaternion \a q. The center() will remain in the
+ same position, but the upVector() and eye() may be altered by
+ the rotation.
+
+ \sa rotateEye(), tilt(), pan(), roll()
+*/
+void QGLCamera::rotateCenter(const QQuaternion& q)
+{
+ Q_D(QGLCamera);
+ d->upVector = q.rotatedVector(d->upVector);
+ d->viewVector = q.rotatedVector(d->viewVector);
+ d->eye = d->center - d->viewVector;
+ emit viewChanged();
+}
+
+/*!
+ Returns a translation vector that can be used to adjust the eye()
+ or center() by \a x units side-ways, \a y units up,
+ and \a z units forwards.
+
+ This function is useful when implementing operations such as
+ "step left", "jump up", and so on where the movement should be
+ interpreted relative to the viewer's current orientation, not the
+ world co-ordinate axes,
+
+ The translation vector can be applied to eye() or center() by
+ calling translateEye() or translateCenter() respectively.
+
+ \sa translateEye(), translateCenter()
+*/
+QVector3D QGLCamera::translation(qreal x, qreal y, qreal z) const
+{
+ Q_D(const QGLCamera);
+ QVector3D vector(0.0f, 0.0f, 0.0f);
+ if (x != 0.0f)
+ vector += QVector3D::normal(d->viewVector, d->upVector) * x;
+ if (y != 0.0f)
+ vector += d->upVector.normalized() * y;
+ if (z != 0.0f)
+ vector += d->viewVector.normalized() * z;
+ return vector;
+}
+
+/*!
+ Returns the transformation matrix to apply to the projection matrix
+ to present the scene as viewed from the camera position.
+
+ The \a aspectRatio specifies the aspect ratio of the window the
+ camera view is being displayed in. An \a aspectRatio of 1 indicates that
+ the window is square. An \a aspectRatio greater than 1 indicates that
+ the window is wider than it is high. An \a aspectRatio less than 1
+ indicates that the window is higher than it is wide.
+
+ \sa apply(), modelViewMatrix()
+*/
+QMatrix4x4 QGLCamera::projectionMatrix(qreal aspectRatio) const
+{
+ Q_D(const QGLCamera);
+ QMatrix4x4 m;
+ if (d->screenRotation != 0) {
+ m.rotate((qreal)(d->screenRotation), 0.0f, 0.0f, 1.0f);
+ if (d->screenRotation == 90 || d->screenRotation == 270) {
+ if (aspectRatio != 0.0f)
+ aspectRatio = 1.0f / aspectRatio;
+ }
+ }
+ if (d->projectionType == Perspective && d->fieldOfView != 0.0f) {
+ m.perspective(d->fieldOfView, aspectRatio,
+ d->nearPlane, d->farPlane);
+ } else {
+ qreal halfWidth = d->viewSize.width() / 2.0f;
+ qreal halfHeight = d->viewSize.height() / 2.0f;
+ if (aspectRatio > 1.0f) {
+ halfWidth *= aspectRatio;
+ } else if (aspectRatio > 0.0f && aspectRatio < 1.0f) {
+ halfHeight /= aspectRatio;
+ }
+ if (d->projectionType == Perspective) {
+ m.frustum(-halfWidth, halfWidth, -halfHeight, halfHeight,
+ d->nearPlane, d->farPlane);
+ } else {
+ m.ortho(-halfWidth, halfWidth, -halfHeight, halfHeight,
+ d->nearPlane, d->farPlane);
+ }
+ }
+ return m;
+}
+
+/*!
+ Returns the transformation to apply to the modelview matrix
+ to present the scene as viewed from the eye() position.
+
+ \sa apply(), projectionMatrix()
+*/
+QMatrix4x4 QGLCamera::modelViewMatrix() const
+{
+ Q_D(const QGLCamera);
+ QMatrix4x4 m;
+ if (d->motionQuaternion.isIdentity()) {
+ m.lookAt(d->eye, d->center, d->upVector);
+ } else {
+ QVector3D up = d->motionQuaternion.rotatedVector(d->upVector);
+ QVector3D view = d->motionQuaternion.rotatedVector(d->viewVector);
+ QVector3D eye = d->center - view;
+ m.lookAt(eye, d->center, up);
+ }
+ return m;
+}
+
+/*!
+ \fn void QGLCamera::projectionChanged()
+
+ This signal is emitted when one of projectionType(), fieldOfView(),
+ nearPlane(), farPlane(), viewSize(), or screenRotation() changes,
+ indicating a modification to the optical properties of the camera
+ looking at the scene.
+
+ \sa viewChanged()
+*/
+
+/*!
+ \fn void QGLCamera::viewChanged()
+
+ This signal is emitted when one of eye(), upVector(), or center()
+ changes, indicating a modification to the viewer's position or
+ orientation.
+
+ \sa projectionChanged()
+*/
+
+QT_END_NAMESPACE
diff --git a/examples/opencl/bezierpatch/qglcamera.h b/examples/opencl/bezierpatch/qglcamera.h
new file mode 100644
index 0000000..1fb93e6
--- /dev/null
+++ b/examples/opencl/bezierpatch/qglcamera.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGLCAMERA_H
+#define QGLCAMERA_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qsize.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtGui/qquaternion.h>
+
+QT_BEGIN_HEADER
+
+class QGLCameraPrivate;
+
+class QGLCamera : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(ProjectionType)
+ Q_PROPERTY(ProjectionType projectionType READ projectionType WRITE setProjectionType NOTIFY projectionChanged)
+ Q_PROPERTY(qreal fieldOfView READ fieldOfView WRITE setFieldOfView NOTIFY projectionChanged)
+ Q_PROPERTY(qreal nearPlane READ nearPlane WRITE setNearPlane NOTIFY projectionChanged)
+ Q_PROPERTY(qreal farPlane READ farPlane WRITE setFarPlane NOTIFY projectionChanged)
+ Q_PROPERTY(QSizeF viewSize READ viewSize WRITE setViewSize NOTIFY projectionChanged)
+ Q_PROPERTY(QSizeF minViewSize READ minViewSize WRITE setMinViewSize NOTIFY projectionChanged)
+ Q_PROPERTY(int screenRotation READ screenRotation WRITE setScreenRotation NOTIFY projectionChanged)
+ Q_PROPERTY(qreal xEye READ xEye WRITE setXEye NOTIFY viewChanged)
+ Q_PROPERTY(qreal yEye READ yEye WRITE setYEye NOTIFY viewChanged)
+ Q_PROPERTY(qreal zEye READ zEye WRITE setZEye NOTIFY viewChanged)
+ Q_PROPERTY(QVector3D eye READ eye WRITE setEye NOTIFY viewChanged)
+ Q_PROPERTY(QVector3D upVector READ upVector WRITE setUpVector NOTIFY viewChanged)
+ Q_PROPERTY(qreal xCentre READ xCentre WRITE setXCentre NOTIFY viewChanged)
+ Q_PROPERTY(qreal yCentre READ yCentre WRITE setYCentre NOTIFY viewChanged)
+ Q_PROPERTY(qreal zCentre READ zCentre WRITE setZCentre NOTIFY viewChanged)
+ Q_PROPERTY(QVector3D center READ center WRITE setCenter NOTIFY viewChanged)
+ Q_PROPERTY(qreal eyeSeparation READ eyeSeparation WRITE setEyeSeparation NOTIFY viewChanged)
+ Q_PROPERTY(QVector3D motionAdjustment READ motionAdjustment WRITE setMotionAdjustment DESIGNABLE false NOTIFY viewChanged)
+public:
+ explicit QGLCamera(QObject *parent = 0);
+ ~QGLCamera();
+
+ enum ProjectionType
+ {
+ Perspective,
+ Orthographic
+ };
+
+ QGLCamera::ProjectionType projectionType() const;
+ void setProjectionType(QGLCamera::ProjectionType value);
+
+ qreal fieldOfView() const;
+ void setFieldOfView(qreal angle);
+
+ qreal nearPlane() const;
+ void setNearPlane(qreal value);
+
+ qreal farPlane() const;
+ void setFarPlane(qreal value);
+
+ QSizeF viewSize() const;
+ void setViewSize(const QSizeF& size);
+
+ QSizeF minViewSize() const;
+ void setMinViewSize(const QSizeF& size);
+
+ int screenRotation() const;
+ void setScreenRotation(int angle);
+
+ qreal xEye() const;
+ void setXEye(qreal value);
+ qreal yEye() const;
+ void setYEye(qreal value);
+ qreal zEye() const;
+ void setZEye(qreal value);
+
+ QVector3D eye() const;
+ void setEye(const QVector3D& vertex);
+
+ QVector3D upVector() const;
+ void setUpVector(const QVector3D& vector);
+
+ qreal xCentre() const;
+ void setXCentre(qreal value);
+ qreal yCentre() const;
+ void setYCentre(qreal value);
+ qreal zCentre() const;
+ void setZCentre(qreal value);
+
+ QVector3D center() const;
+ void setCenter(const QVector3D& vertex);
+
+ qreal eyeSeparation() const;
+ void setEyeSeparation(qreal value);
+
+ QVector3D motionAdjustment() const;
+ void setMotionAdjustment(const QVector3D& vector);
+
+ QQuaternion tilt(qreal angle) const;
+ QQuaternion pan(qreal angle) const;
+ QQuaternion roll(qreal angle) const;
+
+ void rotateEye(const QQuaternion& q);
+ void rotateCenter(const QQuaternion& q);
+
+ QVector3D translation(qreal x, qreal y, qreal z) const;
+
+ void translateEye(const QVector3D& vector);
+ void translateCenter(const QVector3D& vector);
+
+ QMatrix4x4 projectionMatrix(qreal aspectRatio) const;
+ QMatrix4x4 modelViewMatrix() const;
+
+Q_SIGNALS:
+ void projectionChanged();
+ void viewChanged();
+
+private:
+ QGLCameraPrivate *d_ptr;
+
+ QGLCameraPrivate *d_func() const { return d_ptr; }
+
+ Q_DISABLE_COPY(QGLCamera)
+};
+
+QT_END_HEADER
+
+#endif
diff --git a/examples/opencl/bezierpatch/qtlogo.png b/examples/opencl/bezierpatch/qtlogo.png
new file mode 100644
index 0000000..aa24072
--- /dev/null
+++ b/examples/opencl/bezierpatch/qtlogo.png
Binary files differ
diff --git a/examples/opencl/opencl.pro b/examples/opencl/opencl.pro
index 57abaa8..558760f 100644
--- a/examples/opencl/opencl.pro
+++ b/examples/opencl/opencl.pro
@@ -1,2 +1,2 @@
TEMPLATE = subdirs
-SUBDIRS = vectoradd blur pathdrawing
+SUBDIRS = vectoradd blur pathdrawing bezierpatch