summaryrefslogtreecommitdiffstats
path: root/demos
diff options
context:
space:
mode:
Diffstat (limited to 'demos')
-rw-r--r--demos/cubehouse/cube.qrc7
-rw-r--r--demos/cubehouse/cubehouse.pro12
-rw-r--r--demos/cubehouse/cubeview.cpp460
-rw-r--r--demos/cubehouse/cubeview.h108
-rw-r--r--demos/cubehouse/main.cpp64
-rw-r--r--demos/cubehouse/projectivetextureeffect.cpp148
-rw-r--r--demos/cubehouse/projectivetextureeffect.h79
-rw-r--r--demos/cubehouse/qtlogo.pngbin0 -> 13923 bytes
-rw-r--r--demos/cubehouse/shaders/depth.frag50
-rw-r--r--demos/cubehouse/shaders/depth.vert75
-rw-r--r--demos/cubehouse/shaders/depthTestShader.frag91
-rw-r--r--demos/cubehouse/shaders/depthTestShader.vert91
-rw-r--r--demos/cubehouse/shaders/objectlineartexgen.frag52
-rw-r--r--demos/cubehouse/shaders/objectlineartexgen.vert63
-rw-r--r--demos/declarative/DefaultNavigator.qml181
-rw-r--r--demos/declarative/PhotoPane.qml127
-rw-r--r--demos/declarative/RoboBounce/Assets/QML3DSign.pngbin0 -> 105968 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/button.pngbin0 -> 726 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/calculatorSign.pngbin0 -> 154325 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/cubeButton.pngbin0 -> 1470 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/hazard.pngbin0 -> 64685 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/infobutton.pngbin0 -> 2252 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/qtlogo.pngbin0 -> 48309 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/roboInfo.pngbin0 -> 19189 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/roboticArms.3dsbin0 -> 68300 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/roboticBody.3dsbin0 -> 76250 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/roboticHead.3dsbin0 -> 47828 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/rotateButton2.pngbin0 -> 1804 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/sQt3D_logo.pngbin0 -> 76681 bytes
-rw-r--r--demos/declarative/RoboBounce/Assets/tronscape.pngbin0 -> 311759 bytes
-rw-r--r--demos/declarative/RoboBounce/Calculator/Calculator.qml187
-rw-r--r--demos/declarative/RoboBounce/Calculator/CalculatorCore/Button.qml97
-rw-r--r--demos/declarative/RoboBounce/Calculator/CalculatorCore/Display.qml68
-rw-r--r--demos/declarative/RoboBounce/Calculator/CalculatorCore/calculator.js91
-rw-r--r--demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-.pngbin0 -> 1288 bytes
-rw-r--r--demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-blue.pngbin0 -> 1565 bytes
-rw-r--r--demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-green.pngbin0 -> 1543 bytes
-rw-r--r--demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-purple.pngbin0 -> 1566 bytes
-rw-r--r--demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-red.pngbin0 -> 1586 bytes
-rw-r--r--demos/declarative/RoboBounce/Calculator/CalculatorCore/images/display.pngbin0 -> 998 bytes
-rw-r--r--demos/declarative/RoboBounce/Calculator/CalculatorCore/qmldir2
-rw-r--r--demos/declarative/RoboBounce/RobotCore/PushButton.qml69
-rw-r--r--demos/declarative/RoboBounce/RobotCore/QMLPanels.qml102
-rw-r--r--demos/declarative/RoboBounce/RobotCore/Robot.qml51
-rw-r--r--demos/declarative/RoboBounce/RobotCore/TronCube.qml50
-rw-r--r--demos/declarative/RoboBounce/robobounce.qml616
-rw-r--r--demos/declarative/basket.qml74
-rw-r--r--demos/declarative/button.qml93
-rw-r--r--demos/declarative/cube.qml62
-rw-r--r--demos/declarative/forest/Tree.qml60
-rw-r--r--demos/declarative/forest/forest.qml81
-rw-r--r--demos/declarative/forest/forest.qmlproject16
-rw-r--r--demos/declarative/forest/ground.obj11
-rw-r--r--demos/declarative/forest/tree.obj11
-rw-r--r--demos/declarative/forest/tree.pngbin0 -> 5631 bytes
-rw-r--r--demos/declarative/matrix-animation.qml145
-rw-r--r--demos/declarative/meshes/basket.bez332
-rw-r--r--demos/declarative/meshes/button3d.3dsbin0 -> 3864 bytes
-rw-r--r--demos/declarative/meshes/face.pngbin0 -> 318905 bytes
-rw-r--r--demos/declarative/meshes/full-addressbin0 -> 48485 bytes
-rw-r--r--demos/declarative/meshes/photopane.obj11
-rw-r--r--demos/declarative/meshes/teapot.bez340
-rw-r--r--demos/declarative/modelViewer/FourButtons.qml74
-rw-r--r--demos/declarative/modelViewer/LongButton.qml69
-rw-r--r--demos/declarative/modelViewer/MainButton.qml66
-rw-r--r--demos/declarative/modelViewer/ShortButton.qml71
-rw-r--r--demos/declarative/modelViewer/images/arrow.pngbin0 -> 1338 bytes
-rw-r--r--demos/declarative/modelViewer/images/arrow.svg74
-rw-r--r--demos/declarative/modelViewer/images/cog.svg127
-rw-r--r--demos/declarative/modelViewer/images/cog2.svg126
-rw-r--r--demos/declarative/modelViewer/images/knob.pngbin0 -> 1888 bytes
-rw-r--r--demos/declarative/modelViewer/images/knob.svg867
-rw-r--r--demos/declarative/modelViewer/images/test.svg136
-rw-r--r--demos/declarative/modelViewer/images/zoomin.pngbin0 -> 4970 bytes
-rw-r--r--demos/declarative/modelViewer/images/zoomin.svg74
-rw-r--r--demos/declarative/modelViewer/images/zoomout.pngbin0 -> 4798 bytes
-rw-r--r--demos/declarative/modelViewer/images/zoomout.svg169
-rw-r--r--demos/declarative/modelViewer/meshes/monkey.3dsbin0 -> 13886 bytes
-rw-r--r--demos/declarative/modelViewer/meshes/penguin.3dsbin0 -> 36301 bytes
-rw-r--r--demos/declarative/modelViewer/modelviewer.qml375
-rw-r--r--demos/declarative/monkeygod/Penguin.qml78
-rw-r--r--demos/declarative/monkeygod/meshes/monkey.3dsbin0 -> 13886 bytes
-rw-r--r--demos/declarative/monkeygod/meshes/penguin.3dsbin0 -> 36301 bytes
-rw-r--r--demos/declarative/monkeygod/monkeygod.qml115
-rw-r--r--demos/declarative/monkeygod/monkeygod.qmlproject16
-rw-r--r--demos/declarative/monkeygod/monkeygod_no_platform.qml110
-rw-r--r--demos/declarative/moon/moon-texture.jpgbin0 -> 111322 bytes
-rw-r--r--demos/declarative/moon/moon.qml65
-rw-r--r--demos/declarative/photoroom.qml162
-rw-r--r--demos/declarative/sphere.qml171
-rw-r--r--demos/declarative/stereo/Teapot.qml55
-rw-r--r--demos/declarative/stereo/Time.qml71
-rw-r--r--demos/declarative/stereo/Time20.qml71
-rw-r--r--demos/declarative/stereo/stereo-scenegraph.qml136
-rw-r--r--demos/declarative/stereo/stereo.qml165
-rw-r--r--demos/declarative/stereo/stereo.qmlproject16
-rw-r--r--demos/declarative/teapot-bounce.qml69
-rw-r--r--demos/declarative/teapot-scenegraph.qml50
-rw-r--r--demos/declarative/teapot-shader-animation.qml121
-rw-r--r--demos/declarative/teapot-shader-collapsing.qml122
-rw-r--r--demos/declarative/teapot-shader-images.qml142
-rw-r--r--demos/declarative/teapot-shader.qml123
-rw-r--r--demos/declarative/teapot.qml50
-rw-r--r--demos/declarative/teaservice/Teacup.qml68
-rw-r--r--demos/declarative/teaservice/Teaspoon.qml72
-rw-r--r--demos/declarative/teaservice/teacup.bez280
-rw-r--r--demos/declarative/teaservice/teapot-body.bez332
-rw-r--r--demos/declarative/teaservice/teapot-handle.bez312
-rw-r--r--demos/declarative/teaservice/teapot-spout.bez312
-rw-r--r--demos/declarative/teaservice/teaservice.qml382
-rw-r--r--demos/declarative/teaservice/teaservice.qmlproject16
-rw-r--r--demos/declarative/teaservice/teaspoon.bez275
-rw-r--r--demos/declarative/textures/basket.jpgbin0 -> 454145 bytes
-rw-r--r--demos/declarative/textures/button/face-name.pngbin0 -> 362231 bytes
-rw-r--r--demos/declarative/textures/button/face-name.xcfbin0 -> 818498 bytes
-rw-r--r--demos/declarative/textures/button/face.pngbin0 -> 318905 bytes
-rw-r--r--demos/declarative/textures/button/full-address.pngbin0 -> 48485 bytes
-rw-r--r--demos/declarative/textures/button/full-address.xcfbin0 -> 57519 bytes
-rw-r--r--demos/declarative/textures/button/woman-photo-credit.txt5
-rw-r--r--demos/declarative/textures/button/woman.jpgbin0 -> 83973 bytes
-rw-r--r--demos/declarative/textures/photos/background.jpgbin0 -> 159108 bytes
-rw-r--r--demos/declarative/textures/photos/niagara_falls.jpgbin0 -> 139646 bytes
-rw-r--r--demos/declarative/textures/photos/place.jpgbin0 -> 62438 bytes
-rw-r--r--demos/declarative/textures/qtlogo.pngbin0 -> 13923 bytes
-rw-r--r--demos/demos.pro2
-rw-r--r--demos/pageflip/gradient.pngbin0 -> 229 bytes
-rw-r--r--demos/pageflip/pageflip.cpp380
-rw-r--r--demos/pageflip/pageflip.pro7
-rw-r--r--demos/pageflip/pageflip.qrc9
-rw-r--r--demos/pageflip/pageflipmath.cpp592
-rw-r--r--demos/pageflip/pageflipmath_p.h120
-rw-r--r--demos/pageflip/qqpage1.pngbin0 -> 77887 bytes
-rw-r--r--demos/pageflip/qqpage2.pngbin0 -> 74710 bytes
-rw-r--r--demos/pageflip/qqpage3.pngbin0 -> 73043 bytes
-rw-r--r--demos/pageflip/qqpage4.pngbin0 -> 78092 bytes
-rw-r--r--demos/photobrowser3d/buttons.cpp134
-rw-r--r--demos/photobrowser3d/buttons.h63
-rw-r--r--demos/photobrowser3d/bytereader.cpp158
-rw-r--r--demos/photobrowser3d/bytereader.h66
-rw-r--r--demos/photobrowser3d/filescanner.cpp127
-rw-r--r--demos/photobrowser3d/filescanner.h79
-rw-r--r--demos/photobrowser3d/imagedisplay.cpp225
-rw-r--r--demos/photobrowser3d/imagedisplay.h85
-rw-r--r--demos/photobrowser3d/imageloader.cpp116
-rw-r--r--demos/photobrowser3d/imageloader.h84
-rw-r--r--demos/photobrowser3d/imagemanager.cpp134
-rw-r--r--demos/photobrowser3d/imagemanager.h79
-rw-r--r--demos/photobrowser3d/images/P1000223.JPGbin0 -> 29760 bytes
-rw-r--r--demos/photobrowser3d/images/P1000228.JPGbin0 -> 27685 bytes
-rw-r--r--demos/photobrowser3d/images/P1000441.JPGbin0 -> 453660 bytes
-rw-r--r--demos/photobrowser3d/images/P1000472.JPGbin0 -> 25850 bytes
-rw-r--r--demos/photobrowser3d/images/arrows-left.pngbin0 -> 5303 bytes
-rw-r--r--demos/photobrowser3d/images/arrows.xcfbin0 -> 289659 bytes
-rw-r--r--demos/photobrowser3d/images/default_sky_base.xcfbin0 -> 93208 bytes
-rw-r--r--demos/photobrowser3d/images/default_sky_down.pngbin0 -> 360 bytes
-rw-r--r--demos/photobrowser3d/images/default_sky_east.pngbin0 -> 29427 bytes
-rw-r--r--demos/photobrowser3d/images/default_sky_north.pngbin0 -> 38936 bytes
-rw-r--r--demos/photobrowser3d/images/default_sky_south.pngbin0 -> 29427 bytes
-rw-r--r--demos/photobrowser3d/images/default_sky_up.pngbin0 -> 21806 bytes
-rw-r--r--demos/photobrowser3d/images/default_sky_west.pngbin0 -> 29427 bytes
-rw-r--r--demos/photobrowser3d/images/girder.pngbin0 -> 196973 bytes
-rw-r--r--demos/photobrowser3d/images/no-images-yet.pngbin0 -> 111700 bytes
-rw-r--r--demos/photobrowser3d/images/no-images-yet.xcfbin0 -> 352839 bytes
-rw-r--r--demos/photobrowser3d/images/sample_image.jpgbin0 -> 498466 bytes
-rw-r--r--demos/photobrowser3d/launcher.cpp116
-rw-r--r--demos/photobrowser3d/main.cpp72
-rw-r--r--demos/photobrowser3d/pancontroller.cpp244
-rw-r--r--demos/photobrowser3d/pancontroller.h89
-rw-r--r--demos/photobrowser3d/photobrowser3d.pro62
-rw-r--r--demos/photobrowser3d/photobrowser3d.qrc24
-rw-r--r--demos/photobrowser3d/photobrowser3dview.cpp437
-rw-r--r--demos/photobrowser3d/photobrowser3dview.h112
-rw-r--r--demos/photobrowser3d/qatlas.cpp188
-rw-r--r--demos/photobrowser3d/qatlas.h102
-rw-r--r--demos/photobrowser3d/qfocusadaptor.cpp186
-rw-r--r--demos/photobrowser3d/qfocusadaptor.h80
-rw-r--r--demos/photobrowser3d/qphotobrowser3dscene.cpp58
-rw-r--r--demos/photobrowser3d/qphotobrowser3dscene.h60
-rw-r--r--demos/photobrowser3d/shaders/replace_texture.fsh54
-rw-r--r--demos/photobrowser3d/shaders/replace_texture.vsh58
-rw-r--r--demos/photobrowser3d/skybox.cpp223
-rw-r--r--demos/photobrowser3d/skybox.h70
-rw-r--r--demos/photobrowser3d/threadpool.cpp132
-rw-r--r--demos/photobrowser3d/threadpool.h81
-rw-r--r--demos/photobrowser3d/thumbnailableimage.cpp302
-rw-r--r--demos/photobrowser3d/thumbnailableimage.h98
-rw-r--r--demos/photobrowser3d/thumbnaileffect.cpp186
-rw-r--r--demos/photobrowser3d/thumbnaileffect.h70
-rw-r--r--demos/photobrowser3d/thumbnailnode.cpp281
-rw-r--r--demos/photobrowser3d/thumbnailnode.h97
-rw-r--r--demos/shapes/shapes.cpp424
-rw-r--r--demos/shapes/shapes.pro5
-rw-r--r--demos/teaservice/README7
-rw-r--r--demos/teaservice/meshobject.cpp155
-rw-r--r--demos/teaservice/meshobject.h115
-rw-r--r--demos/teaservice/per_pixel_lighting.fsh112
-rw-r--r--demos/teaservice/per_pixel_lighting.vsh96
-rw-r--r--demos/teaservice/perpixeleffect.cpp56
-rw-r--r--demos/teaservice/perpixeleffect.h58
-rw-r--r--demos/teaservice/sceneobject.cpp72
-rw-r--r--demos/teaservice/sceneobject.h61
-rw-r--r--demos/teaservice/teacup.txt280
-rw-r--r--demos/teaservice/teaservice.cpp379
-rw-r--r--demos/teaservice/teaservice.pro7
-rw-r--r--demos/teaservice/teaservice.qrc8
-rw-r--r--demos/teaservice/teaspoon.txt275
206 files changed, 18419 insertions, 0 deletions
diff --git a/demos/cubehouse/cube.qrc b/demos/cubehouse/cube.qrc
new file mode 100644
index 000000000..9de1d255c
--- /dev/null
+++ b/demos/cubehouse/cube.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>qtlogo.png</file>
+ <file>shaders/objectlineartexgen.frag</file>
+ <file>shaders/objectlineartexgen.vert</file>
+</qresource>
+</RCC>
diff --git a/demos/cubehouse/cubehouse.pro b/demos/cubehouse/cubehouse.pro
new file mode 100644
index 000000000..70ee226aa
--- /dev/null
+++ b/demos/cubehouse/cubehouse.pro
@@ -0,0 +1,12 @@
+TEMPLATE = app
+TARGET = cubehouse
+CONFIG += qt warn_on qt3d
+SOURCES = cubeview.cpp main.cpp projectivetextureeffect.cpp
+HEADERS = cubeview.h projectivetextureeffect.h
+win32:DEFINES+=_CRT_SECURE_NO_WARNINGS
+RESOURCES = cube.qrc
+DESTDIR = ../../bin
+
+OTHER_FILES += \
+ shaders/objectlineartexgen.frag \
+ shaders/objectlineartexgen.vert
diff --git a/demos/cubehouse/cubeview.cpp b/demos/cubehouse/cubeview.cpp
new file mode 100644
index 000000000..13933f957
--- /dev/null
+++ b/demos/cubehouse/cubeview.cpp
@@ -0,0 +1,460 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "cubeview.h"
+#include "qglcube.h"
+#include "qglteapot.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qpropertyanimation.h>
+#include <stdio.h>
+#include <qmath.h>
+#include "projectivetextureeffect.h"
+
+//#define PROJECTOR_CAMERA_DEBUG_MARKERS
+
+
+CubeView::CubeView(QWidget *parent)
+ : QGLView(parent), scene(0), cube(0), teapot(0), room(0),
+ sensitivity(0.1f),
+ lightParameters(0),
+ showFrameRate(false),
+ stereo(false),
+ useProjectiveTextureEffect(false),
+ cangle(0.0f),
+ prevX(0),
+ prevY(0),
+ prevZ(0),
+ havePrev(false),
+ projectiveTextureEffect(0)
+{
+ setOption(CameraNavigation, false);
+
+ roomCamera = new QGLCamera(this);
+ roomCamera->setAdjustForAspectRatio(false);
+
+ QPropertyAnimation *animation;
+
+ animation = new QPropertyAnimation(this, "cubeAngle", this);
+ animation->setStartValue(0.0f);
+ animation->setEndValue(360.0f);
+ animation->setDuration(5000);
+ animation->setLoopCount(-1);
+ animation->start();
+
+ time.start();
+}
+
+void CubeView::initializeGL(QGLPainter *painter)
+{
+ QGLBuilder builder;
+ builder << QGL::Faceted << QGLCube(1.0f);
+ cube = builder.currentNode();
+ builder << QGL::Faceted;
+ room = builder.currentNode();
+ builder.pushNode();
+ QGLSceneNode *back = builder.newNode();
+ {
+ QGeometryData quad;
+ quad.appendVertex(QVector3D(-3.0f, -3.0f, -15.0f));
+ quad.appendVertex(QVector3D( 3.0f, -3.0f, -15.0f));
+ quad.appendVertex(QVector3D( 3.0f, 3.0f, -15.0f));
+ quad.appendVertex(QVector3D(-3.0f, 3.0f, -15.0f));
+ builder.addQuads(quad);
+ }
+ QGLSceneNode *left = builder.newNode();
+ {
+ QGeometryData quad;
+ quad.appendVertex(QVector3D(-3.0f, -3.0f, -15.0f));
+ quad.appendVertex(QVector3D(-3.0f, 3.0f, -15.0f));
+ quad.appendVertex(QVector3D(-3.0f, 3.0f, 0.0f));
+ quad.appendVertex(QVector3D(-3.0f, -3.0f, 0.0f));
+ builder.addQuads(quad);
+ }
+ QGLSceneNode *right = builder.newNode();
+ {
+ QGeometryData quad;
+ quad.appendVertex(QVector3D(3.0f, 3.0f, -15.0f));
+ quad.appendVertex(QVector3D(3.0f, -3.0f, -15.0f));
+ quad.appendVertex(QVector3D(3.0f, -3.0f, 0.0f));
+ quad.appendVertex(QVector3D(3.0f, 3.0f, 0.0f));
+ builder.addQuads(quad);
+ }
+ QGLSceneNode *top = builder.newNode();
+ {
+ QGeometryData quad;
+ quad.appendVertex(QVector3D(-3.0f, 3.0f, -15.0f));
+ quad.appendVertex(QVector3D( 3.0f, 3.0f, -15.0f));
+ quad.appendVertex(QVector3D( 3.0f, 3.0f, 0.0f));
+ quad.appendVertex(QVector3D(-3.0f, 3.0f, 0.0f));
+ builder.addQuads(quad);
+ }
+ QGLSceneNode *bottom = builder.newNode();
+ {
+ QGeometryData quad;
+ quad.appendVertex(QVector3D(-3.0f, -3.0f, -15.0f));
+ quad.appendVertex(QVector3D(-3.0f, -3.0f, 0.0f));
+ quad.appendVertex(QVector3D( 3.0f, -3.0f, 0.0f));
+ quad.appendVertex(QVector3D( 3.0f, -3.0f, -15.0f));
+ builder.addQuads(quad);
+ }
+ builder.popNode();
+
+ int index;
+ QGLMaterialCollection *palette = builder.sceneNode()->palette();
+
+ QGLMaterial *mat1 = new QGLMaterial();
+ mat1->setDiffuseColor(QColor(128, 100, 0));
+ index = palette->addMaterial(mat1);
+ back->setMaterialIndex(index);
+
+ QGLMaterial *mat2 = new QGLMaterial();
+ mat2->setDiffuseColor(Qt::cyan);
+ index = palette->addMaterial(mat2);
+ left->setMaterialIndex(index);
+ right->setMaterialIndex(index);
+
+ QGLMaterial *mat3 = new QGLMaterial();
+ mat3->setDiffuseColor(Qt::yellow);
+ index = palette->addMaterial(mat3);
+ top->setMaterialIndex(index);
+ bottom->setMaterialIndex(index);
+
+ //qDumpScene(room);
+
+ builder.newSection();
+ builder << QGLTeapot();
+ teapot = builder.currentNode();
+ QGLMaterial *china = new QGLMaterial();
+ china->setAmbientColor(QColor(192, 150, 128));
+ china->setSpecularColor(QColor(60, 60, 60));
+ china->setShininess(128);
+ teapot->setMaterial(china);
+
+ scene = builder.finalizedSceneNode();
+ scene->setParent(this);
+
+ roomModel = new QGLLightModel(this);
+ roomModel->setAmbientSceneColor(Qt::white);
+ roomModel->setViewerPosition(QGLLightModel::LocalViewer);
+
+ normalModel = new QGLLightModel(this);
+
+ lightParameters = new QGLLightParameters(this);
+ lightParameters->setPosition(QVector3D(0.0f, 0.0f, 3.0f));
+ painter->setMainLight(lightParameters);
+
+ QImage textureImage(QLatin1String(":/qtlogo.png"));
+ texture.setImage(textureImage);
+
+ if (stereo) {
+ camera()->setEyeSeparation(0.4f);
+ roomCamera->setEyeSeparation(0.1f);
+ }
+
+ if (useProjectiveTextureEffect)
+ {
+ // initialize the projector camera
+ projectorCamera = new QGLCamera(this);
+ projectiveTextureEffect = new ProjectiveTextureEffect;
+ connect(projectorCamera, SIGNAL(viewChanged()),
+ this, SLOT(updateProjectorViewMatrix()));
+ connect(projectorCamera, SIGNAL(projectionChanged()),
+ this, SLOT(updateProjectorProjectionMatrix()));
+ }
+}
+
+void CubeView::paintGL(QGLPainter *painter)
+{
+ if (showFrameRate)
+ qWarning("time since last frame: %d ms", time.restart());
+
+ glDisable(GL_BLEND);
+
+ // Animate the projector position so the effect can be seen
+ if (useProjectiveTextureEffect)
+ {
+ projectorCamera->tiltPanRollCenter
+ (-0.1f, -0.3f, 0.0f, QGLCamera::PanTiltRoll);
+ }
+
+ painter->modelViewMatrix().push();
+ painter->projectionMatrix().push();
+
+ painter->setStandardEffect(QGL::LitMaterial);
+ painter->setCamera(roomCamera);
+ painter->setLightModel(roomModel);
+ room->draw(painter);
+
+ painter->modelViewMatrix().pop();
+ painter->projectionMatrix().pop();
+
+ painter->modelViewMatrix().push();
+ // These are the model transformations
+ painter->modelViewMatrix().translate(-0.8f, -1.5f, -3.0f);
+ painter->setLightModel(normalModel);
+ if (useProjectiveTextureEffect)
+ {
+ modelMatrix.push();
+ // For an effect that looks like we have only one projector
+ // Over the whole screen, we duplicate transformations into the
+ // projector's model matrix. For now, we don't apply the transform
+ // to center the effect on each object and see it more clearly.
+ // modelMatrix.translate(-0.8f, -1.5f, -3.0f);
+
+ updateProjectiveTextureEffect();
+
+ painter->setUserEffect(projectiveTextureEffect);
+ texture.bind();
+ }
+ else
+ {
+ painter->setStandardEffect(QGL::LitMaterial);
+ }
+ teapot->draw(painter);
+
+ if (useProjectiveTextureEffect)
+ modelMatrix.pop();
+ painter->modelViewMatrix().pop();
+
+
+ // These are the model transformations
+ painter->modelViewMatrix().push();
+ painter->modelViewMatrix().translate(1.0f, -0.5f, 0.0f);
+ painter->modelViewMatrix().rotate(cangle, 1.0f, 1.0f, 1.0f);
+
+ texture.bind();
+ if (useProjectiveTextureEffect)
+ {
+ modelMatrix.push();
+ // For an effect that looks like we have only one projector
+ // Over the whole screen, we duplicate transformations into the
+ // projector's model matrix. For now, we don't apply the transform
+ // to center the effect on each object and see it more clearly.
+// modelMatrix.translate(1.0f, -0.5f, 0.0f);
+ modelMatrix.rotate(cangle, 1.0f, 1.0f, 1.0f);
+ updateProjectiveTextureEffect();
+ painter->setUserEffect(projectiveTextureEffect);
+// painter->setStandardEffect(QGL::FlatDecalTexture2D);
+ cube->draw(painter);
+ modelMatrix.pop();
+ }
+ else
+ {
+ glEnable(GL_BLEND);
+ painter->setStandardEffect(QGL::LitDecalTexture2D);
+ painter->setFaceColor(QGL::AllFaces, QColor(170, 202, 0, 120));
+ glDisable(GL_DEPTH_TEST);
+ glCullFace(GL_FRONT);
+ glEnable(GL_CULL_FACE);
+ cube->draw(painter);
+ glCullFace(GL_BACK);
+ cube->draw(painter);
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_DEPTH_TEST);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ }
+
+ painter->modelViewMatrix().pop();
+#ifdef PROJECTOR_CAMERA_DEBUG_MARKERS
+ if (useProjectiveTextureEffect)
+ {
+
+ painter->modelViewMatrix().push();
+ modelMatrix.push();
+ painter->modelViewMatrix().translate(projectorCamera->eye());
+ painter->modelViewMatrix().scale(0.2);
+ painter->setStandardEffect(QGL::LitMaterial);
+ modelMatrix.translate(projectorCamera->eye());
+ cube->draw(painter);
+
+ modelMatrix.pop();
+ painter->modelViewMatrix().pop();
+
+ painter->modelViewMatrix().push();
+ modelMatrix.push();
+ painter->modelViewMatrix().translate(projectorCamera->center());
+ painter->modelViewMatrix().scale(0.1);
+ painter->setStandardEffect(QGL::LitMaterial);
+ cube->draw(painter);
+ modelMatrix.pop();
+ painter->modelViewMatrix().pop();
+
+ QVector3DArray verts;
+
+ QVector3D origin = projectorCamera->eye();
+
+ QVector3D target = projectorCamera->center();
+ QVector3D direction = projectorCamera->center() - projectorCamera->eye();
+
+ QVector3D normal = projectorCamera->upVector().normalized();
+ qreal nearPlane = projectorCamera->nearPlane();
+ qreal farPlane = projectorCamera->farPlane();
+ qreal fieldOfView = projectorCamera->fieldOfView();
+
+ QVector3D nearTopLeft;
+ QVector3D nearTopRight;
+ QVector3D nearBottomLeft;
+ QVector3D nearBottomRight;
+ QVector3D farTopLeft;
+ QVector3D farTopRight;
+ QVector3D farBottomLeft;
+ QVector3D farBottomRight;
+
+ QSizeF viewSize = projectorCamera->viewSize();
+
+ qreal fieldDepthRatio = farPlane / nearPlane;
+
+ QVector3D rightVector = QVector3D::crossProduct(direction, normal).normalized() * viewSize.width() / 2.0;
+ QVector3D topVector = normal * viewSize.height() / 2.0;
+
+ QVector3D topLeftVector = direction + topVector - rightVector;
+ QVector3D topRightVector = direction + topVector + rightVector;
+ QVector3D bottomLeftVector = direction - topVector - rightVector;
+ QVector3D bottomRightVector = direction - topVector + rightVector;
+
+ verts.append(origin, origin + (direction * (farPlane / direction.length())));
+
+ verts.append(origin, origin + (topLeftVector * fieldDepthRatio));
+ verts.append(origin, origin + (topRightVector * fieldDepthRatio));
+ verts.append(origin, origin + (bottomLeftVector * fieldDepthRatio));
+ verts.append(origin, origin + (bottomRightVector * fieldDepthRatio));
+
+ verts.append(origin + topLeftVector, origin + topRightVector);
+ verts.append(origin + topRightVector, origin + bottomRightVector);
+ verts.append(origin + bottomRightVector, origin + bottomLeftVector);
+ verts.append(origin + bottomLeftVector, origin + topLeftVector);
+
+ verts.append(origin + (topLeftVector * fieldDepthRatio),
+ (origin + topRightVector * fieldDepthRatio));
+ verts.append(origin + (topRightVector * fieldDepthRatio),
+ (origin + bottomRightVector * fieldDepthRatio));
+ verts.append(origin + (bottomRightVector * fieldDepthRatio),
+ (origin + bottomLeftVector * fieldDepthRatio));
+ verts.append(origin + (bottomLeftVector * fieldDepthRatio),
+ (origin + topLeftVector * fieldDepthRatio));
+
+ verts.append(origin, origin + normal);
+
+ painter->modelViewMatrix().push();
+ painter->setStandardEffect(QGL::FlatColor);
+ painter->clearAttributes();
+ painter->setVertexAttribute(QGL::Position, QGLAttributeValue(verts));
+ glLineWidth(1.0f);
+
+ painter->setColor(QColor(255,255,255,255));
+ painter->draw(QGL::Lines, verts.size());
+ painter->modelViewMatrix().pop();
+ }
+#endif
+}
+
+//inline void CubeView::setProjectiveTextureEffect(bool value)
+//{
+// useProjectiveTextureEffect = value;
+//}
+
+void CubeView::setCubeAngle(qreal angle)
+{
+ cangle = angle;
+ accelerometerTimeout();
+ update();
+}
+
+void CubeView::accelerometerTimeout()
+{
+ QVector3D g = gravity();
+ camera()->setMotionAdjustment(g);
+ roomCamera->setMotionAdjustment(g);
+}
+
+QVector3D CubeView::gravity() const
+{
+ // Access the raw accelerometer data on the N900.
+ FILE *file = fopen("/sys/class/i2c-adapter/i2c-3/3-001d/coord", "r");
+ if (!file)
+ return QVector3D(0, 0, -1);
+ float x = 0;
+ float y = 0;
+ float z = 0;
+ fscanf(file, "%f %f %f", &x, &y, &z);
+ fclose(file);
+
+ // Smooth out the reported values. Large changes are applied as-is,
+ // and small jitters smooth to the rest position.
+ if (havePrev) {
+ qreal xdiff = x - prevX;
+ qreal ydiff = y - prevY;
+ qreal zdiff = z - prevZ;
+ if (qAbs(xdiff) < 20.0f && qAbs(ydiff) < 20.0f && qAbs(zdiff) < 20.0f) {
+ x = prevX + xdiff * 0.1f;
+ y = prevY + ydiff * 0.1f;
+ z = prevZ + zdiff * 0.1f;
+ }
+ }
+ prevX = x;
+ prevY = y;
+ prevZ = z;
+ havePrev = true;
+
+ return QVector3D((x / 1000.0f) * sensitivity,
+ (-y / 1000.0f) * sensitivity, -z / 1000.0f);
+}
+
+void CubeView::updateProjectorViewMatrix()
+{
+ Q_ASSERT_X(projectorCamera != 0, Q_FUNC_INFO, "Null projector camera in updateProjectorViewMatrix()");
+ projectiveTextureEffect->setProjectorViewMatrix(projectorCamera->modelViewMatrix());
+ updateProjectiveTextureEffect();
+}
+
+void CubeView::updateProjectorProjectionMatrix()
+{
+ qreal projectorAspectRatio = 1.0;
+ projectiveTextureEffect->setProjectorProjectionMatrix(projectorCamera->projectionMatrix(projectorAspectRatio));
+ updateProjectiveTextureEffect();
+}
+
+void CubeView::updateProjectiveTextureEffect()
+{
+ projectiveTextureEffect->setProjectorDirection(projectorCamera->center() - projectorCamera->eye());
+ projectiveTextureEffect->setModelMatrix(modelMatrix);
+}
diff --git a/demos/cubehouse/cubeview.h b/demos/cubehouse/cubeview.h
new file mode 100644
index 000000000..b9e25a20b
--- /dev/null
+++ b/demos/cubehouse/cubeview.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 CUBEVIEW_H
+#define CUBEVIEW_H
+
+#include "qglview.h"
+#include "qglbuilder.h"
+#include "qgltexture2d.h"
+#include <QtCore/qdatetime.h>
+
+class ProjectiveTextureEffect;
+
+class CubeView : public QGLView
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal cubeAngle READ cubeAngle WRITE setCubeAngle)
+public:
+ CubeView(QWidget *parent = 0);
+ ~CubeView() {}
+
+ void setShowFrameRate(bool value) { showFrameRate = value; }
+ void setStereo(bool value) { stereo = value; }
+ void setProjectiveTextureEffect(bool value)
+{
+ useProjectiveTextureEffect = value;
+}
+
+ qreal cubeAngle() const { return cangle; }
+ void setCubeAngle(qreal angle);
+
+protected:
+ void initializeGL(QGLPainter *painter);
+ void paintGL(QGLPainter *painter);
+
+private slots:
+ void accelerometerTimeout();
+ void updateProjectorViewMatrix();
+ void updateProjectorProjectionMatrix();
+ void updateProjectiveTextureEffect();
+
+private:
+ QGLTexture2D texture;
+ QGLSceneNode *scene;
+ QGLSceneNode *cube;
+ QGLSceneNode *teapot;
+ QGLSceneNode *room;
+ QGLCamera *roomCamera;
+ QGLCamera *projectorCamera;
+ qreal sensitivity;
+ QGLLightModel *roomModel;
+ QGLLightModel *normalModel;
+ QGLLightParameters *lightParameters;
+ bool showFrameRate;
+ bool stereo;
+ bool useProjectiveTextureEffect;
+ QTime time;
+ qreal cangle;
+ mutable qreal prevX, prevY, prevZ;
+ mutable bool havePrev;
+
+ QVector3D gravity() const;
+
+ ProjectiveTextureEffect* projectiveTextureEffect;
+ QMatrix4x4 biasMatrix;
+ QMatrix4x4Stack modelMatrix;
+ QMatrix4x4 objectLinearTexgenMatrix;
+};
+
+#endif
diff --git a/demos/cubehouse/main.cpp b/demos/cubehouse/main.cpp
new file mode 100644
index 000000000..29326a535
--- /dev/null
+++ b/demos/cubehouse/main.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "cubeview.h"
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ CubeView view;
+ if (QApplication::arguments().contains(QLatin1String("-framerate")))
+ view.setShowFrameRate(true);
+ if (QApplication::arguments().contains(QLatin1String("-projectivetexture")))
+ view.setProjectiveTextureEffect(true);
+ if (QApplication::arguments().contains(QLatin1String("-stereo")))
+ view.setStereo(true);
+ else if (view.stereoType() != QGLView::RedCyanAnaglyph)
+ view.setStereo(true);
+ if (QApplication::arguments().contains(QLatin1String("-maximize")))
+ view.showMaximized();
+ else if (QApplication::arguments().contains(QLatin1String("-fullscreen")))
+ view.showFullScreen();
+ else
+ view.show();
+ return app.exec();
+}
diff --git a/demos/cubehouse/projectivetextureeffect.cpp b/demos/cubehouse/projectivetextureeffect.cpp
new file mode 100644
index 000000000..6e69a2ebb
--- /dev/null
+++ b/demos/cubehouse/projectivetextureeffect.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 <QFile>
+#include "projectivetextureeffect.h"
+#include <QtOpenGL/qglshaderprogram.h>
+
+static const QMatrix4x4 biasMatrix = QMatrix4x4(0.5, 0.0, 0.0, 0.5,
+ 0.0, 0.5, 0.0, 0.5,
+ 0.0, 0.0, 0.5, 0.5,
+ 0.0, 0.0, 0.0, 1.0);
+
+/*!
+ The ProjectiveTextureEffect mimics the effect of shining a projector onto
+ a scene from a specific direction. Vertex coordinates in object space are
+ transformed into eye-space coordinates relative to the light direction,
+ using the objectLinearTexgenMatrix.
+*/
+ProjectiveTextureEffect::ProjectiveTextureEffect() :
+ matrixDirty(true)
+{
+ setupShaders();
+}
+
+void ProjectiveTextureEffect::setActive(QGLPainter *painter, bool flag)
+{
+ QGLShaderProgramEffect::setActive(painter, flag);
+}
+
+void ProjectiveTextureEffect::update(QGLPainter *painter, QGLPainter::Updates updates)
+{
+ QGLShaderProgramEffect::update(painter, updates);
+
+ if (matrixDirty)
+ {
+ recalulateObjectLinearTexgenMatrix();
+ matrixDirty = false;
+ }
+
+ program()->setUniformValue("objectLinearTexgenMatrix",
+ objectLinearTexgenMatrix);
+ program()->setUniformValue("projectorDirection",
+ projectorDirection);
+}
+
+void ProjectiveTextureEffect::setProjectorDirection(const QVector4D &direction)
+{
+ this->projectorDirection = direction;
+ matrixDirty = true;
+}
+
+void ProjectiveTextureEffect::setCameraModelViewMatrix(const QMatrix4x4 &newCameraModelViewMatrix)
+{
+ cameraModelViewMatrix = newCameraModelViewMatrix;
+ bool invertible;
+ inverseCameraModelViewMatrix =
+ newCameraModelViewMatrix.inverted(&invertible);
+ Q_ASSERT(invertible);
+ if (!invertible)
+ qWarning() << "camera Model view matrix not invertible in ProjectiveDepthTestEffect::setCameraModelViewMatrix()";
+ matrixDirty = true;
+}
+
+void ProjectiveTextureEffect::setProjectorProjectionMatrix(const QMatrix4x4 &newMatrix)
+{
+ projectorProjectionMatrix = newMatrix;
+ matrixDirty = true;
+}
+
+void ProjectiveTextureEffect::setProjectorViewMatrix(const QMatrix4x4 &newMatrix)
+{
+ projectorViewMatrix = newMatrix;
+ matrixDirty = true;
+}
+
+void ProjectiveTextureEffect::setModelMatrix(const QMatrix4x4 &newMatrix)
+{
+ modelMatrix = newMatrix;
+ matrixDirty = true;
+}
+
+void ProjectiveTextureEffect::recalulateObjectLinearTexgenMatrix()
+{
+ objectLinearTexgenMatrix = biasMatrix *
+ projectorProjectionMatrix *
+ projectorViewMatrix *
+ modelMatrix;
+}
+
+void ProjectiveTextureEffect::setupShaders()
+{
+ QString vertexShaderFileName = QLatin1String(":/shaders/objectlineartexgen.vert");
+ QFile vertexShaderFile(vertexShaderFileName);
+ if (vertexShaderFile.open(QIODevice::ReadOnly | QIODevice::Text))
+ {
+ setVertexShader(vertexShaderFile.readAll());
+ } else {
+ qWarning() << "Could not open file "<<vertexShaderFileName<<", failed to load vertex shader";
+ }
+
+ QString fragmentShaderFileName = QLatin1String(":/shaders/objectlineartexgen.frag");
+ QFile fragmentShaderFile(fragmentShaderFileName);
+ if (fragmentShaderFile.open(QIODevice::ReadOnly | QIODevice::Text))
+ {
+ setFragmentShader(fragmentShaderFile.readAll());
+ } else {
+ qWarning() << "Could not open file "<<fragmentShaderFileName<<", failed to load fragment shader";
+ }
+
+}
diff --git a/demos/cubehouse/projectivetextureeffect.h b/demos/cubehouse/projectivetextureeffect.h
new file mode 100644
index 000000000..eb000e68a
--- /dev/null
+++ b/demos/cubehouse/projectivetextureeffect.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 PROJECTIVEDTEXTUREEFFECT_H
+#define PROJECTIVEDTEXTUREEFFECT_H
+
+#include "qglshaderprogrameffect.h"
+//#include "deptheffect.h"
+#include "qmatrix4x4.h"
+
+class ProjectiveTextureEffect : public QGLShaderProgramEffect
+{
+public:
+ explicit ProjectiveTextureEffect();
+ virtual void setActive(QGLPainter *painter, bool flag);
+ virtual void update(QGLPainter *painter, QGLPainter::Updates updates);
+ virtual void setProjectorDirection(const QVector4D &direction);
+
+ void setCameraModelViewMatrix(const QMatrix4x4 &newCameraModelViewMatrix);
+ void setProjectorProjectionMatrix(const QMatrix4x4 &newMatrix);
+ void setProjectorViewMatrix(const QMatrix4x4 &newMatrix);
+ void setModelMatrix(const QMatrix4x4 &newMatrix);
+
+// TODO:
+// QMatrix4x4 eyeLinearTexgenMatrix;
+
+protected:
+ virtual void setupShaders();
+private:
+ virtual void recalulateObjectLinearTexgenMatrix();
+ bool matrixDirty;
+ QMatrix4x4 modelMatrix;
+ QMatrix4x4 objectLinearTexgenMatrix;
+ QMatrix4x4 cameraModelViewMatrix;
+ QMatrix4x4 inverseCameraModelViewMatrix;
+ QMatrix4x4 projectorProjectionMatrix;
+ QMatrix4x4 projectorViewMatrix;
+ QVector4D projectorDirection;
+};
+
+#endif // PROJECTIVEDTEXTUREEFFECT_H
diff --git a/demos/cubehouse/qtlogo.png b/demos/cubehouse/qtlogo.png
new file mode 100644
index 000000000..7d3e97eb3
--- /dev/null
+++ b/demos/cubehouse/qtlogo.png
Binary files differ
diff --git a/demos/cubehouse/shaders/depth.frag b/demos/cubehouse/shaders/depth.frag
new file mode 100644
index 000000000..939cfc954
--- /dev/null
+++ b/demos/cubehouse/shaders/depth.frag
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+varying float depth;
+
+void main(void)
+{
+ float stupidMathsDepth = depth;
+ stupidMathsDepth = (stupidMathsDepth + 10.0) / 20.0;
+// gl_FragColor = vec4(vec3(stupidMathsDepth), 1.0);
+ gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
+};
diff --git a/demos/cubehouse/shaders/depth.vert b/demos/cubehouse/shaders/depth.vert
new file mode 100644
index 000000000..8e13193b9
--- /dev/null
+++ b/demos/cubehouse/shaders/depth.vert
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+attribute highp vec4 vertex;
+varying float depth;
+uniform highp mat4 qt_ModelViewMatrix;
+uniform highp mat4 qt_ProjectionMatrix;
+
+attribute highp vec4 texCoords;
+
+uniform highp mat4 cameraCombinedMatrix;
+uniform highp mat4 cameraModelViewMatrix;
+uniform highp mat4 cameraProjectionMatrix;
+
+uniform highp mat4 lightCombinedMatrix;
+
+varying highp vec4 qt_TexCoord0;
+varying highp vec4 onScreenPosition;
+varying highp vec4 lightScreenPosition;
+varying highp vec4 worldSpaceVertex;
+
+void main(void)
+{
+ qt_TexCoord0 = texCoords;
+
+ // qt_ProjectionMatrix == cameraProjectionMatrix
+// onScreenPosition = qt_ProjectionMatrix * qt_ModelViewMatrix * vertex;
+//onScreenPosition = cameraProjectionMatrix * qt_ModelViewMatrix * vertex;
+
+ onScreenPosition = cameraProjectionMatrix
+ * cameraModelViewMatrix
+// * qt_ModelViewMatrix
+ * vertex;
+ depth = onScreenPosition.z;
+
+ gl_Position = onScreenPosition;
+};
diff --git a/demos/cubehouse/shaders/depthTestShader.frag b/demos/cubehouse/shaders/depthTestShader.frag
new file mode 100644
index 000000000..b2c6957b1
--- /dev/null
+++ b/demos/cubehouse/shaders/depthTestShader.frag
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+// This is equivilent to GL_REPLACE
+varying highp vec4 qt_TexCoord0;
+
+uniform mediump sampler2D texture;
+uniform mediump mat4 textureMatrix;
+varying highp vec4 onScreenPosition;
+varying highp vec4 lightScreenPosition;
+varying highp vec4 worldSpaceVertex;
+varying float lightDepth;
+varying float actualDepth;
+
+void main(void)
+{
+
+ // I should be able to build a matrix to do this:
+// vec4 normalizedOnScreenPosition = (onScreenPosition + 5.0) / 10.0;
+vec4 normalizedLightScreenPosition = (((lightScreenPosition
+//+ lightScreenPosition.w
+) / lightScreenPosition.w ) + 1.0) / 2.0;
+
+// float lightMapDepth = texture2D(texture, normalizedLightScreenPosition.st).z;
+ float lightMapDepth = texture2D(texture, normalizedLightScreenPosition.st ).z;
+// gl_FragColor = vec4(lightMapDepth, lightMapDepth, lightMapDepth, 1.0);
+
+// gl_FragColor = vec4(normalizedLightScreenPosition.st,0.0,1.0);
+
+// float lightActualDepth = normalizedLightScreenPosition.z;
+ float lightActualDepth = lightDepth;
+// gl_FragColor = vec4(lightActualDepth, lightActualDepth, lightActualDepth, 1.0);
+ float lightActualDepthWithStupidMaths = (lightActualDepth + 10.0) / 20.0;
+ float lightDepthWithStupidMaths = (lightDepth + 10.0) / 20.0;
+// gl_FragColor = vec4(vec3(lightActualDepthWithStupidMaths), 1.0);
+
+
+// if (lightActualDepthWithStupidMaths > lightMapDepth )
+// gl_FragColor = vec4(0.2, 0.2, 0.2, 1.0);
+// else
+ gl_FragColor = vec4(1.0, 1.0, 0.5, 1.0);
+
+
+// gl_FragColor = vec4(lightDepthWithStupidMaths, lightDepthWithStupidMaths, lightDepthWithStupidMaths, 1.0);
+
+
+//float stupidMathslightDepth = (lightDepth + 10.0) / 20;
+//gl_FragColor = vec4(stupidMathslightDepth, stupidMathslightDepth, stupidMathslightDepth, 1.0);
+
+//float stupidMathsActualDepth = (actualDepth + 10.0) / 20.0;
+//gl_FragColor = vec4(stupidMathsActualDepth, stupidMathsActualDepth, stupidMathsActualDepth, 1.0);
+
+};
diff --git a/demos/cubehouse/shaders/depthTestShader.vert b/demos/cubehouse/shaders/depthTestShader.vert
new file mode 100644
index 000000000..6f640c875
--- /dev/null
+++ b/demos/cubehouse/shaders/depthTestShader.vert
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+attribute highp vec4 vertex;
+attribute highp vec4 texCoords;
+
+uniform highp mat4 matrix;
+uniform highp mat4 qt_ProjectionMatrix;
+uniform highp mat4 qt_ModelViewMatrix;
+
+uniform highp mat4 cameraCombinedMatrix;
+uniform highp mat4 lightCombinedMatrix;
+
+uniform highp mat4 cameraModelViewMatrix;
+uniform highp mat4 inverseCameraModelViewMatrix;
+uniform highp mat4 lightModelViewMatrix;
+
+uniform highp mat4 cameraProjectionMatrix;
+uniform highp mat4 lightProjectionMatrix;
+
+varying highp vec4 qt_TexCoord0;
+varying highp vec4 onScreenPosition;
+varying highp vec4 lightScreenPosition;
+varying highp vec4 worldSpaceVertex;
+varying float lightDepth;
+varying float actualDepth;
+
+void main(void)
+{
+ qt_TexCoord0 = texCoords;
+// onScreenPosition = matrix * vertex;
+//onScreenPosition = cameraCombinedMatrix * vertex; // works
+ onScreenPosition = qt_ProjectionMatrix *
+ qt_ModelViewMatrix
+ * vertex;
+
+ highp vec4 worldPosition = inverseCameraModelViewMatrix *
+ qt_ModelViewMatrix * vertex;
+
+// lightScreenPosition = lightCombinedMatrix * vertex;
+// lightScreenPosition = lightCombinedMatrix * worldPosition;
+ lightScreenPosition = lightProjectionMatrix * lightModelViewMatrix * vertex;
+ lightDepth = lightScreenPosition.z;
+
+ actualDepth = onScreenPosition.z;
+
+ worldSpaceVertex = vertex;
+
+// gl_Position = qt_ProjectionMatrix * worldPosition;
+//gl_Position = onScreenPosition;
+gl_Position = onScreenPosition;
+// gl_Position = lightScreenPosition;
+};
diff --git a/demos/cubehouse/shaders/objectlineartexgen.frag b/demos/cubehouse/shaders/objectlineartexgen.frag
new file mode 100644
index 000000000..a4439f28a
--- /dev/null
+++ b/demos/cubehouse/shaders/objectlineartexgen.frag
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+uniform sampler2D texture;
+varying highp vec4 texCoord;
+varying float facingProjector;
+
+void main(void)
+{
+ vec2 clampedCoords = texCoord.st;
+ clampedCoords = clamp(texCoord.st, vec2(0.0), vec2(1.0));
+ vec4 textureColor = texture2D(texture, clampedCoords);
+ gl_FragColor = vec4(textureColor.rgb * facingProjector, 1.0);
+};
diff --git a/demos/cubehouse/shaders/objectlineartexgen.vert b/demos/cubehouse/shaders/objectlineartexgen.vert
new file mode 100644
index 000000000..b78b938c5
--- /dev/null
+++ b/demos/cubehouse/shaders/objectlineartexgen.vert
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+attribute highp vec4 qt_Vertex;
+attribute highp vec4 qt_Normal;
+uniform highp mat3 qt_NormalMatrix;
+uniform highp mat4 qt_ModelViewProjectionMatrix;
+
+uniform highp mat4 objectLinearTexgenMatrix;
+uniform highp vec4 projectorDirection;
+
+varying highp vec4 texCoord;
+varying float facingProjector;
+
+void main(void)
+{
+ texCoord = objectLinearTexgenMatrix * qt_Vertex;
+ vec4 normal = normalize(vec4(qt_NormalMatrix * vec3(qt_Vertex), qt_Vertex.w));
+ // We're facing the projector if the normal and projector direction
+ // are pointing in opposite directions, i.e. if their dot product
+ // is negative.
+ facingProjector = -dot(normalize(normal), normalize(projectorDirection));
+ facingProjector = clamp(facingProjector, 0.0, 1.0);
+ gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;
+};
diff --git a/demos/declarative/DefaultNavigator.qml b/demos/declarative/DefaultNavigator.qml
new file mode 100644
index 000000000..70b0ac6b1
--- /dev/null
+++ b/demos/declarative/DefaultNavigator.qml
@@ -0,0 +1,181 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+// This is an example of how to implement a custom navigation strategy
+// to replace the default strategy implemented by "Viewport".
+
+MouseArea {
+ // Set this property to the "Viewport" item to be controlled
+ // by this navigator. By default we assume that it is our parent.
+ property variant viewport: parent
+
+ // The navigator fills the entire viewport.
+ anchors.fill: viewport
+
+ // Private variables.
+ QtObject {
+ id: d_ptr
+ property bool panning: false
+ property int startX: 0
+ property int startY: 0
+ property variant startEye
+ property variant startCenter
+ property variant startUpVector
+ property variant pressedObject: null
+ property variant enteredObject: null
+ property bool sawDoubleClick: false
+ }
+
+ // Handle mouse press events.
+ onPressed: {
+ // Determine which object was pressed in the viewport.
+ var objectUnderMouse;
+ if (!d_ptr.panning && viewport.picking)
+ objectUnderMouse = viewport.objectForPoint(mouse.x, mouse.y);
+ else
+ objectUnderMouse = null;
+ if (d_ptr.pressedObject) {
+ // We already have a pressed object, so nothing to do.
+ mouse.accepted = true;
+ } else if (Qt.isQtObject(objectUnderMouse)) {
+ // Mouse press on a new object.
+ d_ptr.pressedObject = objectUnderMouse;
+ d_ptr.enteredObject = null;
+ d_ptr.sawDoubleClick = false;
+ objectUnderMouse.pressed();
+ mouse.accepted = true;
+ } else if (viewport.navigation && mouse.button == Qt.LeftButton) {
+ // Start panning the view.
+ d_ptr.panning = true;
+ d_ptr.startX = mouse.x;
+ d_ptr.startY = mouse.y;
+ d_ptr.startEye = viewport.camera.eye;
+ d_ptr.startCenter = viewport.camera.center;
+ d_ptr.startUpVector = viewport.camera.upVector;
+ mouse.accepted = true;
+ }
+ }
+
+ // Handle mouse release events.
+ onReleased: {
+ if (d_ptr.panning && mouse.button == Qt.LeftButton) {
+ d_ptr.panning = false;
+ mouse.accepted = true;
+ }
+ if (d_ptr.pressedObject && mouse.button == Qt.LeftButton) {
+ // Deliver the release event to the pressed object.
+ var objectUnderMouse = viewport.objectForPoint(mouse.x, mouse.y);
+ if (objectUnderMouse == d_ptr.pressedObject && !d_ptr.sawDoubleClick) {
+ d_ptr.pressedObject.released();
+ d_ptr.pressedObject.clicked();
+ } else {
+ d_ptr.pressedObject.released();
+ }
+ if (hoverEnabled) {
+ if (Qt.isQtObject(objectUnderMouse))
+ d_ptr.enteredObject = objectUnderMouse;
+ else
+ d_ptr.enteredObject = null;
+ if (d_ptr.enteredObject != d_ptr.pressedObject) {
+ d_ptr.pressedObject.hoverLeave();
+ if (d_ptr.enteredObject)
+ d_ptr.enteredObject.hoverEnter();
+ }
+ }
+ d_ptr.pressedObject = null;
+ mouse.accepted = true;
+ }
+ }
+
+ // Handle mouse double click events.
+ onDoubleClicked: {
+ if (d_ptr.pressedObject) {
+ var objectUnderMouse = viewport.objectForPoint(mouse.x, mouse.y);
+ if (objectUnderMouse == d_ptr.pressedObject) {
+ d_ptr.pressedObject.doubleClicked();
+ d_ptr.sawDoubleClick = true;
+ mouse.accepted = true;
+ }
+ }
+ }
+
+ // Handle mouse move events.
+ onPositionChanged: {
+ if (d_ptr.panning) {
+ var deltaX = mouse.x - d_ptr.startX;
+ var deltaY = mouse.y - d_ptr.startY;
+ var angleAroundY = deltaX * 90 / width;
+ var angleAroundX = deltaY * 90 / height;
+
+ viewport.camera.eye = d_ptr.startEye;
+ viewport.camera.center = d_ptr.startCenter;
+ viewport.camera.upVector = d_ptr.startUpVector;
+ viewport.camera.tiltPanRollCenter
+ (-angleAroundX, -angleAroundY, 0, "TiltPanRoll");
+ } else if (viewport.picking && hoverEnabled) {
+ // Handle object enter/leave events when mouse hover is enabled.
+ var objectUnderMouse = viewport.objectForPoint(mouse.x, mouse.y);
+ if (!d_ptr.pressedObject) {
+ if (Qt.isQtObject(objectUnderMouse)) {
+ if (d_ptr.enteredObject != objectUnderMouse) {
+ if (d_ptr.enteredObject)
+ d_ptr.enteredObject.hoverLeave();
+ d_ptr.enteredObject = objectUnderMouse;
+ d_ptr.enteredObject.hoverEnter();
+ }
+ } else if (d_ptr.enteredObject) {
+ d_ptr.enteredObject.hoverLeave();
+ d_ptr.enteredObject = null;
+ }
+ }
+ }
+ }
+
+ // Handle leave events.
+ onExited: {
+ if (hoverEnabled && !d_ptr.pressedObject && d_ptr.enteredObject) {
+ d_ptr.enteredObject.hoverLeave();
+ d_ptr.enteredObject = null;
+ }
+ }
+}
diff --git a/demos/declarative/PhotoPane.qml b/demos/declarative/PhotoPane.qml
new file mode 100644
index 000000000..1b22c8f07
--- /dev/null
+++ b/demos/declarative/PhotoPane.qml
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Item3D {
+ id: photo
+
+ property real offset
+ property real layer
+ property variant image
+ property bool bounce: false
+
+ mesh: Mesh { source: "meshes/photopane.obj" }
+
+ position: Qt.vector3d(offset, 0, -layer)
+ effect: Effect { decal: true; texture: image }
+
+ onClicked: {
+ if (photo.state == "pulled_out")
+ photo.state = "returned";
+ else
+ photo.state = "pulled_out";
+ }
+
+ onHoverEnter: { photo.state = "pop_up" }
+ onHoverLeave: { photo.state = "returned" }
+
+ states: [
+ State {
+ name: "pop_up"
+ PropertyChanges {
+ target: photo
+ y: 1.0
+ }
+ },
+ State {
+ name: "pulled_out"
+ PropertyChanges {
+ target: photo
+ x: 0
+ }
+ PropertyChanges {
+ target: photo
+ scale: 1.75
+ }
+ PropertyChanges {
+ target: photo
+ z: 2
+ }
+ PropertyChanges {
+ target: viewport
+ state: "show_photo"
+ }
+ },
+ State {
+ name: "returned"
+ PropertyChanges {
+ target: photo
+ x: offset
+ }
+ PropertyChanges {
+ target: photo
+ scale: 1
+ }
+ PropertyChanges {
+ target: photo
+ z: -layer
+ }
+ PropertyChanges {
+ target: viewport
+ state: "show_group"
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "*"
+ to: "*"
+ NumberAnimation {
+ targets: photo
+ properties: "x,scale,z,y"
+ easing.type: "OutBounce"
+ duration: 700
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/RoboBounce/Assets/QML3DSign.png b/demos/declarative/RoboBounce/Assets/QML3DSign.png
new file mode 100644
index 000000000..b4bfb88b2
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/QML3DSign.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/button.png b/demos/declarative/RoboBounce/Assets/button.png
new file mode 100644
index 000000000..2943e2403
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/button.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/calculatorSign.png b/demos/declarative/RoboBounce/Assets/calculatorSign.png
new file mode 100644
index 000000000..3a8fca728
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/calculatorSign.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/cubeButton.png b/demos/declarative/RoboBounce/Assets/cubeButton.png
new file mode 100644
index 000000000..2ea32a8b2
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/cubeButton.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/hazard.png b/demos/declarative/RoboBounce/Assets/hazard.png
new file mode 100644
index 000000000..a7c0b7fea
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/hazard.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/infobutton.png b/demos/declarative/RoboBounce/Assets/infobutton.png
new file mode 100644
index 000000000..e7379f2d2
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/infobutton.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/qtlogo.png b/demos/declarative/RoboBounce/Assets/qtlogo.png
new file mode 100644
index 000000000..3bf1a77d0
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/qtlogo.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/roboInfo.png b/demos/declarative/RoboBounce/Assets/roboInfo.png
new file mode 100644
index 000000000..b7bdda199
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/roboInfo.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/roboticArms.3ds b/demos/declarative/RoboBounce/Assets/roboticArms.3ds
new file mode 100644
index 000000000..478d27bfc
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/roboticArms.3ds
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/roboticBody.3ds b/demos/declarative/RoboBounce/Assets/roboticBody.3ds
new file mode 100644
index 000000000..ed872c82a
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/roboticBody.3ds
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/roboticHead.3ds b/demos/declarative/RoboBounce/Assets/roboticHead.3ds
new file mode 100644
index 000000000..7a517c2b3
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/roboticHead.3ds
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/rotateButton2.png b/demos/declarative/RoboBounce/Assets/rotateButton2.png
new file mode 100644
index 000000000..80a2d82a3
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/rotateButton2.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/sQt3D_logo.png b/demos/declarative/RoboBounce/Assets/sQt3D_logo.png
new file mode 100644
index 000000000..92a071d36
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/sQt3D_logo.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Assets/tronscape.png b/demos/declarative/RoboBounce/Assets/tronscape.png
new file mode 100644
index 000000000..325f60e38
--- /dev/null
+++ b/demos/declarative/RoboBounce/Assets/tronscape.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Calculator/Calculator.qml b/demos/declarative/RoboBounce/Calculator/Calculator.qml
new file mode 100644
index 000000000..b4c704986
--- /dev/null
+++ b/demos/declarative/RoboBounce/Calculator/Calculator.qml
@@ -0,0 +1,187 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+import "CalculatorCore"
+import "CalculatorCore/calculator.js" as CalcEngine
+
+Rectangle {
+ id: window
+
+ width: 640; height: 480
+ color: "#282828"
+
+ property string rotateLeft: "\u2939"
+ property string rotateRight: "\u2935"
+ property string leftArrow: "\u2190"
+ property string division : "\u00f7"
+ property string multiplication : "\u00d7"
+ property string squareRoot : "\u221a"
+ property string plusminus : "\u00b1"
+
+ function doOp(operation) { CalcEngine.doOperation(operation) }
+
+
+ states: [
+ State {
+ name: "hidden";
+ },
+ State {
+ name: "shown";
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "*"
+ to: "hidden"
+ SequentialAnimation {
+ NumberAnimation {target: window; property: "opacity"; to : 0.1; duration: 1000; easing.type:"OutQuad" }
+ PropertyAction {target: window; property: "visible"; value: false}
+ }
+ },
+ Transition {
+ from: "*"
+ to: "shown"
+ SequentialAnimation {
+ PropertyAction {target: window; property: "visible"; value: true}
+ NumberAnimation {target: window; property: "opacity"; to : 1.0; duration: 1000; easing.type:"OutQuad" }
+ }
+ }
+ ]
+
+ Item {
+ id: main
+ state: "orientation " + runtime.orientation
+
+ width: parent.width; height: parent.height; anchors.centerIn: parent
+
+ Column {
+ id: box; spacing: 8
+
+ anchors { fill: parent; topMargin: 6; bottomMargin: 6; leftMargin: 6; rightMargin: 6 }
+
+ Display {
+ id: display
+ width: box.width-3
+ height: 64
+ }
+
+ Column {
+ id: column; spacing: 6
+
+ property real h: ((box.height - 72) / 6) - ((spacing * (6 - 1)) / 6)
+ property real w: (box.width / 4) - ((spacing * (4 - 1)) / 4)
+
+ Row {
+ spacing: 6
+ Button { width: column.w; height: column.h; color: 'purple'; operation: "Off" }
+ Button { width: column.w; height: column.h; color: 'purple'; operation: leftArrow }
+ Button { width: column.w; height: column.h; color: 'purple'; operation: "C" }
+ Button { width: column.w; height: column.h; color: 'purple'; operation: "AC" }
+ }
+
+ Row {
+ spacing: 6
+ property real w: (box.width / 4) - ((spacing * (4 - 1)) / 4)
+
+ Button { width: column.w; height: column.h; color: 'green'; operation: "mc" }
+ Button { width: column.w; height: column.h; color: 'green'; operation: "m+" }
+ Button { width: column.w; height: column.h; color: 'green'; operation: "m-" }
+ Button { width: column.w; height: column.h; color: 'green'; operation: "mr" }
+ }
+
+ Grid {
+ id: grid; rows: 5; columns: 5; spacing: 6
+
+ property real w: (box.width / columns) - ((spacing * (columns - 1)) / columns)
+
+ Button { width: grid.w; height: column.h; operation: "7"; color: 'blue' }
+ Button { width: grid.w; height: column.h; operation: "8"; color: 'blue' }
+ Button { width: grid.w; height: column.h; operation: "9"; color: 'blue' }
+ Button { width: grid.w; height: column.h; operation: division }
+ Button { width: grid.w; height: column.h; operation: squareRoot }
+ Button { width: grid.w; height: column.h; operation: "4"; color: 'blue' }
+ Button { width: grid.w; height: column.h; operation: "5"; color: 'blue' }
+ Button { width: grid.w; height: column.h; operation: "6"; color: 'blue' }
+ Button { width: grid.w; height: column.h; operation: multiplication }
+ Button { width: grid.w; height: column.h; operation: "x^2" }
+ Button { width: grid.w; height: column.h; operation: "1"; color: 'blue' }
+ Button { width: grid.w; height: column.h; operation: "2"; color: 'blue' }
+ Button { width: grid.w; height: column.h; operation: "3"; color: 'blue' }
+ Button { width: grid.w; height: column.h; operation: "-" }
+ Button { width: grid.w; height: column.h; operation: "1/x" }
+ Button { width: grid.w; height: column.h; operation: "0"; color: 'blue' }
+ Button { width: grid.w; height: column.h; operation: "." }
+ Button { width: grid.w; height: column.h; operation: plusminus }
+ Button { width: grid.w; height: column.h; operation: "+" }
+ Button { width: grid.w; height: column.h; operation: "="; color: 'red' }
+ }
+ }
+ }
+
+ states: [
+ State {
+ name: "orientation " + Orientation.Landscape
+ PropertyChanges { target: main; rotation: 90; width: window.height; height: window.width }
+ PropertyChanges { target: rotateButton; operation: rotateLeft }
+ },
+ State {
+ name: "orientation " + Orientation.PortraitInverted
+ PropertyChanges { target: main; rotation: 180; }
+ PropertyChanges { target: rotateButton; operation: rotateRight }
+ },
+ State {
+ name: "orientation " + Orientation.LandscapeInverted
+ PropertyChanges { target: main; rotation: 270; width: window.height; height: window.width }
+ PropertyChanges { target: rotateButton; operation: rotateLeft }
+ }
+ ]
+
+ transitions: Transition {
+ SequentialAnimation {
+ PropertyAction { target: rotateButton; property: "operation" }
+ RotationAnimation { direction: RotationAnimation.Shortest; duration: 300; easing.type: Easing.InOutQuint }
+ NumberAnimation { properties: "x,y,width,height"; duration: 300; easing.type: Easing.InOutQuint }
+ }
+ }
+ }
+}
diff --git a/demos/declarative/RoboBounce/Calculator/CalculatorCore/Button.qml b/demos/declarative/RoboBounce/Calculator/CalculatorCore/Button.qml
new file mode 100644
index 000000000..02a0119a5
--- /dev/null
+++ b/demos/declarative/RoboBounce/Calculator/CalculatorCore/Button.qml
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+BorderImage {
+ id: button
+
+ property alias operation: buttonText.text
+ property string color: ""
+
+ signal clicked
+
+ source: "images/button-" + color + ".png"; clip: true
+ border { left: 10; top: 10; right: 10; bottom: 10 }
+
+ Rectangle {
+ id: shade
+ anchors.fill: button; radius: 10; color: "black"; opacity: 0
+ }
+
+ Text {
+ id: buttonText
+ anchors.centerIn: parent; anchors.verticalCenterOffset: -1
+ font.pixelSize: parent.width > parent.height ? parent.height * .5 : parent.width * .5
+ style: Text.Sunken; color: "white"; styleColor: "black"; smooth: true
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ onClicked: {
+ doOp(operation)
+ button.clicked()
+ }
+ }
+
+ states: State {
+ name: "pressed"; when: mouseArea.pressed == true
+ PropertyChanges { target: shade; opacity: .4 }
+ }
+
+ transitions: [
+ Transition {
+ from: "*"
+ to: "pressed"
+ SequentialAnimation {
+ NumberAnimation {target: button; property: "scale"; to : 0.8; duration: 200; easing.type:"OutQuad" }
+ }
+ },
+ Transition {
+ from: "pressed"
+ to: "*"
+ SequentialAnimation {
+ NumberAnimation {target: button; property: "scale"; to : 1.0; duration: 200; easing.type:"OutQuad" }
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/RoboBounce/Calculator/CalculatorCore/Display.qml b/demos/declarative/RoboBounce/Calculator/CalculatorCore/Display.qml
new file mode 100644
index 000000000..6e9e664b4
--- /dev/null
+++ b/demos/declarative/RoboBounce/Calculator/CalculatorCore/Display.qml
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+import QtQuick 1.0
+
+BorderImage {
+ id: image
+
+ property alias text : displayText.text
+ property alias currentOperation : operationText
+
+ source: "images/display.png"
+ border { left: 10; top: 10; right: 10; bottom: 10 }
+
+ Text {
+ id: displayText
+ anchors {
+ right: parent.right; verticalCenter: parent.verticalCenter; verticalCenterOffset: -1
+ rightMargin: 6; left: operationText.right
+ }
+ font.pixelSize: parent.height * .6; text: "0"; horizontalAlignment: Text.AlignRight; elide: Text.ElideRight
+ color: "#343434"; smooth: true; font.bold: true
+ }
+ Text {
+ id: operationText
+ font.bold: true; font.pixelSize: parent.height * .7
+ color: "#343434"; smooth: true
+ anchors { left: parent.left; leftMargin: 6; verticalCenterOffset: -3; verticalCenter: parent.verticalCenter }
+ }
+}
diff --git a/demos/declarative/RoboBounce/Calculator/CalculatorCore/calculator.js b/demos/declarative/RoboBounce/Calculator/CalculatorCore/calculator.js
new file mode 100644
index 000000000..7c363c7f3
--- /dev/null
+++ b/demos/declarative/RoboBounce/Calculator/CalculatorCore/calculator.js
@@ -0,0 +1,91 @@
+
+var curVal = 0
+var memory = 0
+var lastOp = ""
+var timer = 0
+
+function disabled(op) {
+ if (op == "." && display.text.toString().search(/\./) != -1) {
+ return true
+ } else if (op == squareRoot && display.text.toString().search(/-/) != -1) {
+ return true
+ } else {
+ return false
+ }
+}
+
+function doOperation(op) {
+ if (disabled(op)) {
+ return
+ }
+
+ if (op.toString().length==1 && ((op >= "0" && op <= "9") || op==".") ) {
+ if (display.text.toString().length >= 14)
+ return; // No arbitrary length numbers
+ if (lastOp.toString().length == 1 && ((lastOp >= "0" && lastOp <= "9") || lastOp == ".") ) {
+ display.text = display.text + op.toString()
+ } else {
+ display.text = op
+ }
+ lastOp = op
+ return
+ }
+ lastOp = op
+
+ if (display.currentOperation.text == "+") {
+ display.text = Number(display.text.valueOf()) + Number(curVal.valueOf())
+ } else if (display.currentOperation.text == "-") {
+ display.text = Number(curVal) - Number(display.text.valueOf())
+ } else if (display.currentOperation.text == multiplication) {
+ display.text = Number(curVal) * Number(display.text.valueOf())
+ } else if (display.currentOperation.text == division) {
+ display.text = Number(Number(curVal) / Number(display.text.valueOf())).toString()
+ } else if (display.currentOperation.text == "=") {
+ }
+
+ if (op == "+" || op == "-" || op == multiplication || op == division) {
+ display.currentOperation.text = op
+ curVal = display.text.valueOf()
+ return
+ }
+
+ curVal = 0
+ display.currentOperation.text = ""
+
+ if (op == "1/x") {
+ display.text = (1 / display.text.valueOf()).toString()
+ } else if (op == "x^2") {
+ display.text = (display.text.valueOf() * display.text.valueOf()).toString()
+ } else if (op == "Abs") {
+ display.text = (Math.abs(display.text.valueOf())).toString()
+ } else if (op == "Int") {
+ display.text = (Math.floor(display.text.valueOf())).toString()
+ } else if (op == plusminus) {
+ display.text = (display.text.valueOf() * -1).toString()
+ } else if (op == squareRoot) {
+ display.text = (Math.sqrt(display.text.valueOf())).toString()
+ } else if (op == "mc") {
+ memory = 0;
+ } else if (op == "m+") {
+ memory += display.text.valueOf()
+ } else if (op == "mr") {
+ display.text = memory.toString()
+ } else if (op == "m-") {
+ memory = display.text.valueOf()
+ } else if (op == leftArrow) {
+ display.text = display.text.toString().slice(0, -1)
+ if (display.text.length == 0) {
+ display.text = "0"
+ }
+ } else if (op == "Off") {
+ Qt.quit();
+ } else if (op == "C") {
+ display.text = "0"
+ } else if (op == "AC") {
+ curVal = 0
+ memory = 0
+ lastOp = ""
+ display.text ="0"
+ }
+}
+
diff --git a/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-.png b/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-.png
new file mode 100644
index 000000000..544e51453
--- /dev/null
+++ b/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-blue.png b/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-blue.png
new file mode 100644
index 000000000..5f92de32d
--- /dev/null
+++ b/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-blue.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-green.png b/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-green.png
new file mode 100644
index 000000000..36c93914c
--- /dev/null
+++ b/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-green.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-purple.png b/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-purple.png
new file mode 100644
index 000000000..347cbbea9
--- /dev/null
+++ b/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-purple.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-red.png b/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-red.png
new file mode 100644
index 000000000..3b335891a
--- /dev/null
+++ b/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/button-red.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/display.png b/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/display.png
new file mode 100644
index 000000000..9507f4382
--- /dev/null
+++ b/demos/declarative/RoboBounce/Calculator/CalculatorCore/images/display.png
Binary files differ
diff --git a/demos/declarative/RoboBounce/Calculator/CalculatorCore/qmldir b/demos/declarative/RoboBounce/Calculator/CalculatorCore/qmldir
new file mode 100644
index 000000000..a926b93fa
--- /dev/null
+++ b/demos/declarative/RoboBounce/Calculator/CalculatorCore/qmldir
@@ -0,0 +1,2 @@
+Button Button.qml
+Display Display.qml
diff --git a/demos/declarative/RoboBounce/RobotCore/PushButton.qml b/demos/declarative/RoboBounce/RobotCore/PushButton.qml
new file mode 100644
index 000000000..8cc48744f
--- /dev/null
+++ b/demos/declarative/RoboBounce/RobotCore/PushButton.qml
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Image {
+ id: theButton
+ property bool bounce: false
+ source: "../Assets/button.png"
+ width: 40
+ height: 40
+
+ signal pressed
+
+ SequentialAnimation {
+ running: theButton.bounce
+ NumberAnimation {target: theButton; property: "scale"; duration: 50; to: 0.8;}
+ NumberAnimation {target: theButton; property: "scale"; duration: 50; to: 1;}
+ onCompleted: {theButton.bounce = false}
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ theButton.bounce=true
+ theButton.pressed()
+ }
+ }
+}
+
+
diff --git a/demos/declarative/RoboBounce/RobotCore/QMLPanels.qml b/demos/declarative/RoboBounce/RobotCore/QMLPanels.qml
new file mode 100644
index 000000000..874436dd4
--- /dev/null
+++ b/demos/declarative/RoboBounce/RobotCore/QMLPanels.qml
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Item {
+ Rectangle {
+ id: buttonBox1
+ x: 30
+ y: 110
+ width: 60
+ height: 160
+ opacity: 0.5
+ color: "black"
+ border.color: "#2D918D"
+ border.width: 2
+ radius: 5
+ }
+ PushButton {
+ x: buttonBox1.x+10
+ y: buttonBox1.y+10
+ }
+ PushButton {
+ x: buttonBox1.x+10
+ y: buttonBox1.y+60
+ }
+ PushButton {
+ x: buttonBox1.x+10
+ y: buttonBox1.y+110
+ }
+
+ Rectangle {
+ id: buttonBox2
+ x: 550
+ y: 110
+ width: 60
+ height: 160
+ opacity: 0.5
+ color: "black"
+ border.color: "#2D918D"
+ border.width: 2
+ radius: 5
+ }
+ PushButton {
+ x: buttonBox2.x+10
+ y: buttonBox2.y+10
+ }
+ PushButton {
+ x: buttonBox2.x+10
+ y: buttonBox2.y+60
+ }
+ PushButton {
+ x: buttonBox2.x+10
+ y: buttonBox2.y+110
+ }
+
+ states: [
+ State {},
+ State {}
+
+ ]
+}
+
+
diff --git a/demos/declarative/RoboBounce/RobotCore/Robot.qml b/demos/declarative/RoboBounce/RobotCore/Robot.qml
new file mode 100644
index 000000000..c696b794b
--- /dev/null
+++ b/demos/declarative/RoboBounce/RobotCore/Robot.qml
@@ -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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Item3D {
+ id: robot1
+ scale: 0.3
+ mesh: Mesh { id: roboMesh; source: "../Assets/roboticBody.3ds"; }
+ effect: Effect {}
+}
+
+
diff --git a/demos/declarative/RoboBounce/RobotCore/TronCube.qml b/demos/declarative/RoboBounce/RobotCore/TronCube.qml
new file mode 100644
index 000000000..9e352602c
--- /dev/null
+++ b/demos/declarative/RoboBounce/RobotCore/TronCube.qml
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+import Qt3D.Shapes 1.0
+
+Cube {
+ effect: Effect {color: "#aaaaaa"; texture: "../Assets/qtlogo.png"; decal: true}
+ position: Qt.vector3d(0,-5.01, 0)
+}
+
+
diff --git a/demos/declarative/RoboBounce/robobounce.qml b/demos/declarative/RoboBounce/robobounce.qml
new file mode 100644
index 000000000..a5b871114
--- /dev/null
+++ b/demos/declarative/RoboBounce/robobounce.qml
@@ -0,0 +1,616 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+import Qt3D.Shapes 1.0
+import "Calculator"
+import "RobotCore"
+
+Image {
+ property real eyeSeparation: 0.0 //Eye separation: 0.1 for 3d, 0.0 for standard
+ property real repeatAnimationTimer: 30; //Auto click the 'start' button this often
+
+ id: theBackground
+ width: 640
+ height: 480
+ source: "Assets/tronscape.png"
+
+ focus: true
+ Keys.onSpacePressed: {
+ heartbeat.restart();
+ qt3dButton.bounce = true;
+ console.log("Hide Calc")
+ if (calc.state=="hidden") {
+ calc.state="shown"
+
+ } else {
+ calc.state = "hidden"
+ };
+ }
+ Keys.onLeftPressed: {
+ console.log("Rotate Key Pressed");
+ heartbeat.restart();
+ room.spinning = true;
+ }
+ Keys.onRightPressed: {
+ console.log("Box Drop Key pressed");
+ heartbeat.restart();
+ smallCube.fallingCubeAnimation=true;
+ }
+ Keys.onUpPressed: {
+ console.log("Info Key Pressed");
+ heartbeat.restart();
+ roboInfo.showVisible=true
+ }
+ Keys.onPressed: {
+ heartbeat.restart();
+ if (event.key==Qt.Key_A) {
+ navigator.spindir=1
+ } else if (event.key==Qt.Key_D) {
+ navigator.spindir=2
+ } else if (event.key==Qt.Key_W) {
+ navigator.tiltdir=1
+ } else if (event.key==Qt.Key_S) {
+ navigator.tiltdir=2
+ } else if (event.key==Qt.Key_Plus) {
+ navigator.zoomdir=1
+ } else if (event.key==Qt.Key_Minus) {
+ navigator.zoomdir=2
+ }
+ }
+ Keys.onReleased: {
+ heartbeat.restart();
+ if (event.key==Qt.Key_A) {
+ navigator.spindir=0
+ } else if (event.key==Qt.Key_D) {
+ navigator.spindir=0
+ } else if (event.key==Qt.Key_W) {
+ navigator.tiltdir=0
+ } else if (event.key==Qt.Key_S) {
+ navigator.tiltdir=0
+ } else if (event.key==Qt.Key_Plus) {
+ navigator.zoomdir=0
+ } else if (event.key==Qt.Key_Minus) {
+ navigator.zoomdir=0
+ }
+ }
+
+ Timer {
+ id: navigator;
+ interval: 5;
+ running: true
+ repeat: true
+ property int tiltdir: 0 //1 is forward, 2 is back
+ property int spindir: 0 //1 is right, 2 is left
+ property int zoomdir: 0 //1 is in, 2 is out
+ onTriggered: {
+ if (tiltdir==1) {roomTilt.angle=roomTilt.angle+0.5}
+ else if (tiltdir==2) {roomTilt.angle=roomTilt.angle-0.5}
+ if (spindir==1) {roomSpin.angle=roomSpin.angle+0.5}
+ else if (spindir==2) {roomSpin.angle=roomSpin.angle-0.5}
+ if (spindir==1) {roomSpin.angle=roomSpin.angle+0.5}
+ else if (spindir==2) {roomSpin.angle=roomSpin.angle-0.5}
+ if (zoomdir==1) {
+ if (theCamera.fieldOfView>13) {
+ theCamera.fieldOfView=theCamera.fieldOfView-0.5
+ }
+ } else if (zoomdir==2) {
+ if (theCamera.fieldOfView<80) {
+ theCamera.fieldOfView=theCamera.fieldOfView+0.5
+ }
+ }
+ }
+ }
+
+
+ Timer {
+ id: heartbeat;
+ interval: theBackground.repeatAnimationTimer*1000;
+ running: true
+ repeat: true
+ onTriggered: {
+ qt3dButton.bounce = true;
+ console.log("Hide Calc")
+ if (calc.state=="hidden") {
+ calc.state="shown"
+ } else {
+ calc.state = "hidden"
+ }
+ }
+ }
+
+ StereoView {
+ id: stereo
+ width: 640; height: 480
+ //layout: StereoView.LeftRight
+
+ Viewport {
+ id: viewport
+ width: parent.width
+ height: parent.height
+ navigation: true
+ picking: true
+ //showPicking: true
+
+ Item {
+ visible: false
+ id: buttonPanel
+ state: "panelUp"
+ states: [
+ State { name: "panelDown";},
+ State { name: "panelUp";}
+ ]
+
+ transitions: [
+ Transition {
+ from: "*"
+ to: "panelDown"
+ SequentialAnimation {
+ PropertyAction{target: buttonPanel; property: "visible"; value: true}
+ PauseAnimation{duration: 10}
+ PropertyAction{target: buttonPanel; property: "visible"; value: false}
+ PauseAnimation{duration: 10}
+ PropertyAction{target: buttonPanel; property: "visible"; value: true}
+ PauseAnimation{duration: 10}
+ PropertyAction{target: buttonPanel; property: "visible"; value: true}
+ PauseAnimation{duration: 10}
+ PropertyAction{target: buttonPanel; property: "visible"; value: false}
+ PauseAnimation{duration: 10}
+ PropertyAction{target: buttonPanel; property: "visible"; value: true}
+ }
+ },
+ Transition {
+ from: "*"
+ to: "panelUp"
+ SequentialAnimation {
+ onStarted: { console.log("Panel Up"); }
+ NumberAnimation {target: buttonPanel; property: opacity; to: 0; duration: 2000;}
+ PropertyAction{target: buttonPanel; property: "visible"; value: false}
+ }
+ }
+ ]
+
+ Rectangle {
+ id: buttonBox1
+ x: viewport.width-175
+ y: 10
+ width: 160
+ height: 60
+ opacity: 0.5
+ color: "black"
+ border.color: "#2D918D"
+ border.width: 2
+ radius: 5
+ }
+ PushButton {
+ source: "Assets/rotateButton2.png"
+ x: buttonBox1.x+10
+ y: buttonBox1.y+10
+ onPressed: {
+ console.log("Rotate Pressed");
+ room.spinning = true;
+ heartbeat.restart();
+ }
+ }
+ PushButton {
+ source: "Assets/cubeButton.png"
+ x: buttonBox1.x+60
+ y: buttonBox1.y+10
+ onPressed: {
+ console.log("Box button pressed");
+ smallCube.fallingCubeAnimation=true;
+ heartbeat.restart();
+ }
+ }
+ PushButton {
+ source: "Assets/infobutton.png"
+ x: buttonBox1.x+110
+ y: buttonBox1.y+10
+ onPressed: {
+ console.log("Info Button Pressed");
+ roboInfo.showVisible=true
+ heartbeat.restart();
+ }
+ }
+ }
+
+ Rectangle {
+ id: roboInfo
+ x: 5
+ y: 85
+ width: 150
+ height: 175
+ opacity: 0.0
+ color: "black"
+ property bool showVisible: false
+ border.color: "#2D918D"
+ border.width: 2
+ radius: 5
+ Image {
+ source: "Assets/roboInfo.png"
+ }
+
+ SequentialAnimation {
+ running: roboInfo.showVisible
+ loops: Animation.infinite
+ NumberAnimation {target: roboInfo; property: "opacity"; to: 0.7; duration: 500}
+ PauseAnimation {duration: 3000}
+ NumberAnimation {target: roboInfo; property: "opacity"; to: 0.0; duration: 500}
+ onCompleted: {roboInfo.showVisible=false}
+ }
+ }
+
+ Calculator {
+ id: calc
+ }
+
+ Image {
+ id: qt3dButton
+ source: "Assets/sQt3D_logo.png"
+ property bool bounce: false
+
+ x: 10
+ y: 5
+ width: 110
+ height: 70
+
+ SequentialAnimation {
+ running: qt3dButton.bounce
+ NumberAnimation {target: qt3dButton; property: "scale"; duration: 100; to: 1.2;}
+ NumberAnimation {target: qt3dButton; property: "scale"; duration: 100; to: 1;}
+ onCompleted: {qt3dButton.bounce = false}
+ }
+
+ MouseArea {
+ id: qt3dActivate
+ anchors.fill: parent
+ onClicked: {
+ heartbeat.restart();
+ qt3dButton.bounce = true;
+ console.log("Hide Calc")
+ if (calc.state=="hidden") {
+ calc.state="shown"
+ } else {
+ calc.state = "hidden"
+ }
+ }
+ }
+ }
+
+ camera: Camera {
+ id: theCamera
+ eye: Qt.vector3d(0, 2, 10)
+ nearPlane:2.5
+ center: Qt.vector3d(0,2,0)
+ fieldOfView: 12
+ eyeSeparation: theBackground.eyeSeparation
+ }
+
+ Item3D {
+ id: scene
+
+ states: [
+ State { name: "qmlView"; when: calc.visible},
+ State { name: "threedView"; when: !calc.visible }
+ ]
+
+ transitions: [
+ Transition {
+ from: "*"
+ to: "qmlView"
+ SequentialAnimation {
+ PropertyAction{target: roomSpin; property: "angle"; value: 0}
+ PropertyAction{target: roomTilt; property: "angle"; value: 0}
+ PropertyAction{target: buttonPanel; property: "visible"; value: false}
+ PropertyAction{target: theCamera; property: "eye"; value: Qt.vector3d(0, 2, 10)}
+ PropertyAction{target: theCamera; property: "fieldOfView"; value: 11.45}
+ PropertyAction{target: spinSign; property: "angle"; value: 0}
+ PropertyAction{target: robot; property: "position"; value: Qt.vector3d(0,10,4)}
+ PropertyAction{target: pitch; property: "angle"; value: 0}
+ PropertyAction{target: roll; property: "angle"; value: 75}
+ PropertyAction{target: yaw; property: "angle"; value: 90}
+ PropertyAction{target: spinSign; property: "angle"; value: 0}
+ PropertyAction{target: innerCube; property: "scale"; value: 0.95}
+ PropertyAction{target: signCube; property: "scale"; value: 2.375}
+ }
+ },
+ Transition {
+ from: "*"
+ to: "threedView"
+ SequentialAnimation {
+ onStarted: {console.log("start")}
+ SequentialAnimation {
+ NumberAnimation { target: theCamera; property: "fieldOfView"; to: 20; duration: 1000; easing.type: "InOutQuad" }
+ ParallelAnimation {
+ NumberAnimation { target: spinSign; property: "angle"; to: 720; duration: 500; easing.type: "InOutQuad"}
+ NumberAnimation { target: innerCube; property: "scale"; to: 1.01; duration: 500}
+ }
+ }
+ PauseAnimation {duration: 1000}
+ ParallelAnimation {
+ NumberAnimation {target: theCamera; property: "fieldOfView"; to: 40;
+ duration: 1000; easing.type: "InOutQuad"}
+ Vector3dAnimation {target: theCamera; property: "eye"; to: Qt.vector3d(0,4,10);
+ duration: 2500; easing.type: "InOutQuad"
+ }
+ }
+ PauseAnimation {duration: 1000}
+ NumberAnimation {target: signCube; property: "scale"; to: 0.0; duration: 2500; easing.type: "InOutQuad"}
+ Vector3dAnimation {target: robot; property: "position"; to: Qt.vector3d(0,0,4); duration: 1000; easing.type: "OutBounce"}
+ PauseAnimation {duration: 500}
+ NumberAnimation { target:roll; property: "angle"; to: 0; duration: 2500; easing.type: "InOutElastic"}
+ NumberAnimation { target: theCamera; property: "fieldOfView"; to: 20; duration: 1000; easing.type: "InOutQuad" }
+ NumberAnimation { target: headroll; property: "angle"; to: 0; duration: 500; easing.type: "OutElastic"}
+ NumberAnimation { target: headyaw; property: "angle"; to: 30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: -30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: 30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: -30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: 30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: -30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: 30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: -30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: 00; duration: 100; easing.type: "OutQuad"}
+ NumberAnimation { target: theCamera; property: "fieldOfView"; to: 40; duration: 1000; easing.type: "InOutQuad" }
+ PauseAnimation{duration: 1000}
+ ParallelAnimation {
+ SequentialAnimation {
+ NumberAnimation {target: pitch; property: "angle"; to: -10; duration: 500; easing.type: "InOutBack"}
+ PauseAnimation{duration: 1000}
+ NumberAnimation {target: pitch; property: "angle"; to: 0; duration: 500; easing.type: "InOutBack"}
+ }
+ Vector3dAnimation {target: robot; property: "position"; to: Qt.vector3d(0,0,0); duration: 2000; easing.type: "InOutBack"}
+ }
+ PauseAnimation{duration: 500}
+ SequentialAnimation {
+ PropertyAction{target: buttonPanel; property: "visible"; value: true}
+ PauseAnimation{duration: 50}
+ PropertyAction{target: buttonPanel; property: "visible"; value: false}
+ PauseAnimation{duration: 40}
+ PropertyAction{target: buttonPanel; property: "visible"; value: true}
+ PauseAnimation{duration: 100}
+ PropertyAction{target: buttonPanel; property: "visible"; value: false}
+ PauseAnimation{duration: 40}
+ PropertyAction{target: buttonPanel; property: "visible"; value: true}
+ PauseAnimation{duration: 150}
+ PropertyAction{target: buttonPanel; property: "visible"; value: false}
+ PauseAnimation{duration: 40}
+ PropertyAction{target: buttonPanel; property: "visible"; value: true}
+ PauseAnimation{duration: 300}
+ PropertyAction{target: buttonPanel; property: "visible"; value: false}
+ PauseAnimation{duration: 40}
+ PropertyAction{target: buttonPanel; property: "visible"; value: true}
+ }
+ }
+ }
+ ]
+
+ effect: Effect{}
+
+ Light {position: Qt.vector3d(20,5,00)}
+
+
+ Item3D {
+ id: room
+ property bool spinning: false
+ transform: [
+ Rotation3D{id: roomTilt; angle: 0; axis: Qt.vector3d(1,0,0)},
+ Rotation3D{id: roomSpin; angle: 0; axis: Qt.vector3d(0,1,0)}
+ ]
+
+
+ NumberAnimation {
+ running: room.spinning
+ loops: Animation.infinite
+ target: roomSpin
+ property: "angle"
+ to: 360
+ duration: 3000
+ easing.type: "InOutQuad"
+ onCompleted: {
+ room.spinning=false
+ roomSpin.angle=0
+ }
+ }
+
+ TronCube {
+ id: smallCube
+ property bool fallingCubeAnimation: false
+ position: Qt.vector3d(0,5,0)
+
+ onClicked: {
+ heartbeat.restart();
+ console.log("Small cube clicked");
+ smallCube.fallingCubeAnimation=true;
+ }
+
+ transform: [
+ Rotation3D {id: spinSmallCube; angle: 0; axis: Qt.vector3d(0,1,0)}
+ ]
+
+ SequentialAnimation {
+ running: smallCube.fallingCubeAnimation
+ loops: Animation.infinite
+ onCompleted: {smallCube.fallingCubeAnimation=false;}
+ ParallelAnimation {
+ NumberAnimation {target: spinSmallCube; property: "angle"; to: 360; easing.type: "InOutQuad"; duration: 1750}
+ SequentialAnimation {
+ Vector3dAnimation {target: smallCube; property: "position"; to: Qt.vector3d(0,3.2,0); easing.type: "InQuad"; duration: 250}
+ PropertyAction {target: robotHead; property: "y"; value: 9.00;}
+ ParallelAnimation {
+ NumberAnimation {target: smallCube; property: "x"; to: 2; easing.type: "Linear"; duration: 1500}
+ SequentialAnimation {
+ NumberAnimation {target: smallCube; property: "y"; to: 4.5; easing.type: "OutQuad"; duration: 250}
+ NumberAnimation {target: smallCube; property: "y"; to: 0.5; easing.type: "OutBounce"; duration: 1250}
+ }
+ }
+ }
+ }
+ PauseAnimation {duration: 500 }
+ NumberAnimation { target: robotHead; property: "y"; to: 9.2; easing.type: "OutBounce"; duration: 250 }
+ PauseAnimation {duration: 500 }
+ NumberAnimation { target: headyaw; property: "angle"; to: 30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: -30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: 30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: -30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: 30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: -30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: 30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: -30; duration: 70; easing.type: "InOutQuad"}
+ NumberAnimation { target: headyaw; property: "angle"; to: 00; duration: 100; easing.type: "OutQuad"}
+ NumberAnimation { target: yaw; property: "angle"; to: 180; duration: 250; easing.type: "InOutQuad"}
+ NumberAnimation { target: armBend; property: "angle"; to: -45; duration: 500; easing.type: "InOutQuad"}
+ ParallelAnimation {
+ NumberAnimation { target: robot; property: "x"; to: 0.5; duration: 500; easing.type: "InQuad"}
+ NumberAnimation { target: pitch; property: "angle"; to: 30; duration: 500; easing.type: "InOutQuad"}
+ }
+ ParallelAnimation {
+ NumberAnimation { target: robot; property: "x"; to: 3.5; duration: 1000; easing.type: "Linear"}
+ NumberAnimation { target: smallCube; property: "x"; to: 5; duration: 1000; easing.type: "Linear"}
+ }
+ ParallelAnimation {
+ NumberAnimation { target: smallCube; property: "x"; to: 8; duration: 1000; easing.type: "Linear"}
+ SequentialAnimation {
+ PauseAnimation { duration: 250}
+ NumberAnimation { target: smallCube; property: "y"; to: -5; duration: 750; easing.type: "InQuad"}
+ }
+ ParallelAnimation {
+ SequentialAnimation {
+ NumberAnimation {target: pitch; property: "angle"; to: -10; duration: 750; easing.type: "InOutBack"}
+ PauseAnimation{duration: 1500}
+ NumberAnimation {target: pitch; property: "angle"; to: 0; duration: 750; easing.type: "InOutBack"}
+ }
+ Vector3dAnimation {target: robot; property: "position"; to: Qt.vector3d(0,0,0); duration: 3000; easing.type: "InOutBack"}
+ }
+ }
+ NumberAnimation { target: yaw; property: "angle"; to: 90; duration: 250; easing.type: "InOutQuad"}
+ NumberAnimation { target: armBend; property: "angle"; to: -90; duration: 500; easing.type: "InOutQuad"}
+ PauseAnimation { duration: 1000 }
+ PropertyAction {target: smallCube; property: "position"; value: Qt.vector3d(0,10,0)}
+ NumberAnimation { target: smallCube; property: "y"; to: 5; duration: 1000; easing.type: "OutQuad"}
+ }
+ }
+
+ TronCube {
+ scale: 10.0
+ onClicked: {
+ heartbeat.restart();
+ console.log("Big cube clicked");
+ room.spinning = true;
+ }
+ }
+
+ Cube {
+ id: signCube
+ scale: 2.375
+ position: Qt.vector3d(0,2,0)
+ effect: calcEffect
+ transform: [
+ Rotation3D{id: spinSign; angle: 180; axis:Qt.vector3d(0,1,0)}
+ ]
+
+ Cube {
+ id: innerCube
+ scale: 0.95
+ effect: signEffect
+ }
+
+ Effect {
+ id: signEffect
+ color: "#aaca00"
+ texture: "Assets/QML3DSign.png"
+ decal: true
+ }
+
+ Effect {
+ id: calcEffect
+ color: "#aaca00"
+ texture: "Assets/calculatorSign.png"
+ decal: true
+ }
+ }
+
+ Robot {
+ id: robot
+ position: Qt.vector3d(0,10,4)
+
+ onClicked: {
+ heartbeat.restart();
+ console.log("robot has been clicked")
+ roboInfo.showVisible=true
+ }
+
+ transform: [
+ Rotation3D {id: pitch; angle: 0; axis: Qt.vector3d(0,0,1)},
+ Rotation3D {id: roll; angle: 75; axis: Qt.vector3d(1,0,0)},
+ Rotation3D {id: yaw; angle: 90; axis: Qt.vector3d(0,1,0)}
+ ]
+
+ Item3D {
+ id: robotArms
+ mesh: Mesh { source: "Assets/roboticArms.3ds"}
+ transform: Rotation3D{id: armBend; angle: -90;axis: Qt.vector3d(0,0,1)}
+ position: Qt.vector3d(.18, 5.4,0)
+
+ SequentialAnimation {
+ running: false
+ loops: 100
+ NumberAnimation {target: armBend; property: "angle"; to: 0.0; duration: 1000; easing.type: "OutQuad" }
+ PauseAnimation {duration: 1000}
+ NumberAnimation {target: armBend; property: "angle"; to: -90.0; duration: 1000; easing.type: "OutQuad" }
+ }
+ }
+
+ Item3D {
+ id: robotHead
+ mesh: Mesh { source: "Assets/roboticHead.3ds" }
+ position: Qt.vector3d(0,9.1,0)
+ transform: [
+ Rotation3D {id: headpitch; angle: 0; axis: Qt.vector3d(0,0,1)},
+ Rotation3D {id: headroll; angle: 45; axis: Qt.vector3d(1,0,0)},
+ Rotation3D {id: headyaw; angle: 0; axis: Qt.vector3d(0,1,0)}
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/demos/declarative/basket.qml b/demos/declarative/basket.qml
new file mode 100644
index 000000000..910cc146b
--- /dev/null
+++ b/demos/declarative/basket.qml
@@ -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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//! [1]
+import Qt 4.7
+import Qt3D 1.0
+
+Viewport {
+ width: 640; height: 480
+
+ camera: Camera {
+ eye: Qt.vector3d(0, 4, 10)
+ }
+//! [1]
+
+//! [2]
+ Item3D {
+ mesh: Mesh { source: "meshes/basket.bez" }
+ effect: Effect { texture: "textures/basket.jpg" }
+//! [2]
+//! [3]
+ transform: [
+ Scale3D { scale: 1.5 },
+ Rotation3D {
+ axis: Qt.vector3d(0, 1, 0)
+ NumberAnimation on angle {
+ running: true
+ loops: Animation.Infinite
+ from: 0
+ to: 360
+ duration: 2000
+ }
+ }
+ ]
+ }
+}
+//! [3]
diff --git a/demos/declarative/button.qml b/demos/declarative/button.qml
new file mode 100644
index 000000000..8e00b9762
--- /dev/null
+++ b/demos/declarative/button.qml
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Viewport {
+ width: 640; height: 480
+
+ Item3D {
+ id: button_mesh
+ objectName: "button_mesh"
+ mesh: Mesh {
+ source: "meshes/button3d.3ds"
+ options: "ShowWarnings ForceSmooth"
+ }
+ cullFaces: "CullBackFaces"
+
+ Item3D {
+ id: top_node
+ objectName: "top_node"
+ meshNode: "Top"
+ effect: Effect { material: face_texture }
+ }
+
+ Material {
+ id: face_texture
+ objectName: "face_texture"
+ ambientColor: "#000000"
+ specularColor: "#000000"
+ shininess: 16
+ textureUrl: "textures/button/face.png"
+ }
+
+ Item3D {
+ id: side_plate_node
+ objectName: "side_plate_node"
+ meshNode: "SidePlate"
+ //effect: Effect { material: address_texture }
+ }
+
+ Material {
+ id: address_texture
+ objectName: "address_texture"
+ ambientColor: "#000000"
+ specularColor: "#000000"
+ shininess: 16
+ textureUrl: "textures/button/full-address.png"
+ }
+
+ Light {
+ id: l1
+ position: Qt.vector3d(-1, -10, 10)
+ }
+ }
+}
diff --git a/demos/declarative/cube.qml b/demos/declarative/cube.qml
new file mode 100644
index 000000000..11579dd28
--- /dev/null
+++ b/demos/declarative/cube.qml
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+import Qt3D.Shapes 1.0
+
+Viewport {
+ width: 640; height: 480
+
+ Cube {
+ scale: 1.5
+
+ transform: Rotation3D {
+ angle: 45
+ axis: Qt.vector3d(1, 1, 1)
+ }
+
+ effect: Effect {
+ color: "#aaca00"
+ texture: "textures/qtlogo.png"
+ decal: true
+ }
+ }
+}
diff --git a/demos/declarative/forest/Tree.qml b/demos/declarative/forest/Tree.qml
new file mode 100644
index 000000000..0657d51ad
--- /dev/null
+++ b/demos/declarative/forest/Tree.qml
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//![1]
+import Qt 4.7
+import Qt3D 1.0
+
+Item3D {
+ id: tree
+ mesh: Mesh { source: "tree.obj" }
+ effect: Effect {
+ blending: true
+ texture: "tree.png"
+ }
+//![1]
+//![2]
+ transform: BillboardTransform {
+ preserveUpVector: true
+ }
+//![2]
+//![3]
+}
+//![3]
diff --git a/demos/declarative/forest/forest.qml b/demos/declarative/forest/forest.qml
new file mode 100644
index 000000000..8b0fd545a
--- /dev/null
+++ b/demos/declarative/forest/forest.qml
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//![1]
+import Qt 4.7
+import Qt3D 1.0
+
+Viewport {
+ id: viewport
+ width: 640; height: 480
+ picking: false
+
+ camera: Camera {
+ eye: Qt.vector3d(0, 4, 12)
+ }
+
+ Item3D {
+ id: ground
+ mesh: Mesh { source: "ground.obj" }
+ effect: Effect {
+ color: "#604000"
+ useLighting: false
+ }
+ }
+
+ Item3D {
+ sortChildren: Item3D.BackToFront
+
+ Tree { position: Qt.vector3d(-1.5, 0, -1) }
+ Tree { position: Qt.vector3d(-0.5, 0, -1) }
+ Tree { position: Qt.vector3d(0.5, 0, -1) }
+ Tree { position: Qt.vector3d(1.5, 0, -1) }
+
+ Tree { position: Qt.vector3d(0, 0, 0) }
+ Tree { position: Qt.vector3d(-1, 0, 0) }
+ Tree { position: Qt.vector3d(1, 0, 0) }
+
+ Tree { position: Qt.vector3d(-1.5, 0, 1) }
+ Tree { position: Qt.vector3d(-0.5, 0, 1) }
+ Tree { position: Qt.vector3d(0.5, 0, 1) }
+ Tree { position: Qt.vector3d(1.5, 0, 1) }
+ }
+}
+//![1]
diff --git a/demos/declarative/forest/forest.qmlproject b/demos/declarative/forest/forest.qmlproject
new file mode 100644
index 000000000..d4909f868
--- /dev/null
+++ b/demos/declarative/forest/forest.qmlproject
@@ -0,0 +1,16 @@
+import QmlProject 1.0
+
+Project {
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+ /* List of plugin directories passed to QML runtime */
+ // importPaths: [ " ../exampleplugin " ]
+}
diff --git a/demos/declarative/forest/ground.obj b/demos/declarative/forest/ground.obj
new file mode 100644
index 000000000..d13a931a2
--- /dev/null
+++ b/demos/declarative/forest/ground.obj
@@ -0,0 +1,11 @@
+s 0
+v -3.0 0.0 3.0
+v 3.0 0.0 3.0
+v 3.0 0.0 -3.0
+v -3.0 0.0 -3.0
+vt 0.0 0.0
+vt 1.0 0.0
+vt 1.0 1.0
+vt 0.0 1.0
+vn 0.0 1.0 0.0
+f 1/1/1 2/2/1 3/3/1 4/4/1
diff --git a/demos/declarative/forest/tree.obj b/demos/declarative/forest/tree.obj
new file mode 100644
index 000000000..6dd72d7b9
--- /dev/null
+++ b/demos/declarative/forest/tree.obj
@@ -0,0 +1,11 @@
+s 0
+v -0.5 0.0 0.0
+v 0.5 0.0 0.0
+v 0.5 1.0 0.0
+v -0.5 1.0 0.0
+vt 0.0 0.0
+vt 1.0 0.0
+vt 1.0 1.0
+vt 0.0 1.0
+vn 0.0 0.0 1.0
+f 1/1/1 2/2/1 3/3/1 4/4/1
diff --git a/demos/declarative/forest/tree.png b/demos/declarative/forest/tree.png
new file mode 100644
index 000000000..c6a27748f
--- /dev/null
+++ b/demos/declarative/forest/tree.png
Binary files differ
diff --git a/demos/declarative/matrix-animation.qml b/demos/declarative/matrix-animation.qml
new file mode 100644
index 000000000..78bd71d22
--- /dev/null
+++ b/demos/declarative/matrix-animation.qml
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Viewport {
+ width: 640; height: 480
+ id: viewPort
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: program.scalex = 2.5 - program.scalex
+ }
+
+ Item3D {
+ mesh: Mesh { source: "meshes/teapot.bez" }
+ effect: program
+
+
+ transform: Rotation3D {
+ NumberAnimation on angle{
+ running: true
+ loops: Animation.Infinite
+ from: 0
+ to: 360
+ duration: 18000
+ }
+ axis: Qt.vector3d(1, -0.3, 0)
+ }
+
+ ShaderProgram {
+ id: program
+ property real qt_Custom : 1.0
+ property int customInt : 1
+ property color customColor : "#3333ff"
+ property real scalex : 1.0
+ property real scaley : 1.0
+ property real scalez : 1.0
+ property real translationX : 0.0
+ property real translationY : 0.0
+ property real translationZ : 0.0
+
+ property variant matrix4x4 :[
+ scalex , 0.0, 0.0, translationX,
+ 0.0, scaley, 0.0, translationY,
+ 0.0, 0.0, scalez, translationZ,
+ 0.0, 0.0, 0.0, 1.0 ]
+
+ SequentialAnimation on translationY {
+ running: true
+ loops: Animation.Infinite
+ PauseAnimation { duration: 2000 }
+ NumberAnimation { from: 1.0; to: 0.001; duration: 1500; easing.type:"OutBounce" }
+ PauseAnimation { duration: 2000 }
+ NumberAnimation { from: 0.001; to: 1.0; duration: 1500; easing.type:"OutBounce" }
+ }
+
+ SequentialAnimation on customInt {
+ running: true
+ loops: Animation.Infinite
+ PauseAnimation { duration: 2500 }
+ NumberAnimation { from: 1.0; to: 0.001; duration: 1500; easing.type:"OutBounce" }
+ PauseAnimation { duration: 2500 }
+ NumberAnimation { from: 0.001; to: 1.0; duration: 1500; easing.type:"OutBounce" }
+ }
+
+ texture: "textures/qtlogo.png"
+
+ vertexShader: "
+ attribute highp vec4 qt_Vertex;
+ attribute highp vec4 qt_MultiTexCoord0;
+ uniform mediump mat4 qt_ModelViewProjectionMatrix;
+ varying highp vec4 texCoord;
+ // uniform highp float qt_Custom;
+ uniform int customInt;
+ uniform vec2 vector;
+
+ uniform mat3 matrix3x3;
+ uniform mat4 matrix4x4;
+
+ void main(void)
+ {
+ gl_Position = qt_ModelViewProjectionMatrix *
+ (matrix4x4 * qt_Vertex);
+ texCoord = -qt_MultiTexCoord0;
+
+ }
+ "
+ fragmentShader: "
+ varying highp vec4 texCoord;
+ uniform sampler2D qt_Texture0;
+ uniform lowp vec4 customColor;
+ uniform bool customBoolean;
+
+ void main(void)
+ {
+ mediump vec4 textureColor =
+ texture2D(qt_Texture0, texCoord.st);
+ gl_FragColor = clamp(vec4(
+ customColor.rgb * (1.0 - textureColor.a) +
+ textureColor.rgb, 1.0), 0.0, 1.0);
+ }
+ "
+ }
+ }
+
+}
diff --git a/demos/declarative/meshes/basket.bez b/demos/declarative/meshes/basket.bez
new file mode 100644
index 000000000..614daf09b
--- /dev/null
+++ b/demos/declarative/meshes/basket.bez
@@ -0,0 +1,332 @@
+24
+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
+4,17,18,19,8,20,21,22,12,23,24,25,16,26,27,28
+19,29,30,31,22,32,33,34,25,35,36,37,28,38,39,40
+31,41,42,1,34,43,44,5,37,45,46,9,40,47,48,13
+13,14,15,16,49,50,51,52,53,54,55,56,57,58,59,60
+16,26,27,28,52,61,62,63,56,64,65,66,60,67,68,69
+28,38,39,40,63,70,71,72,66,73,74,75,69,76,77,78
+40,47,48,13,72,79,80,49,75,81,82,53,78,83,84,57
+57,58,59,60,85,86,87,88,89,90,91,92,93,94,95,96
+60,67,68,69,88,97,98,99,92,100,101,102,96,103,104,105
+69,76,77,78,99,106,107,108,102,109,110,111,105,112,113,114
+78,83,84,57,108,115,116,85,111,117,118,89,114,119,120,93
+204,204,204,204,207,208,209,210,211,211,211,211,212,213,214,215,4
+204,204,204,204,210,217,218,219,211,211,211,211,215,220,221,222,4
+204,204,204,204,219,224,225,226,211,211,211,211,222,227,228,229,4
+204,204,204,204,226,230,231,207,211,211,211,211,229,232,233,212,4
+212,213,214,215,234,235,236,237,238,239,240,241,242,243,244,245
+215,220,221,222,237,246,247,248,241,249,250,251,245,252,253,254
+222,227,228,229,248,255,256,257,251,258,259,260,254,261,262,263
+229,232,233,212,257,264,265,234,260,266,267,238,263,268,269,242
+270,270,270,270,279,280,281,282,275,276,277,278,271,272,273,274,4
+270,270,270,270,282,289,290,291,278,286,287,288,274,283,284,285,4
+270,270,270,270,291,298,299,300,288,295,296,297,285,292,293,294,4
+270,270,270,270,300,305,306,279,297,303,304,275,294,301,302,271,4
+306
+0.700000,0.450000,-0.000000
+0.700000,0.450000,0.392000
+0.392000,0.450000,0.700000
+0.000000,0.450000,0.700000
+0.668750,0.515625,-0.000000
+0.668750,0.515625,0.374500
+0.374500,0.515625,0.668750
+0.000000,0.515625,0.668750
+0.718750,0.515625,-0.000000
+0.718750,0.515625,0.402500
+0.402500,0.515625,0.718750
+0.000000,0.515625,0.718750
+0.750000,0.450000,-0.000000
+0.750000,0.450000,0.420000
+0.420000,0.450000,0.750000
+0.000000,0.450000,0.750000
+-0.392000,0.450000,0.700000
+-0.700000,0.450000,0.392000
+-0.700000,0.450000,-0.000000
+-0.374500,0.515625,0.668750
+-0.668750,0.515625,0.374500
+-0.668750,0.515625,-0.000000
+-0.402500,0.515625,0.718750
+-0.718750,0.515625,0.402500
+-0.718750,0.515625,-0.000000
+-0.420000,0.450000,0.750000
+-0.750000,0.450000,0.420000
+-0.750000,0.450000,-0.000000
+-0.700000,0.450000,-0.392000
+-0.392000,0.450000,-0.700000
+0.000000,0.450000,-0.700000
+-0.668750,0.515625,-0.374500
+-0.374500,0.515625,-0.668750
+0.000000,0.515625,-0.668750
+-0.718750,0.515625,-0.402500
+-0.402500,0.515625,-0.718750
+0.000000,0.515625,-0.718750
+-0.750000,0.450000,-0.420000
+-0.420000,0.450000,-0.750000
+0.000000,0.450000,-0.750000
+0.392000,0.450000,-0.700000
+0.700000,0.450000,-0.392000
+0.374500,0.515625,-0.668750
+0.668750,0.515625,-0.374500
+0.402500,0.515625,-0.718750
+0.718750,0.515625,-0.402500
+0.420000,0.450000,-0.750000
+0.750000,0.450000,-0.420000
+0.875000,0.187500,-0.000000
+0.875000,0.187500,0.490000
+0.490000,0.187500,0.875000
+0.000000,0.187500,0.875000
+1.000000,-0.075000,-0.000000
+1.000000,-0.075000,0.560000
+0.560000,-0.075000,1.000000
+0.000000,-0.075000,1.000000
+1.000000,-0.300000,-0.000000
+1.000000,-0.300000,0.560000
+0.560000,-0.300000,1.000000
+0.000000,-0.300000,1.000000
+-0.490000,0.187500,0.875000
+-0.875000,0.187500,0.490000
+-0.875000,0.187500,-0.000000
+-0.560000,-0.075000,1.000000
+-1.000000,-0.075000,0.560000
+-1.000000,-0.075000,-0.000000
+-0.560000,-0.300000,1.000000
+-1.000000,-0.300000,0.560000
+-1.000000,-0.300000,-0.000000
+-0.875000,0.187500,-0.490000
+-0.490000,0.187500,-0.875000
+0.000000,0.187500,-0.875000
+-1.000000,-0.075000,-0.560000
+-0.560000,-0.075000,-1.000000
+0.000000,-0.075000,-1.000000
+-1.000000,-0.300000,-0.560000
+-0.560000,-0.300000,-1.000000
+0.000000,-0.300000,-1.000000
+0.490000,0.187500,-0.875000
+0.875000,0.187500,-0.490000
+0.560000,-0.075000,-1.000000
+1.000000,-0.075000,-0.560000
+0.560000,-0.300000,-1.000000
+1.000000,-0.300000,-0.560000
+1.000000,-0.525000,-0.000000
+1.000000,-0.525000,0.560000
+0.560000,-0.525000,1.000000
+0.000000,-0.525000,1.000000
+0.750000,-0.637500,-0.000000
+0.750000,-0.637500,0.420000
+0.420000,-0.637500,0.750000
+0.000000,-0.637500,0.750000
+0.750000,-0.675000,-0.000000
+0.750000,-0.675000,0.420000
+0.420000,-0.675000,0.750000
+0.000000,-0.675000,0.750000
+-0.560000,-0.525000,1.000000
+-1.000000,-0.525000,0.560000
+-1.000000,-0.525000,-0.000000
+-0.420000,-0.637500,0.750000
+-0.750000,-0.637500,0.420000
+-0.750000,-0.637500,-0.000000
+-0.420000,-0.675000,0.750000
+-0.750000,-0.675000,0.420000
+-0.750000,-0.675000,-0.000000
+-1.000000,-0.525000,-0.560000
+-0.560000,-0.525000,-1.000000
+0.000000,-0.525000,-1.000000
+-0.750000,-0.637500,-0.420000
+-0.420000,-0.637500,-0.750000
+0.000000,-0.637500,-0.750000
+-0.750000,-0.675000,-0.420000
+-0.420000,-0.675000,-0.750000
+0.000000,-0.675000,-0.750000
+0.560000,-0.525000,-1.000000
+1.000000,-0.525000,-0.560000
+0.420000,-0.637500,-0.750000
+0.750000,-0.637500,-0.420000
+0.420000,-0.675000,-0.750000
+0.750000,-0.675000,-0.420000
+-0.800000,0.262500,-0.000000
+-0.800000,0.262500,0.150000
+-0.750000,0.375000,0.150000
+-0.750000,0.375000,-0.000000
+-1.150000,0.262500,-0.000000
+-1.150000,0.262500,0.150000
+-1.250000,0.375000,0.150000
+-1.250000,0.375000,-0.000000
+-1.350000,0.262500,-0.000000
+-1.350000,0.262500,0.150000
+-1.500000,0.375000,0.150000
+-1.500000,0.375000,-0.000000
+-1.350000,0.150000,-0.000000
+-1.350000,0.150000,0.150000
+-1.500000,0.150000,0.150000
+-1.500000,0.150000,-0.000000
+-0.750000,0.375000,-0.150000
+-0.800000,0.262500,-0.150000
+-1.250000,0.375000,-0.150000
+-1.150000,0.262500,-0.150000
+-1.500000,0.375000,-0.150000
+-1.350000,0.262500,-0.150000
+-1.500000,0.150000,-0.150000
+-1.350000,0.150000,-0.150000
+-1.350000,0.037500,-0.000000
+-1.350000,0.037500,0.150000
+-1.500000,-0.075000,0.150000
+-1.500000,-0.075000,-0.000000
+-1.250000,-0.187500,-0.000000
+-1.250000,-0.187500,0.150000
+-1.325000,-0.281250,0.150000
+-1.325000,-0.281250,-0.000000
+-1.000000,-0.300000,0.150000
+-0.950000,-0.450000,0.150000
+-0.950000,-0.450000,-0.000000
+-1.500000,-0.075000,-0.150000
+-1.350000,0.037500,-0.150000
+-1.325000,-0.281250,-0.150000
+-1.250000,-0.187500,-0.150000
+-0.950000,-0.450000,-0.150000
+-1.000000,-0.300000,-0.150000
+0.850000,-0.037500,-0.000000
+0.850000,-0.037500,0.330000
+0.850000,-0.450000,0.330000
+0.850000,-0.450000,-0.000000
+1.300000,-0.037500,-0.000000
+1.300000,-0.037500,0.330000
+1.550000,-0.337500,0.330000
+1.550000,-0.337500,-0.000000
+1.150000,0.300000,-0.000000
+1.150000,0.300000,0.125000
+1.200000,0.262500,0.125000
+1.200000,0.262500,-0.000000
+1.350000,0.450000,-0.000000
+1.350000,0.450000,0.125000
+1.650000,0.450000,0.125000
+1.650000,0.450000,-0.000000
+0.850000,-0.450000,-0.330000
+0.850000,-0.037500,-0.330000
+1.550000,-0.337500,-0.330000
+1.300000,-0.037500,-0.330000
+1.200000,0.262500,-0.125000
+1.150000,0.300000,-0.125000
+1.650000,0.450000,-0.125000
+1.350000,0.450000,-0.125000
+1.400000,0.487500,-0.000000
+1.400000,0.487500,0.125000
+1.762500,0.496875,0.125000
+1.762500,0.496875,-0.000000
+1.450000,0.487500,-0.000000
+1.450000,0.487500,0.075000
+1.725000,0.506250,0.075000
+1.725000,0.506250,-0.000000
+1.400000,0.450000,-0.000000
+1.400000,0.450000,0.075000
+1.600000,0.450000,0.075000
+1.600000,0.450000,-0.000000
+1.762500,0.496875,-0.125000
+1.400000,0.487500,-0.125000
+1.725000,0.506250,-0.075000
+1.450000,0.487500,-0.075000
+1.600000,0.450000,-0.075000
+1.400000,0.450000,-0.075000
+0.000000,0.825000,-0.000000
+0.000000,0.825000,0.001000
+0.001000,0.825000,-0.000000
+0.400000,0.825000,-0.000000
+0.400000,0.825000,0.225000
+0.225000,0.825000,0.400000
+0.000000,0.825000,0.400000
+0.000000,0.675000,-0.000000
+0.100000,0.600000,-0.000000
+0.100000,0.600000,0.056000
+0.056000,0.600000,0.100000
+0.000000,0.600000,0.100000
+-0.001000,0.825000,-0.000000
+-0.225000,0.825000,0.400000
+-0.400000,0.825000,0.225000
+-0.400000,0.825000,-0.000000
+-0.056000,0.600000,0.100000
+-0.100000,0.600000,0.056000
+-0.100000,0.600000,-0.000000
+0.000000,0.825000,-0.001000
+-0.400000,0.825000,-0.225000
+-0.225000,0.825000,-0.400000
+0.000000,0.825000,-0.400000
+-0.100000,0.600000,-0.056000
+-0.056000,0.600000,-0.100000
+0.000000,0.600000,-0.100000
+0.225000,0.825000,-0.400000
+0.400000,0.825000,-0.225000
+0.056000,0.600000,-0.100000
+0.100000,0.600000,-0.056000
+0.200000,0.525000,-0.000000
+0.200000,0.525000,0.112000
+0.112000,0.525000,0.200000
+0.000000,0.525000,0.200000
+0.650000,0.525000,-0.000000
+0.650000,0.525000,0.364000
+0.364000,0.525000,0.650000
+0.000000,0.525000,0.650000
+0.650000,0.450000,-0.000000
+0.650000,0.450000,0.364000
+0.364000,0.450000,0.650000
+0.000000,0.450000,0.650000
+-0.112000,0.525000,0.200000
+-0.200000,0.525000,0.112000
+-0.200000,0.525000,-0.000000
+-0.364000,0.525000,0.650000
+-0.650000,0.525000,0.364000
+-0.650000,0.525000,-0.000000
+-0.364000,0.450000,0.650000
+-0.650000,0.450000,0.364000
+-0.650000,0.450000,-0.000000
+-0.200000,0.525000,-0.112000
+-0.112000,0.525000,-0.200000
+0.000000,0.525000,-0.200000
+-0.650000,0.525000,-0.364000
+-0.364000,0.525000,-0.650000
+0.000000,0.525000,-0.650000
+-0.650000,0.450000,-0.364000
+-0.364000,0.450000,-0.650000
+0.000000,0.450000,-0.650000
+0.112000,0.525000,-0.200000
+0.200000,0.525000,-0.112000
+0.364000,0.525000,-0.650000
+0.650000,0.525000,-0.364000
+0.364000,0.450000,-0.650000
+0.650000,0.450000,-0.364000
+0.000000,-0.750000,-0.000000
+0.750000,-0.675000,-0.000000
+0.750000,-0.675000,-0.420000
+0.420000,-0.675000,-0.750000
+0.000000,-0.675000,-0.750000
+0.750000,-0.712500,-0.000000
+0.750000,-0.712500,-0.420000
+0.420000,-0.712500,-0.750000
+0.000000,-0.712500,-0.750000
+0.712500,-0.750000,-0.000000
+0.712500,-0.750000,-0.399000
+0.399000,-0.750000,-0.712500
+0.000000,-0.750000,-0.712500
+-0.420000,-0.675000,-0.750000
+-0.750000,-0.675000,-0.420000
+-0.750000,-0.675000,-0.000000
+-0.420000,-0.712500,-0.750000
+-0.750000,-0.712500,-0.420000
+-0.750000,-0.712500,-0.000000
+-0.399000,-0.750000,-0.712500
+-0.712500,-0.750000,-0.399000
+-0.712500,-0.750000,-0.000000
+-0.750000,-0.675000,0.420000
+-0.420000,-0.675000,0.750000
+0.000000,-0.675000,0.750000
+-0.750000,-0.712500,0.420000
+-0.420000,-0.712500,0.750000
+0.000000,-0.712500,0.750000
+-0.712500,-0.750000,0.399000
+-0.399000,-0.750000,0.712500
+0.000000,-0.750000,0.712500
+0.420000,-0.675000,0.750000
+0.750000,-0.675000,0.420000
+0.420000,-0.712500,0.750000
+0.750000,-0.712500,0.420000
+0.399000,-0.750000,0.712500
+0.712500,-0.750000,0.399000
diff --git a/demos/declarative/meshes/button3d.3ds b/demos/declarative/meshes/button3d.3ds
new file mode 100644
index 000000000..a84933f43
--- /dev/null
+++ b/demos/declarative/meshes/button3d.3ds
Binary files differ
diff --git a/demos/declarative/meshes/face.png b/demos/declarative/meshes/face.png
new file mode 100644
index 000000000..327c88423
--- /dev/null
+++ b/demos/declarative/meshes/face.png
Binary files differ
diff --git a/demos/declarative/meshes/full-address b/demos/declarative/meshes/full-address
new file mode 100644
index 000000000..8c83ac062
--- /dev/null
+++ b/demos/declarative/meshes/full-address
Binary files differ
diff --git a/demos/declarative/meshes/photopane.obj b/demos/declarative/meshes/photopane.obj
new file mode 100644
index 000000000..1f5e91dfd
--- /dev/null
+++ b/demos/declarative/meshes/photopane.obj
@@ -0,0 +1,11 @@
+s 0
+v -2 -1.5 0.0
+v 2 -1.5 0.0
+v 2 1.5 0.0
+v -2 1.5 0.0
+vt 0.0 0.0
+vt 1.0 0.0
+vt 1.0 1.0
+vt 0.0 1.0
+vn 0.0 0.0 1.0
+f 1/1/1 2/2/1 3/3/1 4/4/1
diff --git a/demos/declarative/meshes/teapot.bez b/demos/declarative/meshes/teapot.bez
new file mode 100644
index 000000000..02b2ac447
--- /dev/null
+++ b/demos/declarative/meshes/teapot.bez
@@ -0,0 +1,340 @@
+32
+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
+4,17,18,19,8,20,21,22,12,23,24,25,16,26,27,28
+19,29,30,31,22,32,33,34,25,35,36,37,28,38,39,40
+31,41,42,1,34,43,44,5,37,45,46,9,40,47,48,13
+13,14,15,16,49,50,51,52,53,54,55,56,57,58,59,60
+16,26,27,28,52,61,62,63,56,64,65,66,60,67,68,69
+28,38,39,40,63,70,71,72,66,73,74,75,69,76,77,78
+40,47,48,13,72,79,80,49,75,81,82,53,78,83,84,57
+57,58,59,60,85,86,87,88,89,90,91,92,93,94,95,96
+60,67,68,69,88,97,98,99,92,100,101,102,96,103,104,105
+69,76,77,78,99,106,107,108,102,109,110,111,105,112,113,114
+78,83,84,57,108,115,116,85,111,117,118,89,114,119,120,93
+121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136
+124,137,138,121,128,139,140,125,132,141,142,129,136,143,144,133
+133,134,135,136,145,146,147,148,149,150,151,152,69,153,154,155
+136,143,144,133,148,156,157,145,152,158,159,149,155,160,161,69
+162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177
+165,178,179,162,169,180,181,166,173,182,183,170,177,184,185,174
+174,175,176,177,186,187,188,189,190,191,192,193,194,195,196,197
+177,184,185,174,189,198,199,186,193,200,201,190,197,202,203,194
+204,204,204,204,207,208,209,210,211,211,211,211,212,213,214,215,4
+204,204,204,204,210,217,218,219,211,211,211,211,215,220,221,222,4
+204,204,204,204,219,224,225,226,211,211,211,211,222,227,228,229,4
+204,204,204,204,226,230,231,207,211,211,211,211,229,232,233,212,4
+212,213,214,215,234,235,236,237,238,239,240,241,242,243,244,245
+215,220,221,222,237,246,247,248,241,249,250,251,245,252,253,254
+222,227,228,229,248,255,256,257,251,258,259,260,254,261,262,263
+229,232,233,212,257,264,265,234,260,266,267,238,263,268,269,242
+270,270,270,270,279,280,281,282,275,276,277,278,271,272,273,274,4
+270,270,270,270,282,289,290,291,278,286,287,288,274,283,284,285,4
+270,270,270,270,291,298,299,300,288,295,296,297,285,292,293,294,4
+270,270,270,270,300,305,306,279,297,303,304,275,294,301,302,271,4
+306
+0.700000,0.450000,-0.000000
+0.700000,0.450000,0.392000
+0.392000,0.450000,0.700000
+0.000000,0.450000,0.700000
+0.668750,0.515625,-0.000000
+0.668750,0.515625,0.374500
+0.374500,0.515625,0.668750
+0.000000,0.515625,0.668750
+0.718750,0.515625,-0.000000
+0.718750,0.515625,0.402500
+0.402500,0.515625,0.718750
+0.000000,0.515625,0.718750
+0.750000,0.450000,-0.000000
+0.750000,0.450000,0.420000
+0.420000,0.450000,0.750000
+0.000000,0.450000,0.750000
+-0.392000,0.450000,0.700000
+-0.700000,0.450000,0.392000
+-0.700000,0.450000,-0.000000
+-0.374500,0.515625,0.668750
+-0.668750,0.515625,0.374500
+-0.668750,0.515625,-0.000000
+-0.402500,0.515625,0.718750
+-0.718750,0.515625,0.402500
+-0.718750,0.515625,-0.000000
+-0.420000,0.450000,0.750000
+-0.750000,0.450000,0.420000
+-0.750000,0.450000,-0.000000
+-0.700000,0.450000,-0.392000
+-0.392000,0.450000,-0.700000
+0.000000,0.450000,-0.700000
+-0.668750,0.515625,-0.374500
+-0.374500,0.515625,-0.668750
+0.000000,0.515625,-0.668750
+-0.718750,0.515625,-0.402500
+-0.402500,0.515625,-0.718750
+0.000000,0.515625,-0.718750
+-0.750000,0.450000,-0.420000
+-0.420000,0.450000,-0.750000
+0.000000,0.450000,-0.750000
+0.392000,0.450000,-0.700000
+0.700000,0.450000,-0.392000
+0.374500,0.515625,-0.668750
+0.668750,0.515625,-0.374500
+0.402500,0.515625,-0.718750
+0.718750,0.515625,-0.402500
+0.420000,0.450000,-0.750000
+0.750000,0.450000,-0.420000
+0.875000,0.187500,-0.000000
+0.875000,0.187500,0.490000
+0.490000,0.187500,0.875000
+0.000000,0.187500,0.875000
+1.000000,-0.075000,-0.000000
+1.000000,-0.075000,0.560000
+0.560000,-0.075000,1.000000
+0.000000,-0.075000,1.000000
+1.000000,-0.300000,-0.000000
+1.000000,-0.300000,0.560000
+0.560000,-0.300000,1.000000
+0.000000,-0.300000,1.000000
+-0.490000,0.187500,0.875000
+-0.875000,0.187500,0.490000
+-0.875000,0.187500,-0.000000
+-0.560000,-0.075000,1.000000
+-1.000000,-0.075000,0.560000
+-1.000000,-0.075000,-0.000000
+-0.560000,-0.300000,1.000000
+-1.000000,-0.300000,0.560000
+-1.000000,-0.300000,-0.000000
+-0.875000,0.187500,-0.490000
+-0.490000,0.187500,-0.875000
+0.000000,0.187500,-0.875000
+-1.000000,-0.075000,-0.560000
+-0.560000,-0.075000,-1.000000
+0.000000,-0.075000,-1.000000
+-1.000000,-0.300000,-0.560000
+-0.560000,-0.300000,-1.000000
+0.000000,-0.300000,-1.000000
+0.490000,0.187500,-0.875000
+0.875000,0.187500,-0.490000
+0.560000,-0.075000,-1.000000
+1.000000,-0.075000,-0.560000
+0.560000,-0.300000,-1.000000
+1.000000,-0.300000,-0.560000
+1.000000,-0.525000,-0.000000
+1.000000,-0.525000,0.560000
+0.560000,-0.525000,1.000000
+0.000000,-0.525000,1.000000
+0.750000,-0.637500,-0.000000
+0.750000,-0.637500,0.420000
+0.420000,-0.637500,0.750000
+0.000000,-0.637500,0.750000
+0.750000,-0.675000,-0.000000
+0.750000,-0.675000,0.420000
+0.420000,-0.675000,0.750000
+0.000000,-0.675000,0.750000
+-0.560000,-0.525000,1.000000
+-1.000000,-0.525000,0.560000
+-1.000000,-0.525000,-0.000000
+-0.420000,-0.637500,0.750000
+-0.750000,-0.637500,0.420000
+-0.750000,-0.637500,-0.000000
+-0.420000,-0.675000,0.750000
+-0.750000,-0.675000,0.420000
+-0.750000,-0.675000,-0.000000
+-1.000000,-0.525000,-0.560000
+-0.560000,-0.525000,-1.000000
+0.000000,-0.525000,-1.000000
+-0.750000,-0.637500,-0.420000
+-0.420000,-0.637500,-0.750000
+0.000000,-0.637500,-0.750000
+-0.750000,-0.675000,-0.420000
+-0.420000,-0.675000,-0.750000
+0.000000,-0.675000,-0.750000
+0.560000,-0.525000,-1.000000
+1.000000,-0.525000,-0.560000
+0.420000,-0.637500,-0.750000
+0.750000,-0.637500,-0.420000
+0.420000,-0.675000,-0.750000
+0.750000,-0.675000,-0.420000
+-0.800000,0.262500,-0.000000
+-0.800000,0.262500,0.150000
+-0.750000,0.375000,0.150000
+-0.750000,0.375000,-0.000000
+-1.150000,0.262500,-0.000000
+-1.150000,0.262500,0.150000
+-1.250000,0.375000,0.150000
+-1.250000,0.375000,-0.000000
+-1.350000,0.262500,-0.000000
+-1.350000,0.262500,0.150000
+-1.500000,0.375000,0.150000
+-1.500000,0.375000,-0.000000
+-1.350000,0.150000,-0.000000
+-1.350000,0.150000,0.150000
+-1.500000,0.150000,0.150000
+-1.500000,0.150000,-0.000000
+-0.750000,0.375000,-0.150000
+-0.800000,0.262500,-0.150000
+-1.250000,0.375000,-0.150000
+-1.150000,0.262500,-0.150000
+-1.500000,0.375000,-0.150000
+-1.350000,0.262500,-0.150000
+-1.500000,0.150000,-0.150000
+-1.350000,0.150000,-0.150000
+-1.350000,0.037500,-0.000000
+-1.350000,0.037500,0.150000
+-1.500000,-0.075000,0.150000
+-1.500000,-0.075000,-0.000000
+-1.250000,-0.187500,-0.000000
+-1.250000,-0.187500,0.150000
+-1.325000,-0.281250,0.150000
+-1.325000,-0.281250,-0.000000
+-1.000000,-0.300000,0.150000
+-0.950000,-0.450000,0.150000
+-0.950000,-0.450000,-0.000000
+-1.500000,-0.075000,-0.150000
+-1.350000,0.037500,-0.150000
+-1.325000,-0.281250,-0.150000
+-1.250000,-0.187500,-0.150000
+-0.950000,-0.450000,-0.150000
+-1.000000,-0.300000,-0.150000
+0.850000,-0.037500,-0.000000
+0.850000,-0.037500,0.330000
+0.850000,-0.450000,0.330000
+0.850000,-0.450000,-0.000000
+1.300000,-0.037500,-0.000000
+1.300000,-0.037500,0.330000
+1.550000,-0.337500,0.330000
+1.550000,-0.337500,-0.000000
+1.150000,0.300000,-0.000000
+1.150000,0.300000,0.125000
+1.200000,0.262500,0.125000
+1.200000,0.262500,-0.000000
+1.350000,0.450000,-0.000000
+1.350000,0.450000,0.125000
+1.650000,0.450000,0.125000
+1.650000,0.450000,-0.000000
+0.850000,-0.450000,-0.330000
+0.850000,-0.037500,-0.330000
+1.550000,-0.337500,-0.330000
+1.300000,-0.037500,-0.330000
+1.200000,0.262500,-0.125000
+1.150000,0.300000,-0.125000
+1.650000,0.450000,-0.125000
+1.350000,0.450000,-0.125000
+1.400000,0.487500,-0.000000
+1.400000,0.487500,0.125000
+1.762500,0.496875,0.125000
+1.762500,0.496875,-0.000000
+1.450000,0.487500,-0.000000
+1.450000,0.487500,0.075000
+1.725000,0.506250,0.075000
+1.725000,0.506250,-0.000000
+1.400000,0.450000,-0.000000
+1.400000,0.450000,0.075000
+1.600000,0.450000,0.075000
+1.600000,0.450000,-0.000000
+1.762500,0.496875,-0.125000
+1.400000,0.487500,-0.125000
+1.725000,0.506250,-0.075000
+1.450000,0.487500,-0.075000
+1.600000,0.450000,-0.075000
+1.400000,0.450000,-0.075000
+0.000000,0.825000,-0.000000
+0.000000,0.825000,0.001000
+0.001000,0.825000,-0.000000
+0.400000,0.825000,-0.000000
+0.400000,0.825000,0.225000
+0.225000,0.825000,0.400000
+0.000000,0.825000,0.400000
+0.000000,0.675000,-0.000000
+0.100000,0.600000,-0.000000
+0.100000,0.600000,0.056000
+0.056000,0.600000,0.100000
+0.000000,0.600000,0.100000
+-0.001000,0.825000,-0.000000
+-0.225000,0.825000,0.400000
+-0.400000,0.825000,0.225000
+-0.400000,0.825000,-0.000000
+-0.056000,0.600000,0.100000
+-0.100000,0.600000,0.056000
+-0.100000,0.600000,-0.000000
+0.000000,0.825000,-0.001000
+-0.400000,0.825000,-0.225000
+-0.225000,0.825000,-0.400000
+0.000000,0.825000,-0.400000
+-0.100000,0.600000,-0.056000
+-0.056000,0.600000,-0.100000
+0.000000,0.600000,-0.100000
+0.225000,0.825000,-0.400000
+0.400000,0.825000,-0.225000
+0.056000,0.600000,-0.100000
+0.100000,0.600000,-0.056000
+0.200000,0.525000,-0.000000
+0.200000,0.525000,0.112000
+0.112000,0.525000,0.200000
+0.000000,0.525000,0.200000
+0.650000,0.525000,-0.000000
+0.650000,0.525000,0.364000
+0.364000,0.525000,0.650000
+0.000000,0.525000,0.650000
+0.650000,0.450000,-0.000000
+0.650000,0.450000,0.364000
+0.364000,0.450000,0.650000
+0.000000,0.450000,0.650000
+-0.112000,0.525000,0.200000
+-0.200000,0.525000,0.112000
+-0.200000,0.525000,-0.000000
+-0.364000,0.525000,0.650000
+-0.650000,0.525000,0.364000
+-0.650000,0.525000,-0.000000
+-0.364000,0.450000,0.650000
+-0.650000,0.450000,0.364000
+-0.650000,0.450000,-0.000000
+-0.200000,0.525000,-0.112000
+-0.112000,0.525000,-0.200000
+0.000000,0.525000,-0.200000
+-0.650000,0.525000,-0.364000
+-0.364000,0.525000,-0.650000
+0.000000,0.525000,-0.650000
+-0.650000,0.450000,-0.364000
+-0.364000,0.450000,-0.650000
+0.000000,0.450000,-0.650000
+0.112000,0.525000,-0.200000
+0.200000,0.525000,-0.112000
+0.364000,0.525000,-0.650000
+0.650000,0.525000,-0.364000
+0.364000,0.450000,-0.650000
+0.650000,0.450000,-0.364000
+0.000000,-0.750000,-0.000000
+0.750000,-0.675000,-0.000000
+0.750000,-0.675000,-0.420000
+0.420000,-0.675000,-0.750000
+0.000000,-0.675000,-0.750000
+0.750000,-0.712500,-0.000000
+0.750000,-0.712500,-0.420000
+0.420000,-0.712500,-0.750000
+0.000000,-0.712500,-0.750000
+0.712500,-0.750000,-0.000000
+0.712500,-0.750000,-0.399000
+0.399000,-0.750000,-0.712500
+0.000000,-0.750000,-0.712500
+-0.420000,-0.675000,-0.750000
+-0.750000,-0.675000,-0.420000
+-0.750000,-0.675000,-0.000000
+-0.420000,-0.712500,-0.750000
+-0.750000,-0.712500,-0.420000
+-0.750000,-0.712500,-0.000000
+-0.399000,-0.750000,-0.712500
+-0.712500,-0.750000,-0.399000
+-0.712500,-0.750000,-0.000000
+-0.750000,-0.675000,0.420000
+-0.420000,-0.675000,0.750000
+0.000000,-0.675000,0.750000
+-0.750000,-0.712500,0.420000
+-0.420000,-0.712500,0.750000
+0.000000,-0.712500,0.750000
+-0.712500,-0.750000,0.399000
+-0.399000,-0.750000,0.712500
+0.000000,-0.750000,0.712500
+0.420000,-0.675000,0.750000
+0.750000,-0.675000,0.420000
+0.420000,-0.712500,0.750000
+0.750000,-0.712500,0.420000
+0.399000,-0.750000,0.712500
+0.712500,-0.750000,0.399000
diff --git a/demos/declarative/modelViewer/FourButtons.qml b/demos/declarative/modelViewer/FourButtons.qml
new file mode 100644
index 000000000..dfc4a8409
--- /dev/null
+++ b/demos/declarative/modelViewer/FourButtons.qml
@@ -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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+
+Item {
+
+ anchors.left : parent.left
+ anchors.leftMargin: 40
+ width: 750
+ height: 51
+
+
+ ShortButton {
+ id: button1
+ //anchors.left:
+ //anchors.verticalCenter: parent.verticalCenter
+ }
+ ShortButton {
+ id: button2
+ anchors.left: button1.right
+ //anchors.leftMargin: 3
+ //anchors.verticalCenter: parent.verticalCenter
+ }
+ ShortButton {
+ id: button3
+ anchors.left: button2.right
+ //anchors.leftMargin: 3
+ //anchors.verticalCenter: parent.verticalCenter
+ }
+ ShortButton {
+ id: button4
+ anchors.left: button3.right
+ //anchors.leftMargin: 3
+ //anchors.verticalCenter: parent.verticalCenter
+ }
+}
diff --git a/demos/declarative/modelViewer/LongButton.qml b/demos/declarative/modelViewer/LongButton.qml
new file mode 100644
index 000000000..f06c1bf31
--- /dev/null
+++ b/demos/declarative/modelViewer/LongButton.qml
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+
+Rectangle {
+ id: button
+ anchors.left : parent.left
+ anchors.leftMargin: 40
+ gradient: Gradient {
+ GradientStop { position: 1.0; color: "black" }
+ GradientStop { position: 0.0; color: "gray" }
+ }
+ border.color : "gray"
+ border.width : 1
+ radius: 10
+ width: 610
+ height: 51
+ property bool bounce: false
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: { button.bounce = true; console.log("Clicked") }
+ }
+
+ SequentialAnimation on scale{
+ running: button.bounce
+ NumberAnimation { to : 0.98; duration: 300; easing.type: "OutQuad" }
+ NumberAnimation { to : 1.0; duration: 300; easing.type: "OutBounce" }
+ onCompleted: button.bounce = false
+ }
+}
diff --git a/demos/declarative/modelViewer/MainButton.qml b/demos/declarative/modelViewer/MainButton.qml
new file mode 100644
index 000000000..6f5cf0d0e
--- /dev/null
+++ b/demos/declarative/modelViewer/MainButton.qml
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Image {
+ id: mainbutton
+
+ source: imageSource
+
+ width: 100
+ height: 100
+ property bool bounce: false
+ property string imageSource: "images/cog.svg"
+
+ anchors.right: parent.right
+ anchors.rightMargin: 10
+ anchors.topMargin: 20
+
+
+ SequentialAnimation on scale{
+ running: mainbutton.bounce
+ NumberAnimation { to : 0.8; duration: 50; easing.type: "OutQuad" }
+ NumberAnimation { to : 1.0; duration: 50; easing.type: "OutBounce" }
+
+ onCompleted: mainbutton.bounce = false
+ }
+}
diff --git a/demos/declarative/modelViewer/ShortButton.qml b/demos/declarative/modelViewer/ShortButton.qml
new file mode 100644
index 000000000..665840bb1
--- /dev/null
+++ b/demos/declarative/modelViewer/ShortButton.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+
+Rectangle {
+ id: button
+
+ gradient: Gradient {
+ GradientStop { position: 1.0; color: "black" }
+ GradientStop { position: 0.0; color: "gray" }
+ }
+ border.color : "gray"
+ border.width : 1
+ radius: 10
+ width: 150
+ height: 51
+ property bool bounce: false
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: { button.bounce = true; console.log("Clicked") }
+ }
+
+ SequentialAnimation on scale{
+ running: button.bounce
+ NumberAnimation { to : 0.98; duration: 300; easing.type: "OutQuad" }
+ NumberAnimation { to : 1.0; duration: 300; easing.type: "OutBounce" }
+
+ onCompleted: button.bounce = false
+ }
+
+ anchors.leftMargin: 3
+}
diff --git a/demos/declarative/modelViewer/images/arrow.png b/demos/declarative/modelViewer/images/arrow.png
new file mode 100644
index 000000000..0ea53c179
--- /dev/null
+++ b/demos/declarative/modelViewer/images/arrow.png
Binary files differ
diff --git a/demos/declarative/modelViewer/images/arrow.svg b/demos/declarative/modelViewer/images/arrow.svg
new file mode 100644
index 000000000..6665e81dc
--- /dev/null
+++ b/demos/declarative/modelViewer/images/arrow.svg
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="100"
+ height="100"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47+devel r9541"
+ sodipodi:docname="arrow.svg">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.979899"
+ inkscape:cx="36.315176"
+ inkscape:cy="49.177003"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1348"
+ inkscape:window-height="684"
+ inkscape:window-x="177"
+ inkscape:window-y="346"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-952.36218)">
+ <rect
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="rect2993"
+ width="100"
+ height="100"
+ x="0.16797371"
+ y="952.60327"
+ rx="15"
+ ry="15" />
+ <image
+ y="970.86469"
+ x="14.027932"
+ id="image4316"
+ xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAE0AAABACAYAAABfl/puAAAABHNCSVQICAgIfAhkiAAABMxJREFU eJzt3E9MI1UcB/DvvE63zBRIydRiCIfFg1E5cMAQEmLyAuUABAH/nMzqxWyiiXL1oKd116PJHoye PKmHNcsfkWAo8kw8woUEVAIMB08wBFYYbDvlPQ9QRISWTqfTfW2/pzm89+aXT3+vM520DUCyDAwM vNja2hra3t4+LFcNpFwndhNKaVhRlO/C4fAPlNLnylWHVGg4rddwHKcjHA5/Xy442dAAAN3d3cQw jBfKBSclWlNTE8bGxrRywUmJBvwP7hGl9Fm/zi0tGnAKNzIyomma9lJ9ff3nlNIGP84rNRoAGIaB oaGhukAg8Go4HP7CDzjp0QCgra0No6Ojuqqqr/kBVxFogL9wFYMG+AcnG1o9gDpd168d4AecbGjP cM71SCSSc1Cp4WRDu3FKCVexaEDp4CoaDSgNXMWjAf/CEUJeb2ho+IhSGihmvapAA07hent76xzH Gdc07cNi4KoGDQA6OjqUvr4+TQhxrxg4FQAopbcBNHpZYInyvBBCcTuZEILOzk4CQFtYWLinaRoo pQ8ZYyeFrKNSSm/ruv4r57zJbTE+hhBCQoeHh2hubna7QNFwKoBGznnT8PCwHo1GXRXiVyzLgmEY aG5uhhACiuKu6YqFU7MH0WjU9avnV2Kx2PmxW7BsioGrqgvB5WThCr04VDUa4A6u6tGAwuFqaGe5 DKfr+t1rx/pZ2NOeLFxPT48mhPg0Ho/Hrxznd2FPewgh6OrqIu3t7Q3BYPCbq+CkQ3McB0KIkp4j FAqhv78/2N7e3nQVnHRowWCw6Hu0myQXnHRofuY6uBpanoRCIcTj8aBhGJFAIPAZpTSs5p9W3eGc Y2VlJbmzs5PMZDJfAziudVqOcM6xtLSUTCQSyUwm8zHn/CvGmKh12jVxHAdLS0upxcXFLNiX2Q/z NbQrkkqlMD8/76ysrNiZTOaTsw47f/pRQ7uULNjq6uo+5/wO53yeMfafG8Ma2oVcBHMc561EIpG4 alztQnCWm4IBtU4DcAo2Nzf3ZG1t7fjk5OTtXGBADe0cbHV19TCdTr/DGPs535yq3p5uwADJOo1z DkK8eZ0PDg6QSCQO19fXCwIDLqBZluVJMaWMZVloaWlBvu+n5cv+/j4mJib+3tnZ+TOdTr/HGPul kPkqgL8URfljbm6uAUBpH1QVnwjn3BgfHye3bt1ytUAWbG9v7/dkMvkGY2yr0DVUxtg2pfQVSPD+ pmnau7quPxBC1LmZfxHMtm1XYMDZ9mSM2W4m+53BwcGk2weQXoEBEnSXF/ESDKgCNK/BAMluOQrN 3t4epqamPAUDKhjNNE3Mzs6mj4+Pf7Nt+02vwADJtichpFFVVZHvYmCaJqanpx3O+U+2bQ95CQZI 1mmKorwci8XUXPdoWbBAIDBrWdYdxpjnfxAgVacBCObqMj/AAPnQro1pmpiamkoSQn4sJRgg2fa8 LqZpYnJy8jiTyTw+ODh4v5RgQAV02kUw27ZLDgZI3Gmcc2xubmJmZsZXMEBSNM45lpeXwRhLKYry yLbtD/wCAyTcnkIILC8vY3FxMaVp2v2jo6O7foIBEnba1taWurGxkdJ1/b5lWQ8K/bWJF5Gq04QQ IpVKnZQTDJCs0zjnDyORyLe7u7uPywUGAP8AGpq/aU97o64AAAAASUVORK5CYII= "
+ height="64"
+ width="77"
+ style="opacity:0.75" />
+ </g>
+</svg>
diff --git a/demos/declarative/modelViewer/images/cog.svg b/demos/declarative/modelViewer/images/cog.svg
new file mode 100644
index 000000000..e8a993d31
--- /dev/null
+++ b/demos/declarative/modelViewer/images/cog.svg
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="100"
+ height="100"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47+devel r9541"
+ sodipodi:docname="cog.svg">
+ <defs
+ id="defs4">
+ <filter
+ id="filter6134"
+ inkscape:label="Jam spread"
+ inkscape:menu="Textures"
+ inkscape:menu-tooltip="Glossy clumpy jam spread"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ id="feGaussianBlur6136"
+ stdDeviation="1"
+ in="SourceGraphic"
+ result="result0" />
+ <feTurbulence
+ id="feTurbulence6138"
+ result="result1"
+ numOctaves="7"
+ seed="488"
+ baseFrequency="0.017"
+ type="turbulence" />
+ <feComposite
+ id="feComposite6140"
+ in2="result1"
+ in="result0"
+ operator="out"
+ result="result2" />
+ <feGaussianBlur
+ id="feGaussianBlur6142"
+ stdDeviation="0.5"
+ result="result5" />
+ <feSpecularLighting
+ id="feSpecularLighting6144"
+ in="result5"
+ specularExponent="100"
+ specularConstant="4"
+ result="result4"
+ surfaceScale="1.5">
+ <feDistantLight
+ id="feDistantLight6146"
+ azimuth="225"
+ elevation="62" />
+ </feSpecularLighting>
+ <feComposite
+ id="feComposite6148"
+ in2="result2"
+ operator="atop"
+ in="result4"
+ result="result91" />
+ <feBlend
+ id="feBlend6150"
+ in2="result91"
+ mode="multiply" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.979899"
+ inkscape:cx="-21.768595"
+ inkscape:cy="49.177003"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1118"
+ inkscape:window-height="684"
+ inkscape:window-x="243"
+ inkscape:window-y="161"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-952.36218)"
+ style="opacity:0.75">
+ <rect
+ style="opacity:0.20000000000000001;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="rect2993"
+ width="100"
+ height="100"
+ x="0.16797371"
+ y="952.60327"
+ rx="15"
+ ry="15" />
+ <image
+ y="955.81396"
+ x="2.9568648"
+ id="image4099"
+ xlink:href="data:image/png;base64,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 sc8FnQAAAABJRU5ErkJggg== "
+ height="84"
+ width="85"
+ style="opacity:0.75000000000000000;filter:url(#filter6134)" />
+ </g>
+</svg>
diff --git a/demos/declarative/modelViewer/images/cog2.svg b/demos/declarative/modelViewer/images/cog2.svg
new file mode 100644
index 000000000..21f25d95d
--- /dev/null
+++ b/demos/declarative/modelViewer/images/cog2.svg
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="100"
+ height="100"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47+devel r9541"
+ sodipodi:docname="cog.svg">
+ <defs
+ id="defs4">
+ <filter
+ id="filter6134"
+ inkscape:label="Jam spread"
+ inkscape:menu="Textures"
+ inkscape:menu-tooltip="Glossy clumpy jam spread"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ id="feGaussianBlur6136"
+ stdDeviation="1"
+ in="SourceGraphic"
+ result="result0" />
+ <feTurbulence
+ id="feTurbulence6138"
+ result="result1"
+ numOctaves="7"
+ seed="488"
+ baseFrequency="0.017"
+ type="turbulence" />
+ <feComposite
+ id="feComposite6140"
+ in2="result1"
+ in="result0"
+ operator="out"
+ result="result2" />
+ <feGaussianBlur
+ id="feGaussianBlur6142"
+ stdDeviation="0.5"
+ result="result5" />
+ <feSpecularLighting
+ id="feSpecularLighting6144"
+ in="result5"
+ specularExponent="100"
+ specularConstant="4"
+ result="result4"
+ surfaceScale="1.5">
+ <feDistantLight
+ id="feDistantLight6146"
+ azimuth="225"
+ elevation="62" />
+ </feSpecularLighting>
+ <feComposite
+ id="feComposite6148"
+ in2="result2"
+ operator="atop"
+ in="result4"
+ result="result91" />
+ <feBlend
+ id="feBlend6150"
+ in2="result91"
+ mode="multiply" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.979899"
+ inkscape:cx="36.315176"
+ inkscape:cy="49.177003"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1118"
+ inkscape:window-height="684"
+ inkscape:window-x="310"
+ inkscape:window-y="375"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-952.36218)">
+ <rect
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="rect2993"
+ width="100"
+ height="100"
+ x="0.16797371"
+ y="952.60327"
+ rx="15"
+ ry="15" />
+ <image
+ y="955.81396"
+ x="2.9568648"
+ id="image4099"
+ xlink:href="data:image/png;base64,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 sc8FnQAAAABJRU5ErkJggg== "
+ height="84"
+ width="85"
+ style="opacity:0.75000000000000000;filter:url(#filter6134)" />
+ </g>
+</svg>
diff --git a/demos/declarative/modelViewer/images/knob.png b/demos/declarative/modelViewer/images/knob.png
new file mode 100644
index 000000000..0d5d8f0eb
--- /dev/null
+++ b/demos/declarative/modelViewer/images/knob.png
Binary files differ
diff --git a/demos/declarative/modelViewer/images/knob.svg b/demos/declarative/modelViewer/images/knob.svg
new file mode 100644
index 000000000..a14019298
--- /dev/null
+++ b/demos/declarative/modelViewer/images/knob.svg
@@ -0,0 +1,867 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://web.resource.org/cc/"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ x="0px"
+ y="0px"
+ width="52px"
+ height="52px"
+ viewBox="0 0 52 52"
+ enable-background="new 0 0 52 52"
+ xml:space="preserve"
+ id="svg3883"
+ sodipodi:version="0.32"
+ inkscape:version="0.44.1"
+ sodipodi:docname="knob_on.svg"
+ sodipodi:docbase="/local/axel/embeddedwidgets/embeddedstories/skins/svgslideswitch/MetallicBrush"><metadata
+ id="metadata4200"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><sodipodi:namedview
+ inkscape:window-height="640"
+ inkscape:window-width="937"
+ inkscape:pageshadow="2"
+ inkscape:pageopacity="0.0"
+ guidetolerance="10.0"
+ gridtolerance="10.0"
+ objecttolerance="10.0"
+ borderopacity="1.0"
+ bordercolor="#666666"
+ pagecolor="#ffffff"
+ id="base"
+ inkscape:zoom="8.3653846"
+ inkscape:cx="26.000002"
+ inkscape:cy="26"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:current-layer="svg3883" />
+<defs
+ id="defs3885">
+</defs>
+<linearGradient
+ id="SVGID_1_"
+ gradientUnits="userSpaceOnUse"
+ x1="-59.7866"
+ y1="-115.917"
+ x2="-93.2123"
+ y2="-76.0818"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#000000"
+ id="stop3888" />
+ <stop
+ offset="1"
+ style="stop-color:#EAECEF"
+ id="stop3890" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="26"
+ id="circle3892"
+ style="fill:url(#SVGID_1_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="26"
+ sodipodi:ry="26"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_2_"
+ gradientUnits="userSpaceOnUse"
+ x1="-100.5"
+ y1="-96"
+ x2="-52.5"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3895" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3897" />
+ <stop
+ offset="0.6043"
+ style="stop-color:#E7EAED"
+ id="stop3899" />
+ <stop
+ offset="0.6751"
+ style="stop-color:#DEE4E7"
+ id="stop3901" />
+ <stop
+ offset="0.7358"
+ style="stop-color:#CFD9DD"
+ id="stop3903" />
+ <stop
+ offset="0.791"
+ style="stop-color:#B9CACF"
+ id="stop3905" />
+ <stop
+ offset="0.8425"
+ style="stop-color:#9EB6BD"
+ id="stop3907" />
+ <stop
+ offset="0.891"
+ style="stop-color:#7B9EA7"
+ id="stop3909" />
+ <stop
+ offset="0.9374"
+ style="stop-color:#53828C"
+ id="stop3911" />
+ <stop
+ offset="0.9809"
+ style="stop-color:#25626E"
+ id="stop3913" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop3915" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="24"
+ id="circle3917"
+ style="fill:url(#SVGID_2_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="24"
+ sodipodi:ry="24"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_3_"
+ gradientUnits="userSpaceOnUse"
+ x1="-98.6328"
+ y1="-96"
+ x2="-54.3672"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3920" />
+ <stop
+ offset="0.073"
+ style="stop-color:#8FAECB"
+ id="stop3922" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3924" />
+ <stop
+ offset="0.5902"
+ style="stop-color:#E7E9ED"
+ id="stop3926" />
+ <stop
+ offset="0.618"
+ style="stop-color:#E4E7EB"
+ id="stop3928" />
+ <stop
+ offset="0.6697"
+ style="stop-color:#E0E4E9"
+ id="stop3930" />
+ <stop
+ offset="0.7211"
+ style="stop-color:#D4DCE1"
+ id="stop3932" />
+ <stop
+ offset="0.7722"
+ style="stop-color:#C0CFD5"
+ id="stop3934" />
+ <stop
+ offset="0.809"
+ style="stop-color:#ADC2C9"
+ id="stop3936" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop3938" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="22.132999"
+ id="circle3940"
+ style="fill:url(#SVGID_3_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="22.132999"
+ sodipodi:ry="22.132999"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_4_"
+ gradientUnits="userSpaceOnUse"
+ x1="-96.7671"
+ y1="-96"
+ x2="-56.2324"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3943" />
+ <stop
+ offset="0.073"
+ style="stop-color:#86A7C4"
+ id="stop3945" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3947" />
+ <stop
+ offset="0.577"
+ style="stop-color:#E7EAED"
+ id="stop3949" />
+ <stop
+ offset="0.618"
+ style="stop-color:#E1E6EA"
+ id="stop3951" />
+ <stop
+ offset="0.6697"
+ style="stop-color:#DDE3E8"
+ id="stop3953" />
+ <stop
+ offset="0.7211"
+ style="stop-color:#D1DBE1"
+ id="stop3955" />
+ <stop
+ offset="0.7722"
+ style="stop-color:#BDCDD5"
+ id="stop3957" />
+ <stop
+ offset="0.809"
+ style="stop-color:#AAC0CA"
+ id="stop3959" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop3961" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="20.267"
+ id="circle3963"
+ style="fill:url(#SVGID_4_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="20.267"
+ sodipodi:ry="20.267"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_5_"
+ gradientUnits="userSpaceOnUse"
+ x1="-94.8999"
+ y1="-96"
+ x2="-58.0996"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3966" />
+ <stop
+ offset="0.073"
+ style="stop-color:#7E9FBC"
+ id="stop3968" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3970" />
+ <stop
+ offset="0.5709"
+ style="stop-color:#E6E9ED"
+ id="stop3972" />
+ <stop
+ offset="0.618"
+ style="stop-color:#DFE4E9"
+ id="stop3974" />
+ <stop
+ offset="0.6687"
+ style="stop-color:#DBE1E7"
+ id="stop3976" />
+ <stop
+ offset="0.7193"
+ style="stop-color:#CFD9E0"
+ id="stop3978" />
+ <stop
+ offset="0.7695"
+ style="stop-color:#BBCCD6"
+ id="stop3980" />
+ <stop
+ offset="0.809"
+ style="stop-color:#A6BECA"
+ id="stop3982" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop3984" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="18.4"
+ id="circle3986"
+ style="fill:url(#SVGID_5_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="18.4"
+ sodipodi:ry="18.4"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_6_"
+ gradientUnits="userSpaceOnUse"
+ x1="-93.0332"
+ y1="-96"
+ x2="-59.9668"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop3989" />
+ <stop
+ offset="0.073"
+ style="stop-color:#7697B4"
+ id="stop3991" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop3993" />
+ <stop
+ offset="0.5636"
+ style="stop-color:#E6E9ED"
+ id="stop3995" />
+ <stop
+ offset="0.618"
+ style="stop-color:#DCE2E8"
+ id="stop3997" />
+ <stop
+ offset="0.6687"
+ style="stop-color:#D8DFE6"
+ id="stop3999" />
+ <stop
+ offset="0.7193"
+ style="stop-color:#CCD7E0"
+ id="stop4001" />
+ <stop
+ offset="0.7695"
+ style="stop-color:#B8CAD5"
+ id="stop4003" />
+ <stop
+ offset="0.809"
+ style="stop-color:#A3BCCA"
+ id="stop4005" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4007" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="16.533001"
+ id="circle4009"
+ style="fill:url(#SVGID_6_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="16.533001"
+ sodipodi:ry="16.533001"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_7_"
+ gradientUnits="userSpaceOnUse"
+ x1="-91.167"
+ y1="-96"
+ x2="-61.833"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4012" />
+ <stop
+ offset="0.073"
+ style="stop-color:#6D8FAD"
+ id="stop4014" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4016" />
+ <stop
+ offset="0.5605"
+ style="stop-color:#E5E8EC"
+ id="stop4018" />
+ <stop
+ offset="0.618"
+ style="stop-color:#DAE1E7"
+ id="stop4020" />
+ <stop
+ offset="0.6679"
+ style="stop-color:#D6DEE5"
+ id="stop4022" />
+ <stop
+ offset="0.7175"
+ style="stop-color:#CAD6DF"
+ id="stop4024" />
+ <stop
+ offset="0.7669"
+ style="stop-color:#B6C9D6"
+ id="stop4026" />
+ <stop
+ offset="0.809"
+ style="stop-color:#9FBACB"
+ id="stop4028" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4030" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="14.667"
+ id="circle4032"
+ style="fill:url(#SVGID_7_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="14.667"
+ sodipodi:ry="14.667"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_8_"
+ gradientUnits="userSpaceOnUse"
+ x1="-89.2998"
+ y1="-96"
+ x2="-63.7002"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4035" />
+ <stop
+ offset="0.073"
+ style="stop-color:#6587A5"
+ id="stop4037" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4039" />
+ <stop
+ offset="0.5588"
+ style="stop-color:#E4E8EC"
+ id="stop4041" />
+ <stop
+ offset="0.618"
+ style="stop-color:#D8DFE7"
+ id="stop4043" />
+ <stop
+ offset="0.6675"
+ style="stop-color:#D4DCE5"
+ id="stop4045" />
+ <stop
+ offset="0.7167"
+ style="stop-color:#C8D5E0"
+ id="stop4047" />
+ <stop
+ offset="0.7657"
+ style="stop-color:#B4C8D6"
+ id="stop4049" />
+ <stop
+ offset="0.809"
+ style="stop-color:#9CB8CB"
+ id="stop4051" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4053" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="12.8"
+ id="circle4055"
+ style="fill:url(#SVGID_8_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="12.8"
+ sodipodi:ry="12.8"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_9_"
+ gradientUnits="userSpaceOnUse"
+ x1="-87.4331"
+ y1="-96"
+ x2="-65.5664"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4058" />
+ <stop
+ offset="0.073"
+ style="stop-color:#5D809D"
+ id="stop4060" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4062" />
+ <stop
+ offset="0.5567"
+ style="stop-color:#E3E7EC"
+ id="stop4064" />
+ <stop
+ offset="0.618"
+ style="stop-color:#D5DDE6"
+ id="stop4066" />
+ <stop
+ offset="0.6671"
+ style="stop-color:#D1DAE4"
+ id="stop4068" />
+ <stop
+ offset="0.7159"
+ style="stop-color:#C5D3DF"
+ id="stop4070" />
+ <stop
+ offset="0.7645"
+ style="stop-color:#B1C6D6"
+ id="stop4072" />
+ <stop
+ offset="0.809"
+ style="stop-color:#98B5CB"
+ id="stop4074" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4076" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="10.933"
+ id="circle4078"
+ style="fill:url(#SVGID_9_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="10.933"
+ sodipodi:ry="10.933"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_10_"
+ gradientUnits="userSpaceOnUse"
+ x1="-85.5659"
+ y1="-96"
+ x2="-67.4336"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4081" />
+ <stop
+ offset="0.073"
+ style="stop-color:#547896"
+ id="stop4083" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4085" />
+ <stop
+ offset="0.5588"
+ style="stop-color:#E1E6EB"
+ id="stop4087" />
+ <stop
+ offset="0.618"
+ style="stop-color:#D3DCE5"
+ id="stop4089" />
+ <stop
+ offset="0.6663"
+ style="stop-color:#CFD9E3"
+ id="stop4091" />
+ <stop
+ offset="0.7143"
+ style="stop-color:#C3D2DF"
+ id="stop4093" />
+ <stop
+ offset="0.7621"
+ style="stop-color:#AFC5D7"
+ id="stop4095" />
+ <stop
+ offset="0.809"
+ style="stop-color:#94B3CC"
+ id="stop4097" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4099" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="9.066"
+ id="circle4101"
+ style="fill:url(#SVGID_10_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="9.066"
+ sodipodi:ry="9.066"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_11_"
+ gradientUnits="userSpaceOnUse"
+ x1="-83.7002"
+ y1="-96"
+ x2="-69.2998"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4104" />
+ <stop
+ offset="0.073"
+ style="stop-color:#4C708E"
+ id="stop4106" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4108" />
+ <stop
+ offset="0.5625"
+ style="stop-color:#DEE4EA"
+ id="stop4110" />
+ <stop
+ offset="0.618"
+ style="stop-color:#D0DAE4"
+ id="stop4112" />
+ <stop
+ offset="0.6663"
+ style="stop-color:#CCD7E2"
+ id="stop4114" />
+ <stop
+ offset="0.7143"
+ style="stop-color:#C0D0DE"
+ id="stop4116" />
+ <stop
+ offset="0.7621"
+ style="stop-color:#ACC3D6"
+ id="stop4118" />
+ <stop
+ offset="0.809"
+ style="stop-color:#91B1CC"
+ id="stop4120" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4122" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="7.1999998"
+ id="circle4124"
+ style="fill:url(#SVGID_11_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="7.1999998"
+ sodipodi:ry="7.1999998"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_12_"
+ gradientUnits="userSpaceOnUse"
+ x1="-81.833"
+ y1="-96"
+ x2="-71.167"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4127" />
+ <stop
+ offset="0.073"
+ style="stop-color:#446986"
+ id="stop4129" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4131" />
+ <stop
+ offset="0.5757"
+ style="stop-color:#D9E0E8"
+ id="stop4133" />
+ <stop
+ offset="0.618"
+ style="stop-color:#CED8E3"
+ id="stop4135" />
+ <stop
+ offset="0.6655"
+ style="stop-color:#CAD5E2"
+ id="stop4137" />
+ <stop
+ offset="0.7129"
+ style="stop-color:#BECEDD"
+ id="stop4139" />
+ <stop
+ offset="0.7601"
+ style="stop-color:#AAC1D6"
+ id="stop4141" />
+ <stop
+ offset="0.807"
+ style="stop-color:#8EB0CC"
+ id="stop4143" />
+ <stop
+ offset="0.809"
+ style="stop-color:#8DAFCC"
+ id="stop4145" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4147" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="5.3330002"
+ id="circle4149"
+ style="fill:url(#SVGID_12_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="5.3330002"
+ sodipodi:ry="5.3330002"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_13_"
+ gradientUnits="userSpaceOnUse"
+ x1="-79.9658"
+ y1="-96"
+ x2="-73.0342"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4152" />
+ <stop
+ offset="0.073"
+ style="stop-color:#3B617F"
+ id="stop4154" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4156" />
+ <stop
+ offset="0.6087"
+ style="stop-color:#CED9E3"
+ id="stop4158" />
+ <stop
+ offset="0.618"
+ style="stop-color:#CBD7E2"
+ id="stop4160" />
+ <stop
+ offset="0.6655"
+ style="stop-color:#C7D4E1"
+ id="stop4162" />
+ <stop
+ offset="0.7129"
+ style="stop-color:#BBCDDD"
+ id="stop4164" />
+ <stop
+ offset="0.7601"
+ style="stop-color:#A7C0D6"
+ id="stop4166" />
+ <stop
+ offset="0.807"
+ style="stop-color:#8BAECD"
+ id="stop4168" />
+ <stop
+ offset="0.809"
+ style="stop-color:#8AADCD"
+ id="stop4170" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4172" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="3.4660001"
+ id="circle4174"
+ style="fill:url(#SVGID_13_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="3.4660001"
+ sodipodi:ry="3.4660001"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+<linearGradient
+ id="SVGID_14_"
+ gradientUnits="userSpaceOnUse"
+ x1="-78.1001"
+ y1="-96"
+ x2="-74.9004"
+ y2="-96"
+ gradientTransform="matrix(1,0,0,-1,102.5,-70)">
+ <stop
+ offset="0.0056"
+ style="stop-color:#8AADCE"
+ id="stop4177" />
+ <stop
+ offset="0.073"
+ style="stop-color:#335977"
+ id="stop4179" />
+ <stop
+ offset="0.5"
+ style="stop-color:#EAECEF"
+ id="stop4181" />
+ <stop
+ offset="0.618"
+ style="stop-color:#C9D5E1"
+ id="stop4183" />
+ <stop
+ offset="0.6648"
+ style="stop-color:#C5D3E0"
+ id="stop4185" />
+ <stop
+ offset="0.7114"
+ style="stop-color:#B9CBDC"
+ id="stop4187" />
+ <stop
+ offset="0.758"
+ style="stop-color:#A5BFD6"
+ id="stop4189" />
+ <stop
+ offset="0.8042"
+ style="stop-color:#89ADCE"
+ id="stop4191" />
+ <stop
+ offset="0.809"
+ style="stop-color:#86ABCD"
+ id="stop4193" />
+ <stop
+ offset="1"
+ style="stop-color:#0E525F"
+ id="stop4195" />
+</linearGradient>
+<circle
+ cx="26"
+ cy="26"
+ r="1.6"
+ id="circle4197"
+ style="fill:url(#SVGID_14_)"
+ sodipodi:cx="26"
+ sodipodi:cy="26"
+ sodipodi:rx="1.6"
+ sodipodi:ry="1.6"
+ transform="matrix(0.923077,0,0,0.923077,2,1.999996)" />
+</svg>
diff --git a/demos/declarative/modelViewer/images/test.svg b/demos/declarative/modelViewer/images/test.svg
new file mode 100644
index 000000000..6d51cc9e7
--- /dev/null
+++ b/demos/declarative/modelViewer/images/test.svg
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="100"
+ height="100"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47+devel r9541"
+ sodipodi:docname="test.svg">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.979899"
+ inkscape:cx="114.34946"
+ inkscape:cy="49.177003"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1118"
+ inkscape:window-height="684"
+ inkscape:window-x="465"
+ inkscape:window-y="406"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-952.36218)">
+ <rect
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="rect2993"
+ width="100"
+ height="100"
+ x="0.16797371"
+ y="952.60327"
+ rx="15"
+ ry="15" />
+ <image
+ y="952.36218"
+ x="0.173319"
+ id="image3901"
+ xlink:href="data:image/png;base64,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
+RU5ErkJggg==
+"
+ height="100"
+ width="100" />
+ </g>
+</svg>
diff --git a/demos/declarative/modelViewer/images/zoomin.png b/demos/declarative/modelViewer/images/zoomin.png
new file mode 100644
index 000000000..b17cbe81d
--- /dev/null
+++ b/demos/declarative/modelViewer/images/zoomin.png
Binary files differ
diff --git a/demos/declarative/modelViewer/images/zoomin.svg b/demos/declarative/modelViewer/images/zoomin.svg
new file mode 100644
index 000000000..d517e3e5d
--- /dev/null
+++ b/demos/declarative/modelViewer/images/zoomin.svg
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="100"
+ height="100"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47+devel r9541"
+ sodipodi:docname="zoomin.svg">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.979899"
+ inkscape:cx="36.315176"
+ inkscape:cy="49.177003"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1118"
+ inkscape:window-height="684"
+ inkscape:window-x="465"
+ inkscape:window-y="406"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-952.36218)">
+ <rect
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="rect2993"
+ width="100"
+ height="100"
+ x="0.16797371"
+ y="952.60327"
+ rx="15"
+ ry="15" />
+ <image
+ y="957.90533"
+ x="7.5177755"
+ id="image4088"
+ xlink:href="data:image/png;base64,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 YII= "
+ height="98"
+ width="88"
+ style="opacity:0.75" />
+ </g>
+</svg>
diff --git a/demos/declarative/modelViewer/images/zoomout.png b/demos/declarative/modelViewer/images/zoomout.png
new file mode 100644
index 000000000..01ed6f25d
--- /dev/null
+++ b/demos/declarative/modelViewer/images/zoomout.png
Binary files differ
diff --git a/demos/declarative/modelViewer/images/zoomout.svg b/demos/declarative/modelViewer/images/zoomout.svg
new file mode 100644
index 000000000..ab722c1b6
--- /dev/null
+++ b/demos/declarative/modelViewer/images/zoomout.svg
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="100"
+ height="100"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.47+devel r9541"
+ sodipodi:docname="zoomout.svg">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.979899"
+ inkscape:cx="114.34946"
+ inkscape:cy="49.177003"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1118"
+ inkscape:window-height="684"
+ inkscape:window-x="465"
+ inkscape:window-y="406"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-952.36218)">
+ <rect
+ style="opacity:0.2;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="rect2993"
+ width="100"
+ height="100"
+ x="0.16797371"
+ y="952.60327"
+ rx="15"
+ ry="15" />
+ <image
+ y="962.42053"
+ x="-2.5685232"
+ id="image4305"
+ xlink:href="data:image/png;base64,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
+kIVqMoUAAAAASUVORK5CYII=
+"
+ height="92"
+ width="91"
+ style="opacity:0.75" />
+ </g>
+</svg>
diff --git a/demos/declarative/modelViewer/meshes/monkey.3ds b/demos/declarative/modelViewer/meshes/monkey.3ds
new file mode 100644
index 000000000..e9a007b20
--- /dev/null
+++ b/demos/declarative/modelViewer/meshes/monkey.3ds
Binary files differ
diff --git a/demos/declarative/modelViewer/meshes/penguin.3ds b/demos/declarative/modelViewer/meshes/penguin.3ds
new file mode 100644
index 000000000..26c09ac07
--- /dev/null
+++ b/demos/declarative/modelViewer/meshes/penguin.3ds
Binary files differ
diff --git a/demos/declarative/modelViewer/modelviewer.qml b/demos/declarative/modelViewer/modelviewer.qml
new file mode 100644
index 000000000..251547a72
--- /dev/null
+++ b/demos/declarative/modelViewer/modelviewer.qml
@@ -0,0 +1,375 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Rectangle {
+ id: mainwindow
+ width: 800
+ height: 500
+
+ gradient: Gradient {
+ GradientStop { position: 0.0; color: "#300000" }
+ GradientStop { position: 0.3; color: "darkred" }
+ GradientStop { position: 1.0; color: "#300000" }
+ }
+
+ states: [
+ State {
+ name: "Open"
+
+ PropertyChanges { target: mainwindow; x: -800}
+
+ },
+ State {
+ name: "NotImplemented"
+
+ //PropertyChanges { target: container; y: 0 }
+ }
+ ]
+
+ transitions: Transition {
+ NumberAnimation { properties: "x"; easing.type: Easing.OutQuad; duration: 600 }
+ }
+
+
+ Viewport {
+ visible: false
+ x: 800
+ id: viewport1
+ width: 800; height: 500
+ picking: false
+
+ camera: Camera {
+ eye: Qt.vector3d(0, 0, 350)
+ farPlane: 2000
+ }
+
+
+ Text {
+ id: imgSrc
+ text: "Image Source"; font.family: "Helvetica"; font.pointSize: 22; color: "white"
+ anchors.top: parent.top
+ z: 10
+ }
+
+ LongButton {
+ //width: 800
+ id: imgSrcButton
+ anchors.top: imgSrc.bottom
+ anchors.topMargin: 2
+ z: 10
+ }
+ Text {
+ id: displayOptions
+ anchors.top: imgSrcButton.bottom
+ anchors.topMargin: 2
+ text: "Display Options"; font.family: "Helvetica"; font.pointSize: 22; color: "white"
+ z: 10
+ }
+ FourButtons {
+ id: displayOptionsButton
+ anchors.top: displayOptions.bottom
+ anchors.topMargin: 2
+ z: 10
+ }
+ Text {
+ id: texture
+ anchors.top: displayOptionsButton.bottom
+ anchors.topMargin: 2
+ text: "Texture"; font.family: "Helvetica"; font.pointSize:22; color: "white"
+ z: 10
+ }
+ LongButton {
+ id: textureButton
+ anchors.top: texture.bottom
+ anchors.topMargin: 2
+ z: 10
+ }
+ Text {
+ id: navigation
+ anchors.top: textureButton.bottom
+ anchors.topMargin: 2
+ text: "Navigation"; font.family: "Helvetica"; font.pointSize: 22; color: "white"
+ z: 10
+ }
+ FourButtons {
+ id: navigationButton
+ anchors.top: navigation.bottom
+ anchors.topMargin: 2
+ z: 10
+ }
+ Text {
+ id: background
+ anchors.top: navigationButton.bottom
+ anchors.topMargin: 2
+ text: "Background"; font.family: "Helvetica"; font.pointSize: 22; color: "white"
+ z: 10
+ }
+ LongButton {
+ id: backgroundButton
+ anchors.top: background.bottom
+ anchors.topMargin: 2
+ z: 10
+ }
+
+ //Button 1
+ MainButton {
+ id: button1c
+ anchors.top: parent.top
+ imageSource: "images/cog.svg"
+
+
+ MouseArea {
+ //property bool on: false
+ anchors.fill: parent
+ onClicked: {
+ //source_mesh.options = "ForceSmooth";
+ //source_mesh.source = textInput.text;
+ parent.bounce = true;
+
+ if (mainwindow.state == "")mainwindow.state = "Open"; else mainwindow.state = "";
+ }
+ }
+ }
+
+ }
+
+ Item {
+ width: 800; height: 500
+
+ Viewport {
+ anchors.fill: parent
+ id: viewport
+ picking: false
+ blending: true
+
+ camera: Camera {
+ eye: Qt.vector3d(0, 0, 350)
+ farPlane: 2000
+ }
+
+ Item3D {
+ id: mainItem
+ scale: 50
+ mesh: source_mesh
+ effect: Effect {}
+ cullFaces: "CullBackFaces"
+ }
+
+ Mesh {
+ id: source_mesh
+ source: "meshes/monkey.3ds"
+ }
+
+ MouseArea {
+ id: mouseArea
+ property bool rotating: false
+ property int startX: 0
+ property int startY: 0
+ property variant startEye
+ property variant startCenter
+ property variant startUpVector
+ anchors.fill: parent
+ onPressed: {
+ if (mouse.button == Qt.LeftButton) {
+ rotating = true;
+ startX = mouse.x;
+ startY = mouse.y;
+ startEye = viewport.camera.eye;
+ startCenter = viewport.camera.center;
+ startUpVector = viewport.camera.upVector;
+ }
+ }
+ onReleased: {
+ if (mouse.button == Qt.LeftButton)
+ rotating = false;
+ }
+ onPositionChanged: {
+ if (rotating) {
+ var deltaX = mouse.x - startX;
+ var deltaY = mouse.y - startY;
+ var angleAroundY = deltaX * 90 / mouseArea.width;
+ var angleAroundX = deltaY * 90 / mouseArea.height;
+
+ viewport.camera.eye = startEye;
+ viewport.camera.center = startCenter;
+ viewport.camera.upVector = startUpVector;
+ viewport.camera.tiltPanRollCenter
+ (-angleAroundX, -angleAroundY, 0);
+ }
+ }
+ }
+ }
+
+ Rectangle {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottomMargin: 15
+ anchors.bottom: parent.bottom
+ radius: 10
+ border.width: 1
+ border.color: "black"
+ color: "white"
+ width: 500
+ height: 25
+ //Enter text here
+ TextInput {
+ anchors.verticalCenter: parent.verticalCenter
+ anchors.horizontalCenter: parent.horizontalCenter
+ id: textInput
+ text: source_mesh.source
+ activeFocusOnPress: false
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ if (!textInput.activeFocus) {
+ textInput.forceActiveFocus();
+ textInput.openSoftwareInputPanel();
+ } else {
+ textInput.focus = false;
+ }
+ }
+ onPressAndHold: textInput.closeSoftwareInputPanel();
+ }
+ }
+ }
+
+
+ //Button 1
+ MainButton {
+ id: button1
+ anchors.top: parent.top
+ imageSource: "images/cog.svg"
+
+ MouseArea {
+ //property bool on: false
+ anchors.fill: parent
+ onClicked: {
+ //source_mesh.options = "ForceSmooth";
+ //source_mesh.source = textInput.text;
+ parent.bounce = true;
+
+ if (mainwindow.state == "")mainwindow.state = "Open"; else mainwindow.state = "";
+ }
+ }
+ }
+
+ //Button 2
+ MainButton {
+ id: button2
+ anchors.top: button1.bottom
+ imageSource: "images/zoomin.svg";
+ property bool zoom: false
+ property real changeScale: 1.1
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ button2.changeScale = 1.1
+ button2.zoom = true
+ parent.bounce = true;
+ }
+ onPressAndHold: {
+ button2.changeScale = 2
+ button2.zoom = true
+ parent.bounce = true;
+ }
+
+ }
+
+ SequentialAnimation {
+ running: button2.zoom
+ loops: 1
+ NumberAnimation { target: mainItem; property: "scale"; to: mainItem.scale*button2.changeScale; duration: 50;}
+ onCompleted: button2.zoom = false
+ }
+ }
+
+ //Buton 3
+ MainButton {
+ id: button3
+ anchors.top: button2.bottom
+ imageSource: "images/zoomout.svg"
+ property bool zoom: false
+ property real changeScale: 1.1
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ button3.changeScale = 1.1
+ button3.zoom = true
+ parent.bounce = true;
+ }
+ onPressAndHold: {
+ button3.changeScale = 2
+ button3.zoom = true
+ parent.bounce = true;
+ }
+ }
+
+ SequentialAnimation {
+ running: button3.zoom
+ loops: 1
+ NumberAnimation { target: mainItem; property: "scale"; to: mainItem.scale/button3.changeScale; duration: 50;}
+ onCompleted: button3.zoom = false
+ }
+ }
+
+ //Buton 4
+ MainButton {
+ id: button4
+ anchors.top: button3.bottom
+ imageSource: "images/arrow.svg"
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+
+ parent.bounce = true;
+
+ source_mesh.source = textInput.text;
+ }
+ }
+ }
+
+
+ }
+}
diff --git a/demos/declarative/monkeygod/Penguin.qml b/demos/declarative/monkeygod/Penguin.qml
new file mode 100644
index 000000000..394110840
--- /dev/null
+++ b/demos/declarative/monkeygod/Penguin.qml
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Item3D {
+ id: penguin
+ scale: 0.2
+ effect: Effect{}
+ transform: [
+ Rotation3D {
+ id: penguinTilt
+ angle: -100
+ axis: Qt.vector3d(1,0,0)
+ },
+ Rotation3D {
+ id: penguinFacing
+ angle: 180
+ axis: Qt.vector3d(0,1,0)
+ }
+ ]
+
+ light: Light {}
+
+ mesh: Mesh { source: "meshes/penguin.3ds" }
+
+ SequentialAnimation {
+ running: true
+ loops: 100
+ NumberAnimation {target: penguinTilt; property: "angle"; to: -45; duration: 600; easing.type: "OutQuad"}
+ NumberAnimation {target: penguinTilt; property: "angle"; to: -100; duration: 600; easing.type: "OutQuad"}
+ }
+
+ SequentialAnimation on y {
+ running: true
+ loops: 100
+ NumberAnimation {to: 0.5; duration: 200; easing.type: "OutQuad"}
+ NumberAnimation {to: 0.0; duration: 200; easing.type: "OutQuad"}
+ }
+}
diff --git a/demos/declarative/monkeygod/meshes/monkey.3ds b/demos/declarative/monkeygod/meshes/monkey.3ds
new file mode 100644
index 000000000..e9a007b20
--- /dev/null
+++ b/demos/declarative/monkeygod/meshes/monkey.3ds
Binary files differ
diff --git a/demos/declarative/monkeygod/meshes/penguin.3ds b/demos/declarative/monkeygod/meshes/penguin.3ds
new file mode 100644
index 000000000..26c09ac07
--- /dev/null
+++ b/demos/declarative/monkeygod/meshes/penguin.3ds
Binary files differ
diff --git a/demos/declarative/monkeygod/monkeygod.qml b/demos/declarative/monkeygod/monkeygod.qml
new file mode 100644
index 000000000..0782f5e5f
--- /dev/null
+++ b/demos/declarative/monkeygod/monkeygod.qml
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+ Viewport {
+ width: 1000
+ height: 800
+
+ camera: Camera { eye: Qt.vector3d(21,7,19)}
+
+ Item3D {
+ id: monkey
+ scale: 2
+ position: Qt.vector3d(0, 1.5, -6)
+
+ mesh: Mesh { source: "meshes/monkey.3ds"; options: "ForceSmooth"}
+ effect: Effect { material: gold}
+ transform: LookAt { subject: focalPenguin}
+ }
+
+ Item3D
+ {
+ Penguin {position: Qt.vector3d(-1.5,0,1)}
+ Penguin {position: Qt.vector3d(1.5,0,1)}
+ Penguin {id: focalPenguin; position: Qt.vector3d(-0.5,0,2)}
+ Penguin {position: Qt.vector3d(0.5,0,2)}
+
+ transform: [
+ Rotation3D {id: swivel1; angle: -20; axis: Qt.vector3d(0,1,0)}
+ ]
+
+ SequentialAnimation {
+ running: true
+ loops: 100
+ NumberAnimation {target: swivel1; property: "angle"; to: 20; duration: 1200; easing.type: "OutQuad"}
+ NumberAnimation {target: swivel1; property: "angle"; to: -20; duration: 1200; easing.type: "OutQuad"}
+ }
+ }
+
+ Item3D {
+ scale: 0.012
+ y: -6.5
+ z: -2
+ mesh: Mesh { source: "meshes/lintel.3ds"}
+ transform: [Rotation3D {angle: -90; axis: Qt.vector3d(1,0,0)}]
+ effect: Effect{}
+ }
+
+ Item3D
+ {
+ Penguin {position: Qt.vector3d(-2.5,0,2)}
+ Penguin {position: Qt.vector3d(2.5,0,2)}
+ Penguin {position: Qt.vector3d(-1.5,0,3)}
+ Penguin {position: Qt.vector3d(1.5,0,3)}
+ Penguin {position: Qt.vector3d(-0.5,0,3.5)}
+ Penguin {position: Qt.vector3d(0.5,0,3.5)}
+
+ transform: [
+ Rotation3D {id: swivel2; angle: 20; axis: Qt.vector3d(0,1,0)}
+ ]
+
+ SequentialAnimation {
+ running: true
+ loops: 100
+ NumberAnimation {target: swivel2; property: "angle"; to: -20; duration: 1200; easing.type: "OutQuad"}
+ NumberAnimation {target: swivel2; property: "angle"; to: 20; duration: 1200; easing.type: "OutQuad"}
+ }
+ }
+
+ Material {
+ id: gold
+ ambientColor: "#EEDD00"
+ specularColor: "#FFFFFF"
+ shininess: 200
+ }
+ }
diff --git a/demos/declarative/monkeygod/monkeygod.qmlproject b/demos/declarative/monkeygod/monkeygod.qmlproject
new file mode 100644
index 000000000..d4909f868
--- /dev/null
+++ b/demos/declarative/monkeygod/monkeygod.qmlproject
@@ -0,0 +1,16 @@
+import QmlProject 1.0
+
+Project {
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+ /* List of plugin directories passed to QML runtime */
+ // importPaths: [ " ../exampleplugin " ]
+}
diff --git a/demos/declarative/monkeygod/monkeygod_no_platform.qml b/demos/declarative/monkeygod/monkeygod_no_platform.qml
new file mode 100644
index 000000000..eb2ee3fa4
--- /dev/null
+++ b/demos/declarative/monkeygod/monkeygod_no_platform.qml
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Rectangle {
+ color: "#AAAA22"
+ width: 1000
+ height: 800
+
+ Viewport {
+ anchors.fill: parent
+
+ camera: Camera { eye: Qt.vector3d(21,7,19)}
+
+ Item3D {
+ id: monkey
+ scale: 2
+ position: Qt.vector3d(0, 1.5, -6)
+
+ mesh: Mesh { source: "meshes/monkey.3ds"; options: "ForceSmooth"}
+ effect: Effect { material: gold}
+ }
+
+ Item3D
+ {
+ Penguin {position: Qt.vector3d(-1.5,0,1)}
+ Penguin {position: Qt.vector3d(1.5,0,1)}
+ Penguin {position: Qt.vector3d(-0.5,0,2)}
+ Penguin {position: Qt.vector3d(0.5,0,2)}
+
+ transform: [
+ Rotation3D {id: swivel1; angle: -20; axis: Qt.vector3d(0,1,0)}
+ ]
+
+ SequentialAnimation {
+ running: true
+ loops: 100
+ NumberAnimation {target: swivel1; property: "angle"; to: 20; duration: 1200; easing.type: "OutQuad"}
+ NumberAnimation {target: swivel1; property: "angle"; to: -20; duration: 1200; easing.type: "OutQuad"}
+ }
+ }
+
+ Item3D
+ {
+ Penguin {position: Qt.vector3d(-2.5,0,2)}
+ Penguin {position: Qt.vector3d(2.5,0,2)}
+ Penguin {position: Qt.vector3d(-1.5,0,3)}
+ Penguin {position: Qt.vector3d(1.5,0,3)}
+ Penguin {position: Qt.vector3d(-0.5,0,3.5)}
+ Penguin {position: Qt.vector3d(0.5,0,3.5)}
+
+ transform: [
+ Rotation3D {id: swivel2; angle: 20; axis: Qt.vector3d(0,1,0)}
+ ]
+
+ SequentialAnimation {
+ running: true
+ loops: 100
+ NumberAnimation {target: swivel2; property: "angle"; to: -20; duration: 1200; easing.type: "OutQuad"}
+ NumberAnimation {target: swivel2; property: "angle"; to: 20; duration: 1200; easing.type: "OutQuad"}
+ }
+ }
+
+ Material {
+ id: gold
+ ambientColor: "#EEDD00"
+ specularColor: "#FFFFFF"
+ shininess: 200
+ }
+ }
+}
diff --git a/demos/declarative/moon/moon-texture.jpg b/demos/declarative/moon/moon-texture.jpg
new file mode 100644
index 000000000..b6955e389
--- /dev/null
+++ b/demos/declarative/moon/moon-texture.jpg
Binary files differ
diff --git a/demos/declarative/moon/moon.qml b/demos/declarative/moon/moon.qml
new file mode 100644
index 000000000..e8d265e45
--- /dev/null
+++ b/demos/declarative/moon/moon.qml
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+import Qt3D.Shapes 1.0
+
+Viewport {
+ width: 640; height: 480
+
+ light: Light {
+ direction: Qt.vector3d(1, 0, 2)
+ }
+
+ Sphere {
+ scale: 1.5
+ levelOfDetail: 6
+ axis: Qt.YAxis
+
+ effect: Effect {
+ // Moon texture sourced from:
+ // http://www.lns.cornell.edu/~seb/celestia/moon-4k-18.jpg
+ // The source texture was scaled down to a more reasonable size,
+ // and the brightness and contrast were increased.
+ texture: "moon-texture.jpg"
+ }
+ }
+}
diff --git a/demos/declarative/photoroom.qml b/demos/declarative/photoroom.qml
new file mode 100644
index 000000000..120ad0a29
--- /dev/null
+++ b/demos/declarative/photoroom.qml
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Viewport {
+ id: viewport
+ width: 800; height: 480
+ picking: true
+ //navigation: false
+ //showPicking: true
+
+ camera: Camera {
+ id: main_camera
+ eye: Qt.vector3d(0, 4, 12)
+ center: Qt.vector3d(0, 0, -2.5)
+ }
+
+ PhotoPane {
+ offset: -2.1
+ layer: 0
+ image: "textures/button/woman.jpg"
+ }
+ PhotoPane {
+ offset: -2.1
+ layer: 1
+ image: "textures/photos/niagara_falls.jpg"
+ }
+ PhotoPane {
+ offset: -2.1
+ layer: 2
+ image: "textures/photos/place.jpg"
+ }
+ PhotoPane {
+ offset: -2.1
+ layer: 3
+ image: "textures/photos/background.jpg"
+ }
+ PhotoPane {
+ offset: -2.1
+ layer: 4
+ image: "textures/basket.jpg"
+ }
+ PhotoPane {
+ offset: -2.1
+ layer: 5
+ image: "textures/qtlogo.png"
+ effect.color: "#006090"
+ }
+
+ PhotoPane {
+ offset: 2.1
+ layer: 0
+ image: "textures/photos/niagara_falls.jpg"
+ }
+ PhotoPane {
+ offset: 2.1
+ layer: 1
+ image: "textures/photos/place.jpg"
+ }
+ PhotoPane {
+ offset: 2.1
+ layer: 2
+ image: "textures/photos/background.jpg"
+ }
+ PhotoPane {
+ offset: 2.1
+ layer: 3
+ image: "textures/basket.jpg"
+ }
+ PhotoPane {
+ offset: 2.1
+ layer: 4
+ image: "textures/qtlogo.png"
+ effect.color: "#006090"
+ }
+ PhotoPane {
+ offset: 2.1
+ layer: 5
+ image: "textures/button/woman.jpg"
+ }
+
+ states: [
+ State {
+ name: "show_photo"
+ PropertyChanges {
+ target: main_camera
+ eye.y: 0
+ }
+ PropertyChanges {
+ target: main_camera
+ eye.x: 0
+ }
+ PropertyChanges {
+ target: main_camera
+ eye.z: 12
+ }
+ PropertyChanges {
+ target: main_camera
+ upVector: Qt.vector3d(0, 1, 0)
+ }
+ },
+ State {
+ name: "show_group"
+ PropertyChanges {
+ target: main_camera
+ eye.y: 4
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "*"
+ to: "*"
+ NumberAnimation {
+ targets: main_camera
+ properties: "eye.y"
+ easing.type: "OutBounce"
+ duration: 700
+ }
+ }
+ ]
+}
diff --git a/demos/declarative/sphere.qml b/demos/declarative/sphere.qml
new file mode 100644
index 000000000..b6adacb30
--- /dev/null
+++ b/demos/declarative/sphere.qml
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+import Qt3D.Shapes 1.0
+
+Viewport {
+ width: 800; height: 480
+
+ Item3D {
+ effect: Effect { color: "#aaca00" }
+
+ Sphere {
+ radius: 0.5
+ x: -2.5
+ y: 0.6
+ levelOfDetail: 1
+
+ transform: Rotation3D {
+ angle: 45
+ axis: Qt.vector3d(1, -1, 1)
+ }
+ }
+
+ Sphere {
+ radius: 0.5
+ x: -1.25
+ y: 0.6
+ levelOfDetail: 2
+
+ transform: Rotation3D {
+ angle: 45
+ axis: Qt.vector3d(1, -1, 1)
+ }
+ }
+
+ Sphere {
+ radius: 0.5
+ x: 0
+ y: 0.6
+ levelOfDetail: 3
+
+ transform: Rotation3D {
+ angle: 45
+ axis: Qt.vector3d(1, -1, 1)
+ }
+ }
+
+ Sphere {
+ radius: 0.5
+ x: 1.25
+ y: 0.6
+ levelOfDetail: 4
+
+ transform: Rotation3D {
+ angle: 45
+ axis: Qt.vector3d(1, -1, 1)
+ }
+ }
+
+ Sphere {
+ radius: 0.5
+ x: 2.5
+ y: 0.6
+ levelOfDetail: 5
+
+ transform: Rotation3D {
+ angle: 45
+ axis: Qt.vector3d(1, -1, 1)
+ }
+ }
+
+ Sphere {
+ radius: 0.5
+ x: -2.5
+ y: -0.6
+ levelOfDetail: 6
+
+ transform: Rotation3D {
+ angle: 45
+ axis: Qt.vector3d(1, -1, 1)
+ }
+ }
+
+ Sphere {
+ radius: 0.5
+ x: -1.25
+ y: -0.6
+ levelOfDetail: 7
+
+ transform: Rotation3D {
+ angle: 45
+ axis: Qt.vector3d(1, -1, 1)
+ }
+ }
+
+ Sphere {
+ radius: 0.5
+ x: 0
+ y: -0.6
+ levelOfDetail: 8
+
+ transform: Rotation3D {
+ angle: 45
+ axis: Qt.vector3d(1, -1, 1)
+ }
+ }
+
+ Sphere {
+ radius: 0.5
+ x: 1.25
+ y: -0.6
+ levelOfDetail: 9
+
+ transform: Rotation3D {
+ angle: 45
+ axis: Qt.vector3d(1, -1, 1)
+ }
+ }
+
+ Sphere {
+ radius: 0.5
+ x: 2.5
+ y: -0.6
+ levelOfDetail: 10
+
+ transform: Rotation3D {
+ angle: 45
+ axis: Qt.vector3d(1, -1, 1)
+ }
+ }
+ }
+}
diff --git a/demos/declarative/stereo/Teapot.qml b/demos/declarative/stereo/Teapot.qml
new file mode 100644
index 000000000..572cc3ec1
--- /dev/null
+++ b/demos/declarative/stereo/Teapot.qml
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Item3D {
+ id: teapot
+ mesh: Mesh { source: "../meshes/teapot.bez" }
+ effect: Effect {
+ material: Material {
+ id: china
+ ambientColor: "#c09680"
+ specularColor: "#3c3c3c"
+ shininess: 128
+ }
+ }
+}
diff --git a/demos/declarative/stereo/Time.qml b/demos/declarative/stereo/Time.qml
new file mode 100644
index 000000000..c29568c64
--- /dev/null
+++ b/demos/declarative/stereo/Time.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+
+Item {
+ id: container
+ property variant currentDateTime
+
+ Rectangle {
+ anchors.fill: parent
+ border.color: "black"
+ radius: 5
+ }
+
+ width: 150
+ height: 50
+
+ Text {
+ text: Qt.formatTime(container.currentDateTime, "h:mm'<sup><small> 'ap'</small></sup>'")
+ font.pixelSize: 30; font.bold: true
+ color: "black"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Timer {
+ interval: 1000
+ running: true
+ repeat: true
+ triggeredOnStart: true
+ onTriggered: container.currentDateTime = new Date()
+ }
+}
diff --git a/demos/declarative/stereo/Time20.qml b/demos/declarative/stereo/Time20.qml
new file mode 100644
index 000000000..98ad69e3d
--- /dev/null
+++ b/demos/declarative/stereo/Time20.qml
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Item {
+ id: container
+ property variant currentDateTime
+
+ Rectangle {
+ anchors.fill: parent
+ border.color: "black"
+ radius: 5
+ }
+
+ width: 150
+ height: 50
+
+ Text {
+ text: Qt.formatTime(container.currentDateTime, "h:mm'<sup><small> 'ap'</small></sup>'")
+ font.pixelSize: 30; font.bold: true
+ color: "black"
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Timer {
+ interval: 1000
+ running: true
+ repeat: true
+ triggeredOnStart: true
+ onTriggered: container.currentDateTime = new Date()
+ }
+}
diff --git a/demos/declarative/stereo/stereo-scenegraph.qml b/demos/declarative/stereo/stereo-scenegraph.qml
new file mode 100644
index 000000000..1f41819cf
--- /dev/null
+++ b/demos/declarative/stereo/stereo-scenegraph.qml
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Qt3D 2.0
+import Qt3D.Shapes 1.0
+
+Item {
+ id: stereo
+ width: 640; height: 450
+
+ FloatingItem {
+ anchors.fill: parent
+ depth: -10
+ Image {
+ anchors.fill: parent
+ source: "../textures/photos/niagara_falls.jpg"
+ }
+ }
+
+ Viewport {
+ anchors.fill: parent
+ navigation: false
+
+ camera: Camera {
+ eye: Qt.vector3d(0, 0, 10)
+ eyeSeparation: 0.08
+ }
+
+ Teapot {
+ id: teapot
+ position: Qt.vector3d(-1.0, -1.0, -5.0)
+
+ SequentialAnimation on y {
+ running: true
+ loops: Animation.Infinite
+ PauseAnimation { duration: 500 }
+ NumberAnimation { to : 1.0; duration: 300; easing.type:"OutQuad" }
+ NumberAnimation { to : -1.0; duration: 300; easing.type:"OutBounce" }
+ }
+ }
+
+ Cube {
+ id: cube
+ position: Qt.vector3d(1.0, -0.5, 0.0)
+
+ transform: Rotation3D {
+ axis: Qt.vector3d(1, 1, 1)
+
+ NumberAnimation on angle {
+ running: true
+ loops: Animation.Infinite
+ from: 0
+ to: 360
+ duration: 5000
+ }
+ }
+
+ effect: Effect {
+ color: "#aaca00"
+ texture: "../textures/qtlogo.png"
+ decal: true
+ }
+ }
+ }
+
+ Time20 { x: 5; y: 5 }
+
+ FloatingItem {
+ id: button
+ x: 250; y: 50
+ width: 300; height: 80
+ depth: 4
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#90e020"
+ opacity: 0.7
+ radius: 5
+ }
+
+ Text {
+ anchors.centerIn: parent
+ color: "black"
+ font.pointSize: 14
+ text: "Drag Me!"
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ drag.target: button
+ drag.axis: Drag.XandYAxis
+ drag.minimumX: 0
+ drag.maximumX: stereo.width - parent.width
+ drag.minimumY: 0
+ drag.maximumY: stereo.height - parent.height
+ }
+ }
+}
diff --git a/demos/declarative/stereo/stereo.qml b/demos/declarative/stereo/stereo.qml
new file mode 100644
index 000000000..3d550ff06
--- /dev/null
+++ b/demos/declarative/stereo/stereo.qml
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//![1]
+import Qt 4.7
+import Qt3D 1.0
+import Qt3D.Shapes 1.0
+
+//![3]
+StereoView {
+ id: stereo
+//![3]
+ width: 640; height: 450
+//![1]
+
+/*
+//![4]
+ width: 1280; height: 450
+ layout: StereoView.LeftRight
+//![4]
+*/
+
+//![5]
+ FloatingItem {
+ anchors.fill: parent
+ depth: -10
+ Image {
+ anchors.fill: parent
+ source: "../textures/photos/niagara_falls.jpg"
+ }
+ }
+//![5]
+
+//![6]
+ Viewport {
+ anchors.fill: parent
+ navigation: false
+
+ camera: Camera {
+ eye: Qt.vector3d(0, 0, 10)
+ eyeSeparation: 0.08
+ }
+//![6]
+
+//![8]
+ Teapot {
+ id: teapot
+ position: Qt.vector3d(-1.0, -1.0, -5.0)
+//![8]
+
+ SequentialAnimation on y {
+ running: true
+ loops: Animation.Infinite
+ PauseAnimation { duration: 500 }
+ NumberAnimation { to : 1.0; duration: 300; easing.type:"OutQuad" }
+ NumberAnimation { to : -1.0; duration: 300; easing.type:"OutBounce" }
+ }
+//![9]
+ }
+
+ Cube {
+ id: cube
+ position: Qt.vector3d(1.0, -0.5, 0.0)
+//![9]
+
+ transform: Rotation3D {
+ axis: Qt.vector3d(1, 1, 1)
+
+ NumberAnimation on angle {
+ running: true
+ loops: Animation.Infinite
+ from: 0
+ to: 360
+ duration: 5000
+ }
+ }
+
+ effect: Effect {
+ color: "#aaca00"
+ texture: "../textures/qtlogo.png"
+ decal: true
+ }
+//![10]
+ }
+//![10]
+//![7]
+ }
+//![7]
+
+//![11]
+ Time { x: 5; y: 5 }
+//![11]
+
+//![12]
+ FloatingItem {
+ id: button
+ x: 250; y: 50
+ width: 300; height: 80
+ depth: 4
+
+ Rectangle {
+ anchors.fill: parent
+ color: "#90e020"
+ opacity: 0.7
+ radius: 5
+ }
+
+ Text {
+ anchors.centerIn: parent
+ color: "black"
+ font.pointSize: 14
+ text: "Drag Me!"
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ drag.target: button
+ drag.axis: Drag.XandYAxis
+ drag.minimumX: 0
+ drag.maximumX: stereo.viewport.width - parent.width
+ drag.minimumY: 0
+ drag.maximumY: stereo.viewport.height - parent.height
+ }
+ }
+//![12]
+//![2]
+}
+//![2]
diff --git a/demos/declarative/stereo/stereo.qmlproject b/demos/declarative/stereo/stereo.qmlproject
new file mode 100644
index 000000000..d4909f868
--- /dev/null
+++ b/demos/declarative/stereo/stereo.qmlproject
@@ -0,0 +1,16 @@
+import QmlProject 1.0
+
+Project {
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+ /* List of plugin directories passed to QML runtime */
+ // importPaths: [ " ../exampleplugin " ]
+}
diff --git a/demos/declarative/teapot-bounce.qml b/demos/declarative/teapot-bounce.qml
new file mode 100644
index 000000000..7abfe76d8
--- /dev/null
+++ b/demos/declarative/teapot-bounce.qml
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Viewport {
+ width: 640; height: 480
+
+ Item3D {
+ id: teapot
+ mesh: Mesh { source: "meshes/teapot.bez" }
+ effect: Effect {
+ material: china
+ }
+
+ SequentialAnimation on y{
+ running: true
+ loops: Animation.Infinite
+ PauseAnimation { duration: 500 }
+ NumberAnimation { to : 1.0; duration: 300; easing.type:"OutQuad" }
+ NumberAnimation { to : 0.0; duration: 300; easing.type:"OutBounce" }
+ }
+
+ Material {
+ id: china
+ ambientColor: "#c09680"
+ specularColor: "#3c3c3c"
+ shininess: 128
+ }
+ }
+}
diff --git a/demos/declarative/teapot-scenegraph.qml b/demos/declarative/teapot-scenegraph.qml
new file mode 100644
index 000000000..c4e1c146e
--- /dev/null
+++ b/demos/declarative/teapot-scenegraph.qml
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import Qt3D 2.0
+
+Viewport {
+ width: 640; height: 480
+ Item3D {
+ mesh: Mesh { source: "meshes/teapot.bez" }
+ effect: Effect {}
+ }
+}
diff --git a/demos/declarative/teapot-shader-animation.qml b/demos/declarative/teapot-shader-animation.qml
new file mode 100644
index 000000000..0d01113fc
--- /dev/null
+++ b/demos/declarative/teapot-shader-animation.qml
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Viewport {
+ width: 640; height: 480
+
+Item3D {
+ mesh: Mesh { source: "meshes/teapot.bez" }
+ effect: program
+
+ transform: Rotation3D {
+ NumberAnimation on angle{
+ running: true
+ loops: Animation.Infinite
+ from: 0
+ to: 360
+ duration: 18000
+ }
+ axis: Qt.vector3d(1, -0.3, 0)
+ }
+
+ ShaderProgram {
+ id: program
+ property real qt_Custom : 1.0
+ SequentialAnimation on qt_Custom {
+ running: true
+ loops: Animation.Infinite
+ PauseAnimation { duration: 700 }
+ NumberAnimation { from: 1.0; to: 0.001; duration: 1500; easing.type:"OutBounce" }
+ PauseAnimation { duration: 700 }
+ NumberAnimation { from: 0.001; to: 1.0; duration: 1500; easing.type:"OutBounce" }
+ }
+
+ texture: "textures/qtlogo.png"
+
+ SequentialAnimation on color{
+ running: true
+ loops: Animation.Infinite
+ ColorAnimation {
+ from: "#00008a"
+ to: "#003333"
+ duration: 5000
+ }
+ ColorAnimation {
+ from: "#003333"
+ to: "#00008a"
+ duration: 5000
+ }
+ }
+
+ vertexShader: "
+ attribute highp vec4 qt_Vertex;
+ attribute highp vec4 qt_MultiTexCoord0;
+ uniform mediump mat4 qt_ModelViewProjectionMatrix;
+ varying highp vec4 texCoord;
+ uniform highp float qt_Custom;
+
+ void main(void)
+ {
+ gl_Position = qt_ModelViewProjectionMatrix * (qt_Vertex *
+ vec4(1.0, qt_Custom, 1.0, 1.0));
+ texCoord = -qt_MultiTexCoord0 + vec4(qt_Custom, 0.0, 0.0, 0.0);
+
+ }
+ "
+ fragmentShader: "
+ varying highp vec4 texCoord;
+ uniform sampler2D qt_Texture0;
+ uniform mediump vec4 qt_Color;
+
+ void main(void)
+ {
+ mediump vec4 col = texture2D(qt_Texture0, texCoord.st);
+ gl_FragColor = vec4(clamp(qt_Color.rgb * (1.0 - col.a) +
+ col.rgb, 0.0, 1.0), 1.0);
+ }
+ "
+ }
+}
+
+}
diff --git a/demos/declarative/teapot-shader-collapsing.qml b/demos/declarative/teapot-shader-collapsing.qml
new file mode 100644
index 000000000..1ee799885
--- /dev/null
+++ b/demos/declarative/teapot-shader-collapsing.qml
@@ -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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Viewport {
+ width: 640; height: 480
+
+Item3D {
+ mesh: Mesh { source: "meshes/teapot.bez" }
+ effect: program
+
+ transform: Rotation3D {
+ NumberAnimation on angle{
+ running: true
+ loops: Animation.Infinite
+ from: 0
+ to: 360
+ duration: 8000
+ }
+ axis: Qt.vector3d(1, -0.3, 0)
+ }
+
+ ShaderProgram {
+ id: program
+ property real collapseFactor : 0.0
+
+ SequentialAnimation on collapseFactor {
+ running: true
+ loops: Animation.Infinite
+ PauseAnimation { duration: 700 }
+ NumberAnimation { from: 0.0; to: 1.0; duration: 1500; easing.type:"OutBounce" }
+ PauseAnimation { duration: 700 }
+ NumberAnimation { from: 1.0; to: 0.0; duration: 1500; easing.type:"OutBounce" }
+ }
+ texture: "textures/qtlogo.png"
+
+ SequentialAnimation on color{
+ running: true
+ loops: Animation.Infinite
+ ColorAnimation {
+ from: "#00008a"
+ to: "#003333"
+ duration: 5000
+ }
+ ColorAnimation {
+ from: "#003333"
+ to: "#00008a"
+ duration: 5000
+ }
+ }
+
+ vertexShader: "
+ attribute highp vec4 qt_Vertex;
+ attribute highp vec4 qt_MultiTexCoord0;
+ uniform mediump mat4 qt_ModelViewProjectionMatrix;
+ varying highp vec4 texCoord;
+ uniform highp float collapseFactor;
+
+ void main(void)
+ {
+ // Interpolate between the actual position of the input vertex
+ // and treating the tex-coordinates as vertex positions to
+ // create a neat collapsing effect.
+ vec4 workingPosition = mix( qt_Vertex, vec4(-qt_MultiTexCoord0.xyz, 1.0) , collapseFactor);
+ gl_Position = qt_ModelViewProjectionMatrix * workingPosition;
+ texCoord = -qt_MultiTexCoord0;
+ }
+ "
+ fragmentShader: "
+ varying highp vec4 texCoord;
+ uniform sampler2D qt_Texture0;
+ uniform mediump vec4 qt_Color;
+
+ void main(void)
+ {
+ mediump vec4 col = texture2D(qt_Texture0, texCoord.st);
+ gl_FragColor = vec4(clamp(qt_Color.rgb * (1.0 - col.a) +
+ col.rgb, 0.0, 1.0), 1.0);
+ }
+ "
+ }
+ }
+}
diff --git a/demos/declarative/teapot-shader-images.qml b/demos/declarative/teapot-shader-images.qml
new file mode 100644
index 000000000..292c7f940
--- /dev/null
+++ b/demos/declarative/teapot-shader-images.qml
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Rectangle {
+ width: 640; height: 480
+ id: top
+ color: "black"
+
+ property bool flag : true
+
+ // This is a the Qt Logo fetched from wikipedia.
+ property string imageUrl: flag ?
+ "http://upload.wikimedia.org/wikipedia/en/thumb/4/4e/Qt_Development_Frameworks_logo.svg/220px-Qt_Development_Frameworks_logo.svg.png" :
+ "textures/basket.jpg"
+
+ Image {
+ id: myChangingImage
+ source: imageUrl
+ }
+
+ Viewport {
+ anchors.fill: parent
+
+ MouseArea
+ {
+ anchors.fill: parent
+ onClicked: top.flag = !top.flag
+ }
+
+ Item3D {
+ mesh: Mesh { source: "meshes/teapot.bez" }
+ effect: shaderEffect
+
+ transform: Rotation3D {
+ NumberAnimation on angle{
+ running: true
+ loops: Animation.Infinite
+ from: 0
+ to: 360
+ duration: 18000
+ }
+ axis: Qt.vector3d(1, -0.3, 0)
+ }
+ }
+
+ ShaderProgram {
+ id: shaderEffect
+ property alias myBoolean : top.flag
+ property variant textureOffset : Qt.size(textureOffsetX * 5, 0.0)
+ property real textureOffsetX : 0.0
+
+
+ // Default texture that the shaderprogram will get until something else
+ // is bound:
+ texture: "textures/qtlogo.png"
+
+ // This property is automatically hooked up to the image uniform
+ // in the shader program below.
+ property string image : imageUrl
+
+ SequentialAnimation on textureOffsetX {
+ running: true
+ loops: Animation.Infinite
+ PauseAnimation { duration: 2500 }
+ NumberAnimation { from: 0.0; to: 1.0; duration: 1500; easing.type:"OutBounce" }
+ PauseAnimation { duration: 2500 }
+ NumberAnimation { from: 1.0; to: 0.0; duration: 1500; easing.type:"OutBounce" }
+ }
+
+ vertexShader: "
+ attribute highp vec4 qt_Vertex;
+ attribute highp vec4 qt_MultiTexCoord0;
+ uniform mediump mat4 qt_ModelViewProjectionMatrix;
+ varying highp vec4 texCoord;
+
+ uniform mediump vec2 textureOffset;
+
+ void main(void)
+ {
+ gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;
+ texCoord = -qt_MultiTexCoord0 + vec4(textureOffset.x, textureOffset.y, 0.0, 0.0);
+ }
+ "
+
+ fragmentShader: "
+ varying highp vec4 texCoord;
+ uniform sampler2D qt_Texture0;
+ uniform bool myBoolean;
+
+ // This image uniform is automatically associated with the image
+ // property of the shader program.
+ uniform sampler2D image;
+
+ void main(void)
+ {
+ mediump vec4 imageColor = texture2D(image, texCoord.st);
+ gl_FragColor = imageColor;
+ }
+ "
+ }
+ }
+}
diff --git a/demos/declarative/teapot-shader.qml b/demos/declarative/teapot-shader.qml
new file mode 100644
index 000000000..202a04103
--- /dev/null
+++ b/demos/declarative/teapot-shader.qml
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Viewport {
+ width: 640; height: 480
+
+Item3D {
+ mesh: Mesh { source: "meshes/teapot.bez" }
+ effect: program
+
+ transform: Rotation3D {
+ NumberAnimation on angle{
+ running: true
+ loops: Animation.Infinite
+ from: 0
+ to: 360
+ duration: 5000
+ }
+ axis: Qt.vector3d(1, -0.3, 0)
+ }
+
+ ShaderProgram {
+ id: program
+ texture: "textures/basket.jpg"
+ property variant texture2 : "textures/qtlogo.png"
+ property real interpolationFactor : 1.0
+
+ SequentialAnimation on interpolationFactor {
+ running: true
+ loops: Animation.Infinite
+ NumberAnimation { to : 1.0; duration: 750; }
+
+
+ PauseAnimation { duration: 550 }
+ NumberAnimation { to : 0.0; duration: 750; }
+ PauseAnimation { duration: 550 }
+ }
+
+ SequentialAnimation on color{
+ running: true
+ loops: Animation.Infinite
+ ColorAnimation {
+ from: "#aaca00"
+ to: "#0033ca"
+ duration: 500
+ }
+ ColorAnimation {
+ from: "#0033ca"
+ to: "#aaca00"
+ duration: 500
+ }
+ }
+
+ vertexShader: "
+ attribute highp vec4 qt_Vertex;
+ attribute highp vec4 qt_MultiTexCoord0;
+ uniform mediump mat4 qt_ModelViewProjectionMatrix;
+ varying highp vec4 texCoord;
+
+ void main(void)
+ {
+ gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;
+ texCoord = qt_MultiTexCoord0;
+ }
+ "
+ fragmentShader: "
+ varying highp vec4 texCoord;
+ uniform sampler2D qt_Texture0;
+ uniform sampler2D texture2;
+ uniform mediump vec4 qt_Color;
+ uniform mediump float interpolationFactor;
+
+ void main(void)
+ {
+ mediump vec4 col1 = texture2D(qt_Texture0, texCoord.st);
+ mediump vec4 col2 = texture2D(texture2, texCoord.st);
+ gl_FragColor = mix(col1, col2, interpolationFactor);
+ }
+ "
+ }
+}
+
+}
diff --git a/demos/declarative/teapot.qml b/demos/declarative/teapot.qml
new file mode 100644
index 000000000..ebb126c01
--- /dev/null
+++ b/demos/declarative/teapot.qml
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Viewport {
+ width: 640; height: 480
+ Item3D {
+ mesh: Mesh { source: "meshes/teapot.bez" }
+ effect: Effect {}
+ }
+}
diff --git a/demos/declarative/teaservice/Teacup.qml b/demos/declarative/teaservice/Teacup.qml
new file mode 100644
index 000000000..f4c868253
--- /dev/null
+++ b/demos/declarative/teaservice/Teacup.qml
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Item3D {
+ id: top
+ property real spoonY
+ property bool bounce: false
+
+ Item3D {
+ mesh: teacup_mesh
+ effect: Effect {
+ material: china
+ }
+
+ onHoverEnter: { effect.material = china_highlight }
+ onHoverLeave: { effect.material = china }
+ onClicked: { top.bounce = true }
+
+ y: top.spoonY
+ }
+
+ SequentialAnimation on spoonY {
+ running: top.bounce
+ NumberAnimation { to : 1; duration: 300; easing.type:"OutQuad" }
+ NumberAnimation { to : 0; duration: 300; easing.type:"OutBounce" }
+ onCompleted: top.bounce = false
+ }
+}
diff --git a/demos/declarative/teaservice/Teaspoon.qml b/demos/declarative/teaservice/Teaspoon.qml
new file mode 100644
index 000000000..72125f4be
--- /dev/null
+++ b/demos/declarative/teaservice/Teaspoon.qml
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Item3D {
+ id: "top"
+ property real saucerY
+ Item3D {
+ id: teaspoon1
+ property real y_lift
+ y: Math.max(y_lift,top.saucerY)
+ transform: Rotation3D {
+ angle: 275
+ axis: Qt.vector3d(1, 0, 0)
+ }
+ mesh: teaspoon_mesh
+ effect: Effect {
+ material: metal
+ }
+ property bool bounce: false
+
+ onHoverEnter: { effect.material = metal_highlight }
+ onHoverLeave: { effect.material = metal }
+ onClicked: { teaspoon1.bounce = true }
+
+ SequentialAnimation on y_lift {
+ running: teaspoon1.bounce
+ NumberAnimation { to : 1; duration: 300; easing.type:"OutQuad" }
+ NumberAnimation { to : 0; duration: 300; easing.type:"OutBounce" }
+ onCompleted: teaspoon1.bounce = false
+ }
+ }
+}
diff --git a/demos/declarative/teaservice/teacup.bez b/demos/declarative/teaservice/teacup.bez
new file mode 100644
index 000000000..f4dde3efd
--- /dev/null
+++ b/demos/declarative/teaservice/teacup.bez
@@ -0,0 +1,280 @@
+26
+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
+4,17,18,19,8,20,21,22,12,23,24,25,16,26,27,28
+19,29,30,31,22,32,33,34,25,35,36,37,28,38,39,40
+31,41,42,1,34,43,44,5,37,45,46,9,40,47,48,13
+13,14,15,16,49,50,51,52,53,54,55,56,57,58,59,60
+16,26,27,28,52,61,62,63,56,64,65,66,60,67,68,69
+28,38,39,40,63,70,71,72,66,73,74,75,69,76,77,78
+40,47,48,13,72,79,80,49,75,81,82,53,78,83,84,57
+193,194,195,196,197,198,199,200,201,202,203,204,1,2,3,4
+196,205,206,207,200,208,209,210,204,211,212,213,4,17,18,19
+207,214,215,216,210,217,218,219,213,220,221,222,19,29,30,31
+216,223,224,193,219,225,226,197,222,227,228,201,31,41,42,1
+229,230,231,28,232,233,234,235,236,237,238,239,240,241,242,243
+28,244,245,229,235,246,247,232,239,248,249,236,243,250,251,240
+57,58,59,60,85,86,87,88,89,90,91,92,93,94,95,96
+60,67,68,69,88,97,98,99,92,100,101,102,96,103,104,105
+69,76,77,78,99,106,107,108,102,109,110,111,105,112,113,114
+78,83,84,57,108,115,116,85,111,117,118,89,114,119,120,93
+93,94,95,96,121,122,123,124,125,126,127,128,129,130,131,132
+96,103,104,105,124,133,134,135,128,136,137,138,132,139,140,141
+105,112,113,114,135,142,143,144,138,145,146,147,141,148,149,150
+114,119,120,93,144,151,152,121,147,153,154,125,150,155,156,129
+129,130,131,132,157,158,159,160,161,162,163,164,165,166,167,168
+132,139,140,141,160,169,170,171,164,172,173,174,168,175,176,177
+141,148,149,150,171,178,179,180,174,181,182,183,177,184,185,186
+150,155,156,129,180,187,188,157,183,189,190,161,186,191,192,165
+251
+0.409091,0.772727,0.0
+0.409091,0.772727,-0.229091
+0.229091,0.772727,-0.409091
+0.0,0.772727,-0.409091
+0.409091,0.886364,0.0
+0.409091,0.886364,-0.229091
+0.229091,0.886364,-0.409091
+0.0,0.886364,-0.409091
+0.454545,0.886364,0.0
+0.454545,0.886364,-0.254545
+0.254545,0.886364,-0.454545
+0.0,0.886364,-0.454545
+0.454545,0.772727,0.0
+0.454545,0.772727,-0.254545
+0.254545,0.772727,-0.454545
+0.0,0.772727,-0.454545
+-0.229091,0.772727,-0.409091
+-0.409091,0.772727,-0.229091
+-0.409091,0.772727,0.0
+-0.229091,0.886364,-0.409091
+-0.409091,0.886364,-0.229091
+-0.409091,0.886364,0.0
+-0.254545,0.886364,-0.454545
+-0.454545,0.886364,-0.254545
+-0.454545,0.886364,0.0
+-0.254545,0.772727,-0.454545
+-0.454545,0.772727,-0.254545
+-0.454545,0.772727,0.0
+-0.409091,0.772727,0.229091
+-0.229091,0.772727,0.409091
+0.0,0.772727,0.409091
+-0.409091,0.886364,0.229091
+-0.229091,0.886364,0.409091
+0.0,0.886364,0.409091
+-0.454545,0.886364,0.254545
+-0.254545,0.886364,0.454545
+0.0,0.886364,0.454545
+-0.454545,0.772727,0.254545
+-0.254545,0.772727,0.454545
+0.0,0.772727,0.454545
+0.229091,0.772727,0.409091
+0.409091,0.772727,0.229091
+0.229091,0.886364,0.409091
+0.409091,0.886364,0.229091
+0.254545,0.886364,0.454545
+0.454545,0.886364,0.254545
+0.254545,0.772727,0.454545
+0.454545,0.772727,0.254545
+0.454545,0.545455,0.0
+0.454545,0.545455,-0.254545
+0.254545,0.545455,-0.454545
+0.0,0.545455,-0.454545
+0.454545,0.272727,0.0
+0.454545,0.272727,-0.254545
+0.254545,0.272727,-0.454545
+0.0,0.272727,-0.454545
+0.318182,0.0454545,0.0
+0.318182,0.0454545,-0.178182
+0.178182,0.0454545,-0.318182
+0.0,0.0454545,-0.318182
+-0.254545,0.545455,-0.454545
+-0.454545,0.545455,-0.254545
+-0.454545,0.545455,0.0
+-0.254545,0.272727,-0.454545
+-0.454545,0.272727,-0.254545
+-0.454545,0.272727,0.0
+-0.178182,0.0454545,-0.318182
+-0.318182,0.0454545,-0.178182
+-0.318182,0.0454545,0.0
+-0.454545,0.545455,0.254545
+-0.254545,0.545455,0.454545
+0.0,0.545455,0.454545
+-0.454545,0.272727,0.254545
+-0.254545,0.272727,0.454545
+0.0,0.272727,0.454545
+-0.318182,0.0454545,0.178182
+-0.178182,0.0454545,0.318182
+0.0,0.0454545,0.318182
+0.254545,0.545455,0.454545
+0.454545,0.545455,0.254545
+0.254545,0.272727,0.454545
+0.454545,0.272727,0.254545
+0.178182,0.0454545,0.318182
+0.318182,0.0454545,0.178182
+0.545455,0.0454545,0.0
+0.545455,0.0454545,-0.305455
+0.305455,0.0454545,-0.545455
+0.0,0.0454545,-0.545455
+0.727273,0.136364,0.0
+0.727273,0.136364,-0.407273
+0.407273,0.136364,-0.727273
+0.0,0.136364,-0.727273
+0.909091,0.136364,0.0
+0.909091,0.136364,-0.509091
+0.509091,0.136364,-0.909091
+0.0,0.136364,-0.909091
+-0.305455,0.0454545,-0.545455
+-0.545455,0.0454545,-0.305455
+-0.545455,0.0454545,0.0
+-0.407273,0.136364,-0.727273
+-0.727273,0.136364,-0.407273
+-0.727273,0.136364,0.0
+-0.509091,0.136364,-0.909091
+-0.909091,0.136364,-0.509091
+-0.909091,0.136364,0.0
+-0.545455,0.0454545,0.305455
+-0.305455,0.0454545,0.545455
+0.0,0.0454545,0.545455
+-0.727273,0.136364,0.407273
+-0.407273,0.136364,0.727273
+0.0,0.136364,0.727273
+-0.909091,0.136364,0.509091
+-0.509091,0.136364,0.909091
+0.0,0.136364,0.909091
+0.305455,0.0454545,0.545455
+0.545455,0.0454545,0.305455
+0.407273,0.136364,0.727273
+0.727273,0.136364,0.407273
+0.509091,0.136364,0.909091
+0.909091,0.136364,0.509091
+1.0,0.136364,0.0
+1.0,0.136364,-0.56
+0.56,0.136364,-1.0
+0.0,0.136364,-1.0
+1.0,0.0909091,0.0
+1.0,0.0909091,-0.56
+0.56,0.0909091,-1.0
+0.0,0.0909091,-1.0
+0.909091,0.0909091,0.0
+0.909091,0.0909091,-0.509091
+0.509091,0.0909091,-0.909091
+0.0,0.0909091,-0.909091
+-0.56,0.136364,-1.0
+-1.0,0.136364,-0.56
+-1.0,0.136364,0.0
+-0.56,0.0909091,-1.0
+-1.0,0.0909091,-0.56
+-1.0,0.0909091,0.0
+-0.509091,0.0909091,-0.909091
+-0.909091,0.0909091,-0.509091
+-0.909091,0.0909091,0.0
+-1.0,0.136364,0.56
+-0.56,0.136364,1.0
+0.0,0.136364,1.0
+-1.0,0.0909091,0.56
+-0.56,0.0909091,1.0
+0.0,0.0909091,1.0
+-0.909091,0.0909091,0.509091
+-0.509091,0.0909091,0.909091
+0.0,0.0909091,0.909091
+0.56,0.136364,1.0
+1.0,0.136364,0.56
+0.56,0.0909091,1.0
+1.0,0.0909091,0.56
+0.509091,0.0909091,0.909091
+0.909091,0.0909091,0.509091
+0.727273,0.0909091,0.0
+0.727273,0.0909091,-0.407273
+0.407273,0.0909091,-0.727273
+0.0,0.0909091,-0.727273
+0.545455,0.0,0.0
+0.545455,0.0,-0.305455
+0.305455,0.0,-0.545455
+0.0,0.0,-0.545455
+0.318182,0.0,0.0
+0.318182,0.0,-0.178182
+0.178182,0.0,-0.318182
+0.0,0.0,-0.318182
+-0.407273,0.0909091,-0.727273
+-0.727273,0.0909091,-0.407273
+-0.727273,0.0909091,0.0
+-0.305455,0.0,-0.545455
+-0.545455,0.0,-0.305455
+-0.545455,0.0,0.0
+-0.178182,0.0,-0.318182
+-0.318182,0.0,-0.178182
+-0.318182,0.0,0.0
+-0.727273,0.0909091,0.407273
+-0.407273,0.0909091,0.727273
+0.0,0.0909091,0.727273
+-0.545455,0.0,0.305455
+-0.305455,0.0,0.545455
+0.0,0.0,0.545455
+-0.318182,0.0,0.178182
+-0.178182,0.0,0.318182
+0.0,0.0,0.318182
+0.407273,0.0909091,0.727273
+0.727273,0.0909091,0.407273
+0.305455,0.0,0.545455
+0.545455,0.0,0.305455
+0.178182,0.0,0.318182
+0.318182,0.0,0.178182
+0.272727,0.0454545,0.0
+0.272727,0.0454545,-0.152727
+0.152727,0.0454545,-0.272727
+0.0,0.0454545,-0.272727
+0.409091,0.272727,0.0
+0.409091,0.272727,-0.229091
+0.229091,0.272727,-0.409091
+0.0,0.272727,-0.409091
+0.409091,0.545455,0.0
+0.409091,0.545455,-0.229091
+0.229091,0.545455,-0.409091
+0.0,0.545455,-0.409091
+-0.152727,0.0454545,-0.272727
+-0.272727,0.0454545,-0.152727
+-0.272727,0.0454545,0.0
+-0.229091,0.272727,-0.409091
+-0.409091,0.272727,-0.229091
+-0.409091,0.272727,0.0
+-0.229091,0.545455,-0.409091
+-0.409091,0.545455,-0.229091
+-0.409091,0.545455,0.0
+-0.272727,0.0454545,0.152727
+-0.152727,0.0454545,0.272727
+0.0,0.0454545,0.272727
+-0.409091,0.272727,0.229091
+-0.229091,0.272727,0.409091
+0.0,0.272727,0.409091
+-0.409091,0.545455,0.229091
+-0.229091,0.545455,0.409091
+0.0,0.545455,0.409091
+0.152727,0.0454545,0.272727
+0.272727,0.0454545,0.152727
+0.229091,0.272727,0.409091
+0.409091,0.272727,0.229091
+0.229091,0.545455,0.409091
+0.409091,0.545455,0.229091
+-0.454545,0.704545,0.0
+-0.454545,0.704545,-0.0454545
+-0.454545,0.772727,-0.0454545
+-0.772727,0.863636,0.0
+-0.772727,0.863636,-0.0454545
+-0.818182,0.954545,-0.0454545
+-0.818182,0.954545,0.0
+-0.772727,0.522727,0.0
+-0.772727,0.522727,-0.0454545
+-0.909091,0.477273,-0.0454545
+-0.909091,0.477273,0.0
+-0.409091,0.363636,0.0
+-0.409091,0.363636,-0.0454545
+-0.409091,0.295455,-0.0454545
+-0.409091,0.295455,0.0
+-0.454545,0.772727,0.0454545
+-0.454545,0.704545,0.0454545
+-0.818182,0.954545,0.0454545
+-0.772727,0.863636,0.0454545
+-0.909091,0.477273,0.0454545
+-0.772727,0.522727,0.0454545
+-0.409091,0.295455,0.0454545
+-0.409091,0.363636,0.0454545
+# reverse-patches
diff --git a/demos/declarative/teaservice/teapot-body.bez b/demos/declarative/teaservice/teapot-body.bez
new file mode 100644
index 000000000..614daf09b
--- /dev/null
+++ b/demos/declarative/teaservice/teapot-body.bez
@@ -0,0 +1,332 @@
+24
+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
+4,17,18,19,8,20,21,22,12,23,24,25,16,26,27,28
+19,29,30,31,22,32,33,34,25,35,36,37,28,38,39,40
+31,41,42,1,34,43,44,5,37,45,46,9,40,47,48,13
+13,14,15,16,49,50,51,52,53,54,55,56,57,58,59,60
+16,26,27,28,52,61,62,63,56,64,65,66,60,67,68,69
+28,38,39,40,63,70,71,72,66,73,74,75,69,76,77,78
+40,47,48,13,72,79,80,49,75,81,82,53,78,83,84,57
+57,58,59,60,85,86,87,88,89,90,91,92,93,94,95,96
+60,67,68,69,88,97,98,99,92,100,101,102,96,103,104,105
+69,76,77,78,99,106,107,108,102,109,110,111,105,112,113,114
+78,83,84,57,108,115,116,85,111,117,118,89,114,119,120,93
+204,204,204,204,207,208,209,210,211,211,211,211,212,213,214,215,4
+204,204,204,204,210,217,218,219,211,211,211,211,215,220,221,222,4
+204,204,204,204,219,224,225,226,211,211,211,211,222,227,228,229,4
+204,204,204,204,226,230,231,207,211,211,211,211,229,232,233,212,4
+212,213,214,215,234,235,236,237,238,239,240,241,242,243,244,245
+215,220,221,222,237,246,247,248,241,249,250,251,245,252,253,254
+222,227,228,229,248,255,256,257,251,258,259,260,254,261,262,263
+229,232,233,212,257,264,265,234,260,266,267,238,263,268,269,242
+270,270,270,270,279,280,281,282,275,276,277,278,271,272,273,274,4
+270,270,270,270,282,289,290,291,278,286,287,288,274,283,284,285,4
+270,270,270,270,291,298,299,300,288,295,296,297,285,292,293,294,4
+270,270,270,270,300,305,306,279,297,303,304,275,294,301,302,271,4
+306
+0.700000,0.450000,-0.000000
+0.700000,0.450000,0.392000
+0.392000,0.450000,0.700000
+0.000000,0.450000,0.700000
+0.668750,0.515625,-0.000000
+0.668750,0.515625,0.374500
+0.374500,0.515625,0.668750
+0.000000,0.515625,0.668750
+0.718750,0.515625,-0.000000
+0.718750,0.515625,0.402500
+0.402500,0.515625,0.718750
+0.000000,0.515625,0.718750
+0.750000,0.450000,-0.000000
+0.750000,0.450000,0.420000
+0.420000,0.450000,0.750000
+0.000000,0.450000,0.750000
+-0.392000,0.450000,0.700000
+-0.700000,0.450000,0.392000
+-0.700000,0.450000,-0.000000
+-0.374500,0.515625,0.668750
+-0.668750,0.515625,0.374500
+-0.668750,0.515625,-0.000000
+-0.402500,0.515625,0.718750
+-0.718750,0.515625,0.402500
+-0.718750,0.515625,-0.000000
+-0.420000,0.450000,0.750000
+-0.750000,0.450000,0.420000
+-0.750000,0.450000,-0.000000
+-0.700000,0.450000,-0.392000
+-0.392000,0.450000,-0.700000
+0.000000,0.450000,-0.700000
+-0.668750,0.515625,-0.374500
+-0.374500,0.515625,-0.668750
+0.000000,0.515625,-0.668750
+-0.718750,0.515625,-0.402500
+-0.402500,0.515625,-0.718750
+0.000000,0.515625,-0.718750
+-0.750000,0.450000,-0.420000
+-0.420000,0.450000,-0.750000
+0.000000,0.450000,-0.750000
+0.392000,0.450000,-0.700000
+0.700000,0.450000,-0.392000
+0.374500,0.515625,-0.668750
+0.668750,0.515625,-0.374500
+0.402500,0.515625,-0.718750
+0.718750,0.515625,-0.402500
+0.420000,0.450000,-0.750000
+0.750000,0.450000,-0.420000
+0.875000,0.187500,-0.000000
+0.875000,0.187500,0.490000
+0.490000,0.187500,0.875000
+0.000000,0.187500,0.875000
+1.000000,-0.075000,-0.000000
+1.000000,-0.075000,0.560000
+0.560000,-0.075000,1.000000
+0.000000,-0.075000,1.000000
+1.000000,-0.300000,-0.000000
+1.000000,-0.300000,0.560000
+0.560000,-0.300000,1.000000
+0.000000,-0.300000,1.000000
+-0.490000,0.187500,0.875000
+-0.875000,0.187500,0.490000
+-0.875000,0.187500,-0.000000
+-0.560000,-0.075000,1.000000
+-1.000000,-0.075000,0.560000
+-1.000000,-0.075000,-0.000000
+-0.560000,-0.300000,1.000000
+-1.000000,-0.300000,0.560000
+-1.000000,-0.300000,-0.000000
+-0.875000,0.187500,-0.490000
+-0.490000,0.187500,-0.875000
+0.000000,0.187500,-0.875000
+-1.000000,-0.075000,-0.560000
+-0.560000,-0.075000,-1.000000
+0.000000,-0.075000,-1.000000
+-1.000000,-0.300000,-0.560000
+-0.560000,-0.300000,-1.000000
+0.000000,-0.300000,-1.000000
+0.490000,0.187500,-0.875000
+0.875000,0.187500,-0.490000
+0.560000,-0.075000,-1.000000
+1.000000,-0.075000,-0.560000
+0.560000,-0.300000,-1.000000
+1.000000,-0.300000,-0.560000
+1.000000,-0.525000,-0.000000
+1.000000,-0.525000,0.560000
+0.560000,-0.525000,1.000000
+0.000000,-0.525000,1.000000
+0.750000,-0.637500,-0.000000
+0.750000,-0.637500,0.420000
+0.420000,-0.637500,0.750000
+0.000000,-0.637500,0.750000
+0.750000,-0.675000,-0.000000
+0.750000,-0.675000,0.420000
+0.420000,-0.675000,0.750000
+0.000000,-0.675000,0.750000
+-0.560000,-0.525000,1.000000
+-1.000000,-0.525000,0.560000
+-1.000000,-0.525000,-0.000000
+-0.420000,-0.637500,0.750000
+-0.750000,-0.637500,0.420000
+-0.750000,-0.637500,-0.000000
+-0.420000,-0.675000,0.750000
+-0.750000,-0.675000,0.420000
+-0.750000,-0.675000,-0.000000
+-1.000000,-0.525000,-0.560000
+-0.560000,-0.525000,-1.000000
+0.000000,-0.525000,-1.000000
+-0.750000,-0.637500,-0.420000
+-0.420000,-0.637500,-0.750000
+0.000000,-0.637500,-0.750000
+-0.750000,-0.675000,-0.420000
+-0.420000,-0.675000,-0.750000
+0.000000,-0.675000,-0.750000
+0.560000,-0.525000,-1.000000
+1.000000,-0.525000,-0.560000
+0.420000,-0.637500,-0.750000
+0.750000,-0.637500,-0.420000
+0.420000,-0.675000,-0.750000
+0.750000,-0.675000,-0.420000
+-0.800000,0.262500,-0.000000
+-0.800000,0.262500,0.150000
+-0.750000,0.375000,0.150000
+-0.750000,0.375000,-0.000000
+-1.150000,0.262500,-0.000000
+-1.150000,0.262500,0.150000
+-1.250000,0.375000,0.150000
+-1.250000,0.375000,-0.000000
+-1.350000,0.262500,-0.000000
+-1.350000,0.262500,0.150000
+-1.500000,0.375000,0.150000
+-1.500000,0.375000,-0.000000
+-1.350000,0.150000,-0.000000
+-1.350000,0.150000,0.150000
+-1.500000,0.150000,0.150000
+-1.500000,0.150000,-0.000000
+-0.750000,0.375000,-0.150000
+-0.800000,0.262500,-0.150000
+-1.250000,0.375000,-0.150000
+-1.150000,0.262500,-0.150000
+-1.500000,0.375000,-0.150000
+-1.350000,0.262500,-0.150000
+-1.500000,0.150000,-0.150000
+-1.350000,0.150000,-0.150000
+-1.350000,0.037500,-0.000000
+-1.350000,0.037500,0.150000
+-1.500000,-0.075000,0.150000
+-1.500000,-0.075000,-0.000000
+-1.250000,-0.187500,-0.000000
+-1.250000,-0.187500,0.150000
+-1.325000,-0.281250,0.150000
+-1.325000,-0.281250,-0.000000
+-1.000000,-0.300000,0.150000
+-0.950000,-0.450000,0.150000
+-0.950000,-0.450000,-0.000000
+-1.500000,-0.075000,-0.150000
+-1.350000,0.037500,-0.150000
+-1.325000,-0.281250,-0.150000
+-1.250000,-0.187500,-0.150000
+-0.950000,-0.450000,-0.150000
+-1.000000,-0.300000,-0.150000
+0.850000,-0.037500,-0.000000
+0.850000,-0.037500,0.330000
+0.850000,-0.450000,0.330000
+0.850000,-0.450000,-0.000000
+1.300000,-0.037500,-0.000000
+1.300000,-0.037500,0.330000
+1.550000,-0.337500,0.330000
+1.550000,-0.337500,-0.000000
+1.150000,0.300000,-0.000000
+1.150000,0.300000,0.125000
+1.200000,0.262500,0.125000
+1.200000,0.262500,-0.000000
+1.350000,0.450000,-0.000000
+1.350000,0.450000,0.125000
+1.650000,0.450000,0.125000
+1.650000,0.450000,-0.000000
+0.850000,-0.450000,-0.330000
+0.850000,-0.037500,-0.330000
+1.550000,-0.337500,-0.330000
+1.300000,-0.037500,-0.330000
+1.200000,0.262500,-0.125000
+1.150000,0.300000,-0.125000
+1.650000,0.450000,-0.125000
+1.350000,0.450000,-0.125000
+1.400000,0.487500,-0.000000
+1.400000,0.487500,0.125000
+1.762500,0.496875,0.125000
+1.762500,0.496875,-0.000000
+1.450000,0.487500,-0.000000
+1.450000,0.487500,0.075000
+1.725000,0.506250,0.075000
+1.725000,0.506250,-0.000000
+1.400000,0.450000,-0.000000
+1.400000,0.450000,0.075000
+1.600000,0.450000,0.075000
+1.600000,0.450000,-0.000000
+1.762500,0.496875,-0.125000
+1.400000,0.487500,-0.125000
+1.725000,0.506250,-0.075000
+1.450000,0.487500,-0.075000
+1.600000,0.450000,-0.075000
+1.400000,0.450000,-0.075000
+0.000000,0.825000,-0.000000
+0.000000,0.825000,0.001000
+0.001000,0.825000,-0.000000
+0.400000,0.825000,-0.000000
+0.400000,0.825000,0.225000
+0.225000,0.825000,0.400000
+0.000000,0.825000,0.400000
+0.000000,0.675000,-0.000000
+0.100000,0.600000,-0.000000
+0.100000,0.600000,0.056000
+0.056000,0.600000,0.100000
+0.000000,0.600000,0.100000
+-0.001000,0.825000,-0.000000
+-0.225000,0.825000,0.400000
+-0.400000,0.825000,0.225000
+-0.400000,0.825000,-0.000000
+-0.056000,0.600000,0.100000
+-0.100000,0.600000,0.056000
+-0.100000,0.600000,-0.000000
+0.000000,0.825000,-0.001000
+-0.400000,0.825000,-0.225000
+-0.225000,0.825000,-0.400000
+0.000000,0.825000,-0.400000
+-0.100000,0.600000,-0.056000
+-0.056000,0.600000,-0.100000
+0.000000,0.600000,-0.100000
+0.225000,0.825000,-0.400000
+0.400000,0.825000,-0.225000
+0.056000,0.600000,-0.100000
+0.100000,0.600000,-0.056000
+0.200000,0.525000,-0.000000
+0.200000,0.525000,0.112000
+0.112000,0.525000,0.200000
+0.000000,0.525000,0.200000
+0.650000,0.525000,-0.000000
+0.650000,0.525000,0.364000
+0.364000,0.525000,0.650000
+0.000000,0.525000,0.650000
+0.650000,0.450000,-0.000000
+0.650000,0.450000,0.364000
+0.364000,0.450000,0.650000
+0.000000,0.450000,0.650000
+-0.112000,0.525000,0.200000
+-0.200000,0.525000,0.112000
+-0.200000,0.525000,-0.000000
+-0.364000,0.525000,0.650000
+-0.650000,0.525000,0.364000
+-0.650000,0.525000,-0.000000
+-0.364000,0.450000,0.650000
+-0.650000,0.450000,0.364000
+-0.650000,0.450000,-0.000000
+-0.200000,0.525000,-0.112000
+-0.112000,0.525000,-0.200000
+0.000000,0.525000,-0.200000
+-0.650000,0.525000,-0.364000
+-0.364000,0.525000,-0.650000
+0.000000,0.525000,-0.650000
+-0.650000,0.450000,-0.364000
+-0.364000,0.450000,-0.650000
+0.000000,0.450000,-0.650000
+0.112000,0.525000,-0.200000
+0.200000,0.525000,-0.112000
+0.364000,0.525000,-0.650000
+0.650000,0.525000,-0.364000
+0.364000,0.450000,-0.650000
+0.650000,0.450000,-0.364000
+0.000000,-0.750000,-0.000000
+0.750000,-0.675000,-0.000000
+0.750000,-0.675000,-0.420000
+0.420000,-0.675000,-0.750000
+0.000000,-0.675000,-0.750000
+0.750000,-0.712500,-0.000000
+0.750000,-0.712500,-0.420000
+0.420000,-0.712500,-0.750000
+0.000000,-0.712500,-0.750000
+0.712500,-0.750000,-0.000000
+0.712500,-0.750000,-0.399000
+0.399000,-0.750000,-0.712500
+0.000000,-0.750000,-0.712500
+-0.420000,-0.675000,-0.750000
+-0.750000,-0.675000,-0.420000
+-0.750000,-0.675000,-0.000000
+-0.420000,-0.712500,-0.750000
+-0.750000,-0.712500,-0.420000
+-0.750000,-0.712500,-0.000000
+-0.399000,-0.750000,-0.712500
+-0.712500,-0.750000,-0.399000
+-0.712500,-0.750000,-0.000000
+-0.750000,-0.675000,0.420000
+-0.420000,-0.675000,0.750000
+0.000000,-0.675000,0.750000
+-0.750000,-0.712500,0.420000
+-0.420000,-0.712500,0.750000
+0.000000,-0.712500,0.750000
+-0.712500,-0.750000,0.399000
+-0.399000,-0.750000,0.712500
+0.000000,-0.750000,0.712500
+0.420000,-0.675000,0.750000
+0.750000,-0.675000,0.420000
+0.420000,-0.712500,0.750000
+0.750000,-0.712500,0.420000
+0.399000,-0.750000,0.712500
+0.712500,-0.750000,0.399000
diff --git a/demos/declarative/teaservice/teapot-handle.bez b/demos/declarative/teaservice/teapot-handle.bez
new file mode 100644
index 000000000..a2a3503ec
--- /dev/null
+++ b/demos/declarative/teaservice/teapot-handle.bez
@@ -0,0 +1,312 @@
+4
+121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136
+124,137,138,121,128,139,140,125,132,141,142,129,136,143,144,133
+133,134,135,136,145,146,147,148,149,150,151,152,69,153,154,155
+136,143,144,133,148,156,157,145,152,158,159,149,155,160,161,69
+306
+0.700000,0.450000,-0.000000
+0.700000,0.450000,0.392000
+0.392000,0.450000,0.700000
+0.000000,0.450000,0.700000
+0.668750,0.515625,-0.000000
+0.668750,0.515625,0.374500
+0.374500,0.515625,0.668750
+0.000000,0.515625,0.668750
+0.718750,0.515625,-0.000000
+0.718750,0.515625,0.402500
+0.402500,0.515625,0.718750
+0.000000,0.515625,0.718750
+0.750000,0.450000,-0.000000
+0.750000,0.450000,0.420000
+0.420000,0.450000,0.750000
+0.000000,0.450000,0.750000
+-0.392000,0.450000,0.700000
+-0.700000,0.450000,0.392000
+-0.700000,0.450000,-0.000000
+-0.374500,0.515625,0.668750
+-0.668750,0.515625,0.374500
+-0.668750,0.515625,-0.000000
+-0.402500,0.515625,0.718750
+-0.718750,0.515625,0.402500
+-0.718750,0.515625,-0.000000
+-0.420000,0.450000,0.750000
+-0.750000,0.450000,0.420000
+-0.750000,0.450000,-0.000000
+-0.700000,0.450000,-0.392000
+-0.392000,0.450000,-0.700000
+0.000000,0.450000,-0.700000
+-0.668750,0.515625,-0.374500
+-0.374500,0.515625,-0.668750
+0.000000,0.515625,-0.668750
+-0.718750,0.515625,-0.402500
+-0.402500,0.515625,-0.718750
+0.000000,0.515625,-0.718750
+-0.750000,0.450000,-0.420000
+-0.420000,0.450000,-0.750000
+0.000000,0.450000,-0.750000
+0.392000,0.450000,-0.700000
+0.700000,0.450000,-0.392000
+0.374500,0.515625,-0.668750
+0.668750,0.515625,-0.374500
+0.402500,0.515625,-0.718750
+0.718750,0.515625,-0.402500
+0.420000,0.450000,-0.750000
+0.750000,0.450000,-0.420000
+0.875000,0.187500,-0.000000
+0.875000,0.187500,0.490000
+0.490000,0.187500,0.875000
+0.000000,0.187500,0.875000
+1.000000,-0.075000,-0.000000
+1.000000,-0.075000,0.560000
+0.560000,-0.075000,1.000000
+0.000000,-0.075000,1.000000
+1.000000,-0.300000,-0.000000
+1.000000,-0.300000,0.560000
+0.560000,-0.300000,1.000000
+0.000000,-0.300000,1.000000
+-0.490000,0.187500,0.875000
+-0.875000,0.187500,0.490000
+-0.875000,0.187500,-0.000000
+-0.560000,-0.075000,1.000000
+-1.000000,-0.075000,0.560000
+-1.000000,-0.075000,-0.000000
+-0.560000,-0.300000,1.000000
+-1.000000,-0.300000,0.560000
+-1.000000,-0.300000,-0.000000
+-0.875000,0.187500,-0.490000
+-0.490000,0.187500,-0.875000
+0.000000,0.187500,-0.875000
+-1.000000,-0.075000,-0.560000
+-0.560000,-0.075000,-1.000000
+0.000000,-0.075000,-1.000000
+-1.000000,-0.300000,-0.560000
+-0.560000,-0.300000,-1.000000
+0.000000,-0.300000,-1.000000
+0.490000,0.187500,-0.875000
+0.875000,0.187500,-0.490000
+0.560000,-0.075000,-1.000000
+1.000000,-0.075000,-0.560000
+0.560000,-0.300000,-1.000000
+1.000000,-0.300000,-0.560000
+1.000000,-0.525000,-0.000000
+1.000000,-0.525000,0.560000
+0.560000,-0.525000,1.000000
+0.000000,-0.525000,1.000000
+0.750000,-0.637500,-0.000000
+0.750000,-0.637500,0.420000
+0.420000,-0.637500,0.750000
+0.000000,-0.637500,0.750000
+0.750000,-0.675000,-0.000000
+0.750000,-0.675000,0.420000
+0.420000,-0.675000,0.750000
+0.000000,-0.675000,0.750000
+-0.560000,-0.525000,1.000000
+-1.000000,-0.525000,0.560000
+-1.000000,-0.525000,-0.000000
+-0.420000,-0.637500,0.750000
+-0.750000,-0.637500,0.420000
+-0.750000,-0.637500,-0.000000
+-0.420000,-0.675000,0.750000
+-0.750000,-0.675000,0.420000
+-0.750000,-0.675000,-0.000000
+-1.000000,-0.525000,-0.560000
+-0.560000,-0.525000,-1.000000
+0.000000,-0.525000,-1.000000
+-0.750000,-0.637500,-0.420000
+-0.420000,-0.637500,-0.750000
+0.000000,-0.637500,-0.750000
+-0.750000,-0.675000,-0.420000
+-0.420000,-0.675000,-0.750000
+0.000000,-0.675000,-0.750000
+0.560000,-0.525000,-1.000000
+1.000000,-0.525000,-0.560000
+0.420000,-0.637500,-0.750000
+0.750000,-0.637500,-0.420000
+0.420000,-0.675000,-0.750000
+0.750000,-0.675000,-0.420000
+-0.800000,0.262500,-0.000000
+-0.800000,0.262500,0.150000
+-0.750000,0.375000,0.150000
+-0.750000,0.375000,-0.000000
+-1.150000,0.262500,-0.000000
+-1.150000,0.262500,0.150000
+-1.250000,0.375000,0.150000
+-1.250000,0.375000,-0.000000
+-1.350000,0.262500,-0.000000
+-1.350000,0.262500,0.150000
+-1.500000,0.375000,0.150000
+-1.500000,0.375000,-0.000000
+-1.350000,0.150000,-0.000000
+-1.350000,0.150000,0.150000
+-1.500000,0.150000,0.150000
+-1.500000,0.150000,-0.000000
+-0.750000,0.375000,-0.150000
+-0.800000,0.262500,-0.150000
+-1.250000,0.375000,-0.150000
+-1.150000,0.262500,-0.150000
+-1.500000,0.375000,-0.150000
+-1.350000,0.262500,-0.150000
+-1.500000,0.150000,-0.150000
+-1.350000,0.150000,-0.150000
+-1.350000,0.037500,-0.000000
+-1.350000,0.037500,0.150000
+-1.500000,-0.075000,0.150000
+-1.500000,-0.075000,-0.000000
+-1.250000,-0.187500,-0.000000
+-1.250000,-0.187500,0.150000
+-1.325000,-0.281250,0.150000
+-1.325000,-0.281250,-0.000000
+-1.000000,-0.300000,0.150000
+-0.950000,-0.450000,0.150000
+-0.950000,-0.450000,-0.000000
+-1.500000,-0.075000,-0.150000
+-1.350000,0.037500,-0.150000
+-1.325000,-0.281250,-0.150000
+-1.250000,-0.187500,-0.150000
+-0.950000,-0.450000,-0.150000
+-1.000000,-0.300000,-0.150000
+0.850000,-0.037500,-0.000000
+0.850000,-0.037500,0.330000
+0.850000,-0.450000,0.330000
+0.850000,-0.450000,-0.000000
+1.300000,-0.037500,-0.000000
+1.300000,-0.037500,0.330000
+1.550000,-0.337500,0.330000
+1.550000,-0.337500,-0.000000
+1.150000,0.300000,-0.000000
+1.150000,0.300000,0.125000
+1.200000,0.262500,0.125000
+1.200000,0.262500,-0.000000
+1.350000,0.450000,-0.000000
+1.350000,0.450000,0.125000
+1.650000,0.450000,0.125000
+1.650000,0.450000,-0.000000
+0.850000,-0.450000,-0.330000
+0.850000,-0.037500,-0.330000
+1.550000,-0.337500,-0.330000
+1.300000,-0.037500,-0.330000
+1.200000,0.262500,-0.125000
+1.150000,0.300000,-0.125000
+1.650000,0.450000,-0.125000
+1.350000,0.450000,-0.125000
+1.400000,0.487500,-0.000000
+1.400000,0.487500,0.125000
+1.762500,0.496875,0.125000
+1.762500,0.496875,-0.000000
+1.450000,0.487500,-0.000000
+1.450000,0.487500,0.075000
+1.725000,0.506250,0.075000
+1.725000,0.506250,-0.000000
+1.400000,0.450000,-0.000000
+1.400000,0.450000,0.075000
+1.600000,0.450000,0.075000
+1.600000,0.450000,-0.000000
+1.762500,0.496875,-0.125000
+1.400000,0.487500,-0.125000
+1.725000,0.506250,-0.075000
+1.450000,0.487500,-0.075000
+1.600000,0.450000,-0.075000
+1.400000,0.450000,-0.075000
+0.000000,0.825000,-0.000000
+0.000000,0.825000,0.001000
+0.001000,0.825000,-0.000000
+0.400000,0.825000,-0.000000
+0.400000,0.825000,0.225000
+0.225000,0.825000,0.400000
+0.000000,0.825000,0.400000
+0.000000,0.675000,-0.000000
+0.100000,0.600000,-0.000000
+0.100000,0.600000,0.056000
+0.056000,0.600000,0.100000
+0.000000,0.600000,0.100000
+-0.001000,0.825000,-0.000000
+-0.225000,0.825000,0.400000
+-0.400000,0.825000,0.225000
+-0.400000,0.825000,-0.000000
+-0.056000,0.600000,0.100000
+-0.100000,0.600000,0.056000
+-0.100000,0.600000,-0.000000
+0.000000,0.825000,-0.001000
+-0.400000,0.825000,-0.225000
+-0.225000,0.825000,-0.400000
+0.000000,0.825000,-0.400000
+-0.100000,0.600000,-0.056000
+-0.056000,0.600000,-0.100000
+0.000000,0.600000,-0.100000
+0.225000,0.825000,-0.400000
+0.400000,0.825000,-0.225000
+0.056000,0.600000,-0.100000
+0.100000,0.600000,-0.056000
+0.200000,0.525000,-0.000000
+0.200000,0.525000,0.112000
+0.112000,0.525000,0.200000
+0.000000,0.525000,0.200000
+0.650000,0.525000,-0.000000
+0.650000,0.525000,0.364000
+0.364000,0.525000,0.650000
+0.000000,0.525000,0.650000
+0.650000,0.450000,-0.000000
+0.650000,0.450000,0.364000
+0.364000,0.450000,0.650000
+0.000000,0.450000,0.650000
+-0.112000,0.525000,0.200000
+-0.200000,0.525000,0.112000
+-0.200000,0.525000,-0.000000
+-0.364000,0.525000,0.650000
+-0.650000,0.525000,0.364000
+-0.650000,0.525000,-0.000000
+-0.364000,0.450000,0.650000
+-0.650000,0.450000,0.364000
+-0.650000,0.450000,-0.000000
+-0.200000,0.525000,-0.112000
+-0.112000,0.525000,-0.200000
+0.000000,0.525000,-0.200000
+-0.650000,0.525000,-0.364000
+-0.364000,0.525000,-0.650000
+0.000000,0.525000,-0.650000
+-0.650000,0.450000,-0.364000
+-0.364000,0.450000,-0.650000
+0.000000,0.450000,-0.650000
+0.112000,0.525000,-0.200000
+0.200000,0.525000,-0.112000
+0.364000,0.525000,-0.650000
+0.650000,0.525000,-0.364000
+0.364000,0.450000,-0.650000
+0.650000,0.450000,-0.364000
+0.000000,-0.750000,-0.000000
+0.750000,-0.675000,-0.000000
+0.750000,-0.675000,-0.420000
+0.420000,-0.675000,-0.750000
+0.000000,-0.675000,-0.750000
+0.750000,-0.712500,-0.000000
+0.750000,-0.712500,-0.420000
+0.420000,-0.712500,-0.750000
+0.000000,-0.712500,-0.750000
+0.712500,-0.750000,-0.000000
+0.712500,-0.750000,-0.399000
+0.399000,-0.750000,-0.712500
+0.000000,-0.750000,-0.712500
+-0.420000,-0.675000,-0.750000
+-0.750000,-0.675000,-0.420000
+-0.750000,-0.675000,-0.000000
+-0.420000,-0.712500,-0.750000
+-0.750000,-0.712500,-0.420000
+-0.750000,-0.712500,-0.000000
+-0.399000,-0.750000,-0.712500
+-0.712500,-0.750000,-0.399000
+-0.712500,-0.750000,-0.000000
+-0.750000,-0.675000,0.420000
+-0.420000,-0.675000,0.750000
+0.000000,-0.675000,0.750000
+-0.750000,-0.712500,0.420000
+-0.420000,-0.712500,0.750000
+0.000000,-0.712500,0.750000
+-0.712500,-0.750000,0.399000
+-0.399000,-0.750000,0.712500
+0.000000,-0.750000,0.712500
+0.420000,-0.675000,0.750000
+0.750000,-0.675000,0.420000
+0.420000,-0.712500,0.750000
+0.750000,-0.712500,0.420000
+0.399000,-0.750000,0.712500
+0.712500,-0.750000,0.399000
diff --git a/demos/declarative/teaservice/teapot-spout.bez b/demos/declarative/teaservice/teapot-spout.bez
new file mode 100644
index 000000000..7674812ea
--- /dev/null
+++ b/demos/declarative/teaservice/teapot-spout.bez
@@ -0,0 +1,312 @@
+4
+162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177
+165,178,179,162,169,180,181,166,173,182,183,170,177,184,185,174
+174,175,176,177,186,187,188,189,190,191,192,193,194,195,196,197
+177,184,185,174,189,198,199,186,193,200,201,190,197,202,203,194
+306
+0.700000,0.450000,-0.000000
+0.700000,0.450000,0.392000
+0.392000,0.450000,0.700000
+0.000000,0.450000,0.700000
+0.668750,0.515625,-0.000000
+0.668750,0.515625,0.374500
+0.374500,0.515625,0.668750
+0.000000,0.515625,0.668750
+0.718750,0.515625,-0.000000
+0.718750,0.515625,0.402500
+0.402500,0.515625,0.718750
+0.000000,0.515625,0.718750
+0.750000,0.450000,-0.000000
+0.750000,0.450000,0.420000
+0.420000,0.450000,0.750000
+0.000000,0.450000,0.750000
+-0.392000,0.450000,0.700000
+-0.700000,0.450000,0.392000
+-0.700000,0.450000,-0.000000
+-0.374500,0.515625,0.668750
+-0.668750,0.515625,0.374500
+-0.668750,0.515625,-0.000000
+-0.402500,0.515625,0.718750
+-0.718750,0.515625,0.402500
+-0.718750,0.515625,-0.000000
+-0.420000,0.450000,0.750000
+-0.750000,0.450000,0.420000
+-0.750000,0.450000,-0.000000
+-0.700000,0.450000,-0.392000
+-0.392000,0.450000,-0.700000
+0.000000,0.450000,-0.700000
+-0.668750,0.515625,-0.374500
+-0.374500,0.515625,-0.668750
+0.000000,0.515625,-0.668750
+-0.718750,0.515625,-0.402500
+-0.402500,0.515625,-0.718750
+0.000000,0.515625,-0.718750
+-0.750000,0.450000,-0.420000
+-0.420000,0.450000,-0.750000
+0.000000,0.450000,-0.750000
+0.392000,0.450000,-0.700000
+0.700000,0.450000,-0.392000
+0.374500,0.515625,-0.668750
+0.668750,0.515625,-0.374500
+0.402500,0.515625,-0.718750
+0.718750,0.515625,-0.402500
+0.420000,0.450000,-0.750000
+0.750000,0.450000,-0.420000
+0.875000,0.187500,-0.000000
+0.875000,0.187500,0.490000
+0.490000,0.187500,0.875000
+0.000000,0.187500,0.875000
+1.000000,-0.075000,-0.000000
+1.000000,-0.075000,0.560000
+0.560000,-0.075000,1.000000
+0.000000,-0.075000,1.000000
+1.000000,-0.300000,-0.000000
+1.000000,-0.300000,0.560000
+0.560000,-0.300000,1.000000
+0.000000,-0.300000,1.000000
+-0.490000,0.187500,0.875000
+-0.875000,0.187500,0.490000
+-0.875000,0.187500,-0.000000
+-0.560000,-0.075000,1.000000
+-1.000000,-0.075000,0.560000
+-1.000000,-0.075000,-0.000000
+-0.560000,-0.300000,1.000000
+-1.000000,-0.300000,0.560000
+-1.000000,-0.300000,-0.000000
+-0.875000,0.187500,-0.490000
+-0.490000,0.187500,-0.875000
+0.000000,0.187500,-0.875000
+-1.000000,-0.075000,-0.560000
+-0.560000,-0.075000,-1.000000
+0.000000,-0.075000,-1.000000
+-1.000000,-0.300000,-0.560000
+-0.560000,-0.300000,-1.000000
+0.000000,-0.300000,-1.000000
+0.490000,0.187500,-0.875000
+0.875000,0.187500,-0.490000
+0.560000,-0.075000,-1.000000
+1.000000,-0.075000,-0.560000
+0.560000,-0.300000,-1.000000
+1.000000,-0.300000,-0.560000
+1.000000,-0.525000,-0.000000
+1.000000,-0.525000,0.560000
+0.560000,-0.525000,1.000000
+0.000000,-0.525000,1.000000
+0.750000,-0.637500,-0.000000
+0.750000,-0.637500,0.420000
+0.420000,-0.637500,0.750000
+0.000000,-0.637500,0.750000
+0.750000,-0.675000,-0.000000
+0.750000,-0.675000,0.420000
+0.420000,-0.675000,0.750000
+0.000000,-0.675000,0.750000
+-0.560000,-0.525000,1.000000
+-1.000000,-0.525000,0.560000
+-1.000000,-0.525000,-0.000000
+-0.420000,-0.637500,0.750000
+-0.750000,-0.637500,0.420000
+-0.750000,-0.637500,-0.000000
+-0.420000,-0.675000,0.750000
+-0.750000,-0.675000,0.420000
+-0.750000,-0.675000,-0.000000
+-1.000000,-0.525000,-0.560000
+-0.560000,-0.525000,-1.000000
+0.000000,-0.525000,-1.000000
+-0.750000,-0.637500,-0.420000
+-0.420000,-0.637500,-0.750000
+0.000000,-0.637500,-0.750000
+-0.750000,-0.675000,-0.420000
+-0.420000,-0.675000,-0.750000
+0.000000,-0.675000,-0.750000
+0.560000,-0.525000,-1.000000
+1.000000,-0.525000,-0.560000
+0.420000,-0.637500,-0.750000
+0.750000,-0.637500,-0.420000
+0.420000,-0.675000,-0.750000
+0.750000,-0.675000,-0.420000
+-0.800000,0.262500,-0.000000
+-0.800000,0.262500,0.150000
+-0.750000,0.375000,0.150000
+-0.750000,0.375000,-0.000000
+-1.150000,0.262500,-0.000000
+-1.150000,0.262500,0.150000
+-1.250000,0.375000,0.150000
+-1.250000,0.375000,-0.000000
+-1.350000,0.262500,-0.000000
+-1.350000,0.262500,0.150000
+-1.500000,0.375000,0.150000
+-1.500000,0.375000,-0.000000
+-1.350000,0.150000,-0.000000
+-1.350000,0.150000,0.150000
+-1.500000,0.150000,0.150000
+-1.500000,0.150000,-0.000000
+-0.750000,0.375000,-0.150000
+-0.800000,0.262500,-0.150000
+-1.250000,0.375000,-0.150000
+-1.150000,0.262500,-0.150000
+-1.500000,0.375000,-0.150000
+-1.350000,0.262500,-0.150000
+-1.500000,0.150000,-0.150000
+-1.350000,0.150000,-0.150000
+-1.350000,0.037500,-0.000000
+-1.350000,0.037500,0.150000
+-1.500000,-0.075000,0.150000
+-1.500000,-0.075000,-0.000000
+-1.250000,-0.187500,-0.000000
+-1.250000,-0.187500,0.150000
+-1.325000,-0.281250,0.150000
+-1.325000,-0.281250,-0.000000
+-1.000000,-0.300000,0.150000
+-0.950000,-0.450000,0.150000
+-0.950000,-0.450000,-0.000000
+-1.500000,-0.075000,-0.150000
+-1.350000,0.037500,-0.150000
+-1.325000,-0.281250,-0.150000
+-1.250000,-0.187500,-0.150000
+-0.950000,-0.450000,-0.150000
+-1.000000,-0.300000,-0.150000
+0.850000,-0.037500,-0.000000
+0.850000,-0.037500,0.330000
+0.850000,-0.450000,0.330000
+0.850000,-0.450000,-0.000000
+1.300000,-0.037500,-0.000000
+1.300000,-0.037500,0.330000
+1.550000,-0.337500,0.330000
+1.550000,-0.337500,-0.000000
+1.150000,0.300000,-0.000000
+1.150000,0.300000,0.125000
+1.200000,0.262500,0.125000
+1.200000,0.262500,-0.000000
+1.350000,0.450000,-0.000000
+1.350000,0.450000,0.125000
+1.650000,0.450000,0.125000
+1.650000,0.450000,-0.000000
+0.850000,-0.450000,-0.330000
+0.850000,-0.037500,-0.330000
+1.550000,-0.337500,-0.330000
+1.300000,-0.037500,-0.330000
+1.200000,0.262500,-0.125000
+1.150000,0.300000,-0.125000
+1.650000,0.450000,-0.125000
+1.350000,0.450000,-0.125000
+1.400000,0.487500,-0.000000
+1.400000,0.487500,0.125000
+1.762500,0.496875,0.125000
+1.762500,0.496875,-0.000000
+1.450000,0.487500,-0.000000
+1.450000,0.487500,0.075000
+1.725000,0.506250,0.075000
+1.725000,0.506250,-0.000000
+1.400000,0.450000,-0.000000
+1.400000,0.450000,0.075000
+1.600000,0.450000,0.075000
+1.600000,0.450000,-0.000000
+1.762500,0.496875,-0.125000
+1.400000,0.487500,-0.125000
+1.725000,0.506250,-0.075000
+1.450000,0.487500,-0.075000
+1.600000,0.450000,-0.075000
+1.400000,0.450000,-0.075000
+0.000000,0.825000,-0.000000
+0.000000,0.825000,0.001000
+0.001000,0.825000,-0.000000
+0.400000,0.825000,-0.000000
+0.400000,0.825000,0.225000
+0.225000,0.825000,0.400000
+0.000000,0.825000,0.400000
+0.000000,0.675000,-0.000000
+0.100000,0.600000,-0.000000
+0.100000,0.600000,0.056000
+0.056000,0.600000,0.100000
+0.000000,0.600000,0.100000
+-0.001000,0.825000,-0.000000
+-0.225000,0.825000,0.400000
+-0.400000,0.825000,0.225000
+-0.400000,0.825000,-0.000000
+-0.056000,0.600000,0.100000
+-0.100000,0.600000,0.056000
+-0.100000,0.600000,-0.000000
+0.000000,0.825000,-0.001000
+-0.400000,0.825000,-0.225000
+-0.225000,0.825000,-0.400000
+0.000000,0.825000,-0.400000
+-0.100000,0.600000,-0.056000
+-0.056000,0.600000,-0.100000
+0.000000,0.600000,-0.100000
+0.225000,0.825000,-0.400000
+0.400000,0.825000,-0.225000
+0.056000,0.600000,-0.100000
+0.100000,0.600000,-0.056000
+0.200000,0.525000,-0.000000
+0.200000,0.525000,0.112000
+0.112000,0.525000,0.200000
+0.000000,0.525000,0.200000
+0.650000,0.525000,-0.000000
+0.650000,0.525000,0.364000
+0.364000,0.525000,0.650000
+0.000000,0.525000,0.650000
+0.650000,0.450000,-0.000000
+0.650000,0.450000,0.364000
+0.364000,0.450000,0.650000
+0.000000,0.450000,0.650000
+-0.112000,0.525000,0.200000
+-0.200000,0.525000,0.112000
+-0.200000,0.525000,-0.000000
+-0.364000,0.525000,0.650000
+-0.650000,0.525000,0.364000
+-0.650000,0.525000,-0.000000
+-0.364000,0.450000,0.650000
+-0.650000,0.450000,0.364000
+-0.650000,0.450000,-0.000000
+-0.200000,0.525000,-0.112000
+-0.112000,0.525000,-0.200000
+0.000000,0.525000,-0.200000
+-0.650000,0.525000,-0.364000
+-0.364000,0.525000,-0.650000
+0.000000,0.525000,-0.650000
+-0.650000,0.450000,-0.364000
+-0.364000,0.450000,-0.650000
+0.000000,0.450000,-0.650000
+0.112000,0.525000,-0.200000
+0.200000,0.525000,-0.112000
+0.364000,0.525000,-0.650000
+0.650000,0.525000,-0.364000
+0.364000,0.450000,-0.650000
+0.650000,0.450000,-0.364000
+0.000000,-0.750000,-0.000000
+0.750000,-0.675000,-0.000000
+0.750000,-0.675000,-0.420000
+0.420000,-0.675000,-0.750000
+0.000000,-0.675000,-0.750000
+0.750000,-0.712500,-0.000000
+0.750000,-0.712500,-0.420000
+0.420000,-0.712500,-0.750000
+0.000000,-0.712500,-0.750000
+0.712500,-0.750000,-0.000000
+0.712500,-0.750000,-0.399000
+0.399000,-0.750000,-0.712500
+0.000000,-0.750000,-0.712500
+-0.420000,-0.675000,-0.750000
+-0.750000,-0.675000,-0.420000
+-0.750000,-0.675000,-0.000000
+-0.420000,-0.712500,-0.750000
+-0.750000,-0.712500,-0.420000
+-0.750000,-0.712500,-0.000000
+-0.399000,-0.750000,-0.712500
+-0.712500,-0.750000,-0.399000
+-0.712500,-0.750000,-0.000000
+-0.750000,-0.675000,0.420000
+-0.420000,-0.675000,0.750000
+0.000000,-0.675000,0.750000
+-0.750000,-0.712500,0.420000
+-0.420000,-0.712500,0.750000
+0.000000,-0.712500,0.750000
+-0.712500,-0.750000,0.399000
+-0.399000,-0.750000,0.712500
+0.000000,-0.750000,0.712500
+0.420000,-0.675000,0.750000
+0.750000,-0.675000,0.420000
+0.420000,-0.712500,0.750000
+0.750000,-0.712500,0.420000
+0.399000,-0.750000,0.712500
+0.712500,-0.750000,0.399000
diff --git a/demos/declarative/teaservice/teaservice.qml b/demos/declarative/teaservice/teaservice.qml
new file mode 100644
index 000000000..f549fd50f
--- /dev/null
+++ b/demos/declarative/teaservice/teaservice.qml
@@ -0,0 +1,382 @@
+/****************************************************************************
+**
+** 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 QtQuick3D examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor
+** the names of its contributors may be used to endorse or promote
+** products derived from this software without specific prior written
+** permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import Qt 4.7
+import Qt3D 1.0
+
+Viewport {
+ width: 850
+ height: 480
+ picking: true
+ //showPicking: true
+
+ camera: Camera {
+ eye: Qt.vector3d(0, 3, 10)
+ }
+
+ Item3D {
+ id: teapot
+ transform: [
+ Rotation3D {
+ id: teapot_rotate1
+ angle: 0
+ axis: Qt.vector3d(0, 1, 0)
+ },
+ Rotation3D {
+ id: teapot_rotate2
+ angle: 0
+ axis: Qt.vector3d(0, 0, 1)
+ }
+ ]
+ property bool bounce: false
+
+ Item3D {
+ id: body
+ mesh: Mesh { source: "teapot-body.bez" }
+ effect: Effect {
+ material: china
+ }
+
+ onHoverEnter: { effect.material = china_highlight }
+ onHoverLeave: { effect.material = china }
+ onClicked: { teapot.bounce = true }
+ }
+
+ Item3D {
+ id: handle
+ mesh: Mesh { source: "teapot-handle.bez" }
+ effect: Effect {
+ material: china
+ }
+
+ onHoverEnter: { effect.material = china_highlight }
+ onHoverLeave: { effect.material = china }
+ onClicked: {
+ if (teapot.state == "facing_left" ||
+ teapot.state == "pour_left") {
+ teapot.state = "facing_right";
+ } else if (teapot.state == "facing_right" ||
+ teapot.state == "pour_right") {
+ teapot_rotate1.angle = 0;
+ teapot.state = "facing_left";
+ } else {
+ teapot.state = "facing_left";
+ }
+ }
+ }
+
+ Item3D {
+ id: spout
+ mesh: Mesh { source: "teapot-spout.bez" }
+ effect: Effect {
+ material: china
+ }
+
+ onHoverEnter: { effect.material = china_highlight }
+ onHoverLeave: { effect.material = china }
+ onClicked: {
+ if (teapot.state == "facing_left") {
+ teapot.state = "pour_left";
+ } else if (teapot.state == "pour_left") {
+ teapot.state = "facing_left";
+ teapot.state = "pour_left";
+ } else if (teapot.state == "pour_right" ||
+ teapot.state == "facing_right") {
+ teapot.state = "";
+ teapot_rotate1.angle = 0;
+ teapot.state = "pour_right";
+ } else {
+ teapot.state = "pour_right";
+ }
+ }
+ }
+
+ SequentialAnimation on y{
+ running: teapot.bounce
+ NumberAnimation { to : 1.0; duration: 300; easing.type: "OutQuad" }
+ NumberAnimation { to : 0.0; duration: 300; easing.type: "OutBounce" }
+ onCompleted: teapot.bounce = false
+ }
+
+ states: [
+ State {
+ name: "facing_left"
+ PropertyChanges {
+ target: teapot_rotate1
+ angle: 180
+ }
+ },
+ State {
+ name: "facing_right"
+ PropertyChanges {
+ target: teapot_rotate1
+ angle: 360
+ }
+ },
+ State {
+ name: "pour_left"
+ PropertyChanges {
+ target: teapot
+ y: 0
+ }
+ PropertyChanges {
+ target: teapot
+ x: 0
+ }
+ PropertyChanges {
+ target: teapot_rotate1
+ angle: 180
+ }
+ PropertyChanges {
+ target: teapot_rotate2
+ angle: 0
+ }
+ },
+ State {
+ name: "pour_right"
+ PropertyChanges {
+ target: teapot
+ y: 0
+ }
+ PropertyChanges {
+ target: teapot
+ x: 0
+ }
+ PropertyChanges {
+ target: teapot_rotate2
+ angle: 0
+ }
+ }
+ ]
+
+ transitions: [
+ Transition {
+ from: "*"
+ to: "facing_left"
+ NumberAnimation {
+ targets: teapot_rotate1
+ properties: "angle"
+ duration: 300
+ }
+ },
+ Transition {
+ from: "*"
+ to: "facing_right"
+ NumberAnimation {
+ targets: teapot_rotate1
+ properties: "angle"
+ duration: 300
+ }
+ },
+ Transition {
+ from: "*"
+ to: "pour_left"
+ SequentialAnimation {
+ ParallelAnimation {
+ NumberAnimation {
+ target: teapot
+ property: "y"
+ duration: 500
+ to: 1
+ easing.type: "OutQuad"
+ }
+ NumberAnimation {
+ target: teapot
+ property: "x"
+ duration: 500
+ to: -0.5
+ easing.type: "OutQuad"
+ }
+ NumberAnimation {
+ target: teapot_rotate2
+ property: "angle"
+ duration: 500
+ to: 45
+ easing.type: "OutQuad"
+ }
+ }
+ PauseAnimation { duration: 700 }
+ ParallelAnimation {
+ NumberAnimation {
+ target: teapot
+ property: "y"
+ duration: 500
+ to: 0
+ easing.type: "OutQuad"
+ }
+ NumberAnimation {
+ target: teapot
+ property: "x"
+ duration: 500
+ to: 0
+ easing.type: "OutQuad"
+ }
+ NumberAnimation {
+ target: teapot_rotate2
+ property: "angle"
+ duration: 500
+ to: 0
+ easing.type: "OutQuad"
+ }
+ }
+ }
+ },
+ Transition {
+ from: "*"
+ to: "pour_right"
+ SequentialAnimation {
+ ParallelAnimation {
+ NumberAnimation {
+ target: teapot
+ property: "y"
+ duration: 500
+ to: 1
+ easing.type: "OutQuad"
+ }
+ NumberAnimation {
+ target: teapot
+ property: "x"
+ duration: 500
+ to: 0.5
+ easing.type: "OutQuad"
+ }
+ NumberAnimation {
+ target: teapot_rotate2
+ property: "angle"
+ duration: 500
+ to: -45
+ easing.type: "OutQuad"
+ }
+ }
+ PauseAnimation { duration: 700 }
+ ParallelAnimation {
+ NumberAnimation {
+ target: teapot
+ property: "y"
+ duration: 500
+ to: 0
+ easing.type: "OutQuad"
+ }
+ NumberAnimation {
+ target: teapot
+ property: "x"
+ duration: 500
+ to: 0
+ easing.type: "OutQuad"
+ }
+ NumberAnimation {
+ target: teapot_rotate2
+ property: "angle"
+ duration: 500
+ to: 0
+ easing.type: "OutQuad"
+ }
+ }
+ }
+ }
+ ]
+ }
+
+ Teacup {
+ id: teacup1
+ position: Qt.vector3d(-2.3, -0.75, 0.0)
+ }
+
+ Teacup {
+ id: teacup2
+ position: Qt.vector3d(2.3, -0.75, 0.0)
+ transform: Rotation3D {
+ angle: 180
+ axis: Qt.vector3d(0, 1, 0)
+ }
+ }
+
+ Teaspoon {
+ x: -1.7
+ y: -0.58
+ saucerY: teacup1.spoonY
+ }
+
+ Teaspoon {
+ x: 1.7
+ y: -0.58
+ saucerY: teacup2.spoonY
+ }
+
+ Mesh {
+ id: teacup_mesh
+ source: "teacup.bez"
+ }
+
+ Mesh {
+ id: teaspoon_mesh
+ source: "teaspoon.bez"
+ }
+
+ Material {
+ id: china
+ ambientColor: "#c09680"
+ specularColor: "#3c3c3c"
+ shininess: 128
+ }
+
+ Material {
+ id: china_highlight
+ ambientColor: "#ffc000"
+ specularColor: "#3c3c00"
+ shininess: 128
+ }
+
+ Material {
+ id: metal
+ ambientColor: "#ffffff"
+ diffuseColor: "#969696"
+ specularColor: "#ffffff"
+ shininess: 128
+ }
+
+ Material {
+ id: metal_highlight
+ ambientColor: "#ffff60"
+ diffuseColor: "#969660"
+ specularColor: "#ffffff"
+ shininess: 128
+ }
+}
diff --git a/demos/declarative/teaservice/teaservice.qmlproject b/demos/declarative/teaservice/teaservice.qmlproject
new file mode 100644
index 000000000..d4909f868
--- /dev/null
+++ b/demos/declarative/teaservice/teaservice.qmlproject
@@ -0,0 +1,16 @@
+import QmlProject 1.0
+
+Project {
+ /* Include .qml, .js, and image files from current directory and subdirectories */
+ QmlFiles {
+ directory: "."
+ }
+ JavaScriptFiles {
+ directory: "."
+ }
+ ImageFiles {
+ directory: "."
+ }
+ /* List of plugin directories passed to QML runtime */
+ // importPaths: [ " ../exampleplugin " ]
+}
diff --git a/demos/declarative/teaservice/teaspoon.bez b/demos/declarative/teaservice/teaspoon.bez
new file mode 100644
index 000000000..c304fbde0
--- /dev/null
+++ b/demos/declarative/teaservice/teaspoon.bez
@@ -0,0 +1,275 @@
+16
+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
+17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
+33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48
+49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64
+65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80
+81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96
+97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112
+113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128
+129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144
+145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160
+161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176
+177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192
+193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208
+209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224
+225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240
+241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256
+256
+-0.000107143,0.205357,0.0
+0.0,0.196429,-0.0178571
+0.0,0.196429,-0.0178571
+0.000107143,0.205357,0.0
+-0.0535714,0.205357,0.0
+-0.0222714,0.178571,-0.0534286
+0.0222714,0.178571,-0.0534286
+0.0535714,0.205357,0.0
+-0.107143,0.0952429,-0.0178571
+-0.0446429,0.0952429,-0.0892857
+0.0446429,0.0952429,-0.0892857
+0.107143,0.0952429,-0.0178571
+-0.107143,0.0,-0.0178571
+-0.0446429,0.0,-0.0892857
+0.0446429,0.0,-0.0892857
+0.107143,0.0,-0.0178571
+0.000107143,0.205357,0.0
+0.000135714,0.207589,0.00446429
+0.000157143,0.216518,0.00446429
+0.000125,0.214286,0.0
+0.0535714,0.205357,0.0
+0.0613964,0.212054,0.0133571
+0.0714286,0.220982,0.015625
+0.0625,0.214286,0.0
+0.107143,0.0952429,-0.0178571
+0.122768,0.0952429,0.0
+0.142857,0.0952429,0.00446429
+0.125,0.0952429,-0.0178571
+0.107143,0.0,-0.0178571
+0.122768,0.0,0.0
+0.142857,0.0,0.00446429
+0.125,0.0,-0.0178571
+0.000125,0.214286,0.0
+0.0,0.205357,-0.0178571
+0.0,0.205357,-0.0178571
+-0.000125,0.214286,0.0
+0.0625,0.214286,0.0
+0.0267857,0.1875,-0.0625
+-0.0267857,0.1875,-0.0625
+-0.0625,0.214286,0.0
+0.125,0.0952429,-0.0178571
+0.0535714,0.0952429,-0.107143
+-0.0535714,0.0952429,-0.107143
+-0.125,0.0952429,-0.0178571
+0.125,0.0,-0.0178571
+0.0535714,0.0,-0.107143
+-0.0535714,0.0,-0.107143
+-0.125,0.0,-0.0178571
+-0.000125,0.214286,0.0
+-0.000157143,0.216518,0.00446429
+-0.000135714,0.207589,0.00446429
+-0.000107143,0.205357,0.0
+-0.0625,0.214286,0.0
+-0.0714286,0.220982,0.015625
+-0.0613964,0.212054,0.0133571
+-0.0535714,0.205357,0.0
+-0.125,0.0952429,-0.0178571
+-0.142857,0.0952429,0.00446429
+-0.122768,0.0952429,0.0
+-0.107143,0.0952429,-0.0178571
+-0.125,0.0,-0.0178571
+-0.142857,0.0,0.00446429
+-0.122768,0.0,0.0
+-0.107143,0.0,-0.0178571
+-0.107143,0.0,-0.0178571
+-0.0446429,0.0,-0.0892857
+0.0446429,0.0,-0.0892857
+0.107143,0.0,-0.0178571
+-0.107143,-0.142857,-0.0178571
+-0.0446429,-0.142857,-0.0892857
+0.0446429,-0.142857,-0.0892857
+0.107143,-0.142857,-0.0178571
+-0.0133929,-0.160714,0.0386893
+-0.00557857,-0.160714,0.0386893
+0.00557857,-0.160714,0.0386893
+0.0133929,-0.160714,0.0386893
+-0.0133929,-0.25,0.0535714
+-0.00557857,-0.25,0.0535714
+0.00557857,-0.25,0.0535714
+0.0133929,-0.25,0.0535714
+0.107143,0.0,-0.0178571
+0.122768,0.0,0.0
+0.142857,0.0,0.00446429
+0.125,0.0,-0.0178571
+0.107143,-0.142857,-0.0178571
+0.122768,-0.142857,0.0
+0.142857,-0.142857,0.00446429
+0.125,-0.142857,-0.0178571
+0.0133929,-0.160714,0.0386893
+0.0153464,-0.160714,0.0386893
+0.0178571,-0.160714,0.0314357
+0.015625,-0.160714,0.0297607
+0.0133929,-0.25,0.0535714
+0.0153464,-0.25,0.0535714
+0.0178571,-0.25,0.0463179
+0.015625,-0.25,0.0446429
+0.125,0.0,-0.0178571
+0.0535714,0.0,-0.107143
+-0.0535714,0.0,-0.107143
+-0.125,0.0,-0.0178571
+0.125,-0.142857,-0.0178571
+0.0535714,-0.142857,-0.107143
+-0.0535714,-0.142857,-0.107143
+-0.125,-0.142857,-0.0178571
+0.015625,-0.160714,0.0297607
+0.00669643,-0.160714,0.0230643
+-0.00781071,-0.160714,0.0208321
+-0.015625,-0.160714,0.0297607
+0.015625,-0.25,0.0446429
+0.00669643,-0.25,0.0379464
+-0.00781071,-0.25,0.0357143
+-0.015625,-0.25,0.0446429
+-0.125,0.0,-0.0178571
+-0.142857,0.0,0.00446429
+-0.122768,0.0,0.0
+-0.107143,0.0,-0.0178571
+-0.125,-0.142857,-0.0178571
+-0.142857,-0.142857,0.00446429
+-0.122768,-0.142857,0.0
+-0.107143,-0.142857,-0.0178571
+-0.015625,-0.160714,0.0297607
+-0.0175786,-0.160714,0.0319929
+-0.0153464,-0.160714,0.0386893
+-0.0133929,-0.160714,0.0386893
+-0.015625,-0.25,0.0446429
+-0.0175786,-0.25,0.046875
+-0.0153464,-0.25,0.0535714
+-0.0133929,-0.25,0.0535714
+-0.0133929,-0.25,0.0535714
+-0.00557857,-0.25,0.0535714
+0.00557857,-0.25,0.0535714
+0.0133929,-0.25,0.0535714
+-0.0133929,-0.46425,0.0892857
+-0.00557857,-0.46425,0.0892857
+0.00557857,-0.46425,0.0892857
+0.0133929,-0.46425,0.0892857
+-0.0446429,-0.678571,0.0535714
+-0.00892857,-0.678571,0.0625
+0.00892857,-0.678571,0.0625
+0.0446429,-0.678571,0.0535714
+-0.0446429,-0.857143,0.0357143
+-0.00892857,-0.857143,0.0446429
+0.00892857,-0.857143,0.0446429
+0.0446429,-0.857143,0.0357143
+0.0133929,-0.25,0.0535714
+0.0153464,-0.25,0.0535714
+0.0178571,-0.25,0.0463179
+0.015625,-0.25,0.0446429
+0.0133929,-0.46425,0.0892857
+0.0153464,-0.464286,0.0892857
+0.0178571,-0.46425,0.0820321
+0.015625,-0.46425,0.0803571
+0.0446429,-0.678571,0.0535714
+0.0535714,-0.678571,0.0513393
+0.0535714,-0.678571,0.0334821
+0.0446429,-0.678571,0.0357143
+0.0446429,-0.857143,0.0357143
+0.0535714,-0.857143,0.0334821
+0.0535714,-0.857143,0.015625
+0.0446429,-0.857143,0.0178571
+0.015625,-0.25,0.0446429
+0.00669643,-0.25,0.0379464
+-0.00781071,-0.25,0.0357143
+-0.015625,-0.25,0.0446429
+0.015625,-0.46425,0.0803571
+0.00669643,-0.464286,0.0736607
+-0.00781071,-0.46425,0.0714286
+-0.015625,-0.46425,0.0803571
+0.0446429,-0.678571,0.0357143
+0.00892857,-0.678571,0.0446429
+-0.00892857,-0.678571,0.0446429
+-0.0446429,-0.678571,0.0357143
+0.0446429,-0.857143,0.0178571
+0.00892857,-0.857143,0.0267857
+-0.00892857,-0.857143,0.0267857
+-0.0446429,-0.857143,0.0178571
+-0.015625,-0.25,0.0446429
+-0.0175786,-0.25,0.046875
+-0.0153464,-0.25,0.0535714
+-0.0133929,-0.25,0.0535714
+-0.015625,-0.46425,0.0803571
+-0.0175786,-0.464286,0.0825893
+-0.0153464,-0.464286,0.0892857
+-0.0133929,-0.46425,0.0892857
+-0.0446429,-0.678571,0.0357143
+-0.0535714,-0.678571,0.0334821
+-0.0535714,-0.678571,0.0513393
+-0.0446429,-0.678571,0.0535714
+-0.0446429,-0.857143,0.0178571
+-0.0535714,-0.857143,0.015625
+-0.0535714,-0.857143,0.0334821
+-0.0446429,-0.857143,0.0357143
+-0.0446429,-0.857143,0.0357143
+-0.00892857,-0.857143,0.0446429
+0.00892857,-0.857143,0.0446429
+0.0446429,-0.857143,0.0357143
+-0.0446429,-0.928571,0.0285714
+-0.00892857,-0.928571,0.0375
+0.00892857,-0.928571,0.0375
+0.0446429,-0.928571,0.0285714
+-0.0539286,-0.999643,0.0178571
+0.000357143,-0.999643,0.0178571
+0.0,-0.999643,0.0178571
+0.0535714,-0.999643,0.0178571
+-0.000357143,-1,0.0178571
+0.000357143,-1,0.0178571
+0.0,-1,0.0178571
+0.0,-1,0.0178571
+0.0446429,-0.857143,0.0357143
+0.0535714,-0.857143,0.0334821
+0.0535714,-0.857143,0.015625
+0.0446429,-0.857143,0.0178571
+0.0446429,-0.928571,0.0285714
+0.0535714,-0.928571,0.0263393
+0.0535714,-0.928571,0.00848214
+0.0446429,-0.928571,0.0107143
+0.0535714,-0.999643,0.0178571
+0.0669643,-0.999643,0.0178571
+0.0673214,-0.999643,0.0
+0.0539286,-0.999643,0.0
+0.0,-1,0.0178571
+0.0,-1,0.0178571
+0.000357143,-1,0.0
+0.000357143,-1,0.0
+0.0446429,-0.857143,0.0178571
+0.00892857,-0.857143,0.0267857
+-0.00892857,-0.857143,0.0267857
+-0.0446429,-0.857143,0.0178571
+0.0446429,-0.928571,0.0107143
+0.00892857,-0.928571,0.0196429
+-0.00892857,-0.928571,0.0196429
+-0.0446429,-0.928571,0.0107143
+0.0539286,-0.999643,0.0
+0.000357143,-0.999643,0.0
+-0.000357143,-0.999643,0.0
+-0.0539286,-0.999643,0.0
+0.000357143,-1,0.0
+0.000357143,-1,0.0
+-0.000357143,-1,0.0
+-0.000357143,-1,0.0
+-0.0446429,-0.857143,0.0178571
+-0.0535714,-0.857143,0.015625
+-0.0535714,-0.857143,0.0334821
+-0.0446429,-0.857143,0.0357143
+-0.0446429,-0.928571,0.0107143
+-0.0535714,-0.928571,0.00848214
+-0.0535714,-0.928571,0.0263393
+-0.0446429,-0.928571,0.0285714
+-0.0539286,-0.999643,0.0
+-0.0673214,-0.999643,0.0
+-0.0675,-0.999643,0.0178571
+-0.0539286,-0.999643,0.0178571
+-0.000357143,-1,0.0
+-0.000357143,-1,0.0
+-0.000535714,-1,0.0178571
+-0.000357143,-1,0.0178571
+# reverse-patches
diff --git a/demos/declarative/textures/basket.jpg b/demos/declarative/textures/basket.jpg
new file mode 100644
index 000000000..438e7a0c2
--- /dev/null
+++ b/demos/declarative/textures/basket.jpg
Binary files differ
diff --git a/demos/declarative/textures/button/face-name.png b/demos/declarative/textures/button/face-name.png
new file mode 100644
index 000000000..280aa62f7
--- /dev/null
+++ b/demos/declarative/textures/button/face-name.png
Binary files differ
diff --git a/demos/declarative/textures/button/face-name.xcf b/demos/declarative/textures/button/face-name.xcf
new file mode 100644
index 000000000..ea733fce5
--- /dev/null
+++ b/demos/declarative/textures/button/face-name.xcf
Binary files differ
diff --git a/demos/declarative/textures/button/face.png b/demos/declarative/textures/button/face.png
new file mode 100644
index 000000000..327c88423
--- /dev/null
+++ b/demos/declarative/textures/button/face.png
Binary files differ
diff --git a/demos/declarative/textures/button/full-address.png b/demos/declarative/textures/button/full-address.png
new file mode 100644
index 000000000..8c83ac062
--- /dev/null
+++ b/demos/declarative/textures/button/full-address.png
Binary files differ
diff --git a/demos/declarative/textures/button/full-address.xcf b/demos/declarative/textures/button/full-address.xcf
new file mode 100644
index 000000000..1b1815382
--- /dev/null
+++ b/demos/declarative/textures/button/full-address.xcf
Binary files differ
diff --git a/demos/declarative/textures/button/woman-photo-credit.txt b/demos/declarative/textures/button/woman-photo-credit.txt
new file mode 100644
index 000000000..c7f04c1c9
--- /dev/null
+++ b/demos/declarative/textures/button/woman-photo-credit.txt
@@ -0,0 +1,5 @@
+http://www.flickr.com/photos/fromthefrontend/
+
+Attribution:
+
+<div xmlns:cc="http://creativecommons.org/ns#" about="http://www.flickr.com/photos/fromthefrontend/4527587863/"><a rel="cc:attributionURL" href="http://www.flickr.com/photos/fromthefrontend/">http://www.flickr.com/photos/fromthefrontend/</a> / <a rel="license" href="http://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a></div>
diff --git a/demos/declarative/textures/button/woman.jpg b/demos/declarative/textures/button/woman.jpg
new file mode 100644
index 000000000..f3a6abc28
--- /dev/null
+++ b/demos/declarative/textures/button/woman.jpg
Binary files differ
diff --git a/demos/declarative/textures/photos/background.jpg b/demos/declarative/textures/photos/background.jpg
new file mode 100644
index 000000000..9884233a2
--- /dev/null
+++ b/demos/declarative/textures/photos/background.jpg
Binary files differ
diff --git a/demos/declarative/textures/photos/niagara_falls.jpg b/demos/declarative/textures/photos/niagara_falls.jpg
new file mode 100644
index 000000000..7a912d3b9
--- /dev/null
+++ b/demos/declarative/textures/photos/niagara_falls.jpg
Binary files differ
diff --git a/demos/declarative/textures/photos/place.jpg b/demos/declarative/textures/photos/place.jpg
new file mode 100644
index 000000000..03e534433
--- /dev/null
+++ b/demos/declarative/textures/photos/place.jpg
Binary files differ
diff --git a/demos/declarative/textures/qtlogo.png b/demos/declarative/textures/qtlogo.png
new file mode 100644
index 000000000..7d3e97eb3
--- /dev/null
+++ b/demos/declarative/textures/qtlogo.png
Binary files differ
diff --git a/demos/demos.pro b/demos/demos.pro
new file mode 100644
index 000000000..d506a9909
--- /dev/null
+++ b/demos/demos.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = teaservice shapes pageflip photobrowser3d cubehouse
diff --git a/demos/pageflip/gradient.png b/demos/pageflip/gradient.png
new file mode 100644
index 000000000..ddadf69d2
--- /dev/null
+++ b/demos/pageflip/gradient.png
Binary files differ
diff --git a/demos/pageflip/pageflip.cpp b/demos/pageflip/pageflip.cpp
new file mode 100644
index 000000000..5e5768843
--- /dev/null
+++ b/demos/pageflip/pageflip.cpp
@@ -0,0 +1,380 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 <QTimer>
+#include <QMouseEvent>
+#include "qglpainter.h"
+#include "qglabstracteffect.h"
+#include "qgltexture2d.h"
+#include "qglshaderprogrameffect.h"
+#include <QtOpenGL/qglshaderprogram.h>
+#include "pageflipmath_p.h"
+
+class PageFlipGradientEffect;
+
+class PageFlipView : public QGLWidget
+{
+ Q_OBJECT
+public:
+ PageFlipView(QWidget *parent = 0);
+ ~PageFlipView();
+
+ void setBlend(bool value) { blend = value; }
+ void setVertical(bool value) { vertical = value; }
+
+protected:
+ void resizeGL(int width, int height);
+ void initializeGL();
+ void paintGL();
+ void mousePressEvent(QMouseEvent *e);
+
+private slots:
+ void animate();
+
+private:
+ bool blend;
+ bool vertical;
+
+ qreal posn; // Position within the animation - 0...1
+ QSize pageSize; // Size of a page within the window.
+
+ QRect pageRect1;
+ QRect pageRect2;
+
+ QColor colors[4];
+ int colorIndex;
+
+ QGLTexture2D textures[4];
+
+ QGLTexture2D gradientTexture;
+
+ PageFlipMath pageFlipMath;
+
+ PageFlipGradientEffect *effect;
+
+ void setAlphaValue(QGLPainter *painter, GLfloat value);
+};
+
+class PageFlipGradientEffect : public QGLShaderProgramEffect
+{
+public:
+ PageFlipGradientEffect();
+ ~PageFlipGradientEffect();
+
+ void setAlphaValue(GLfloat value);
+};
+
+PageFlipView::PageFlipView(QWidget *parent)
+ : QGLWidget(parent)
+{
+ posn = 0.0f;
+ blend = false;
+ vertical = false;
+
+ colors[0] = QColor(0, 192, 192, 255);
+ colors[1] = QColor(192, 0, 0, 255);
+ colors[2] = QColor(192, 192, 0, 255);
+ colors[3] = QColor(128, 128, 0, 255);
+ colorIndex = 0;
+
+ QTimer *timer = new QTimer(this);
+ connect(timer, SIGNAL(timeout()), this, SLOT(animate()));
+ timer->start(40);
+
+ effect = new PageFlipGradientEffect();
+}
+
+PageFlipView::~PageFlipView()
+{
+ delete effect;
+}
+
+void PageFlipView::resizeGL(int width, int height)
+{
+ glViewport(0, 0, width, height);
+}
+
+void PageFlipView::initializeGL()
+{
+ QGLPainter painter(this);
+
+ //QSize size = rect().size();
+ //int width = size.width() / 3;
+ //int height = (int)(width * 1.414f);
+ int width = 227;
+ int height = 320;
+ pageSize = QSize(width, height);
+
+ textures[0].setImage(QImage(QLatin1String(":/qqpage1.png")));
+ textures[1].setImage(QImage(QLatin1String(":/qqpage2.png")));
+ textures[2].setImage(QImage(QLatin1String(":/qqpage3.png")));
+ textures[3].setImage(QImage(QLatin1String(":/qqpage4.png")));
+
+ gradientTexture.setImage(QImage(QLatin1String(":/gradient.png")));
+
+ if (painter.hasOpenGLFeature(QOpenGLFunctions::BlendColor))
+ painter.glBlendColor(0, 0, 0, 0);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ if (painter.hasOpenGLFeature(QOpenGLFunctions::BlendEquation))
+ painter.glBlendEquation(GL_FUNC_ADD);
+ else if (painter.hasOpenGLFeature(QOpenGLFunctions::BlendEquationSeparate))
+ painter.glBlendEquationSeparate(GL_FUNC_ADD, GL_FUNC_ADD);
+
+ glEnable(GL_BLEND);
+
+ if (vertical)
+ pageFlipMath.setStartCorner(PageFlipMath::VerticalBottomRight);
+ else
+ pageFlipMath.setStartCorner(PageFlipMath::BottomRight);
+}
+
+void PageFlipView::paintGL()
+{
+ QGLPainter painter(this);
+
+ QRect rect = this->rect();
+ int midx = rect.width() / 2;
+ int topy = (rect.height() - pageSize.height()) / 2;
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ QMatrix4x4 projm;
+ projm.ortho(rect);
+ painter.projectionMatrix() = projm;
+ painter.modelViewMatrix().setToIdentity();
+
+ if (vertical) {
+ pageRect2 = QRect(QPoint(midx - pageSize.width() / 2, topy), pageSize);
+ pageRect1 = QRect(QPoint(pageRect2.x() - pageSize.width(), topy), pageSize);
+ } else {
+ pageRect1 = QRect(QPoint(midx - pageSize.width(), topy), pageSize);
+ pageRect2 = QRect(QPoint(midx, topy), pageSize);
+ }
+ pageFlipMath.setPageRect(pageRect2);
+ pageFlipMath.setShowPageReverse(false);
+ pageFlipMath.compute(posn);
+
+ QGLAttributeValue positions
+ (2, GL_FLOAT, pageFlipMath.stride(), pageFlipMath.vertexArray());
+ QGLAttributeValue texCoords
+ (2, GL_FLOAT, pageFlipMath.stride(), pageFlipMath.vertexArray() + 2);
+ QGLAttributeValue gradientCoords
+ (1, GL_FLOAT, pageFlipMath.stride(), pageFlipMath.vertexArray() + 4);
+
+ if (painter.isFixedFunction())
+ painter.setStandardEffect(QGL::FlatReplaceTexture2D);
+ else
+ painter.setUserEffect(effect);
+ painter.setColor(colors[colorIndex]);
+ painter.glActiveTexture(GL_TEXTURE0);
+ textures[colorIndex].bind();
+ if (!painter.isFixedFunction()) {
+ painter.glActiveTexture(GL_TEXTURE1);
+ gradientTexture.bind();
+ }
+ painter.clearAttributes();
+ painter.setVertexAttribute(QGL::Position, positions);
+ painter.setVertexAttribute(QGL::TextureCoord0, texCoords);
+ painter.setVertexAttribute(QGL::CustomVertex0, gradientCoords);
+ setAlphaValue(&painter, 1.0f);
+ painter.update();
+ pageFlipMath.drawPage(0);
+
+ painter.setColor(colors[(colorIndex + 1) % 4]);
+ painter.glActiveTexture(GL_TEXTURE0);
+ textures[(colorIndex + 1) % 4].bind();
+ setAlphaValue(&painter, 1.0f);
+ painter.update();
+ pageFlipMath.drawPage(1);
+
+ painter.setColor(colors[(colorIndex + 2) % 4]);
+ if (!pageFlipMath.showPageReverse())
+ textures[(colorIndex + 2) % 4].bind();
+ if (blend)
+ setAlphaValue(&painter, 0.75f);
+ else
+ setAlphaValue(&painter, 1.0f);
+ painter.update();
+ pageFlipMath.drawPage(2);
+
+ painter.setColor(colors[(colorIndex + 3) % 4]);
+ textures[(colorIndex + 3) % 4].bind();
+ setAlphaValue(&painter, 1.0f);
+ painter.update();
+ pageFlipMath.drawPage(3);
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ painter.glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ painter.setStandardEffect(QGL::FlatColor);
+ painter.clearAttributes();
+ painter.setVertexAttribute(QGL::Position, positions);
+ painter.setVertexAttribute(QGL::TextureCoord0, texCoords);
+ painter.setVertexAttribute(QGL::CustomVertex0, gradientCoords);
+ painter.setColor(QColor(0, 0, 0, 255));
+ painter.update();
+ pageFlipMath.drawOutline(2);
+}
+
+void PageFlipView::mousePressEvent(QMouseEvent *e)
+{
+ int x = e->x();
+ int y = e->y();
+ bool changed = true;
+ if (vertical) {
+ if (x >= pageRect2.x() && x < (pageRect2.x() + 20) &&
+ y >= pageRect2.y() && y < (pageRect2.y() + 20))
+ pageFlipMath.setStartCorner(PageFlipMath::VerticalTopLeft);
+ else if (x >= pageRect2.x() && x < (pageRect2.x() + 20) &&
+ y >= (pageRect2.bottom() - 20) && y <= pageRect2.bottom())
+ pageFlipMath.setStartCorner(PageFlipMath::VerticalBottomLeft);
+ else if (x >= (pageRect2.right() - 20) && x <= pageRect2.right() &&
+ y >= pageRect2.y() && y < (pageRect2.y() + 20))
+ pageFlipMath.setStartCorner(PageFlipMath::VerticalTopRight);
+ else if (x >= (pageRect2.right() - 20) && x <= pageRect2.right() &&
+ y >= (pageRect2.bottom() - 20) && y <= pageRect2.bottom())
+ pageFlipMath.setStartCorner(PageFlipMath::VerticalBottomRight);
+ else
+ changed = false;
+ } else {
+ if (x >= pageRect1.x() && x < (pageRect1.x() + 20) &&
+ y >= pageRect1.y() && y < (pageRect1.y() + 20))
+ pageFlipMath.setStartCorner(PageFlipMath::TopLeft);
+ else if (x >= pageRect1.x() && x < (pageRect1.x() + 20) &&
+ y >= (pageRect1.bottom() - 20) && y <= pageRect1.bottom())
+ pageFlipMath.setStartCorner(PageFlipMath::BottomLeft);
+ else if (x >= pageRect2.x() && x < (pageRect2.x() + 20) &&
+ y >= pageRect2.y() && y < (pageRect2.y() + 20))
+ pageFlipMath.setStartCorner(PageFlipMath::TopLeftOnePage);
+ else if (x >= pageRect2.x() && x < (pageRect2.x() + 20) &&
+ y >= (pageRect2.bottom() - 20) && y <= pageRect2.bottom())
+ pageFlipMath.setStartCorner(PageFlipMath::BottomLeftOnePage);
+ else if (x >= (pageRect2.right() - 20) && x <= pageRect2.right() &&
+ y >= pageRect2.y() && y < (pageRect2.y() + 20))
+ pageFlipMath.setStartCorner(PageFlipMath::TopRight);
+ else if (x >= (pageRect2.right() - 20) && x <= pageRect2.right() &&
+ y >= (pageRect2.bottom() - 20) && y <= pageRect2.bottom())
+ pageFlipMath.setStartCorner(PageFlipMath::BottomRight);
+ else
+ changed = false;
+ }
+ if (changed)
+ posn = 0.0f;
+ QGLWidget::mousePressEvent(e);
+}
+
+void PageFlipView::animate()
+{
+ posn += 0.04f;
+ if (posn >= 1.0f) {
+ posn = 0.0f;
+ colorIndex = (colorIndex + 2) % 4;
+ }
+ updateGL();
+}
+
+void PageFlipView::setAlphaValue(QGLPainter *painter, GLfloat value)
+{
+ if (!painter->isFixedFunction())
+ effect->setAlphaValue(value);
+}
+
+static char const gradientVertexShader[] =
+ "attribute highp vec4 qt_Vertex;\n"
+ "attribute highp vec4 qt_MultiTexCoord0;\n"
+ "attribute highp float qt_Custom0;\n"
+ "uniform mediump mat4 qt_ModelViewProjectionMatrix;\n"
+ "varying highp vec4 qt_TexCoord0;\n"
+ "varying highp float qGradCtrl;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;\n"
+ " qt_TexCoord0 = qt_MultiTexCoord0;\n"
+ " qGradCtrl = qt_Custom0;\n"
+ "}\n";
+
+static char const gradientFragmentShader[] =
+ "uniform sampler2D qt_Texture0;\n"
+ "uniform sampler2D qt_Texture1;\n"
+ "uniform mediump float alphaValue;\n"
+ "varying highp vec4 qt_TexCoord0;\n"
+ "varying highp float qGradCtrl;\n"
+ "void main(void)\n"
+ "{\n"
+ " mediump vec4 col = texture2D(qt_Texture0, qt_TexCoord0.st);\n"
+ " mediump vec4 gradcol = texture2D(qt_Texture1, vec2(qGradCtrl, qt_TexCoord0.t));\n"
+ " gl_FragColor = vec4((col * gradcol).xyz, alphaValue);\n"
+ "}\n";
+
+PageFlipGradientEffect::PageFlipGradientEffect()
+{
+ setVertexShader(gradientVertexShader);
+ setFragmentShader(gradientFragmentShader);
+}
+
+PageFlipGradientEffect::~PageFlipGradientEffect()
+{
+}
+
+void PageFlipGradientEffect::setAlphaValue(GLfloat value)
+{
+ program()->setUniformValue("alphaValue", value);
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ PageFlipView view;
+ if (QApplication::arguments().contains(QLatin1String("-blend")))
+ view.setBlend(true);
+ if (QApplication::arguments().contains(QLatin1String("-vertical")))
+ view.setVertical(true);
+ if (QApplication::arguments().contains(QLatin1String("-maximize")))
+ view.showMaximized();
+ else if (QApplication::arguments().contains(QLatin1String("-fullscreen")))
+ view.showFullScreen();
+ else
+ view.show();
+ return app.exec();
+}
+
+#include "pageflip.moc"
diff --git a/demos/pageflip/pageflip.pro b/demos/pageflip/pageflip.pro
new file mode 100644
index 000000000..4d94c8e8c
--- /dev/null
+++ b/demos/pageflip/pageflip.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+TARGET = pageflip
+CONFIG += qt warn_on qt3d
+SOURCES = pageflip.cpp pageflipmath.cpp
+HEADERS = pageflipmath_p.h
+RESOURCES = pageflip.qrc
+DESTDIR = ../../bin
diff --git a/demos/pageflip/pageflip.qrc b/demos/pageflip/pageflip.qrc
new file mode 100644
index 000000000..1584add51
--- /dev/null
+++ b/demos/pageflip/pageflip.qrc
@@ -0,0 +1,9 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>qqpage1.png</file>
+ <file>qqpage2.png</file>
+ <file>qqpage3.png</file>
+ <file>qqpage4.png</file>
+ <file>gradient.png</file>
+</qresource>
+</RCC>
diff --git a/demos/pageflip/pageflipmath.cpp b/demos/pageflip/pageflipmath.cpp
new file mode 100644
index 000000000..edf747bff
--- /dev/null
+++ b/demos/pageflip/pageflipmath.cpp
@@ -0,0 +1,592 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "pageflipmath_p.h"
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+PageFlipMath::PageFlipMath()
+{
+ m_showPageReverse = false;
+ m_startCorner = BottomRight;
+
+ qMemSet(vertices, 0, sizeof(vertices));
+ qMemSet(pageCount, 0, sizeof(pageCount));
+}
+
+PageFlipMath::~PageFlipMath()
+{
+}
+
+void PageFlipMath::drawPage(int page) const
+{
+ if (page < 0 || page >= 4 || pageCount[page] == 0)
+ return;
+ glDrawArrays(GL_TRIANGLE_FAN, page * 5, pageCount[page]);
+}
+
+void PageFlipMath::drawOutline(int page) const
+{
+ if (page < 0 || page >= 4 || pageCount[page] == 0)
+ return;
+ glDrawArrays(GL_LINE_LOOP, page * 5, pageCount[page]);
+}
+
+void PageFlipMath::compute(qreal t)
+{
+ int page, vertex;
+
+ // Compute the relative vertices for position t.
+ if (m_startCorner < VerticalBottomRight)
+ flip(m_pageRect.width() - 1, m_pageRect.height() - 1, t);
+ else
+ flip(m_pageRect.height() - 1, m_pageRect.width() - 1, t);
+
+ // Deal with starting corner issues by swapping co-ordinates.
+ switch (m_startCorner) {
+
+ case BottomRight: break;
+
+ case TopRight:
+ for (page = 0; page < 4; ++page) {
+ for (vertex = 0; vertex < pageCount[page]; ++vertex) {
+ vertices[page][vertex][1]
+ = m_pageRect.height() - 1 - vertices[page][vertex][1];
+ vertices[page][vertex][3]
+ = 1.0f - vertices[page][vertex][3];
+ }
+ }
+ break;
+
+ case BottomLeft:
+ for (page = 0; page < 4; ++page) {
+ for (vertex = 0; vertex < pageCount[page]; ++vertex) {
+ vertices[page][vertex][0]
+ = m_pageRect.width() - 1 - vertices[page][vertex][0];
+ vertices[page][vertex][0] -= m_pageRect.width();
+ vertices[page][vertex][2]
+ = 1.0f - vertices[page][vertex][2];
+ }
+ }
+ break;
+
+ case TopLeft:
+ for (page = 0; page < 4; ++page) {
+ for (vertex = 0; vertex < pageCount[page]; ++vertex) {
+ vertices[page][vertex][0]
+ = m_pageRect.width() - 1 - vertices[page][vertex][0];
+ vertices[page][vertex][0] -= m_pageRect.width();
+ vertices[page][vertex][1]
+ = m_pageRect.height() - 1 - vertices[page][vertex][1];
+ vertices[page][vertex][2]
+ = 1.0f - vertices[page][vertex][2];
+ vertices[page][vertex][3]
+ = 1.0f - vertices[page][vertex][3];
+ }
+ }
+ break;
+
+ case BottomLeftOnePage:
+ for (page = 1; page < 4; ++page) {
+ for (vertex = 0; vertex < pageCount[page]; ++vertex) {
+ vertices[page][vertex][0]
+ = m_pageRect.width() - 1 - vertices[page][vertex][0];
+ vertices[page][vertex][2]
+ = 1.0f - vertices[page][vertex][2];
+ }
+ }
+ break;
+
+ case TopLeftOnePage:
+ for (page = 1; page < 4; ++page) {
+ for (vertex = 0; vertex < pageCount[page]; ++vertex) {
+ vertices[page][vertex][0]
+ = m_pageRect.width() - 1 - vertices[page][vertex][0];
+ vertices[page][vertex][1]
+ = m_pageRect.height() - 1 - vertices[page][vertex][1];
+ vertices[page][vertex][2]
+ = 1.0f - vertices[page][vertex][2];
+ vertices[page][vertex][3]
+ = 1.0f - vertices[page][vertex][3];
+ }
+ }
+ break;
+
+ case VerticalBottomRight:
+ for (page = 0; page < 4; ++page) {
+ for (vertex = 0; vertex < pageCount[page]; ++vertex) {
+ qSwap(vertices[page][vertex][0], vertices[page][vertex][1]);
+ vertices[page][vertex][0]
+ = m_pageRect.width() - 1 - vertices[page][vertex][0];
+ vertices[page][vertex][1]
+ = m_pageRect.height() - 1 - vertices[page][vertex][1];
+ qSwap(vertices[page][vertex][2], vertices[page][vertex][3]);
+ vertices[page][vertex][2]
+ = 1.0f - vertices[page][vertex][2];
+ vertices[page][vertex][3]
+ = 1.0f - vertices[page][vertex][3];
+ }
+ }
+ break;
+
+ case VerticalTopRight:
+ for (page = 0; page < 4; ++page) {
+ for (vertex = 0; vertex < pageCount[page]; ++vertex) {
+ qSwap(vertices[page][vertex][0], vertices[page][vertex][1]);
+ vertices[page][vertex][0]
+ = m_pageRect.width() - 1 - vertices[page][vertex][0];
+ qSwap(vertices[page][vertex][2], vertices[page][vertex][3]);
+ vertices[page][vertex][2]
+ = 1.0f - vertices[page][vertex][2];
+ }
+ }
+ break;
+
+ case VerticalBottomLeft:
+ for (page = 0; page < 4; ++page) {
+ for (vertex = 0; vertex < pageCount[page]; ++vertex) {
+ qSwap(vertices[page][vertex][0], vertices[page][vertex][1]);
+ vertices[page][vertex][1]
+ = m_pageRect.height() - 1 - vertices[page][vertex][1];
+ qSwap(vertices[page][vertex][2], vertices[page][vertex][3]);
+ vertices[page][vertex][3]
+ = 1.0f - vertices[page][vertex][3];
+ }
+ }
+ break;
+
+ case VerticalTopLeft:
+ for (page = 0; page < 4; ++page) {
+ for (vertex = 0; vertex < pageCount[page]; ++vertex) {
+ qSwap(vertices[page][vertex][0], vertices[page][vertex][1]);
+ qSwap(vertices[page][vertex][2], vertices[page][vertex][3]);
+ }
+ }
+ break;
+ }
+
+ // Adjust the vertices for the final rectangle position.
+ for (page = 0; page < 4; ++page) {
+ for (vertex = 0; vertex < pageCount[page]; ++vertex) {
+ vertices[page][vertex][0] += m_pageRect.x();
+ vertices[page][vertex][1]
+ = m_pageRect.y() +
+ (m_pageRect.height() - 1 - vertices[page][vertex][1]);
+ }
+ }
+
+ // Flip the x texture co-ordinates for page 2 if showing the page reverse.
+ if (m_showPageReverse) {
+ if (m_startCorner < VerticalBottomRight) {
+ for (int vertex = 0; vertex < pageCount[2]; ++vertex)
+ vertices[2][vertex][2] = 1.0f - vertices[2][vertex][2];
+ } else {
+ for (int vertex = 0; vertex < pageCount[2]; ++vertex)
+ vertices[2][vertex][3] = 1.0f - vertices[2][vertex][3];
+ }
+ }
+}
+
+// Page 1 is the reference page and extends from the bottom-left
+// corner at (0, 0) to the top-right corner at (pageWidth, pageHeight).
+// The flip starts at the bottom-right corner and proceeds leftwards
+// across the page. All other flip directions and starting corners
+// can be derived from this basic reference flip animation.
+void PageFlipMath::flip(qreal pageWidth, qreal pageHeight, qreal t)
+{
+ // Handle the simple start and end position cases first.
+ if (t <= 0.0f) {
+ // Starting position: pages 0 and 1 in their rest states
+ // and pages 2 and 3 not visible.
+ pageCount[0] = 4;
+ pageCount[1] = 4;
+ pageCount[2] = 0;
+ pageCount[3] = 0;
+
+ vertices[0][0][0] = -pageWidth; // corner 0 at (-pageWidth, 0)
+ vertices[0][0][1] = 0.0f;
+ vertices[0][0][2] = 0.0f; // texture co-ordinate
+ vertices[0][0][3] = 0.0f;
+ vertices[0][0][4] = 0.0f; // gradient control
+
+ vertices[0][1][0] = 0.0f; // corner 1 at (0, 0)
+ vertices[0][1][1] = 0.0f;
+ vertices[0][1][2] = 1.0f;
+ vertices[0][1][3] = 0.0f;
+ vertices[0][1][4] = 1.0f; // gradient along fold on the right
+
+ vertices[0][2][0] = 0.0f; // corner 2 at (0, pageHeight)
+ vertices[0][2][1] = pageHeight;
+ vertices[0][2][2] = 1.0f;
+ vertices[0][2][3] = 1.0f;
+ vertices[0][2][4] = 1.0f;
+
+ vertices[0][3][0] = -pageWidth; // corner 3 at (-pageWidth, pageHeight)
+ vertices[0][3][1] = pageHeight;
+ vertices[0][3][2] = 0.0f;
+ vertices[0][3][3] = 1.0f;
+ vertices[0][3][4] = 0.0f;
+
+ vertices[1][0][0] = 0.0f; // corner 0 at (0, 0)
+ vertices[1][0][1] = 0.0f;
+ vertices[1][0][2] = 0.0f; // texture co-ordinate
+ vertices[1][0][3] = 0.0f;
+ vertices[1][0][4] = 1.0f; // gradient along fold on the left
+
+ vertices[1][1][0] = pageWidth; // corner 1 at (pageWidth, 0)
+ vertices[1][1][1] = 0.0f;
+ vertices[1][1][2] = 1.0f;
+ vertices[1][1][3] = 0.0f;
+ vertices[1][1][4] = 0.0f;
+
+ vertices[1][2][0] = pageWidth; // corner 2 at (pageWidth, pageHeight)
+ vertices[1][2][1] = pageHeight;
+ vertices[1][2][2] = 1.0f;
+ vertices[1][2][3] = 1.0f;
+ vertices[1][2][4] = 0.0f;
+
+ vertices[1][3][0] = 0.0f; // corner 3 at (0, pageHeight)
+ vertices[1][3][1] = pageHeight;
+ vertices[1][3][2] = 0.0f;
+ vertices[1][3][3] = 1.0f;
+ vertices[1][3][4] = 1.0f;
+ return;
+ } else if (t >= 1.0f) {
+ // Ending position: pages 0 and 1 are not visible, but
+ // pages 2 and 3 are visible in the rest states.
+ pageCount[0] = 0;
+ pageCount[1] = 0;
+ pageCount[2] = 4;
+ pageCount[3] = 4;
+
+ vertices[2][0][0] = -pageWidth; // corner 0 at (-pageWidth, 0)
+ vertices[2][0][1] = 0.0f;
+ vertices[2][0][2] = 0.0f; // texture co-ordinate
+ vertices[2][0][3] = 0.0f;
+ vertices[2][0][4] = 0.0f; // gradient control
+
+ vertices[2][1][0] = 0.0f; // corner 1 at (0, 0)
+ vertices[2][1][1] = 0.0f;
+ vertices[2][1][2] = 1.0f;
+ vertices[2][1][3] = 0.0f;
+ vertices[2][1][4] = 1.0f; // gradient along fold on the right
+
+ vertices[2][2][0] = 0.0f; // corner 2 at (0, pageHeight)
+ vertices[2][2][1] = pageHeight;
+ vertices[2][2][2] = 1.0f;
+ vertices[2][2][3] = 1.0f;
+ vertices[2][2][4] = 1.0f;
+
+ vertices[2][3][0] = -pageWidth; // corner 3 at (-pageWidth, pageHeight)
+ vertices[2][3][1] = pageHeight;
+ vertices[2][3][2] = 0.0f;
+ vertices[2][3][3] = 1.0f;
+ vertices[2][3][4] = 0.0f;
+
+ vertices[3][0][0] = 0.0f; // corner 0 at (0, 0)
+ vertices[3][0][1] = 0.0f;
+ vertices[3][0][2] = 0.0f; // texture co-ordinate
+ vertices[3][0][3] = 0.0f;
+ vertices[3][0][4] = 1.0f; // gradient along fold on the left
+
+ vertices[3][1][0] = pageWidth; // corner 1 at (pageWidth, 0)
+ vertices[3][1][1] = 0.0f;
+ vertices[3][1][2] = 1.0f;
+ vertices[3][1][3] = 0.0f;
+ vertices[3][1][4] = 0.0f;
+
+ vertices[3][2][0] = pageWidth; // corner 2 at (pageWidth, pageHeight)
+ vertices[3][2][1] = pageHeight;
+ vertices[3][2][2] = 1.0f;
+ vertices[3][2][3] = 1.0f;
+ vertices[3][2][4] = 0.0f;
+
+ vertices[3][3][0] = 0.0f; // corner 3 at (0, pageHeight)
+ vertices[3][3][1] = pageHeight;
+ vertices[3][3][2] = 0.0f;
+ vertices[3][3][3] = 1.0f;
+ vertices[3][3][4] = 1.0f;
+ return;
+ }
+
+ // Page 0 is the same for all other animation positions.
+ pageCount[0] = 4;
+
+ vertices[0][0][0] = -pageWidth; // corner 0 at (-pageWidth, 0)
+ vertices[0][0][1] = 0.0f;
+ vertices[0][0][2] = 0.0f; // texture co-ordinate
+ vertices[0][0][3] = 0.0f;
+ vertices[0][0][4] = 0.0f; // gradient control
+
+ vertices[0][1][0] = 0.0f; // corner 1 at (0, 0)
+ vertices[0][1][1] = 0.0f;
+ vertices[0][1][2] = 1.0f;
+ vertices[0][1][3] = 0.0f;
+ vertices[0][1][4] = 1.0f; // gradient along fold on the right
+
+ vertices[0][2][0] = 0.0f; // corner 2 at (0, pageHeight)
+ vertices[0][2][1] = pageHeight;
+ vertices[0][2][2] = 1.0f;
+ vertices[0][2][3] = 1.0f;
+ vertices[0][2][4] = 1.0f;
+
+ vertices[0][3][0] = -pageWidth; // corner 3 at (-pageWidth, pageHeight)
+ vertices[0][3][1] = pageHeight;
+ vertices[0][3][2] = 0.0f;
+ vertices[0][3][3] = 1.0f;
+ vertices[0][3][4] = 0.0f;
+
+ // Get the angle of the "curling" dividing line to the bottom of the page.
+ // Basically: 45deg + (45deg * t) = 45deg * (1 + t), where t is between
+ // 0 and 1 but is neither 0 nor 1.
+ qreal angle = (M_PI / 4.0f) * (1.0f + t);
+
+ // We need the cos and sin of both the angle and angle * 2.
+ qreal cosAngle = qCos(angle);
+ qreal sinAngle = qSin(angle);
+ qreal cosAngle2 = qCos(angle * 2.0f);
+ qreal sinAngle2 = qSin(angle * 2.0f);
+
+ // Find the reference point. This is the point along the bottom of
+ // the page where the dividing line intersects the page bottom.
+ qreal refx = pageWidth * (1.0f - t);
+ qreal refy = 0.0f;
+
+ // Distance from the reference point to the right side of the page.
+ qreal d = pageWidth - refx;
+
+ // Determine the intersection of the dividing line with the
+ // top of the page. If the intersection is not on the page (k >= d),
+ // then we need to generate similar triangles. If the intersection is
+ // on the page (k < d), then we need to generate similar trapezoids.
+ qreal k = (pageHeight * cosAngle) / sinAngle;
+ if (k >= d) {
+ // Generate similar triangles. Find the intersection with
+ // the right-hand side of the page at x == pageWidth.
+ qreal intx = pageWidth;
+ qreal inty = refy + (d * sinAngle) / cosAngle;
+
+ // Find the opposite triangle corner on the back page.
+ qreal oppx = refx + d * cosAngle2;
+ qreal oppy = refy + d * sinAngle2;
+
+ // Generate vertices and texture co-ordinates for the back page.
+ qreal texa = 1.0f - (d * sinAngle) / (pageHeight * cosAngle);
+ qreal texb = d / pageWidth;
+ vertices[2][0][0] = intx;
+ vertices[2][0][1] = inty;
+ vertices[2][0][2] = 0.0f;
+ vertices[2][0][3] = 1.0f - texa;
+ vertices[2][0][4] = 1.0f;
+
+ vertices[2][1][0] = oppx;
+ vertices[2][1][1] = oppy;
+ vertices[2][1][2] = 0.0f;
+ vertices[2][1][3] = 0.0f;
+ vertices[2][1][4] = 1.0f - texb;
+
+ vertices[2][2][0] = refx;
+ vertices[2][2][1] = refy;
+ vertices[2][2][2] = texb;
+ vertices[2][2][3] = 0.0f;
+ vertices[2][2][4] = 1.0f;
+
+ pageCount[2] = 3;
+
+ // Generate vertices and texture co-ordinates for the next page.
+ vertices[3][0][0] = intx;
+ vertices[3][0][1] = inty;
+ vertices[3][0][2] = 1.0f;
+ vertices[3][0][3] = 1.0f - texa;
+ vertices[3][0][4] = 1.0f;
+
+ vertices[3][1][0] = refx;
+ vertices[3][1][1] = refy;
+ vertices[3][1][2] = 1.0f - texb;
+ vertices[3][1][3] = 0.0f;
+ vertices[3][1][4] = 1.0f;
+
+ vertices[3][2][0] = pageWidth;
+ vertices[3][2][1] = 0.0f;
+ vertices[3][2][2] = 1.0f;
+ vertices[3][2][3] = 0.0f;
+ vertices[3][2][4] = 1.0f - texb;
+
+ pageCount[3] = 3;
+
+ // Set page 1's vertices to clip off pixels we don't need to draw.
+ vertices[1][0][0] = 0.0f;
+ vertices[1][0][1] = 0.0f;
+ vertices[1][0][2] = 0.0f;
+ vertices[1][0][3] = 0.0f;
+ vertices[1][0][4] = 1.0f;
+
+ vertices[1][1][0] = pageWidth - d;
+ vertices[1][1][1] = 0.0f;
+ vertices[1][1][2] = 1.0f - texb;
+ vertices[1][1][3] = 0.0f;
+ vertices[1][1][4] = texb;
+
+ vertices[1][2][0] = intx;
+ vertices[1][2][1] = inty;
+ vertices[1][2][2] = 1.0f;
+ vertices[1][2][3] = 1.0f - texa;
+ vertices[1][2][4] = 0.0f;
+
+ vertices[1][3][0] = pageWidth;
+ vertices[1][3][1] = pageHeight;
+ vertices[1][3][2] = 1.0f;
+ vertices[1][3][3] = 1.0f;
+ vertices[1][3][4] = 0.0f;
+
+ vertices[1][4][0] = 0.0f;
+ vertices[1][4][1] = pageHeight;
+ vertices[1][4][2] = 0.0f;
+ vertices[1][4][3] = 1.0f;
+ vertices[1][4][4] = 1.0f;
+
+ pageCount[1] = 5;
+ } else {
+ // Generate similar trapezoids. Find the intersection with
+ // the top of the page at y == pageHeight.
+ qreal intx = refx + (pageHeight * cosAngle) / sinAngle;
+ qreal inty = pageHeight;
+
+ // Get the distance between the intersection and the right of the page.
+ qreal e = pageWidth - intx;
+
+ // Find the opposite trapezoid corners to "ref" and "int".
+ qreal opprefx = refx + d * cosAngle2;
+ qreal opprefy = refy + d * sinAngle2;
+ qreal oppintx = intx + e * cosAngle2;
+ qreal oppinty = inty + e * sinAngle2;
+
+ // Generate vertices and texture co-ordinates for the back page.
+ qreal texa = e / pageWidth;
+ qreal texb = d / pageWidth;
+ vertices[2][0][0] = intx;
+ vertices[2][0][1] = inty;
+ vertices[2][0][2] = texa;
+ vertices[2][0][3] = 1.0f;
+ vertices[2][0][4] = 1.0f;
+
+ vertices[2][1][0] = oppintx;
+ vertices[2][1][1] = oppinty;
+ vertices[2][1][2] = 0.0f;
+ vertices[2][1][3] = 1.0f;
+ vertices[2][1][4] = 1.0f - texa;
+
+ vertices[2][2][0] = opprefx;
+ vertices[2][2][1] = opprefy;
+ vertices[2][2][2] = 0.0f;
+ vertices[2][2][3] = 0.0f;
+ vertices[2][2][4] = 1.0f - texb;
+
+ vertices[2][3][0] = refx;
+ vertices[2][3][1] = refy;
+ vertices[2][3][2] = texb;
+ vertices[2][3][3] = 0.0f;
+ vertices[2][3][4] = 1.0f;
+
+ pageCount[2] = 4;
+
+ // Generate vertices and texture co-ordinates for the next page.
+ vertices[3][0][0] = intx;
+ vertices[3][0][1] = inty;
+ vertices[3][0][2] = 1.0f - texa;
+ vertices[3][0][3] = 1.0f;
+ vertices[3][0][4] = 1.0f;
+
+ vertices[3][1][0] = refx;
+ vertices[3][1][1] = refy;
+ vertices[3][1][2] = 1.0f - texb;
+ vertices[3][1][3] = 0.0f;
+ vertices[3][1][4] = 1.0f;
+
+ vertices[3][2][0] = pageWidth;
+ vertices[3][2][1] = 0.0f;
+ vertices[3][2][2] = 1.0f;
+ vertices[3][2][3] = 0.0f;
+ vertices[3][2][4] = 1.0f - texb;
+
+ vertices[3][3][0] = pageWidth;
+ vertices[3][3][1] = pageHeight;
+ vertices[3][3][2] = 1.0f;
+ vertices[3][3][3] = 1.0f;
+ vertices[3][3][4] = 1.0f - texa;
+
+ pageCount[3] = 4;
+
+ // Set page 1's vertices to clip off pixels we don't need to draw.
+ vertices[1][0][0] = 0.0f;
+ vertices[1][0][1] = 0.0f;
+ vertices[1][0][2] = 0.0f;
+ vertices[1][0][3] = 0.0f;
+ vertices[1][0][4] = 1.0f;
+
+ vertices[1][1][0] = pageWidth - d;
+ vertices[1][1][1] = 0.0f;
+ vertices[1][1][2] = 1.0f - texb;
+ vertices[1][1][3] = 0.0f;
+ vertices[1][1][4] = texb;
+
+ vertices[1][2][0] = pageWidth - e;
+ vertices[1][2][1] = pageHeight;
+ vertices[1][2][2] = 1.0f - texa;
+ vertices[1][2][3] = 1.0f;
+ vertices[1][2][4] = texa;
+
+ vertices[1][3][0] = 0.0f;
+ vertices[1][3][1] = pageHeight;
+ vertices[1][3][2] = 0.0f;
+ vertices[1][3][3] = 1.0f;
+ vertices[1][3][4] = 1.0f;
+
+ pageCount[1] = 4;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/demos/pageflip/pageflipmath_p.h b/demos/pageflip/pageflipmath_p.h
new file mode 100644
index 000000000..b926fac29
--- /dev/null
+++ b/demos/pageflip/pageflipmath_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 PAGEFLIPMATH_P_H
+#define PAGEFLIPMATH_P_H
+
+#include <QtOpenGL/qgl.h>
+
+QT_BEGIN_NAMESPACE
+
+class PageFlipMath
+{
+public:
+ PageFlipMath();
+ ~PageFlipMath();
+
+ enum StartCorner
+ {
+ BottomRight,
+ TopRight,
+ BottomLeft,
+ TopLeft,
+ BottomLeftOnePage,
+ TopLeftOnePage,
+ VerticalBottomRight,
+ VerticalTopRight,
+ VerticalBottomLeft,
+ VerticalTopLeft
+ };
+
+ // Corner to start flipping from.
+ StartCorner startCorner() const { return m_startCorner; }
+ void setStartCorner(StartCorner value) { m_startCorner = value; }
+
+ // Rectangle to display the main page (usually the one on the right).
+ QRect pageRect() const { return m_pageRect; }
+ void setPageRect(const QRect& rect) { m_pageRect = rect; }
+
+ // Show the reverse of the right-hand page on the back when
+ // flipping pages. That is, the user will essentially see
+ // the texture on the front of the page "through" it in reverse
+ // while it is being flipped.
+ bool showPageReverse() const { return m_showPageReverse; }
+ void setShowPageReverse(bool value) { m_showPageReverse = value; }
+
+ // Get the vertex array pointer.
+ const GLfloat *vertexArray() const { return vertices[0][0]; }
+
+ // Get the vertex array stride in bytes.
+ int stride() const { return 5 * sizeof(GLfloat); }
+
+ // Draw a specific page.
+ void drawPage(int page) const;
+
+ // Draw the outline of a page as a set of lines.
+ void drawOutline(int page) const;
+
+ // Compute the frame at position t (0...1) in the animation.
+ void compute(qreal t);
+
+private:
+ StartCorner m_startCorner;
+ QRect m_pageRect;
+ bool m_showPageReverse;
+
+ // Vertex array: up to 4 pages, with up to 5 vertices per page,
+ // and 5 components (2D position, 2D texcoord, 1D gradient control)
+ // per vertex. The gradient control value is interpolated between
+ // 0 and 1 - it is 1 at the fold point and 0 on the side of the page
+ // opposite the fold point. Shaders can use this to extract a color
+ // value from a gradient texture to blend with the page texture.
+ GLfloat vertices[4][5][5];
+
+ // Number of vertices for drawing the triangle fan for each page.
+ int pageCount[4];
+
+ void flip(qreal pageWidth, qreal pageHeight, qreal t);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/demos/pageflip/qqpage1.png b/demos/pageflip/qqpage1.png
new file mode 100644
index 000000000..8abf37d94
--- /dev/null
+++ b/demos/pageflip/qqpage1.png
Binary files differ
diff --git a/demos/pageflip/qqpage2.png b/demos/pageflip/qqpage2.png
new file mode 100644
index 000000000..afd1b0474
--- /dev/null
+++ b/demos/pageflip/qqpage2.png
Binary files differ
diff --git a/demos/pageflip/qqpage3.png b/demos/pageflip/qqpage3.png
new file mode 100644
index 000000000..fa2a85a02
--- /dev/null
+++ b/demos/pageflip/qqpage3.png
Binary files differ
diff --git a/demos/pageflip/qqpage4.png b/demos/pageflip/qqpage4.png
new file mode 100644
index 000000000..0a6ba7b03
--- /dev/null
+++ b/demos/pageflip/qqpage4.png
Binary files differ
diff --git a/demos/photobrowser3d/buttons.cpp b/demos/photobrowser3d/buttons.cpp
new file mode 100644
index 000000000..497a4b5b2
--- /dev/null
+++ b/demos/photobrowser3d/buttons.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "buttons.h"
+#include "qglpainter.h"
+
+Buttons::Buttons(QObject *parent, QGLMaterialCollection *palette)
+ : QGLSceneNode(parent)
+{
+ setObjectName("Buttons");
+ setPalette(palette);
+ setOption(QGLSceneNode::CullBoundingBox, false);
+
+ m_left = new QGLSceneNode(this);
+ m_left->setObjectName("Left Button");
+ m_right = new QGLSceneNode(this);
+ m_right->setObjectName("Right Button");
+
+ QGLMaterial *mat = new QGLMaterial;
+ QImage im(":/controls/arrows-left.png");
+ m_size = im.size();
+ QGLTexture2D *tex = new QGLTexture2D(mat);
+ tex->setImage(im);
+ mat->setTexture(tex);
+
+ setMaterial(mat);
+ setEffect(QGL::FlatReplaceTexture2D);
+
+ QGeometryData data;
+ QSize f = im.size() / 2;
+ QVector2D a(-f.width(), -f.height());
+ QVector2D b(f.width(), -f.height());
+ QVector2D c(f.width(), f.height());
+ QVector2D d(-f.width(), f.height());
+ QVector2D ta(0, 1);
+ QVector2D tb(1, 1);
+ QVector2D tc(1, 0);
+ QVector2D td(0, 0);
+ data.appendVertex(a, b, c, d);
+ data.appendTexCoord(ta, tb, tc, td);
+ data.appendIndices(0, 1, 2);
+ data.appendIndices(0, 2, 3);
+
+ // the right hand arrow geometry is same as above, flipped X <-> -X
+ data.appendGeometry(data);
+ data.texCoord(4).setX(1);
+ data.texCoord(5).setX(0);
+ data.texCoord(6).setX(0);
+ data.texCoord(7).setX(1);
+ data.appendIndices(4, 5, 6);
+ data.appendIndices(4, 6, 7);
+
+ m_left->setGeometry(data);
+ m_left->setCount(6);
+ m_left->setOption(QGLSceneNode::CullBoundingBox, false);
+
+ m_right->setGeometry(data);
+ m_right->setStart(6);
+ m_right->setCount(6);
+ m_left->setOption(QGLSceneNode::CullBoundingBox, false);
+}
+
+void Buttons::draw(QGLPainter *painter)
+{
+ painter->projectionMatrix().push();
+ painter->modelViewMatrix().push();
+
+ QRect rect = painter->currentSurface()->viewportRect();
+ QMatrix4x4 projm;
+ projm.ortho(rect);
+ painter->projectionMatrix() = projm;
+ painter->modelViewMatrix().setToIdentity();
+
+ if (m_left->position().isNull())
+ {
+ QVector2D pos(m_size.width() / 2, rect.height() - m_size.height() / 2);
+ m_left->setPosition(pos);
+ pos.setX(rect.width() - (m_size.width() / 2));
+ m_right->setPosition(pos);
+ }
+
+ glDisable(GL_DEPTH_TEST);
+
+ QGLSceneNode::draw(painter);
+
+ glEnable(GL_DEPTH_TEST);
+
+ painter->projectionMatrix().pop();
+ painter->modelViewMatrix().pop();
+}
+
+void Buttons::clearPositions()
+{
+ m_left->setPosition(QVector3D());
+ m_right->setPosition(QVector3D());
+}
diff --git a/demos/photobrowser3d/buttons.h b/demos/photobrowser3d/buttons.h
new file mode 100644
index 000000000..1e4475faf
--- /dev/null
+++ b/demos/photobrowser3d/buttons.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 BUTTONS_H
+#define BUTTONS_H
+
+#include "qglscenenode.h"
+
+#include <Qt>
+
+class Buttons : public QGLSceneNode
+{
+ Q_OBJECT
+public:
+ explicit Buttons(QObject *parent, QGLMaterialCollection *palette);
+ void draw(QGLPainter *painter);
+ void clearPositions();
+private:
+ QGLSceneNode *m_left;
+ QGLSceneNode *m_right;
+ QSize m_size;
+};
+
+#endif // BUTTONS_H
diff --git a/demos/photobrowser3d/bytereader.cpp b/demos/photobrowser3d/bytereader.cpp
new file mode 100644
index 000000000..71c3b3f12
--- /dev/null
+++ b/demos/photobrowser3d/bytereader.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "bytereader.h"
+#include "thumbnailableimage.h"
+
+#include <QByteArray>
+#include <QThread>
+#include <QImage>
+#include <QImageReader>
+#include <QUrl>
+#include <QFile>
+#include <QCoreApplication>
+
+ByteReader::ByteReader()
+{
+ m_stop = 0;
+ m_loading = 0;
+}
+
+void ByteReader::loadFile(const ThumbnailableImage &image)
+{
+ if (!m_stop)
+ {
+ m_loading.ref();
+
+ // FIXME: actually handle remote files
+ QUrl url = image.url();
+ QString fn = url.toLocalFile();
+ int pos = fn.lastIndexOf('.');
+ QString ext;
+ if (pos != -1)
+ ext = fn.mid(pos).toUpper();
+ if (ext.isEmpty() ||
+ !QImageReader::supportedImageFormats().contains(ext.toLocal8Bit()))
+ ext = QString();
+ QImage im;
+ QFile f(fn);
+ QString errorMessage;
+ if (f.open(QIODevice::ReadOnly))
+ {
+ QByteArray bytes;
+ while (!f.atEnd() & !m_stop)
+ {
+ bytes.append(f.read(1024));
+ QCoreApplication::processEvents();
+ }
+ im = ext.isEmpty() ? QImage::fromData(bytes)
+ : QImage::fromData(bytes, qPrintable(ext));
+ }
+ else
+ {
+ errorMessage = tr("Could not read: %1").arg(url.toString());
+ }
+
+ QCoreApplication::processEvents();
+ if (!m_stop)
+ {
+ if (im.isNull())
+ {
+ im = QImage(QSize(128, 128), QImage::Format_ARGB32);
+ im.fill(qRgba(0, 30, 50, 64));
+ QPainter ptr;
+ ptr.begin(&im);
+ ptr.setBackgroundMode(Qt::TransparentMode);
+ if (errorMessage.isEmpty())
+ errorMessage = tr("Could not load: %1").arg(url.toString());
+ ptr.setPen(QColor("orange"));
+ ptr.drawText(im.rect(), Qt::AlignCenter, errorMessage);
+ ptr.end();
+ }
+ else
+ {
+ // TODO: Fix size limit
+ // This arbitrary size limit is really a debugging/development thing
+ // In a real program once you had loaded the full image, the photo-
+ // viewer would allow zooming and panning all around in the image
+ // so loading a 2896 pixel × 1944 pixel photo would make sense even
+ // on a small screen. For now work with fairly cruddy image quality.
+ // Probably the fix is to have a separate load call that re-fetches
+ // the full image on a zoom
+ QSize workSize(1024, 768);
+ Qt::TransformationMode mode = Qt::SmoothTransformation;
+ if (QThread::idealThreadCount() < 2)
+ {
+ workSize = workSize / 2;
+ mode = Qt::FastTransformation;
+ }
+ if (im.size().width() > workSize.width() || im.size().height() > workSize.height())
+ im = im.scaled(workSize, Qt::KeepAspectRatio, mode);
+ }
+
+ Q_ASSERT(!im.isNull());
+ ThumbnailableImage result(image);
+ result.setData(im);
+
+ // it would be nice to incur the cost of setThumbnailed() on the image
+ // at this point - in the background thread. Trouble is the atlas is
+ // constantly being accessed by the draw loop and to do anything about
+ // that would mean locking the GUI thread...
+
+ Q_ASSERT(!result.isNull());
+
+ emit imageLoaded(result);
+ }
+
+ m_loading.deref();
+ }
+
+ if (m_stop)
+ emit stopped();
+
+}
+
+void ByteReader::stop()
+{
+ m_stop.ref();
+ if (!m_loading)
+ emit stopped();
+}
diff --git a/demos/photobrowser3d/bytereader.h b/demos/photobrowser3d/bytereader.h
new file mode 100644
index 000000000..2aa7dadf2
--- /dev/null
+++ b/demos/photobrowser3d/bytereader.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 BYTEREADER_H
+#define BYTEREADER_H
+
+#include <QObject>
+
+class ThumbnailableImage;
+class QUrl;
+
+class ByteReader : public QObject
+{
+ Q_OBJECT
+public:
+ ByteReader();
+signals:
+ void imageLoaded(const ThumbnailableImage &image);
+ void stopped();
+public slots:
+ void loadFile(const ThumbnailableImage &url);
+ void stop();
+private:
+ QAtomicInt m_stop;
+ QAtomicInt m_loading;
+};
+
+#endif // BYTEREADER_H
diff --git a/demos/photobrowser3d/filescanner.cpp b/demos/photobrowser3d/filescanner.cpp
new file mode 100644
index 000000000..4010ebdab
--- /dev/null
+++ b/demos/photobrowser3d/filescanner.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "filescanner.h"
+
+#include <QTime>
+#include <QFileInfo>
+#include <QStringList>
+#include <QSet>
+#include <QDir>
+#include <QCoreApplication>
+#include <QImageReader>
+#include <QDebug>
+
+FileScanner::FileScanner(QObject *parent)
+ : QThread(parent)
+{
+ m_stop = 0;
+}
+
+FileScanner::~FileScanner()
+{
+ // nothing to do here
+}
+
+void FileScanner::stop()
+{
+ m_stop.ref();
+}
+
+void FileScanner::run()
+{
+ scan();
+}
+
+void FileScanner::scan()
+{
+ QStringList queue;
+ queue.append(m_url.path());
+ QSet<QString> loopProtect;
+ int count = 0;
+ while (queue.size() > 0 && !m_stop && count < 300)
+ {
+ QString path = queue.takeFirst();
+ QFileInfo u(path);
+ if (u.isSymLink())
+ {
+ path = u.symLinkTarget();
+ u = QFileInfo(path);
+ }
+ if (u.isDir())
+ {
+ if (!loopProtect.contains(path))
+ {
+ loopProtect.insert(path);
+ QDir dir(path);
+ QStringList entries = dir.entryList();
+ QStringList::const_iterator it = entries.constBegin();
+ for ( ; it != entries.constEnd(); ++it)
+ {
+ // ignore hidden files, system directories
+ if ((*it).startsWith("."))
+ continue;
+ queue.append(dir.absoluteFilePath(*it));
+ }
+ }
+ }
+ else
+ {
+ if (u.isFile() && u.isReadable())
+ {
+ // small optimization: if the file has a suffix, check if that
+ // is known as an image format before sending to loader
+ QString ext = u.suffix();
+ if (ext.isEmpty() ||
+ QImageReader::supportedImageFormats().contains(ext.toLocal8Bit()))
+ {
+ QUrl url2;
+ url2.setScheme("file");
+ url2.setPath(u.absoluteFilePath());
+ emit imageUrl(url2);
+ ++count;
+ }
+ }
+ }
+ QCoreApplication::processEvents();
+ QThread::yieldCurrentThread();
+ }
+}
diff --git a/demos/photobrowser3d/filescanner.h b/demos/photobrowser3d/filescanner.h
new file mode 100644
index 000000000..d9f15e9a9
--- /dev/null
+++ b/demos/photobrowser3d/filescanner.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 FILESCANNER_H
+#define FILESCANNER_H
+
+#include <QThread>
+#include <QUrl>
+#include <QDebug>
+
+class FileScanner : public QThread
+{
+ Q_OBJECT
+public:
+ explicit FileScanner(QObject *parent = 0);
+ ~FileScanner();
+
+ // INVARIANT: never get called when the thread is running
+ void setBaseUrl(const QUrl &url)
+ {
+ Q_ASSERT(!isRunning());
+ m_url = url;
+ }
+
+signals:
+ void imageUrl(const QUrl &url);
+
+public slots:
+ void stop();
+ void scan();
+
+protected:
+ void run();
+
+ QUrl m_url;
+ QAtomicInt m_stop;
+private:
+
+};
+
+#endif // FILESCANNER_H
diff --git a/demos/photobrowser3d/imagedisplay.cpp b/demos/photobrowser3d/imagedisplay.cpp
new file mode 100644
index 000000000..73782aeb1
--- /dev/null
+++ b/demos/photobrowser3d/imagedisplay.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "imagedisplay.h"
+#include "thumbnailableimage.h"
+#include "thumbnailnode.h"
+#include "thumbnaileffect.h"
+#include "qglbuilder.h"
+#include "qglcube.h"
+#include "imagemanager.h"
+#include "qatlas.h"
+#include "qglshaderprogrameffect.h"
+#include "qphotobrowser3dscene.h"
+#include "photobrowser3dview.h"
+
+#include <QApplication>
+#include <QChildEvent>
+#include <QUrl>
+#include <QImage>
+
+static inline QImage qMakeFrameImage()
+{
+ QImage frm(QSize(128, 128), QImage::Format_ARGB32);
+ frm.fill(qRgba(8, 8, 8, 255)); // dark grey frame
+ QPainter ptr;
+ ptr.begin(&frm);
+ QRect r(8, 8, 112, 112);
+ ptr.setBackgroundMode(Qt::TransparentMode);
+ ptr.fillRect(r, QColor(0, 30, 50, 64));
+ ptr.setPen(QColor("orange"));
+ ptr.drawText(frm.rect(), Qt::AlignCenter, "Loading...");
+ ptr.end();
+ return frm;
+}
+
+static inline void qAddPane(QSizeF size, QGeometryData *data)
+{
+ Q_ASSERT(data);
+ QSizeF f = size / 2.0f;
+ QVector2D a(-f.width(), -f.height());
+ QVector2D b(f.width(), -f.height());
+ QVector2D c(f.width(), f.height());
+ QVector2D d(-f.width(), f.height());
+ QVector2D ta(0.0f, 0.0f);
+ QVector2D tb(1.0f, 0.0f);
+ QVector2D tc(1.0f, 1.0f);
+ QVector2D td(0.0f, 1.0f);
+ int k = data->count();
+ data->appendVertex(a, b, c, d);
+ data->appendTexCoord(ta, tb, tc, td);
+ data->appendIndices(k, k+1, k+2);
+ data->appendIndices(k, k+2, k+3);
+}
+
+ImageDisplay::ImageDisplay(QObject *parent, QGLMaterialCollection *materials, qreal wallSize)
+ : QGLSceneNode(parent)
+ , m_wall(0)
+ , m_frames(0)
+ , m_currentWall(0)
+ , m_currentFrame(0)
+ , m_imageSetToDefault(false)
+ , m_count(0)
+ , m_size(wallSize)
+ , m_frameSize((m_size * 3.0f) / 4.0f)
+ , m_maxImages(500)
+ , m_frameLoadingMaterial(-1)
+{
+ // the real values will get poked in here by the atlas
+ m_atlasPlaceHolder.append(QVector2D(), QVector2D(), QVector2D(), QVector2D());
+
+ setObjectName("ImageDisplay");
+ setPalette(materials);
+
+ // the frames lie in Z = 0, the wall is set back and lies in
+ // the plane Z = (m_size / -4.0)
+
+ // build the wall
+ qAddPane(QSize(m_size, m_size), &m_wallGeometry);
+ m_wall = new QGLSceneNode(this);
+ m_wall->setObjectName("Wall");
+ m_wall->setPalette(materials);
+ m_currentWall = new QGLSceneNode(m_wall);
+ m_currentWall->setObjectName("wall 0");
+ m_currentWall->setGeometry(m_wallGeometry);
+ m_currentWall->setCount(m_wallGeometry.indexCount());
+ m_wall->setPosition(QVector3D(0.0f, 0.0f, m_size / -4.0));
+
+ // paint the wall
+ m_wall->setEffect(QGL::FlatReplaceTexture2D);
+ QGLMaterial *mat = new QGLMaterial();
+ QGLTexture2D *tex = new QGLTexture2D(mat);
+ tex->setImage(QImage(":/res/images/girder.png"));
+ mat->setTexture(tex);
+ mat->setObjectName("girder material");
+ m_wall->setMaterial(mat);
+
+ // build the frames
+ qAddPane(QSize(m_frameSize, m_frameSize), &m_frameGeometry);
+ m_frameGeometry.appendTexCoordArray(m_atlasPlaceHolder, QGL::TextureCoord1);
+ m_frames = new QGLSceneNode(this);
+ m_frames->setObjectName("Frames");
+ m_currentFrame = new ThumbnailNode(m_frames);
+ m_currentFrame->setObjectName("frame 0");
+ m_currentFrame->setGeometry(m_frameGeometry);
+ m_currentFrame->setCount(m_frameGeometry.indexCount());
+
+ // use the frames geometry to put the atlas data into
+ QAtlas *atlas = QAtlas::instance();
+ atlas->setGeometry(m_frameGeometry);
+
+ // generally the frames use the thumbnail material & effect
+ m_effect = new ThumbnailEffect;
+ m_frames->setUserEffect(m_effect);
+ m_frames->setEffectEnabled(true);
+ m_frames->setMaterial(atlas->material());
+
+ // unless they're loading, in which case use the "loading" image
+ m_frameImage = qMakeFrameImage();
+ mat = new QGLMaterial();
+ tex = new QGLTexture2D(mat);
+ tex->setHorizontalWrap(QGL::Clamp);
+ tex->setImage(m_frameImage);
+ mat->setTexture(tex);
+ mat->setObjectName("loading image material - default");
+ m_frameLoadingMaterial = materials->addMaterial(mat);
+ m_currentFrame->setMaterialIndex(m_frameLoadingMaterial);
+
+ // make the frames pickable
+ PhotoBrowser3DView *view = qobject_cast<PhotoBrowser3DView*>(parent);
+ view->scene()->mainNode()->addNode(m_frames);
+
+ m_imageSetToDefault = true;
+}
+
+ImageDisplay::~ImageDisplay()
+{
+ delete m_effect;
+}
+
+void ImageDisplay::addThumbnailNode(const QUrl &image)
+{
+ Q_ASSERT(QThread::currentThread() == thread());
+ ImageManager *manager = qobject_cast<ImageManager*>(sender());
+ if (!m_imageSetToDefault)
+ {
+ QVector3D p = m_currentFrame->position();
+ p.setX(p.x() - m_size);
+ int start = m_frameGeometry.indexCount();
+ qAddPane(QSize(m_frameSize, m_frameSize), &m_frameGeometry);
+ int count = m_frameGeometry.indexCount() - start;
+ m_frameGeometry.appendTexCoordArray(m_atlasPlaceHolder, QGL::TextureCoord1);
+ m_currentFrame = new ThumbnailNode(m_frames);
+ QString name = QLatin1String("frame %1");
+ name.arg(m_count);
+ m_currentFrame->setObjectName(name);
+ m_currentFrame->setPosition(p);
+ m_currentFrame->setStart(start);
+ m_currentFrame->setCount(count);
+ m_currentFrame->setGeometry(m_frameGeometry);
+ m_currentFrame->setMaterialIndex(m_frameLoadingMaterial);
+
+ QGLSceneNode *s = m_currentWall->clone(m_wall);
+ name = QLatin1String("wall %1");
+ name.arg(m_count);
+ s->setObjectName(name);
+ p = s->position();
+ p.setX(p.x() - m_size);
+ s->setPosition(p);
+ m_currentWall = s;
+ }
+ m_currentFrame->setUrl(image);
+ if (manager)
+ {
+ connect(m_currentFrame, SIGNAL(imageRequired(ThumbnailableImage)),
+ manager, SIGNAL(deployLoader(ThumbnailableImage)));
+ connect(manager, SIGNAL(imageReady(ThumbnailableImage)),
+ m_currentFrame, SLOT(setImage(ThumbnailableImage)));
+ }
+ PhotoBrowser3DView *view = qobject_cast<PhotoBrowser3DView*>(parent());
+ Q_ASSERT(view);
+ connect(m_currentFrame, SIGNAL(nodeChanged()), view, SLOT(update()));
+
+ m_imageSetToDefault = false;
+ emit framesChanged();
+ ++m_count;
+}
diff --git a/demos/photobrowser3d/imagedisplay.h b/demos/photobrowser3d/imagedisplay.h
new file mode 100644
index 000000000..8bd051168
--- /dev/null
+++ b/demos/photobrowser3d/imagedisplay.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 IMAGEDISPLAY_H
+#define IMAGEDISPLAY_H
+
+#include "qglscenenode.h"
+#include "qglmaterialcollection.h"
+
+#include <QString>
+
+class QGLBuilder;
+class QGLTexture2D;
+class QGLPainter;
+class ThumbnailNode;
+
+class ImageDisplay : public QGLSceneNode
+{
+ Q_OBJECT
+public:
+ ImageDisplay(QObject *parent, QGLMaterialCollection *materials, qreal wallSize = 4.0);
+ ~ImageDisplay();
+ int maxImages() const { return m_maxImages; }
+ void setMaxImages(int max) { m_maxImages = max; }
+signals:
+ void framesChanged();
+public slots:
+ void addThumbnailNode(const QUrl &url);
+private:
+ QGLSceneNode *m_wall;
+ QGLSceneNode *m_frames;
+ QGLSceneNode *m_currentWall;
+ ThumbnailNode *m_currentFrame;
+ QGLAbstractEffect *m_effect;
+ bool m_imageSetToDefault;
+ int m_count;
+ qreal m_size;
+ qreal m_frameSize;
+ int m_maxImages;
+ QImage m_frameImage;
+ int m_frameLoadingMaterial;
+ QGeometryData m_frameGeometry;
+ QGeometryData m_wallGeometry;
+ QVector2DArray m_atlasPlaceHolder;
+};
+
+#endif // IMAGEDISPLAY_H
diff --git a/demos/photobrowser3d/imageloader.cpp b/demos/photobrowser3d/imageloader.cpp
new file mode 100644
index 000000000..912ae7209
--- /dev/null
+++ b/demos/photobrowser3d/imageloader.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "imageloader.h"
+#include "imagemanager.h"
+#include "bytereader.h"
+
+#include <QFileInfo>
+#include <QTime>
+#include <QDir>
+#include <QStringList>
+#include <QPixmap>
+#include <QPainter>
+#include <QBuffer>
+#include <QImageReader>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QTimer>
+
+ImageLoader::ImageLoader()
+{
+ m_stop = 0;
+}
+
+ImageLoader::~ImageLoader()
+{
+ // nothing to do here
+}
+
+ThumbnailableImage ImageLoader::image() const
+{
+ return m_image;
+}
+
+void ImageLoader::setImage(const ThumbnailableImage &image)
+{
+ m_image = image;
+ if (!m_stop && isRunning())
+ emit readRequired(image);
+}
+
+void ImageLoader::stop()
+{
+ m_stop.ref();
+ emit stopLoading();
+}
+
+void ImageLoader::queueInitialImage()
+{
+ emit readRequired(m_image);
+}
+
+void ImageLoader::unusedTimeout()
+{
+ emit unused();
+}
+
+void ImageLoader::run()
+{
+ ByteReader reader;
+ connect(this, SIGNAL(readRequired(ThumbnailableImage)),
+ &reader, SLOT(loadFile(ThumbnailableImage)));
+ connect(&reader, SIGNAL(imageLoaded(ThumbnailableImage)),
+ this, SIGNAL(imageLoaded(ThumbnailableImage)));
+
+ connect(this, SIGNAL(stopLoading()), &reader, SLOT(stop()));
+ connect(&reader, SIGNAL(stopped()), this, SLOT(quit()));
+
+ QTimer timer;
+ connect(&timer, SIGNAL(timeout()), this, SLOT(unusedTimeout()));
+ timer.start(2 * 60 * 1000);
+
+ if (!m_image.isNull())
+ QTimer::singleShot(0, this, SLOT(queueInitialImage()));
+
+ exec();
+}
diff --git a/demos/photobrowser3d/imageloader.h b/demos/photobrowser3d/imageloader.h
new file mode 100644
index 000000000..560436ede
--- /dev/null
+++ b/demos/photobrowser3d/imageloader.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 IMAGELOADER_H
+#define IMAGELOADER_H
+
+#include <QThread>
+#include <QUrl>
+#include <QMutex>
+#include <QAtomicInt>
+
+#include "thumbnailableimage.h"
+
+class ImageManager;
+class ByteReader;
+
+class ImageLoader : public QThread
+{
+ Q_OBJECT
+public:
+ ImageLoader();
+ ~ImageLoader();
+ ThumbnailableImage image() const;
+ void setImage(const ThumbnailableImage &image);
+signals:
+ void imageLoaded(const ThumbnailableImage &image);
+ void stopLoading();
+ void readRequired(const ThumbnailableImage &image);
+ void thumbnailRequired(const ThumbnailableImage &image);
+ void thumbnailDone(const ThumbnailableImage &image);
+ void unused();
+public slots:
+ void stop();
+protected:
+ void run();
+private slots:
+ void queueInitialImage();
+ void unusedTimeout();
+private:
+ ThumbnailableImage m_image;
+ QAtomicInt m_stop;
+ ByteReader *m_reader;
+};
+
+#endif // IMAGELOADER_H
diff --git a/demos/photobrowser3d/imagemanager.cpp b/demos/photobrowser3d/imagemanager.cpp
new file mode 100644
index 000000000..30e2148d4
--- /dev/null
+++ b/demos/photobrowser3d/imagemanager.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "imagemanager.h"
+#include "qatlas.h"
+#include "filescanner.h"
+#include "threadpool.h"
+
+#include <QTime>
+#include <QTimer>
+#include <QDir>
+
+ImageManager::ImageManager()
+{
+}
+
+ImageManager::~ImageManager()
+{
+}
+
+// INVARIANT: only ever called before the run() function is started
+// therefore no need for synchronized url
+void ImageManager::setImageBaseUrl(const QUrl &url)
+{
+ Q_ASSERT(!isRunning());
+ m_url = url;
+}
+
+/*!
+ Stop the running threads if any, then sit waiting in the event loop
+ for a quit call.
+*/
+void ImageManager::stop()
+{
+ emit stopAll();
+}
+
+void ImageManager::scanForFiles()
+{
+ // TODO: In a real app there would be a way to detect new files arriving
+ // and trigger a rescan to pick these new files up. Here we just scan
+ // once and then destroy the scanner, to save on resources.
+
+#ifndef QT_USE_TEST_IMAGES
+ // TODO: If the amount of files is large and the app is quit early the
+ // scanner could still be going when the threadpool quits. For now
+ // assume its ok...
+ FileScanner *scanner = new FileScanner;
+ scanner->setBaseUrl(m_url);
+ connect(scanner, SIGNAL(imageUrl(QUrl)), this, SIGNAL(imageUrl(QUrl)));
+ connect(scanner, SIGNAL(finished()), scanner, SLOT(deleteLater()));
+ connect(this, SIGNAL(stopAll()), scanner, SLOT(stop()));
+ scanner->start();
+#else
+ QDir testImages(":/pictures");
+ QStringList pics = testImages.entryList();
+ for (int i = 0; i < pics.size(); ++i)
+ {
+ QUrl url;
+ url.setScheme("file");
+ url.setPath(testImages.filePath(pics.at(i)));
+ emit imageUrl(url);
+ }
+ qDebug() << "== test images loaded ==";
+#endif
+}
+
+void ImageManager::quit()
+{
+ QThread::quit();
+}
+
+void ImageManager::run()
+{
+ if (m_url.scheme() != "file")
+ {
+ qWarning("URL scheme %s not yet supported", qPrintable(m_url.scheme()));
+ return;
+ }
+
+ // execute once in the event loop below
+ QTimer::singleShot(0, this, SLOT(scanForFiles()));
+
+#ifndef QT_NO_THREADED_FILE_LOAD
+ ThreadPool pool;
+
+ connect(this, SIGNAL(deployLoader(ThumbnailableImage)),
+ &pool, SLOT(deployLoader(ThumbnailableImage)));
+
+ connect(this, SIGNAL(stopAll()), &pool, SLOT(stop()));
+ connect(&pool, SIGNAL(stopped()), this, SLOT(quit()));
+#endif
+
+ exec();
+}
diff --git a/demos/photobrowser3d/imagemanager.h b/demos/photobrowser3d/imagemanager.h
new file mode 100644
index 000000000..51482b1cd
--- /dev/null
+++ b/demos/photobrowser3d/imagemanager.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 IMAGEMANAGER_H
+#define IMAGEMANAGER_H
+
+#include <QThread>
+#include <QUrl>
+#include <QImage>
+#include <QMutex>
+
+#include "thumbnailableimage.h"
+
+class Launcher;
+
+class ImageManager : public QThread
+{
+ Q_OBJECT
+public:
+ ImageManager();
+ ~ImageManager();
+ QUrl imageBaseUrl() const { return m_url; }
+ void setImageBaseUrl(const QUrl &url);
+public slots:
+ void stop();
+ void quit();
+signals:
+ void imageUrl(const QUrl &);
+ void imageReady(const ThumbnailableImage &);
+ void deployLoader(const ThumbnailableImage &);
+ void stopAll();
+protected:
+ void run();
+private slots:
+ void scanForFiles();
+private:
+ QUrl m_url;
+};
+
+#endif // IMAGEMANAGER_H
diff --git a/demos/photobrowser3d/images/P1000223.JPG b/demos/photobrowser3d/images/P1000223.JPG
new file mode 100644
index 000000000..48edfbc2d
--- /dev/null
+++ b/demos/photobrowser3d/images/P1000223.JPG
Binary files differ
diff --git a/demos/photobrowser3d/images/P1000228.JPG b/demos/photobrowser3d/images/P1000228.JPG
new file mode 100644
index 000000000..2797b6df5
--- /dev/null
+++ b/demos/photobrowser3d/images/P1000228.JPG
Binary files differ
diff --git a/demos/photobrowser3d/images/P1000441.JPG b/demos/photobrowser3d/images/P1000441.JPG
new file mode 100644
index 000000000..b4037b49e
--- /dev/null
+++ b/demos/photobrowser3d/images/P1000441.JPG
Binary files differ
diff --git a/demos/photobrowser3d/images/P1000472.JPG b/demos/photobrowser3d/images/P1000472.JPG
new file mode 100644
index 000000000..067afdd4a
--- /dev/null
+++ b/demos/photobrowser3d/images/P1000472.JPG
Binary files differ
diff --git a/demos/photobrowser3d/images/arrows-left.png b/demos/photobrowser3d/images/arrows-left.png
new file mode 100644
index 000000000..791f2c6b1
--- /dev/null
+++ b/demos/photobrowser3d/images/arrows-left.png
Binary files differ
diff --git a/demos/photobrowser3d/images/arrows.xcf b/demos/photobrowser3d/images/arrows.xcf
new file mode 100644
index 000000000..302bcd6eb
--- /dev/null
+++ b/demos/photobrowser3d/images/arrows.xcf
Binary files differ
diff --git a/demos/photobrowser3d/images/default_sky_base.xcf b/demos/photobrowser3d/images/default_sky_base.xcf
new file mode 100644
index 000000000..050812f7d
--- /dev/null
+++ b/demos/photobrowser3d/images/default_sky_base.xcf
Binary files differ
diff --git a/demos/photobrowser3d/images/default_sky_down.png b/demos/photobrowser3d/images/default_sky_down.png
new file mode 100644
index 000000000..531ba75e9
--- /dev/null
+++ b/demos/photobrowser3d/images/default_sky_down.png
Binary files differ
diff --git a/demos/photobrowser3d/images/default_sky_east.png b/demos/photobrowser3d/images/default_sky_east.png
new file mode 100644
index 000000000..09bfc3ad5
--- /dev/null
+++ b/demos/photobrowser3d/images/default_sky_east.png
Binary files differ
diff --git a/demos/photobrowser3d/images/default_sky_north.png b/demos/photobrowser3d/images/default_sky_north.png
new file mode 100644
index 000000000..b97aaa20a
--- /dev/null
+++ b/demos/photobrowser3d/images/default_sky_north.png
Binary files differ
diff --git a/demos/photobrowser3d/images/default_sky_south.png b/demos/photobrowser3d/images/default_sky_south.png
new file mode 100644
index 000000000..28db27816
--- /dev/null
+++ b/demos/photobrowser3d/images/default_sky_south.png
Binary files differ
diff --git a/demos/photobrowser3d/images/default_sky_up.png b/demos/photobrowser3d/images/default_sky_up.png
new file mode 100644
index 000000000..a56feddbf
--- /dev/null
+++ b/demos/photobrowser3d/images/default_sky_up.png
Binary files differ
diff --git a/demos/photobrowser3d/images/default_sky_west.png b/demos/photobrowser3d/images/default_sky_west.png
new file mode 100644
index 000000000..4d2746b0d
--- /dev/null
+++ b/demos/photobrowser3d/images/default_sky_west.png
Binary files differ
diff --git a/demos/photobrowser3d/images/girder.png b/demos/photobrowser3d/images/girder.png
new file mode 100644
index 000000000..f9b6c4dc6
--- /dev/null
+++ b/demos/photobrowser3d/images/girder.png
Binary files differ
diff --git a/demos/photobrowser3d/images/no-images-yet.png b/demos/photobrowser3d/images/no-images-yet.png
new file mode 100644
index 000000000..5d4f673ae
--- /dev/null
+++ b/demos/photobrowser3d/images/no-images-yet.png
Binary files differ
diff --git a/demos/photobrowser3d/images/no-images-yet.xcf b/demos/photobrowser3d/images/no-images-yet.xcf
new file mode 100644
index 000000000..f084d45e4
--- /dev/null
+++ b/demos/photobrowser3d/images/no-images-yet.xcf
Binary files differ
diff --git a/demos/photobrowser3d/images/sample_image.jpg b/demos/photobrowser3d/images/sample_image.jpg
new file mode 100644
index 000000000..2826f9251
--- /dev/null
+++ b/demos/photobrowser3d/images/sample_image.jpg
Binary files differ
diff --git a/demos/photobrowser3d/launcher.cpp b/demos/photobrowser3d/launcher.cpp
new file mode 100644
index 000000000..3005bb19c
--- /dev/null
+++ b/demos/photobrowser3d/launcher.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "launcher.h"
+#include "imageloader.h"
+#include "imagemanager.h"
+
+#include <QSemaphore>
+#include <QTime>
+#include <QFileInfo>
+#include <QDir>
+#include <QStringList>
+#include <QSet>
+#include <QDebug>
+
+Launcher::Launcher(ImageManager *manager)
+ : m_manager(manager)
+ , m_stop(false)
+{
+ Q_ASSERT(m_manager);
+}
+
+void Launcher::run()
+{
+ if (m_url.isEmpty())
+ {
+ qWarning("Launcher::run - empty URL!");
+ return;
+ }
+ if (m_url.scheme() != QLatin1String("file"))
+ {
+ qWarning("URL scheme %s not yet supported", qPrintable(m_url.scheme()));
+ return;
+ }
+ QStringList queue;
+ queue.append(m_url.path());
+ QSet<QString> loopProtect;
+ while (queue.size() > 0 && !m_stop)
+ {
+ QString path = queue.takeFirst();
+ QFileInfo u(path);
+ if (u.isSymLink())
+ path = u.symLinkTarget();
+ if (u.isDir())
+ {
+ if (!loopProtect.contains(path))
+ {
+ loopProtect.insert(path);
+ QDir dir(path);
+ QStringList entries = dir.entryList();
+ QStringList::const_iterator it = entries.constBegin();
+ for ( ; it != entries.constEnd(); ++it)
+ {
+ // ignore hidden files, system directories
+ if ((*it).startsWith(QLatin1Char('.')))
+ continue;
+ queue.append(dir.absoluteFilePath(*it));
+ }
+ }
+ }
+ else
+ {
+ if (u.isFile() && u.isReadable())
+ {
+ // do no checking here for file extensions etc - just
+ // forward any readable file found under the pictures
+ // directory to the QImage loader, and let it sort out
+ // if the thing can be loaded as an image.
+ QUrl url2;
+ url2.setScheme(QLatin1String("file"));
+ url2.setPath(u.absoluteFilePath());
+ m_manager->acquire();
+ emit imageUrl(url2);
+ }
+ }
+ }
+}
diff --git a/demos/photobrowser3d/main.cpp b/demos/photobrowser3d/main.cpp
new file mode 100644
index 000000000..748866bab
--- /dev/null
+++ b/demos/photobrowser3d/main.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 <QtGui/QApplication>
+#include <QtCore/QThread>
+
+#include "photobrowser3dview.h"
+
+int main(int argc, char *argv[])
+{
+ Q_INIT_RESOURCE(photobrowser3d);
+
+ QApplication app(argc, argv);
+
+ // for QSettings
+ QCoreApplication::setOrganizationName("Nokia");
+ QCoreApplication::setOrganizationDomain("nokia.com");
+ QCoreApplication::setApplicationName("photobrowser3d");
+
+ int result = 0;
+ {
+ PhotoBrowser3DView view;
+
+ if (QApplication::arguments().contains("-maximize"))
+ view.showMaximized();
+ else if (QApplication::arguments().contains("-fullscreen"))
+ view.showFullScreen();
+ else
+ view.show();
+
+ result = app.exec();
+ }
+ return result;
+}
diff --git a/demos/photobrowser3d/pancontroller.cpp b/demos/photobrowser3d/pancontroller.cpp
new file mode 100644
index 000000000..e45b4abeb
--- /dev/null
+++ b/demos/photobrowser3d/pancontroller.cpp
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "pancontroller.h"
+#include "qglview.h"
+#include "qglcamera.h"
+#include "photobrowser3dview.h"
+
+#include <qmath.h>
+
+#include <QtGlobal>
+#include <QTime>
+
+class PanControllerPrivate
+{
+public:
+ PanControllerPrivate()
+ : speed(0.0f)
+ , angle(0.0f)
+ , arrowDirection(Qt::NoArrow)
+ , view(0)
+ , maxSpeed(4.0f)
+ , defaultDistance(0.0f)
+ , panDistance(0.0f)
+ , panViewAngle(M_PI / 4.0f) // 45 degrees in radians
+ , animating(false)
+ , elapsed(0.0f)
+ {
+ panTime.start();
+ }
+
+ void calculateValues();
+
+ qreal speed;
+ qreal angle;
+ Qt::ArrowType arrowDirection;
+ QGLView *view;
+ QTime panTime;
+ qreal maxSpeed;
+ qreal defaultDistance;
+ qreal panDistance;
+ qreal panViewAngle;
+ bool animating;
+ qreal elapsed;
+};
+
+PanController::PanController(QObject *parent)
+ : QObject(parent)
+ , d(new PanControllerPrivate)
+{
+ QGLView *v = qobject_cast<QGLView*>(parent);
+ if (v)
+ d->view = v;
+}
+
+PanController::~PanController()
+{
+ delete d;
+}
+
+qreal PanController::defaultDistance() const
+{
+ return d->defaultDistance;
+}
+
+void PanController::setDefaultDistance(qreal dist)
+{
+ d->defaultDistance = dist;
+}
+
+qreal PanController::panDistance() const
+{
+ return d->panDistance;
+}
+
+void PanController::setPanDistance(qreal dist)
+{
+ d->panDistance = dist;
+}
+
+qreal PanController::panViewAngle() const
+{
+ return d->panViewAngle;
+}
+
+void PanController::setPanViewAngle(qreal angle)
+{
+ d->panViewAngle = angle;
+}
+
+void PanController::setMaxSpeed(qreal maxSpeed)
+{
+ d->maxSpeed = maxSpeed;
+}
+
+qreal PanController::maxSpeed() const
+{
+ return d->maxSpeed;
+}
+
+void PanController::setSpeed(qreal speed)
+{
+ qreal t = d->panTime.restart();
+ if (d->speed != speed)
+ {
+ d->speed = speed;
+ d->angle = speed * d->panViewAngle;
+ if (!qIsNull(d->speed))
+ d->animating = true;
+ d->elapsed += t;
+ d->calculateValues();
+ emit speedChanged();
+ }
+}
+
+qreal PanController::speed() const
+{
+ return d->speed;
+}
+
+void PanController::pan()
+{
+ if (d->animating)
+ {
+ qreal t = d->panTime.restart();
+ d->elapsed += t;
+ // dont recalculate every single time
+ // 30ms frame time == 33fps - more than enough
+ if (d->elapsed > 30)
+ d->calculateValues();
+
+ PhotoBrowser3DView *view = qobject_cast<PhotoBrowser3DView*>(parent());
+ Q_ASSERT(view);
+ view->update();
+ }
+}
+
+void PanControllerPrivate::calculateValues()
+{
+ if (view && animating)
+ {
+ QGLCamera *cam = view->camera();
+ Q_ASSERT(cam);
+
+ QVector3D c = cam->center();
+ QVector3D e = cam->eye();
+
+ if (qFuzzyIsNull(speed))
+ {
+ c.setX(e.x());
+ e.setZ(defaultDistance);
+ }
+ else
+ {
+ // as speed goes from 0 -> 1, eye moves closer to z=0 plane
+ e.setZ(defaultDistance - (speed * (defaultDistance - panDistance)));
+
+ // the view angle is a direct function of the speed see setSpeed() above
+ // and as view angle increases we look further along the x-axis
+ qreal opp = (e.z() - c.z()) * qTan(angle);
+
+ // velocity along the x axis is controlled by speed (a value from 0 -> 1
+ // which is a modifier for the maxSpeed, a constant). the velocity gives
+ // us the incremental change in x for this unit time
+ qreal dx = (speed * maxSpeed * elapsed);
+
+ if (arrowDirection == Qt::LeftArrow)
+ {
+ e.setX(e.x() - dx);
+ c.setX(e.x() - opp);
+ }
+ else if (arrowDirection == Qt::RightArrow)
+ {
+ e.setX(e.x() + dx);
+ c.setX(e.x() + opp);
+ }
+ }
+ cam->setEye(e);
+ cam->setCenter(c);
+ }
+ elapsed = 0;
+ if (qIsNull(speed))
+ animating = false;
+}
+
+Qt::ArrowType PanController::direction() const
+{
+ return d->arrowDirection;
+}
+
+void PanController::setDirection(Qt::ArrowType arrow)
+{
+ Q_ASSERT(arrow == Qt::LeftArrow || arrow == Qt::RightArrow);
+ d->arrowDirection = arrow;
+}
+
+QGLView *PanController::view() const
+{
+ return d->view;
+}
+
+void PanController::setView(QGLView *view)
+{
+ d->view = view;
+}
+
diff --git a/demos/photobrowser3d/pancontroller.h b/demos/photobrowser3d/pancontroller.h
new file mode 100644
index 000000000..c0354b618
--- /dev/null
+++ b/demos/photobrowser3d/pancontroller.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 PANCONTROLLER_H
+#define PANCONTROLLER_H
+
+#include <QObject>
+#include <Qt>
+
+class PanControllerPrivate;
+class QGLView;
+
+class PanController : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal speed READ speed WRITE setSpeed NOTIFY speedChanged)
+public:
+ explicit PanController(QObject *parent = 0);
+ ~PanController();
+
+ qreal defaultDistance() const;
+ void setDefaultDistance(qreal d);
+
+ qreal panDistance() const;
+ void setPanDistance(qreal d);
+
+ qreal panViewAngle() const;
+ void setPanViewAngle(qreal angle);
+
+ qreal maxSpeed() const;
+ void setMaxSpeed(qreal maxSpeed);
+
+ qreal speed() const;
+ void setSpeed(qreal speed);
+
+ Qt::ArrowType direction() const;
+ void setDirection(Qt::ArrowType arrow);
+
+ QGLView *view() const;
+ void setView(QGLView *view);
+
+ void pan();
+
+signals:
+ void speedChanged();
+
+private:
+ PanControllerPrivate *d;
+};
+
+#endif // PANCONTROLLER_H
diff --git a/demos/photobrowser3d/photobrowser3d.pro b/demos/photobrowser3d/photobrowser3d.pro
new file mode 100644
index 000000000..b5c695bca
--- /dev/null
+++ b/demos/photobrowser3d/photobrowser3d.pro
@@ -0,0 +1,62 @@
+TEMPLATE = app
+TARGET = photobrowser3d
+CONFIG += qt warn_on qt3d
+SOURCES += main.cpp\
+ photobrowser3dview.cpp \
+ imagedisplay.cpp \
+ skybox.cpp \
+ imagemanager.cpp \
+ imageloader.cpp \
+ qfocusadaptor.cpp \
+ thumbnailableimage.cpp \
+ qatlas.cpp \
+ thumbnailnode.cpp \
+ thumbnaileffect.cpp \
+ filescanner.cpp \
+ bytereader.cpp \
+ threadpool.cpp \
+ buttons.cpp \
+ qphotobrowser3dscene.cpp \
+ pancontroller.cpp
+
+HEADERS += photobrowser3dview.h \
+ imagedisplay.h \
+ skybox.h \
+ imagemanager.h \
+ imageloader.h \
+ qfocusadaptor.h \
+ thumbnailableimage.h \
+ qatlas.h \
+ thumbnailnode.h \
+ thumbnaileffect.h \
+ filescanner.h \
+ bytereader.h \
+ threadpool.h \
+ buttons.h \
+ qphotobrowser3dscene.h \
+ pancontroller.h
+
+# Uncomment this line to force all file loading is done in the gui thread
+# instead of a background thread - useful for debugging.
+# DEFINES += QT_NO_THREADED_FILE_LOAD
+
+# Uncomment this to use test images instead of scanning the file-system for
+# pictures. The test images are stored in in-memory resources "files".
+# DEFINES += QT_USE_TEST_IMAGES
+
+RESOURCES += \
+ photobrowser3d.qrc
+
+DESTDIR = ../../bin
+
+OTHER_FILES += \
+ shaders/replace_texture.fsh \
+ shaders/replace_texture.vsh
+
+symbian {
+ symbian-abld|symbian-sbsv2 {
+ # ro-section in photobrowser3d can exceed default allocated space, so move rw-section a little further
+ QMAKE_LFLAGS.ARMCC += --rw-base 0x800000
+ QMAKE_LFLAGS.GCCE += -Tdata 0xC00000
+ }
+}
diff --git a/demos/photobrowser3d/photobrowser3d.qrc b/demos/photobrowser3d/photobrowser3d.qrc
new file mode 100644
index 000000000..351c9faf3
--- /dev/null
+++ b/demos/photobrowser3d/photobrowser3d.qrc
@@ -0,0 +1,24 @@
+<RCC>
+ <qresource prefix="/res">
+ <file>images/sample_image.jpg</file>
+ <file alias="down.png">images/default_sky_down.png</file>
+ <file alias="west.png">images/default_sky_east.png</file>
+ <file alias="north.png">images/default_sky_north.png</file>
+ <file alias="south.png">images/default_sky_south.png</file>
+ <file alias="up.png">images/default_sky_up.png</file>
+ <file alias="east.png">images/default_sky_west.png</file>
+ <file>images/girder.png</file>
+ </qresource>
+ <qresource prefix="/shaders">
+ <file alias="replace_texture.fsh">shaders/replace_texture.fsh</file>
+ <file alias="replace_texture.vsh">shaders/replace_texture.vsh</file>
+ </qresource>
+ <qresource prefix="/pictures">
+ <file alias="im1.jpg">images/P1000223.JPG</file>
+ <file alias="im2.jpg">images/P1000228.JPG</file>
+ <file alias="im3.jpg">images/P1000472.JPG</file>
+ </qresource>
+ <qresource prefix="/controls">
+ <file alias="arrows-left.png">images/arrows-left.png</file>
+ </qresource>
+</RCC>
diff --git a/demos/photobrowser3d/photobrowser3dview.cpp b/demos/photobrowser3d/photobrowser3dview.cpp
new file mode 100644
index 000000000..f73f9a19c
--- /dev/null
+++ b/demos/photobrowser3d/photobrowser3dview.cpp
@@ -0,0 +1,437 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "photobrowser3dview.h"
+#include "imagemanager.h"
+#include "imagedisplay.h"
+#include "skybox.h"
+#include "qglpicknode.h"
+#include "qfocusadaptor.h"
+#include "thumbnailableimage.h"
+#include "qatlas.h"
+#include "filescanner.h"
+#include "buttons.h"
+#include "qphotobrowser3dscene.h"
+#include "pancontroller.h"
+#include "thumbnailnode.h"
+
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QWheelEvent>
+#include <QDir>
+#include <QTimer>
+#include <QTime>
+#include <QStateMachine>
+#include <QState>
+#include <QFinalState>
+#include <QSignalTransition>
+#include <QPropertyAnimation>
+
+PhotoBrowser3DView::PhotoBrowser3DView()
+ : QGLView()
+ , m_scene(0)
+ , m_display(0)
+ , m_images(0)
+ , m_buttons(0)
+ , m_skybox(0)
+ , m_palette(new QGLMaterialCollection(this))
+ , m_state(0)
+ , m_app(0)
+ , m_zoomed(0)
+ , m_browse(0)
+ , m_pan(0)
+ , m_fa(0)
+ , m_pc(0)
+ , m_pickableDirty(true)
+ , m_done(false)
+ , m_closing(false)
+{
+ setOption(QGLView::ObjectPicking, true);
+ // setOption(QGLView::ShowPicking, true);
+ //setOption(QGLView::CameraNavigation, false);
+
+ qRegisterMetaType<ThumbnailableImage>("ThumbnailableImage");
+
+ QString path = ":/res";
+ int ix = qApp->arguments().indexOf("--skybox");
+ if (ix != -1)
+ {
+ if (qApp->arguments().size() > ix+1)
+ path = qApp->arguments().at(ix+1);
+ else
+ qWarning("Expected path/to/skybox/files after \"--skybox\" switch\n");
+ }
+
+ m_displaySize = 4.0;
+ m_scene = new QPhotoBrowser3DScene(this);
+ m_buttons = new Buttons(this, m_palette);
+ m_scene->mainNode()->addNode(m_buttons);
+ m_scene->setPickable(true);
+ m_skybox = new SkyBox(this, path);
+ m_display = new ImageDisplay(this, m_palette, m_displaySize);
+
+ setupStates();
+
+ // make sure this only gets created in the GUI thread
+ QAtlas::instance();
+
+ QTimer::singleShot(0, this, SLOT(initialise()));
+}
+
+PhotoBrowser3DView::~PhotoBrowser3DView()
+{
+ // nothing to be done here
+}
+
+void PhotoBrowser3DView::setupStates()
+{
+ m_state = new QStateMachine(this);
+ m_app = new QState;
+ m_zoomed = new QState(m_app);
+ m_browse = new QState(m_app);
+ m_pan = new QState(m_app);
+ m_app->setInitialState(m_browse);
+ m_state->addState(m_app);
+ QFinalState *end_state = new QFinalState;
+ m_app->addTransition(this, SIGNAL(done()), end_state);
+ m_state->addState(end_state);
+ connect(m_state, SIGNAL(finished()), this, SLOT(close()));
+
+ m_fa = new QFocusAdaptor(this);
+ m_browse->assignProperty(m_fa, "progress", 0.0);
+ m_zoomed->assignProperty(m_fa, "progress", 1.0);
+
+ m_pc = new PanController(this);
+ m_pc->setMaxSpeed(m_displaySize / 1000.0f);
+ m_browse->assignProperty(m_pc, "speed", 0.0);
+ m_pan->assignProperty(m_pc, "speed", 1.0);
+
+ m_state->setObjectName("StateMachine");
+ m_app->setObjectName("Application");
+ m_zoomed->setObjectName("Zoomed");
+ m_browse->setObjectName("Browse");
+ m_pan->setObjectName("Pan");
+ end_state->setObjectName("EndState");
+
+ QSignalTransition *transition = m_browse->addTransition(this, SIGNAL(zoom()), m_zoomed);
+ QPropertyAnimation *a = new QPropertyAnimation(m_fa, "progress");
+ a->setDuration(500);
+ a->setEasingCurve(QEasingCurve::OutQuad);
+ transition->addAnimation(a);
+
+ transition = m_zoomed->addTransition(this, SIGNAL(zoom()), m_browse);
+ a = new QPropertyAnimation(m_fa, "progress");
+ a->setDuration(500);
+ a->setEasingCurve(QEasingCurve::InQuad);
+ transition->addAnimation(a);
+
+ transition = m_browse->addTransition(this, SIGNAL(pan()), m_pan);
+ a = new QPropertyAnimation(m_pc, "speed");
+ a->setDuration(500);
+ a->setEasingCurve(QEasingCurve::OutQuad);
+ transition->addAnimation(a);
+
+ transition = m_pan->addTransition(this, SIGNAL(pan()), m_browse);
+ a = new QPropertyAnimation(m_pc, "speed");
+ a->setDuration(500);
+ a->setEasingCurve(QEasingCurve::InQuad);
+ transition->addAnimation(a);
+
+ m_state->setInitialState(m_app);
+ m_state->start();
+}
+
+void PhotoBrowser3DView::initialise()
+{
+ QString path = QDir::home().absoluteFilePath("Pictures");
+ int ix = qApp->arguments().indexOf("--pictures");
+ if (ix != -1)
+ {
+ if (qApp->arguments().size() > ix+1)
+ path = qApp->arguments().at(ix+1);
+ else
+ qWarning("Expected /path/to/image/files after \"--pictures\" switch\n");
+ }
+
+ QUrl url;
+ url.setScheme("file");
+ url.setPath(path);
+
+ QFileInfo fi(path);
+ if (!fi.exists() || !fi.isDir())
+ {
+ qWarning("No pictures directory found at %s\n"
+ "using test images", qPrintable(path));
+
+ url.setPath(":/pictures");
+ }
+
+#ifdef QT_NO_THREADED_FILE_LOAD
+ nonThreadedFileLoad(url);
+#else
+ initialiseImageManager(url);
+#endif
+}
+
+void PhotoBrowser3DView::initialiseImageManager(const QUrl &url)
+{
+ m_images = new ImageManager;
+
+ connect(m_images, SIGNAL(imageUrl(QUrl)), m_display, SLOT(addThumbnailNode(QUrl)));
+ connect(m_images, SIGNAL(finished()), this, SLOT(waitForExit()));
+
+ connect(m_display, SIGNAL(framesChanged()), this, SLOT(pickableDirty()));
+ connect(m_display, SIGNAL(framesChanged()), this, SLOT(update()));
+
+ m_images->setImageBaseUrl(url);
+ QThread::Priority p = QThread::idealThreadCount() < 2 ?
+ QThread::IdlePriority : QThread::NormalPriority;
+ m_images->start(p);
+}
+
+void PhotoBrowser3DView::nonThreadedFileLoad(const QUrl &url)
+{
+#if defined(QT_USE_TEST_IMAGES)
+ Q_UNUSED(url);
+ QDir testImages(":/pictures");
+ QStringList pics = testImages.entryList();
+ for (int i = 0; i < pics.size(); ++i)
+ {
+ QUrl url;
+ url.setScheme("file");
+ url.setPath(testImages.filePath(pics.at(i)));
+ m_display->addThumbnailNode(url);
+ }
+ pickableDirty();
+ qDumpScene(m_display);
+#else
+ FileScanner *scanner = new FileScanner(this);
+ scanner->setBaseUrl(url);
+ QTimer::singleShot(0, scanner, SLOT(scan()));
+ connect(scanner, SIGNAL(imageUrl(QUrl)), m_display, SLOT(addThumbnailNode(QUrl)));
+#endif
+}
+
+void PhotoBrowser3DView::wheelEvent(QWheelEvent *e)
+{
+ e->accept();
+ QVector3D viewVec = camera()->eye() - camera()->center();
+ qreal zoomMag = viewVec.length();
+ qreal inc = float(e->delta()) / 50.0f;
+ if (!qFuzzyIsNull(inc))
+ {
+ zoomMag += inc;
+ if (zoomMag < 2.0f)
+ zoomMag = 2.0f;
+ QRay3D viewLine(camera()->center(), viewVec.normalized());
+ camera()->setEye(viewLine.point(zoomMag));
+ update();
+ }
+}
+
+void PhotoBrowser3DView::keyPressEvent(QKeyEvent *e)
+{
+ if (e->key() == Qt::Key_Q)
+ {
+ m_done = true;
+ emit done();
+ }
+ else if (e->key() == Qt::Key_Right)
+ {
+ m_pc->setDirection(Qt::RightArrow);
+ emit pan();
+ }
+ else if (e->key() == Qt::Key_Left)
+ {
+ m_pc->setDirection(Qt::LeftArrow);
+ emit pan();
+ }
+ else if (e->key() == Qt::Key_Up || e->key() == Qt::Key_Down)
+ {
+ QVector3D viewVec = camera()->eye() - camera()->center();
+ qreal zoomMag = viewVec.length();
+ zoomMag += (e->key() == Qt::Key_Up) ? -0.5f : 0.5f;
+ if (zoomMag < 5.0f)
+ zoomMag = 5.0f;
+ QRay3D viewLine(camera()->center(), viewVec.normalized());
+ camera()->setEye(viewLine.point(zoomMag));
+ update();
+ }
+ else
+ {
+ QGLView::keyPressEvent(e);
+ }
+}
+
+void PhotoBrowser3DView::waitForExit()
+{
+ QThread::yieldCurrentThread();
+ m_images->wait();
+ m_images->deleteLater();
+ m_images = 0;
+ if (m_closing)
+ {
+ if (!m_done)
+ {
+ emit done();
+ m_done = true;
+ }
+ }
+}
+
+void PhotoBrowser3DView::closeEvent(QCloseEvent *e)
+{
+ if (m_images)
+ {
+ e->ignore();
+ m_images->stop();
+
+ // this was a request to close the main window, so we are closing up shop
+ // set this flag to indicate that when the image manager stops done event
+ // should be signalled to the state machine, resulting in close
+ m_closing = true;
+ fprintf(stderr, "Closing down........");
+ }
+ else
+ {
+ fprintf(stderr, " done\n");
+ e->accept();
+ }
+}
+
+void PhotoBrowser3DView::mousePressEvent(QMouseEvent *e)
+{
+ Q_UNUSED(e);
+ registerPickableNodes();
+ QGLView::mousePressEvent(e);
+}
+
+void PhotoBrowser3DView::initializeGL(QGLPainter *painter)
+{
+ Q_UNUSED(painter);
+ QAtlas::instance()->initialize(painter);
+ camera()->setEye(QVector3D(0.0f, 0.0f, 4.0f * m_displaySize));
+ registerPickableNodes();
+ qreal q = camera()->eye().z();
+ qreal r = qBound(camera()->nearPlane(), q / 2.0f, camera()->nearPlane() * 3.0f);
+ m_pc->setDefaultDistance(q);
+ m_pc->setPanDistance(r);
+}
+
+void PhotoBrowser3DView::earlyPaintGL(QGLPainter *painter)
+{
+ Q_UNUSED(painter);
+
+ if (!painter->isPicking())
+ {
+ QAtlas::instance()->paint(painter);
+ }
+
+ if (!m_done)
+ m_pc->pan();
+
+ painter->setClearColor(Qt::blue);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+void PhotoBrowser3DView::paintGL(QGLPainter *painter)
+{
+ if (!m_done)
+ {
+ glEnable(GL_BLEND);
+ m_skybox->draw(painter);
+ m_display->draw(painter);
+ m_buttons->draw(painter);
+ }
+}
+
+void PhotoBrowser3DView::resizeGL(int w, int h)
+{
+ Q_UNUSED(w);
+ Q_UNUSED(h);
+ m_buttons->clearPositions();
+ m_updateRequired = true;
+}
+
+void PhotoBrowser3DView::zoomImage()
+{
+ QGLPickNode *pn = qobject_cast<QGLPickNode*>(sender());
+ Q_ASSERT(pn);
+ QGLSceneNode *n = pn->target();
+ m_fa->setTarget(n);
+ emit zoom();
+}
+
+void PhotoBrowser3DView::goPan()
+{
+ QGLPickNode *pn = qobject_cast<QGLPickNode*>(sender());
+ Q_ASSERT(pn);
+ QGLSceneNode *n = pn->target();
+ m_pc->setDirection(n->objectName() == "Left Button" ? Qt::LeftArrow : Qt::RightArrow);
+ emit pan();
+}
+
+void PhotoBrowser3DView::pickableDirty()
+{
+ m_pickableDirty = true;
+}
+
+void PhotoBrowser3DView::registerPickableNodes()
+{
+ if (m_pickableDirty)
+ {
+ m_scene->generatePickNodes();
+ QList<QGLPickNode*> pickList = m_scene->pickNodes();
+ QList<QGLPickNode*>::const_iterator it = pickList.constBegin();
+ for ( ; it != pickList.constEnd(); ++it)
+ {
+ QGLPickNode *pn = *it;
+ pn->disconnect(this);
+ ThumbnailNode *node = qobject_cast<ThumbnailNode*>(pn->target());
+ if (node)
+ QObject::connect(pn, SIGNAL(clicked()), this, SLOT(zoomImage()));
+ else
+ QObject::connect(pn, SIGNAL(clicked()), this, SLOT(goPan()));
+ registerObject(pn->id(), pn);
+ }
+ m_pickableDirty = false;
+ }
+}
diff --git a/demos/photobrowser3d/photobrowser3dview.h b/demos/photobrowser3d/photobrowser3dview.h
new file mode 100644
index 000000000..97d484e71
--- /dev/null
+++ b/demos/photobrowser3d/photobrowser3dview.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 PHOTOBROWSER3DVIEW_H
+#define PHOTOBROWSER3DVIEW_H
+
+#include "qglview.h"
+
+class ImageDisplay;
+class SkyBox;
+class QGLMaterialCollection;
+class QGLSceneNode;
+class ImageManager;
+class QState;
+class QStateMachine;
+class QFocusAdaptor;
+class QAtlas;
+class Buttons;
+class QPhotoBrowser3DScene;
+class PanController;
+
+class PhotoBrowser3DView : public QGLView
+{
+ Q_OBJECT
+public:
+ PhotoBrowser3DView();
+ ~PhotoBrowser3DView();
+ void initializeGL(QGLPainter *);
+ QPhotoBrowser3DScene *scene() { return m_scene; }
+signals:
+ void done();
+ void zoom();
+ void pan();
+protected:
+ void earlyPaintGL(QGLPainter *);
+ void paintGL(QGLPainter *);
+ void resizeGL(int w, int h);
+ void wheelEvent(QWheelEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+ void closeEvent(QCloseEvent *e);
+ void mousePressEvent(QMouseEvent *e);
+private slots:
+ void initialise();
+ void zoomImage();
+ void pickableDirty();
+ void waitForExit();
+ void goPan();
+private:
+ void registerPickableNodes();
+ void setupStates();
+ void nonThreadedFileLoad(const QUrl &url);
+ void initialiseImageManager(const QUrl &url);
+
+ QPhotoBrowser3DScene *m_scene;
+ ImageDisplay *m_display;
+ ImageManager *m_images;
+ Buttons *m_buttons;
+ SkyBox *m_skybox;
+ QGLMaterialCollection *m_palette;
+ QStateMachine *m_state;
+ QState *m_app;
+ QState *m_zoomed;
+ QState *m_browse;
+ QState *m_pan;
+ QFocusAdaptor *m_fa;
+ PanController *m_pc;
+ bool m_pickableDirty;
+ qreal m_displaySize;
+ bool m_done;
+ bool m_closing;
+ bool m_updateRequired;
+};
+
+#endif // PHOTOBROWSER3DVIEW_H
diff --git a/demos/photobrowser3d/qatlas.cpp b/demos/photobrowser3d/qatlas.cpp
new file mode 100644
index 000000000..7973a0c0c
--- /dev/null
+++ b/demos/photobrowser3d/qatlas.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "qatlas.h"
+#include "qareaallocator.h"
+#include "qgltexture2d.h"
+#include "qglpainter.h"
+#include "qgeometrydata.h"
+#include "qglmaterial.h"
+#include "qglpainter.h"
+#include "qglframebufferobjectsurface.h"
+#include "qglbuilder.h"
+
+#include <QImage>
+#include <QThread>
+#include <QGLFramebufferObject>
+#include <QGLFramebufferObjectFormat>
+#include <QCoreApplication>
+
+#ifndef GL_MULTISAMPLE
+#define GL_MULTISAMPLE 0x809D
+#endif
+
+QAtlas::QAtlas()
+ : m_size(1024, 1024)
+ , m_data(0)
+ , m_renderTarget(0)
+ , m_allocator(new QSimpleAreaAllocator(m_size))
+ , m_tex(0)
+ , m_material(new QGLMaterial)
+ , m_initialized(false)
+ , m_count(0)
+{
+}
+
+QAtlas::~QAtlas()
+{
+ delete m_data;
+ delete m_renderTarget;
+ delete m_allocator;
+}
+
+void QAtlas::initialize(QGLPainter *painter)
+{
+ Q_UNUSED(painter);
+ if (!m_initialized)
+ {
+ m_data = new QGLFramebufferObject(m_size);
+ m_renderTarget = new QGLFramebufferObjectSurface(m_data);
+ m_tex = QGLTexture2D::fromTextureId(m_data->texture(), m_size);
+ m_material->setTexture(m_tex, 1);
+ m_material->setObjectName("Atlas material");
+ m_initialized = true;
+ }
+}
+
+void QAtlas::paint(QGLPainter *painter)
+{
+ Q_ASSERT(QThread::currentThread() == qApp->thread());
+
+ if (m_allocationQueue.isEmpty() || painter->isPicking())
+ return;
+
+ glDisable(GL_DEPTH_TEST);
+
+ painter->pushSurface(m_renderTarget);
+ painter->setStandardEffect(QGL::FlatReplaceTexture2D);
+ painter->projectionMatrix().push();
+ painter->modelViewMatrix().push();
+ QRect rect = painter->currentSurface()->viewportRect();
+ QMatrix4x4 proj;
+ proj.ortho(rect);
+ painter->projectionMatrix() = proj;
+ painter->modelViewMatrix().setToIdentity();
+
+ painter->update();
+
+ QAtlasEntry entry = m_allocationQueue.takeFirst();
+
+ QRect a = entry.rect;
+ QImage image = entry.image;
+
+ if (a.left() == 0 && a.top() == 0) // first one - paint fill color
+ {
+ painter->setClearColor(Qt::red);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+
+ QGLTexture2D t;
+ t.setImage(image);
+ t.bind();
+ QVector3D va(a.left(), a.bottom()+1, 0);
+ QVector3D vb(a.right()+1, a.bottom()+1, 0);
+ QVector3D vc(a.right()+1, a.top(), 0);
+ QVector3D vd(a.left(), a.top(), 0);
+ QVector2D ta(0.0f, 0.0f);
+ QVector2D tb(1.0f, 0.0f);
+ QVector2D tc(1.0f, 1.0f);
+ QVector2D td(0.0f, 1.0f);
+ QGeometryData quad;
+ quad.setBufferStrategy(QGeometryData::KeepClientData);
+ quad.appendVertex(va, vb, vc, vd);
+ quad.appendTexCoord(ta, tb, tc, td);
+ quad.appendIndices(0, 1, 2);
+ quad.appendIndices(0, 2, 3);
+ quad.draw(painter, 0, 6);
+
+ painter->popSurface();
+
+ glEnable(GL_DEPTH_TEST);
+}
+
+QRect QAtlas::allocate(const QSize &size, const QImage &image, const QGL::IndexArray &indices)
+{
+ Q_ASSERT(QThread::currentThread() == qApp->thread());
+
+ QRect a = m_allocator->allocate(size);
+ if (a.isEmpty())
+ {
+ qWarning("QAtlas::allocate: overflowed");
+ return a;
+ }
+
+ m_allocationQueue.append(QAtlasEntry(image, a));
+ ++m_count;
+
+ QRectF af(a);
+ QSizeF szf(m_size);
+ float l = af.left() / szf.width();
+ float r = af.right() / szf.width();
+ float t = 1.0f - (af.top() / szf.height());
+ float b = 1.0f - (af.bottom() / szf.height());
+ m_geometry.texCoord(indices.at(0), QGL::TextureCoord1) = QVector2D(l, b);
+ m_geometry.texCoord(indices.at(1), QGL::TextureCoord1) = QVector2D(r, b);
+ m_geometry.texCoord(indices.at(2), QGL::TextureCoord1) = QVector2D(r, t);
+ m_geometry.texCoord(indices.at(5), QGL::TextureCoord1) = QVector2D(l, t);
+ return a;
+}
+
+void QAtlas::release(QRect frame)
+{
+ m_allocator->release(frame);
+}
+
+Q_GLOBAL_STATIC(QAtlas, atlasInstance);
+
+QAtlas *QAtlas::instance()
+{
+ return atlasInstance();
+}
diff --git a/demos/photobrowser3d/qatlas.h b/demos/photobrowser3d/qatlas.h
new file mode 100644
index 000000000..555b7e55c
--- /dev/null
+++ b/demos/photobrowser3d/qatlas.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 QATLAS_H
+#define QATLAS_H
+
+#include <QSize>
+
+#include "qarray.h"
+#include "qgeometrydata.h"
+
+class QAreaAllocator;
+class QGLTexture2D;
+class QGLMaterial;
+class QGeometryData;
+class QGLFramebufferObject;
+class QGLFramebufferObjectSurface;
+
+struct QAtlasEntry
+{
+ QAtlasEntry(QImage i, QRect r) : image(i), rect(r) {}
+ QImage image;
+ QRect rect;
+};
+
+class QAtlas
+{
+public:
+ QAtlas();
+ ~QAtlas();
+
+ QAreaAllocator *allocator() const { return m_allocator; }
+ void setAllocator(QAreaAllocator *allocator) { m_allocator = allocator; }
+
+ QRect allocate(const QSize &size, const QImage &image, const QGL::IndexArray &indices);
+
+ void initialize(QGLPainter *painter);
+ void paint(QGLPainter *painter);
+
+ void release(QRect frame);
+
+ void setGeometry(QGeometryData geometry) { m_geometry = geometry; }
+ QGeometryData geometry() { return m_geometry; }
+
+ QGLMaterial *material() { return m_material; }
+
+ QList<QAtlasEntry> allocationQueue() const { return m_allocationQueue; }
+
+ static QAtlas *instance();
+
+private:
+ QSize m_size;
+ QGLFramebufferObject *m_data;
+ QGLFramebufferObjectSurface *m_renderTarget;
+ QAreaAllocator *m_allocator;
+ QGLTexture2D *m_tex;
+ QGLMaterial *m_material;
+ QGeometryData m_geometry;
+ bool m_initialized;
+ QList<QAtlasEntry> m_allocationQueue;
+ int m_count;
+};
+
+#endif // QATLAS_H
diff --git a/demos/photobrowser3d/qfocusadaptor.cpp b/demos/photobrowser3d/qfocusadaptor.cpp
new file mode 100644
index 000000000..cf96f3a01
--- /dev/null
+++ b/demos/photobrowser3d/qfocusadaptor.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "qfocusadaptor.h"
+#include "qglscenenode.h"
+#include "qglview.h"
+#include "qglcamera.h"
+#include "thumbnailnode.h"
+
+class QFocusAdaptorPrivate
+{
+public:
+ QFocusAdaptorPrivate()
+ : progress(0.0)
+ , reset(true)
+ , target(0)
+ , view(0)
+ {}
+ qreal progress;
+ QVector3D targetEye;
+ QVector3D targetCenter;
+ QVector3D sourceEye;
+ QVector3D sourceCenter;
+ bool reset;
+ QGLSceneNode *target;
+ QGLView *view;
+};
+
+QFocusAdaptor::QFocusAdaptor(QObject *parent)
+ : QObject(parent)
+ , d(new QFocusAdaptorPrivate)
+{
+ QGLView *v = qobject_cast<QGLView*>(parent);
+ if (v)
+ d->view = v;
+}
+
+QFocusAdaptor::~QFocusAdaptor()
+{
+ delete d;
+}
+
+qreal QFocusAdaptor::progress() const
+{
+ return d->progress;
+}
+
+void QFocusAdaptor::setProgress(qreal progress)
+{
+ if (d->progress != progress)
+ {
+ d->progress = progress;
+ calculateValues();
+ emit progressChanged();
+ }
+}
+
+QGLView *QFocusAdaptor::view() const
+{
+ return d->view;
+}
+
+void QFocusAdaptor::setView(QGLView *view)
+{
+ d->view = view;
+ d->reset = true;
+}
+
+QGLSceneNode *QFocusAdaptor::target() const
+{
+ return d->target;
+}
+
+void QFocusAdaptor::setTarget(QGLSceneNode *target)
+{
+ if (d->target != target)
+ {
+ d->target = target;
+ d->reset = true;
+ }
+}
+
+void QFocusAdaptor::calculateValues()
+{
+ if (d->target && d->view)
+ {
+ QGLCamera *cam = d->view->camera();
+ Q_ASSERT(cam);
+ if (d->reset)
+ {
+ QGeometryData data = d->target->geometry();
+ if (data.count() == 0 || d->target->count() == 0)
+ {
+ qWarning("Could not setup focus animation");
+ return;
+ }
+ // assume that the first triangle referenced by this node is the one
+ // you want to focus on - works for simple rects and like cases
+ QGL::IndexArray ixs = data.indices();
+ QVector3D a = data.vertexAt(ixs.at(d->target->start()));
+ QVector3D b = data.vertexAt(ixs.at(d->target->start() + 1));
+ QVector3D c = data.vertexAt(ixs.at(d->target->start() + 2));
+
+ // assumes that first triangle is facing the camera
+ QVector3D toCam = QVector3D::normal(a, b, c);
+
+ // wont work very well if the target is not axis-aligned
+ // find the distance q for the eye to be away from this object
+ // in order that it is a tight fit in the viewport
+ QGeometryData g = d->target->geometry();
+ QGL::IndexArray inxs = g.indices();
+ QBox3D box;
+ for (int i = d->target->start(); i < (d->target->start() + d->target->count()); ++i)
+ box.unite(g.vertexAt(inxs.at(i)));
+ QVector3D sz = box.size();
+
+ qreal nearDist = cam->nearPlane();
+
+ QSizeF v = cam->viewSize();
+
+ qreal vh = d->view->rect().height();
+ qreal vw = d->view->rect().width();
+ if (!qFuzzyIsNull(vw - vh))
+ {
+ qreal asp = vh / vw;
+ if (vh > vw)
+ v.setHeight(v.height() * asp);
+ else
+ v.setWidth(v.width() / asp);
+ }
+
+ qreal qh = (nearDist * sz.y()) / v.height();
+ qreal qw = (nearDist * sz.x()) / v.width();
+
+ qreal q = qMax(qh, qw);
+
+ d->sourceCenter = cam->center();
+ d->sourceEye = cam->eye();
+
+ d->targetCenter = d->target->position();
+ d->targetEye = d->targetCenter + (toCam * q);
+
+ d->reset = false;
+ }
+ cam->setCenter(d->sourceCenter + ((d->targetCenter - d->sourceCenter) * d->progress));
+ cam->setEye(d->sourceEye + ((d->targetEye - d->sourceEye) * d->progress));
+ }
+}
diff --git a/demos/photobrowser3d/qfocusadaptor.h b/demos/photobrowser3d/qfocusadaptor.h
new file mode 100644
index 000000000..a8307e74b
--- /dev/null
+++ b/demos/photobrowser3d/qfocusadaptor.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 QFOCUSADAPTOR_H
+#define QFOCUSADAPTOR_H
+
+#include <QObject>
+
+class QGLView;
+class QGLSceneNode;
+class QFocusAdaptorPrivate;
+
+class QFocusAdaptor : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(qreal progress READ progress WRITE setProgress NOTIFY progressChanged)
+public:
+ explicit QFocusAdaptor(QObject *parent = 0);
+ ~QFocusAdaptor();
+
+ qreal progress() const;
+ void setProgress(qreal progress);
+
+ QGLView *view() const;
+ void setView(QGLView *view);
+
+ QGLSceneNode *target() const;
+ void setTarget(QGLSceneNode *target);
+
+signals:
+ void progressChanged();
+
+public slots:
+
+private:
+ void calculateValues();
+
+ QFocusAdaptorPrivate *d;
+};
+
+#endif // QFOCUSADAPTOR_H
diff --git a/demos/photobrowser3d/qphotobrowser3dscene.cpp b/demos/photobrowser3d/qphotobrowser3dscene.cpp
new file mode 100644
index 000000000..d1d70d6f4
--- /dev/null
+++ b/demos/photobrowser3d/qphotobrowser3dscene.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "qphotobrowser3dscene.h"
+#include "qglscenenode.h"
+
+QPhotoBrowser3DScene::QPhotoBrowser3DScene(QObject *parent)
+ : QGLAbstractScene(parent)
+ , m_rootNode(new QGLSceneNode(this))
+{
+}
+
+QList<QObject *> QPhotoBrowser3DScene::objects() const
+{
+ QList<QGLSceneNode *> children = m_rootNode->allChildren();
+ QList<QObject *> objects;
+ for (int index = 0; index < children.size(); ++index)
+ objects.append(children.at(index));
+ return objects;
+}
diff --git a/demos/photobrowser3d/qphotobrowser3dscene.h b/demos/photobrowser3d/qphotobrowser3dscene.h
new file mode 100644
index 000000000..bc70265f3
--- /dev/null
+++ b/demos/photobrowser3d/qphotobrowser3dscene.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 QFRAMESSCENE_H
+#define QFRAMESSCENE_H
+
+#include "qglabstractscene.h"
+
+class QGLSceneNode;
+
+class QPhotoBrowser3DScene : public QGLAbstractScene
+{
+ Q_OBJECT
+public:
+ explicit QPhotoBrowser3DScene(QObject *parent = 0);
+ virtual QList<QObject *> objects() const;
+ QGLSceneNode *mainNode() const { return m_rootNode; }
+private:
+ QGLSceneNode *m_rootNode;
+};
+
+#endif // QFRAMESSCENE_H
diff --git a/demos/photobrowser3d/shaders/replace_texture.fsh b/demos/photobrowser3d/shaders/replace_texture.fsh
new file mode 100644
index 000000000..2c296dc78
--- /dev/null
+++ b/demos/photobrowser3d/shaders/replace_texture.fsh
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+// This is equivilent to GL_REPLACE
+varying highp vec4 qt_TexCoord0;
+uniform bool picking;
+uniform mediump vec4 color;
+uniform sampler2D texture;
+
+void main(void)
+{
+ if (picking)
+ gl_FragColor = color;
+ else
+ gl_FragColor = texture2D(texture, qt_TexCoord0.st);
+}
diff --git a/demos/photobrowser3d/shaders/replace_texture.vsh b/demos/photobrowser3d/shaders/replace_texture.vsh
new file mode 100644
index 000000000..57d43af28
--- /dev/null
+++ b/demos/photobrowser3d/shaders/replace_texture.vsh
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+attribute highp vec4 vertex;
+attribute highp vec4 texcoord;
+attribute highp vec4 thumbcoord;
+
+uniform highp mat4 matrix;
+uniform bool thumb;
+
+varying highp vec4 qt_TexCoord0;
+
+void main(void)
+{
+ if (thumb)
+ qt_TexCoord0 = thumbcoord;
+ else
+ qt_TexCoord0 = texcoord;
+ gl_Position = matrix * vertex;
+}
diff --git a/demos/photobrowser3d/skybox.cpp b/demos/photobrowser3d/skybox.cpp
new file mode 100644
index 000000000..f4d11fbfa
--- /dev/null
+++ b/demos/photobrowser3d/skybox.cpp
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "skybox.h"
+#include "qglbuilder.h"
+#include "qglcube.h"
+#include "qglpainter.h"
+#include "qglview.h"
+
+#include <QDir>
+#include <QFileInfo>
+
+SkyBox::SkyBox(QGLView *view, const QString &imagePath)
+ : m_scene(0)
+ , m_view(view)
+ , m_camera(new QGLCamera(this))
+{
+ m_camera->setEye(QVector3D());
+ m_camera->setNearPlane(0.3f);
+ m_camera->setViewSize(QSizeF(0.3f, 0.3f));
+
+ QGLBuilder builder;
+ builder.newSection(QGL::Faceted);
+ QVector3D blb(-1.0, -1.0, -1.0);
+ QVector3D blf(-1.0, -1.0, 1.0);
+ QVector3D tlf(-1.0, 1.0, 1.0);
+ QVector3D tlb(-1.0, 1.0, -1.0);
+ QVector3D brb(1.0, -1.0, -1.0);
+ QVector3D brf(1.0, -1.0, 1.0);
+ QVector3D trf(1.0, 1.0, 1.0);
+ QVector3D trb(1.0, 1.0, -1.0);
+ QVector2D bl(0.0f, 0.0f);
+ QVector2D br(1.0f, 0.0f);
+ QVector2D tr(1.0f, 1.0f);
+ QVector2D tl(0.0f, 1.0f);
+ {
+ QGeometryData q; // left
+ builder.currentNode()->setObjectName("left");
+ q.appendVertex(blf, blb, tlb, tlf);
+ q.appendTexCoord(bl, br, tr, tl);
+ builder.addQuads(q);
+ m_faces[0] = builder.currentNode();
+ m_faces[0]->setMaterial(new QGLMaterial);
+ }
+ {
+ builder.newNode(); // top
+ builder.currentNode()->setObjectName("top");
+ QGeometryData q;
+ q.appendVertex(trf, tlf, tlb, trb);
+ q.appendTexCoord(bl, br, tr, tl);
+ builder.addQuads(q);
+ m_faces[1] = builder.currentNode();
+ m_faces[1]->setMaterial(new QGLMaterial);
+ }
+ {
+ builder.newNode(); // right
+ builder.currentNode()->setObjectName("right");
+ QGeometryData q;
+ q.appendVertex(brb, brf, trf, trb);
+ q.appendTexCoord(bl, br, tr, tl);
+ builder.addQuads(q);
+ m_faces[2] = builder.currentNode();
+ m_faces[2]->setMaterial(new QGLMaterial);
+ }
+ {
+ builder.newNode(); // bottom
+ builder.currentNode()->setObjectName("bottom");
+ QGeometryData q;
+ q.appendVertex(brb, blb, blf, brf);
+ q.appendTexCoord(bl, br, tr, tl);
+ builder.addQuads(q);
+ m_faces[3] = builder.currentNode();
+ m_faces[3]->setMaterial(new QGLMaterial);
+ }
+ {
+ builder.newNode(); // front
+ builder.currentNode()->setObjectName("front");
+ QGeometryData q;
+ q.appendVertex(brf, blf, tlf, trf);
+ q.appendTexCoord(bl, br, tr, tl);
+ builder.addQuads(q);
+ m_faces[4] = builder.currentNode();
+ m_faces[4]->setMaterial(new QGLMaterial);
+ }
+ {
+ builder.newNode(); // back
+ builder.currentNode()->setObjectName("back");
+ QGeometryData q;
+ q.appendVertex(blb, brb, trb, tlb);
+ q.appendTexCoord(bl, br, tr, tl);
+ builder.addQuads(q);
+ m_faces[5] = builder.currentNode();
+ m_faces[5]->setMaterial(new QGLMaterial);
+ }
+ m_scene = builder.finalizedSceneNode();
+ m_scene->setObjectName("SkyboxList");
+ m_scene->setEffect(QGL::FlatReplaceTexture2D);
+ m_scene->setEffectEnabled(true);
+ m_scene->setParent(this);
+
+ QString resourceBase = QLatin1String(":/");
+ setImagePath(imagePath.isEmpty() ? resourceBase : imagePath);
+}
+
+
+void SkyBox::setImagePath(const QString &imagePath)
+{
+ static QStringList expected2;
+ static QStringList expected;
+
+ if (expected.isEmpty())
+ expected << QLatin1String("east") << QLatin1String("up") << QLatin1String("west")
+ << QLatin1String("down") << QLatin1String("south") << QLatin1String("north");
+ if (expected2.isEmpty())
+ expected2 << QLatin1String("right") << QLatin1String("top") << QLatin1String("left")
+ << QLatin1String("bottom") << QLatin1String("front") << QLatin1String("back");
+ if (imagePath != m_imagePath)
+ {
+ m_imagePath = imagePath;
+ QStringList notFound = expected;
+ QFileInfo info(m_imagePath);
+ if (info.exists() && info.isDir())
+ {
+ QDir imDir(imagePath);
+ QFileInfoList files = imDir.entryInfoList(QDir::Files);
+ QFileInfoList::const_iterator it = files.constBegin();
+ for ( ; it != files.constEnd() && notFound.size() > 0; ++it)
+ {
+ QFileInfo ent = *it;
+ QString tok = ent.baseName().toLower();
+ int ix = 0;
+ for ( ; ix < 6; ++ix)
+ if (tok.contains(expected.at(ix)))
+ break;
+ if (ix == 6)
+ {
+ ix = 0;
+ for ( ; ix < 6; ++ix)
+ if (tok.contains(expected2.at(ix)))
+ break;
+ }
+ if (ix != 6)
+ {
+ notFound.removeOne(expected.at(ix));
+ QUrl url;
+ url.setScheme("file");
+ url.setPath(ent.absoluteFilePath());
+ m_faces[ix]->material()->setTextureUrl(url);
+ m_faces[ix]->material()->texture()->setHorizontalWrap(QGL::ClampToEdge);
+ m_faces[ix]->material()->texture()->setVerticalWrap(QGL::ClampToEdge);
+ }
+ }
+ if (notFound.size() > 2)
+ {
+ qWarning("Could not load textures for");
+ for (int i = 0; i < notFound.size(); ++i)
+ qWarning("\t%s", qPrintable(notFound.at(i)));
+ }
+ }
+ else
+ {
+ qWarning("SkyBox::setImagePath: Not an existing directory %s",
+ qPrintable(m_imagePath));
+ }
+ }
+}
+
+void SkyBox::draw(QGLPainter *painter) const
+{
+ painter->modelViewMatrix().push();
+ painter->modelViewMatrix().setToIdentity();
+
+ QGLCamera *cam = m_view->camera();
+ m_camera->setCenter(-cam->eye());
+ painter->setCamera(m_camera);
+
+ glDisable(GL_DEPTH_TEST);
+
+ m_scene->draw(painter);
+
+ glEnable(GL_DEPTH_TEST);
+
+ painter->setCamera(cam);
+ painter->modelViewMatrix().pop();
+}
diff --git a/demos/photobrowser3d/skybox.h b/demos/photobrowser3d/skybox.h
new file mode 100644
index 000000000..26ce9c26a
--- /dev/null
+++ b/demos/photobrowser3d/skybox.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 QtQuick3D 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 SKYBOX_H
+#define SKYBOX_H
+
+#include <QString>
+#include <QObject>
+
+class QGLBuilder;
+class QGLSceneNode;
+class QGLPainter;
+class QGLView;
+class QGLCamera;
+
+class SkyBox : public QObject
+{
+ Q_OBJECT
+public:
+ SkyBox(QGLView *view, const QString &imagePath = QString());
+ QString imagePath() const { return m_imagePath; }
+ void setImagePath(const QString &imagePath);
+ void draw(QGLPainter *painter) const;
+private:
+ QGLSceneNode *m_scene;
+ QString m_imagePath;
+ QGLSceneNode *m_faces[6];
+ QGLView *m_view;
+ QGLCamera *m_camera;
+};
+
+#endif // SKYBOX_H
diff --git a/demos/photobrowser3d/threadpool.cpp b/demos/photobrowser3d/threadpool.cpp
new file mode 100644
index 000000000..a14a82690
--- /dev/null
+++ b/demos/photobrowser3d/threadpool.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "threadpool.h"
+#include "imageloader.h"
+#include "imagemanager.h"
+
+#include <QSemaphore>
+
+ThreadPool::ThreadPool()
+{
+ m_threadPoolSize = QThread::idealThreadCount();
+ if (m_threadPoolSize < 2)
+ m_threadPoolSize = 2;
+ m_stop = 0;
+}
+
+ThreadPool::~ThreadPool()
+{
+ Q_ASSERT(m_allWorkers.size() == 0);
+}
+
+void ThreadPool::deployLoader(const ThumbnailableImage &image)
+{
+ // INVARIANT: this critical section is only ever executed from its
+ // own thread via queued signals - thus access to it is serialized
+ Q_ASSERT(QThread::currentThread() == thread());
+
+ if (m_stop)
+ return;
+
+ ImageManager *manager = qobject_cast<ImageManager*>(sender());
+ Q_ASSERT(manager);
+
+ ImageLoader *loader = 0;
+ if (m_freeWorkers.size() > 0)
+ loader = m_freeWorkers.takeFirst();
+
+ if (loader)
+ {
+ loader->setImage(image);
+ }
+ else
+ {
+ if (m_allWorkers.size() < m_threadPoolSize)
+ {
+ loader = new ImageLoader;
+ m_allWorkers.append(loader);
+ loader->setImage(image);
+ connect(loader, SIGNAL(imageLoaded(ThumbnailableImage)), manager,
+ SIGNAL(imageReady(ThumbnailableImage)));
+ connect(loader, SIGNAL(imageLoaded(ThumbnailableImage)), this,
+ SLOT(retrieveLoader()));
+ connect(loader, SIGNAL(finished()), this, SLOT(closeLoader()));
+ connect(this, SIGNAL(stopAll()), loader, SLOT(stop()));
+ loader->start();
+ }
+ else
+ {
+ m_workList.append(image);
+ }
+ }
+}
+
+void ThreadPool::retrieveLoader()
+{
+ ImageLoader *loader = qobject_cast<ImageLoader*>(sender());
+ Q_ASSERT(loader);
+ if (!m_stop)
+ {
+ if (!m_workList.isEmpty())
+ loader->setImage(m_workList.takeFirst());
+ else
+ m_freeWorkers.append(loader);
+ }
+}
+
+void ThreadPool::stop()
+{
+ m_stop.ref();
+ emit stopAll();
+}
+
+void ThreadPool::closeLoader()
+{
+ ImageLoader *loader = qobject_cast<ImageLoader*>(sender());
+ Q_ASSERT(loader);
+ m_allWorkers.removeOne(loader);
+ loader->deleteLater();
+ if (m_allWorkers.isEmpty() && m_stop)
+ {
+ emit stopped();
+ }
+}
diff --git a/demos/photobrowser3d/threadpool.h b/demos/photobrowser3d/threadpool.h
new file mode 100644
index 000000000..6d52d2503
--- /dev/null
+++ b/demos/photobrowser3d/threadpool.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 LOADINGJOB_H
+#define LOADINGJOB_H
+
+#include <QObject>
+#include <QAtomicInt>
+#include <QList>
+#include <QUrl>
+
+#include "thumbnailableimage.h"
+
+class ImageLoader;
+
+class ThreadPool : public QObject
+{
+ Q_OBJECT
+public:
+ ThreadPool();
+ ~ThreadPool();
+
+signals:
+ void stopped();
+ void stopAll();
+
+public slots:
+ void deployLoader(const ThumbnailableImage &url);
+ void stop();
+
+private slots:
+ void retrieveLoader();
+ void closeLoader();
+
+private:
+ QList<ImageLoader*> m_freeWorkers;
+ QList<ImageLoader*> m_allWorkers;
+ QList<ThumbnailableImage> m_workList;
+ QAtomicInt m_stop;
+ int m_threadPoolSize;
+};
+
+#endif // LOADINGJOB_H
diff --git a/demos/photobrowser3d/thumbnailableimage.cpp b/demos/photobrowser3d/thumbnailableimage.cpp
new file mode 100644
index 000000000..95e842e0f
--- /dev/null
+++ b/demos/photobrowser3d/thumbnailableimage.cpp
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "thumbnailableimage.h"
+#include "qareaallocator.h"
+#include "qgltexture2d.h"
+#include "qglmaterial.h"
+#include "qatlas.h"
+
+#include <QUrl>
+
+class ThumbnailableImagePrivate
+{
+public:
+ ThumbnailableImagePrivate();
+ ~ThumbnailableImagePrivate();
+
+ ThumbnailableImagePrivate *clone() const
+ {
+ ThumbnailableImagePrivate *temp = new ThumbnailableImagePrivate;
+ temp->thumbnailed = thumbnailed;
+ temp->pending = pending;
+ temp->url = url;
+ temp->data = data;
+ temp->tex = tex;
+ temp->mat = mat;
+ temp->frame = frame;
+ temp->scale = scale;
+ temp->indices = indices;
+ return temp;
+ }
+
+ QBasicAtomicInt ref;
+
+ bool thumbnailed;
+ bool pending;
+ QUrl url;
+ QImage data;
+ QGLTexture2D *tex;
+ QGLMaterial *mat;
+ QRect frame;
+ qreal scale;
+ QGL::IndexArray indices;
+};
+
+ThumbnailableImagePrivate::ThumbnailableImagePrivate()
+ : thumbnailed(false)
+ , pending(false)
+ , tex(0)
+ , mat(0)
+ , scale(15.0f)
+{
+ ref = 0;
+}
+
+ThumbnailableImagePrivate::~ThumbnailableImagePrivate()
+{
+}
+
+ThumbnailableImage::ThumbnailableImage()
+ : d(0)
+{
+}
+
+/*!
+ Construct ThumbnailableImage as a copy of \a other
+*/
+ThumbnailableImage::ThumbnailableImage(const ThumbnailableImage &other)
+ : d(other.d)
+{
+ if (d)
+ d->ref.ref();
+}
+
+/*!
+ Destroys this ThumbnailableImage recovering any resources.
+*/
+ThumbnailableImage::~ThumbnailableImage()
+{
+ if (d && !d->ref.deref())
+ delete d;
+}
+
+/*!
+ Assigns this ThumbnailableImage to be a copy of \a other.
+*/
+ThumbnailableImage &ThumbnailableImage::operator=(const ThumbnailableImage &other)
+{
+ if (d != other.d)
+ {
+ if (d && !d->ref.deref())
+ delete d;
+ d = other.d;
+ if (d)
+ d->ref.ref();
+ }
+ return *this;
+}
+
+void ThumbnailableImage::setThumbnailed(bool enable)
+{
+ detach();
+ if (enable != d->thumbnailed && !d->data.isNull())
+ {
+ if (enable)
+ {
+ if (d->frame.isNull())
+ {
+ Q_ASSERT(!d->data.isNull());
+ QSize sz = (QSizeF(d->data.size()) / d->scale).toSize();
+ QAtlas *atlas = QAtlas::instance();
+ d->frame = atlas->allocate(sz, d->data, d->indices);
+ d->pending = true;
+ }
+ }
+ if (!d->pending)
+ d->thumbnailed = enable;
+ }
+}
+
+bool ThumbnailableImage::isThumbnailed() const
+{
+ bool result = false;
+ if (d)
+ {
+ if (d->pending)
+ {
+ QList<QAtlasEntry> queue = QAtlas::instance()->allocationQueue();
+ int i = 0;
+ for ( ; i < queue.count(); ++i)
+ if (d->frame == queue.at(i).rect)
+ break;
+ if (i == queue.count())
+ {
+ d->pending = false;
+ d->thumbnailed = true;
+ }
+ }
+ result = d->thumbnailed;
+ }
+ return result;
+}
+
+QImage ThumbnailableImage::data() const
+{
+ QImage result;
+ if (d)
+ result = d->data;
+ return result;
+}
+
+void ThumbnailableImage::setData(QImage data)
+{
+ detach();
+ d->data = data;
+}
+
+QUrl ThumbnailableImage::url() const
+{
+ QUrl result;
+ if (d)
+ result = d->url;
+ return result;
+}
+
+void ThumbnailableImage::setUrl(const QUrl &url)
+{
+ detach();
+ d->url = url;
+}
+
+QRectF ThumbnailableImage::frame() const
+{
+ QRectF result;
+ if (d)
+ result = d->frame;
+ return result;
+}
+
+qreal ThumbnailableImage::scale() const
+{
+ qreal result = 0.0f;
+ if (d)
+ result = d->scale;
+ return result;
+}
+
+void ThumbnailableImage::minimize()
+{
+ if (!d)
+ return;
+ detach();
+ if (!isMinimized())
+ {
+ if (d->thumbnailed)
+ {
+ // If thumbnailed, I don't really need the full size image
+ d->data = QImage();
+ }
+ else
+ {
+ // If not thumbnailed, I don't need the atlas resources
+ QAtlas *atlas = QAtlas::instance();
+ atlas->release(d->frame);
+ d->frame = QRect();
+ }
+ }
+}
+
+bool ThumbnailableImage::isMinimized() const
+{
+ bool result = true;
+ if (d)
+ result = (d->thumbnailed) ? (d->data.isNull()) : (d->frame.isNull());
+ return result;
+}
+
+void ThumbnailableImage::setIndices(const QGL::IndexArray &indices)
+{
+ detach();
+ d->indices = indices;
+}
+
+QGL::IndexArray ThumbnailableImage::indices() const
+{
+ QGL::IndexArray result;
+ if (d)
+ result = d->indices;
+ return result;
+}
+
+/*!
+ \internal
+ You know what this is for. No user serviceable parts below here.
+*/
+void ThumbnailableImage::detach()
+{
+ if (!d) // lazy creation of data block
+ {
+ d = new ThumbnailableImagePrivate;
+ d->ref.ref();
+ }
+ else
+ {
+ if (d->ref > 1) // being shared, must detach
+ {
+ ThumbnailableImagePrivate *temp = d->clone();
+ d->ref.deref();
+ d = temp;
+ d->ref.ref();
+ }
+ }
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const ThumbnailableImage &image)
+{
+ dbg << "ThumbnailableImage" << image.url() << "size:" << image.data().size() <<
+ "minimized:" << image.isMinimized() << "-- thumbnailed:" << image.isThumbnailed()
+ << "-- null:" << image.isNull() << "-- image loaded:" << (!image.data().isNull())
+ << "-- index count:" << image.indices().count();
+ return dbg;
+}
+#endif
diff --git a/demos/photobrowser3d/thumbnailableimage.h b/demos/photobrowser3d/thumbnailableimage.h
new file mode 100644
index 000000000..06d940e92
--- /dev/null
+++ b/demos/photobrowser3d/thumbnailableimage.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 THUMBNAILABLEIMAGE_H
+#define THUMBNAILABLEIMAGE_H
+
+#include <QRectF>
+#include <QMetaType>
+
+#include "qarray.h"
+#include "qgeometrydata.h"
+
+class QImage;
+class ThumbnailableImagePrivate;
+class QGLPainter;
+
+class ThumbnailableImage
+{
+public:
+ ThumbnailableImage();
+ ThumbnailableImage(const ThumbnailableImage&);
+ ~ThumbnailableImage();
+
+ ThumbnailableImage &operator=(const ThumbnailableImage &);
+
+ void setThumbnailed(bool enable);
+ bool isThumbnailed() const;
+
+ QImage data() const;
+ void setData(QImage data);
+
+ QUrl url() const;
+ void setUrl(const QUrl &url);
+
+ QRectF frame() const;
+ qreal scale() const;
+
+ void minimize();
+ bool isMinimized() const;
+
+ QGL::IndexArray indices() const;
+ void setIndices(const QGL::IndexArray &indices);
+
+ bool isNull() const { return d == 0; }
+
+ ThumbnailableImagePrivate *priv() const { return d; } /// debug = remove me
+
+private:
+ void detach();
+
+ ThumbnailableImagePrivate *d;
+};
+
+Q_DECLARE_METATYPE(ThumbnailableImage);
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const ThumbnailableImage &image);
+#endif
+
+#endif // THUMBNAILABLEIMAGE_H
diff --git a/demos/photobrowser3d/thumbnaileffect.cpp b/demos/photobrowser3d/thumbnaileffect.cpp
new file mode 100644
index 000000000..9a98b7427
--- /dev/null
+++ b/demos/photobrowser3d/thumbnaileffect.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "thumbnaileffect.h"
+
+#include <QtOpenGL/qglshaderprogram.h>
+
+class ThumbnailEffectPrivate
+{
+public:
+ ThumbnailEffectPrivate()
+ : program(0)
+ , matrixUniform(-1)
+ , thumbnailUniform(-1)
+ , thumbnail(false)
+ , thumbnailUpdateRequired(false)
+ {
+ }
+ ~ThumbnailEffectPrivate() { delete program; }
+
+ QGLShaderProgram *program;
+ int matrixUniform;
+ int thumbnailUniform;
+ int colorUniform;
+ int pickingUniform;
+ // true if we render a thumbnail, false do the large size
+ bool thumbnail;
+ bool thumbnailUpdateRequired;
+};
+
+/*!
+ Constructs a new flat texture effect.
+*/
+ThumbnailEffect::ThumbnailEffect()
+ : d(new ThumbnailEffectPrivate)
+{
+}
+
+/*!
+ Destroys this flat texture effect.
+*/
+ThumbnailEffect::~ThumbnailEffect()
+{
+ delete d;
+}
+
+/*!
+ \reimp
+*/
+QList<QGL::VertexAttribute> ThumbnailEffect::requiredFields() const
+{
+ QList<QGL::VertexAttribute> fields;
+ fields += QGL::Position;
+ fields += QGL::TextureCoord0;
+ fields += QGL::TextureCoord1;
+ return fields;
+}
+
+/*!
+ \reimp
+*/
+void ThumbnailEffect::setActive(QGLPainter *painter, bool flag)
+{
+ Q_UNUSED(painter);
+ if (!d->program) {
+ if (!flag)
+ return;
+ d->program = new QGLShaderProgram();
+ d->program->addShaderFromSourceFile(QGLShader::Vertex, ":/shaders/replace_texture.vsh");
+ d->program->addShaderFromSourceFile(QGLShader::Fragment, ":/shaders/replace_texture.fsh");
+ d->program->bindAttributeLocation("vertex", QGL::Position);
+ d->program->bindAttributeLocation("texcoord", QGL::TextureCoord0);
+ d->program->bindAttributeLocation("thumbcoord", QGL::TextureCoord1);
+ if (!d->program->link()) {
+ qWarning("ThumbnailEffect::setActive(): could not link shader d->program");
+ delete d->program;
+ d->program = 0;
+ return;
+ }
+ d->matrixUniform = d->program->uniformLocation("matrix");
+ d->thumbnailUniform = d->program->uniformLocation("thumb");
+ d->colorUniform = d->program->uniformLocation("color");
+ d->pickingUniform = d->program->uniformLocation("picking");
+ d->program->bind();
+ d->program->setUniformValue("texture", 0);
+ d->program->enableAttributeArray(QGL::Position);
+ d->program->enableAttributeArray(QGL::TextureCoord0);
+ d->program->enableAttributeArray(QGL::TextureCoord1);
+ } else if (flag) {
+ d->matrixUniform = d->program->uniformLocation("matrix");
+ d->program->bind();
+ d->program->setUniformValue("texture", 0);
+ d->program->enableAttributeArray(QGL::Position);
+ d->program->enableAttributeArray(QGL::TextureCoord0);
+ d->program->enableAttributeArray(QGL::TextureCoord1);
+ } else {
+ d->program->disableAttributeArray(QGL::Position);
+ d->program->disableAttributeArray(QGL::TextureCoord0);
+ d->program->disableAttributeArray(QGL::TextureCoord1);
+ d->program->release();
+ }
+}
+
+/*!
+ \reimp
+*/
+void ThumbnailEffect::update
+ (QGLPainter *painter, QGLPainter::Updates updates)
+{
+ Q_ASSERT(d->program);
+ if ((updates & QGLPainter::UpdateMatrices) != 0)
+ {
+ d->program->setUniformValue(d->matrixUniform,
+ painter->combinedMatrix());
+ }
+ if ((updates & QGLPainter::UpdateColor) != 0) {
+ d->program->setUniformValue(d->pickingUniform, painter->isPicking());
+ if (painter->isPicking())
+ d->program->setUniformValue(d->colorUniform, painter->pickColor());
+ else
+ d->program->setUniformValue(d->colorUniform, Qt::green);
+ }
+ if (d->thumbnailUpdateRequired)
+ {
+ d->program->setUniformValue(d->thumbnailUniform, d->thumbnail);
+ d->thumbnailUpdateRequired = false;
+ }
+}
+
+bool ThumbnailEffect::supportsPicking() const
+{
+ return true;
+}
+
+
+void ThumbnailEffect::setThumbnail(bool enable)
+{
+ if (d->thumbnail != enable)
+ {
+ d->thumbnailUpdateRequired = true;
+ d->thumbnail = enable;
+ }
+}
+
+bool ThumbnailEffect::thumbnail() const
+{
+ return d->thumbnail;
+}
diff --git a/demos/photobrowser3d/thumbnaileffect.h b/demos/photobrowser3d/thumbnaileffect.h
new file mode 100644
index 000000000..330e7d04d
--- /dev/null
+++ b/demos/photobrowser3d/thumbnaileffect.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 QtQuick3D 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 QGLFLATTEXTUREEFFECT_H
+#define QGLFLATTEXTUREEFFECT_H
+
+#include "qglabstracteffect.h"
+#include <QtCore/qscopedpointer.h>
+
+class ThumbnailEffectPrivate;
+
+class ThumbnailEffect : public QGLAbstractEffect
+{
+public:
+ ThumbnailEffect();
+ virtual ~ThumbnailEffect();
+
+ QList<QGL::VertexAttribute> requiredFields() const;
+ void setActive(QGLPainter *painter, bool flag);
+ void update(QGLPainter *painter, QGLPainter::Updates updates);
+ bool supportsPicking() const;
+
+ void setThumbnail(bool enable);
+ bool thumbnail() const;
+
+ QString name() const { return QLatin1String("ThumbnailEffect"); }
+
+private:
+ ThumbnailEffectPrivate *d;
+};
+
+#endif
diff --git a/demos/photobrowser3d/thumbnailnode.cpp b/demos/photobrowser3d/thumbnailnode.cpp
new file mode 100644
index 000000000..78ad38d44
--- /dev/null
+++ b/demos/photobrowser3d/thumbnailnode.cpp
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "thumbnailnode.h"
+#include "qglpainter.h"
+#include "thumbnaileffect.h"
+#include "imagemanager.h"
+#include "qatlas.h"
+#include "qglrendersequencer.h"
+#include "qglpicknode.h"
+#include "qlogicalvertex.h"
+
+#include <QMatrix4x4>
+#include <QTimer>
+
+ThumbnailNode::ThumbnailNode(QObject *parent)
+ : QGLSceneNode(parent)
+ , m_thresholdSquared(20.0f * 20.0f)
+ , m_defaultMaterial(-1)
+ , m_loading(false)
+ , m_full(0)
+ , m_manager(0)
+ , m_lastDistance(ThumbnailNode::Unknown)
+{
+ setPalette(new QGLMaterialCollection(this));
+}
+
+ThumbnailNode::~ThumbnailNode()
+{
+ delete m_full;
+}
+
+void ThumbnailNode::setUrl(const QUrl &url)
+{
+ m_url = url;
+ m_image = ThumbnailableImage();
+ m_image.setUrl(m_url);
+ QGL::IndexArray inxs = geometry().indices();
+ m_image.setIndices(inxs.mid(start(), count()));
+}
+
+void ThumbnailNode::setupLoading()
+{
+ if (!m_loading && !m_url.isEmpty() && m_image.data().isNull())
+ {
+ m_loading = true;
+#ifdef QT_NO_THREADED_FILE_LOAD
+ ThumbnailableImage image;
+ image.setUrl(m_url);
+ QImage im(m_url.toLocalFile());
+ if (im.isNull())
+ qDebug() << "ThumbnailNode::setupLoading: could not load image:"
+ << m_url.toLocalFile();
+ if (im.size().width() > 1024 || im.size().height() > 768)
+ im = im.scaled(QSize(1024, 768), Qt::KeepAspectRatio,
+ Qt::SmoothTransformation);
+ image.setData(im);
+ setImage(image);
+#else
+ if (m_manager)
+ // reconnect the signal we disconnnected in setImage() below
+ connect(m_manager, SIGNAL(imageReady(ThumbnailableImage)),
+ this, SLOT(setImage(ThumbnailableImage)));
+ emit imageRequired(m_image);
+ setMaterialIndex(m_defaultMaterial);
+#endif
+ }
+}
+
+void ThumbnailNode::createFullNode()
+{
+ m_full = new QGLSceneNode;
+ m_full->setPosition(position());
+ m_full->setGeometry(geometry());
+ m_full->setStart(start());
+ m_full->setCount(count());
+ m_full->setPalette(palette());
+ m_full->setMaterialIndex(m_defaultMaterial);
+}
+
+void ThumbnailNode::destroyFullNode()
+{
+ if (!m_full)
+ return;
+ QGLMaterial *mat = m_full->material();
+ if (m_full->materialIndex() != m_defaultMaterial)
+ m_full->palette()->removeMaterial(mat);
+ delete m_full;
+ m_full = 0;
+}
+
+void ThumbnailNode::loadFullImage()
+{
+ if (!m_full)
+ createFullNode();
+ Q_CHECK_PTR(m_full);
+ // if we have a valid image, and the full node still has the
+ // default material, switch to a new material which displays
+ // the full size image
+ if (!m_image.data().isNull() &&
+ m_full->materialIndex() == m_defaultMaterial)
+ {
+ QGLMaterial *mat = new QGLMaterial;
+ QGLTexture2D *tex = new QGLTexture2D;
+ tex->setImage(m_image.data());
+ mat->setTexture(tex);
+ mat->setObjectName(m_image.url().path());
+ int ix = palette()->addMaterial(mat);
+ m_full->setMaterialIndex(ix);
+ mat->setParent(m_full);
+ }
+}
+
+void ThumbnailNode::drawGeometry(QGLPainter *painter)
+{
+ QGLSceneNode::drawGeometry(painter);
+}
+
+void ThumbnailNode::draw(QGLPainter *painter)
+{
+ QGLSceneNode *p = qobject_cast<QGLSceneNode*>(parent());
+ Q_ASSERT_X(p && p->userEffect() && (!hasEffect()),
+ "ThumbnailNode::draw", "Should only inherit parents ThumbnailEffect");
+
+ ThumbnailEffect *effect = static_cast<ThumbnailEffect*>(p->userEffect());
+ Q_ASSERT_X(effect && effect->name() == QLatin1String("ThumbnailEffect"),
+ "ThumbnailNode::draw", "Can only be drawn with custom ThumbnailEffect");
+
+ if (m_defaultMaterial == -1)
+ m_defaultMaterial = materialIndex();
+
+ QMatrix4x4 m = painter->modelViewMatrix().top();
+ QVector3D pos = m.map(position());
+ qreal magSquared = pos.lengthSquared();
+
+ Distance distance = Unknown;
+
+ if (magSquared > (4.0f * m_thresholdSquared))
+ distance = VeryFar;
+ else if (magSquared > (2.0f * m_thresholdSquared))
+ distance = Far;
+ else if (magSquared > m_thresholdSquared)
+ distance = Middle;
+ else
+ distance = Near;
+
+ if (true) // distance != m_lastDistance)
+ {
+ m_lastDistance = distance;
+ m_image.setThumbnailed(m_lastDistance > Near);
+ switch (distance)
+ {
+ case Unknown:
+ case Near:
+ setupLoading();
+ loadFullImage();
+ break;
+ case Middle:
+ setupLoading();
+ loadFullImage();
+ break;
+ case Far:
+ setupLoading();
+ break;
+ case VeryFar:
+ destroyFullNode();
+ break;
+ }
+ }
+
+ effect->setThumbnail(m_image.isThumbnailed());
+ if (m_image.isThumbnailed() || !m_full)
+ {
+ QGLSceneNode::draw(painter);
+ }
+ else
+ {
+ if (m_image.data().isNull())
+ m_full->setMaterialIndex(m_defaultMaterial);
+ if (pickNode() && painter->isPicking())
+ painter->setObjectPickId(pickNode()->id());
+ m_full->draw(painter);
+ }
+
+}
+
+void ThumbnailNode::setImage(const ThumbnailableImage &image)
+{
+ Q_ASSERT(QThread::currentThread() == thread());
+ Q_ASSERT(!image.isNull());
+
+ // the manager will be (potentially) loading a number of images, but
+ // we only want our one, so just check this is our order
+ if (m_url != image.url())
+ return;
+
+ // ok we got the right one, stop listening to the manager
+ if (sender())
+ {
+ m_manager = sender();
+ m_manager->disconnect(this, SLOT(setImage(ThumbnailableImage)));
+ }
+
+ // ok maybe we got what we asked for but in the meantime we decided
+ // we did not want it anymore
+ if (!m_loading)
+ return;
+
+ // the indices we are about to set will index this thumbnail image
+ // into the image that its atlas is based on via the texture coords
+ // that the atlas is using - those texture coords must be in the
+ // same geometry that this node is referencing, so that they will
+ // arrive at the vertex shader at the same time - ie they are all
+ // matched in the data arrays in the geometry object
+ //Q_ASSERT(QAtlas::instance()->geometry() == geometry());
+
+ m_image = image;
+ Q_ASSERT(!m_image.data().isNull());
+
+ // configure the placeholder for the actual image size
+ // this makes a photo of 1024 x 768 display on approx 3.0 x 2.8 pane
+ // add salt to taste
+ //QSizeF f = QSizeF(m_image.data().size()) / 600.0f;
+ QSizeF f = QSizeF(m_image.data().size());
+ f.scale(1.6, 1.2, Qt::KeepAspectRatio);
+ QVector3D a(-f.width(), -f.height(), 0.0f);
+ QVector3D b(f.width(), -f.height(), 0.0f);
+ QVector3D c(f.width(), f.height(), 0.0f);
+ QVector3D d(-f.width(), f.height(), 0.0f);
+ int k = start();
+ Q_ASSERT(count() == 6);
+ QGeometryData g = geometry();
+ QGL::IndexArray inxs = g.indices();
+ g.vertex(inxs.at(k)) = a;
+ g.vertex(inxs.at(k+1)) = b;
+ g.vertex(inxs.at(k+2)) = c;
+ g.vertex(inxs.at(k+5)) = d;
+
+ setMaterialIndex(-1);
+ m_loading = false;
+
+ emit nodeChanged();
+}
diff --git a/demos/photobrowser3d/thumbnailnode.h b/demos/photobrowser3d/thumbnailnode.h
new file mode 100644
index 000000000..467c05517
--- /dev/null
+++ b/demos/photobrowser3d/thumbnailnode.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 THUMBNAILNODE_H
+#define THUMBNAILNODE_H
+
+#include "qglscenenode.h"
+#include "thumbnailableimage.h"
+
+#include <QtCore/qmath.h>
+#include <QUrl>
+
+class ThumbnailNode : public QGLSceneNode
+{
+ Q_OBJECT
+public:
+ enum Distance
+ {
+ Unknown,
+ Near,
+ Middle,
+ Far,
+ VeryFar
+ };
+
+ explicit ThumbnailNode(QObject *parent = 0);
+ ~ThumbnailNode();
+ QUrl url() const { return m_url; }
+ void setUrl(const QUrl &url);
+ void setThreshold(qreal threshold) { m_thresholdSquared = threshold * threshold; }
+ qreal threshold() const { return qSqrt(m_thresholdSquared); }
+ void draw(QGLPainter *painter);
+ void drawGeometry(QGLPainter *painter);
+ ThumbnailableImage image() const { return m_image; }
+signals:
+ void imageRequired(const ThumbnailableImage &);
+ void nodeChanged();
+public slots:
+ void setImage(const ThumbnailableImage &image);
+private:
+ void createFullNode();
+ void destroyFullNode();
+ void setupLoading();
+ void setupThumbnailing();
+ void loadFullImage();
+
+ ThumbnailableImage m_image;
+ qreal m_thresholdSquared;
+ int m_defaultMaterial;
+ QUrl m_url;
+ bool m_loading;
+ QGLSceneNode *m_full;
+ QSizeF m_max;
+ QObject *m_manager;
+ Distance m_lastDistance;
+};
+
+#endif // THUMBNAILNODE_H
diff --git a/demos/shapes/shapes.cpp b/demos/shapes/shapes.cpp
new file mode 100644
index 000000000..2ff4b04f4
--- /dev/null
+++ b/demos/shapes/shapes.cpp
@@ -0,0 +1,424 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "qglpainter.h"
+#include "qglbuilder.h"
+#include "qglcube.h"
+#include "qglteapot.h"
+#include "qglcamera.h"
+#include "qgltexture2d.h"
+#include "qglsubsurface.h"
+#include <QApplication>
+#include <QImage>
+#include <QPainter>
+#include <QDebug>
+
+class ShapesWidget : public QGLWidget
+{
+ Q_OBJECT
+public:
+ ShapesWidget(QWidget *parent = 0);
+ ~ShapesWidget();
+
+protected:
+ void initializeGL();
+ void paintGL();
+
+private:
+ void paintPoints(QGLPainter *painter, const QRect& rect);
+ void paintLines(QGLPainter *painter, const QRect& rect);
+ void paintLineStrip(QGLPainter *painter, const QRect& rect);
+ void paintLineLoop(QGLPainter *painter, const QRect& rect);
+ void paintTriangles(QGLPainter *painter, const QRect& rect);
+ void paintTriangleStrip(QGLPainter *painter, const QRect& rect);
+ void paintTriangleFan(QGLPainter *painter, const QRect& rect);
+ void paintCube(QGLPainter *painter, const QRect& rect);
+ void paintTeapot(QGLPainter *painter, const QRect& rect);
+ void drawText(QGLPainter *painter, const QRect& posn, const QString& str);
+
+ static QVector2DArray basicPoints(const QRect& rect);
+
+ QGLCamera camera;
+ QGLSceneNode *scene;
+ QGLSceneNode *cube;
+ QGLSceneNode *teapot;
+ QGLLightModel oneSidedModel;
+ QGLLightModel twoSidedModel;
+};
+
+ShapesWidget::ShapesWidget(QWidget *parent)
+ : QGLWidget(parent)
+{
+ setWindowTitle(tr("GL Primitive Shapes"));
+ oneSidedModel.setModel(QGLLightModel::OneSided);
+ twoSidedModel.setModel(QGLLightModel::TwoSided);
+}
+
+ShapesWidget::~ShapesWidget()
+{
+ delete scene;
+}
+
+void ShapesWidget::initializeGL()
+{
+ QGLPainter painter(this);
+
+ painter.setLightModel(&twoSidedModel);
+ painter.setFaceColor(QGL::FrontFaces, QColor(170, 202, 0));
+ painter.setFaceColor(QGL::BackFaces, QColor(202, 170, 0));
+
+ QGLBuilder builder;
+ builder << QGL::Faceted << QGLCube();
+ cube = builder.currentNode();
+ builder << QGL::Smooth << QGLTeapot();
+ teapot = builder.currentNode();
+ scene = builder.finalizedSceneNode();
+}
+
+void ShapesWidget::paintGL()
+{
+ QGLPainter painter(this);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glDisable(GL_DEPTH_TEST);
+
+ QMatrix4x4 projm;
+ projm.ortho(rect());
+ painter.projectionMatrix() = projm;
+ painter.modelViewMatrix().setToIdentity();
+
+ QRect wrect = rect();
+ int boxw = wrect.width() / 3;
+ int boxh = wrect.height() / 3;
+
+ paintLines(&painter, QRect(0, 0, boxw, boxh));
+ paintLineStrip(&painter, QRect(boxw, 0, boxw, boxh));
+ paintLineLoop(&painter, QRect(boxw * 2, 0, boxw, boxh));
+ paintTriangles(&painter, QRect(0, boxh, boxw, boxh));
+ paintTriangleStrip(&painter, QRect(boxw, boxh, boxw, boxh));
+ paintTriangleFan(&painter, QRect(boxw * 2, boxh, boxw, boxh));
+ paintPoints(&painter, QRect(0, boxh * 2, boxw, boxh));
+
+ glEnable(GL_DEPTH_TEST);
+
+ paintCube(&painter, QRect(boxw, boxh * 2, boxw, boxh));
+ paintTeapot(&painter, QRect(boxw * 2, boxh * 2, boxw, boxh));
+}
+
+QVector2DArray ShapesWidget::basicPoints(const QRect& rect)
+{
+ QVector2DArray vertices;
+ int step = qMin(rect.width() / 6, rect.height() / 6);
+ int midx = rect.x() + rect.width() / 2;
+ int midy = rect.y() + rect.height() / 2;
+ vertices.append(midx - step * 2, midy - step);
+ vertices.append(midx + step, midy - step * 2);
+ vertices.append(midx, midy - step);
+ vertices.append(midx + step * 2 + step / 2, midy - step / 2);
+ vertices.append(midx - step, midy);
+ vertices.append(midx + step * 2, midy + step);
+ vertices.append(midx - step, midy + step);
+ vertices.append(midx + step * 2, midy);
+ return vertices;
+}
+
+void ShapesWidget::paintPoints(QGLPainter *painter, const QRect& rect)
+{
+ painter->setStandardEffect(QGL::FlatColor);
+ painter->setColor(QColor(170, 202, 0));
+
+ painter->clearAttributes();
+ painter->setVertexAttribute(QGL::Position, basicPoints(rect));
+ painter->draw(QGL::Points, 8);
+
+ drawText(painter, rect, tr("Points"));
+}
+
+void ShapesWidget::paintLines(QGLPainter *painter, const QRect& rect)
+{
+ painter->clearAttributes();
+ painter->setVertexAttribute(QGL::Position, basicPoints(rect));
+ painter->draw(QGL::Lines, 8);
+
+ drawText(painter, rect, tr("Lines"));
+}
+
+void ShapesWidget::paintLineStrip(QGLPainter *painter, const QRect& rect)
+{
+ painter->clearAttributes();
+ painter->setVertexAttribute(QGL::Position, basicPoints(rect));
+ painter->draw(QGL::LineStrip, 8);
+
+ drawText(painter, rect, tr("Line strip"));
+}
+
+void ShapesWidget::paintLineLoop(QGLPainter *painter, const QRect& rect)
+{
+ painter->clearAttributes();
+ painter->setVertexAttribute(QGL::Position, basicPoints(rect));
+ painter->draw(QGL::LineLoop, 8);
+
+ drawText(painter, rect, tr("Line loop"));
+}
+
+void ShapesWidget::paintTriangles(QGLPainter *painter, const QRect& rect)
+{
+ painter->setStandardEffect(QGL::LitMaterial);
+
+ QVector2DArray vertices;
+ QVector3DArray normals;
+ int step = qMin(rect.width() / 8, rect.height() / 8);
+ int midx = rect.x() + rect.width() / 2;
+ int midy = rect.y() + rect.height() / 2;
+
+ vertices.append(midx - step * 3, midy);
+ vertices.append(midx - step * 3, midy + step * 2);
+ vertices.append(midx - step, midy + step * 2);
+
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+
+ vertices.append(midx - step * 2, midy - step);
+ vertices.append(midx + step / 2, midy + step * 2);
+ vertices.append(midx + step * 3, midy - step);
+
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+
+ painter->clearAttributes();
+ painter->setVertexAttribute(QGL::Position, vertices);
+ painter->setVertexAttribute(QGL::Normal, normals);
+ painter->draw(QGL::Triangles, 6);
+
+ drawText(painter, rect, tr("Triangles"));
+}
+
+void ShapesWidget::paintTriangleStrip(QGLPainter *painter, const QRect& rect)
+{
+ painter->setStandardEffect(QGL::LitMaterial);
+
+ QVector2DArray vertices;
+ QVector3DArray normals;
+ int step = qMin(rect.width() / 8, rect.height() / 8);
+ int midx = rect.x() + rect.width() / 2;
+ int midy = rect.y() + rect.height() / 2;
+
+ vertices.append(midx - step * 3, midy - step * 2);
+ vertices.append(midx - step * 3, midy + step);
+ vertices.append(midx - step, midy - step * 2);
+ vertices.append(midx, midy + step);
+ vertices.append(midx + step, midy - step * 2);
+ vertices.append(midx + step * 2, midy + step * 2);
+
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+
+ painter->clearAttributes();
+ painter->setVertexAttribute(QGL::Position, vertices);
+ painter->setVertexAttribute(QGL::Normal, normals);
+ painter->draw(QGL::TriangleStrip, 6);
+
+ // Overpaint some lines to show the triangle boundaries.
+ painter->clearAttributes();
+ painter->setStandardEffect(QGL::FlatColor);
+ painter->setColor(QColor(202, 170, 0));
+ painter->setVertexAttribute(QGL::Position, vertices);
+ painter->draw(QGL::LineStrip, 4, 1);
+
+ drawText(painter, rect, tr("Triangle strip"));
+}
+
+void ShapesWidget::paintTriangleFan(QGLPainter *painter, const QRect& rect)
+{
+ painter->setStandardEffect(QGL::LitMaterial);
+
+ QVector2DArray vertices;
+ QVector3DArray normals;
+ int step = qMin(rect.width() / 8, rect.height() / 8);
+ int midx = rect.x() + rect.width() / 2;
+ int midy = rect.y() + rect.height() / 2;
+
+ vertices.append(midx - step, midy + step);
+ vertices.append(midx + step * 2, midy + step * 2);
+ vertices.append(midx + step * 2, midy);
+ vertices.append(midx + step, midy - step);
+ vertices.append(midx - step, midy - step * 2);
+
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+ normals.append(0.0f, 0.0f, 1.0f);
+
+ painter->clearAttributes();
+ painter->setVertexAttribute(QGL::Position, vertices);
+ painter->setVertexAttribute(QGL::Normal, normals);
+ painter->draw(QGL::TriangleFan, 5);
+
+ // Overpaint some lines to show the triangle boundaries.
+ painter->clearAttributes();
+ painter->setStandardEffect(QGL::FlatColor);
+ painter->setColor(QColor(202, 170, 0));
+ static ushort const indices[] = {0, 2, 0, 3};
+ painter->setVertexAttribute(QGL::Position, vertices);
+ painter->draw(QGL::Lines, indices, 4);
+
+ drawText(painter, rect, tr("Triangle fan"));
+}
+
+void ShapesWidget::paintCube(QGLPainter *painter, const QRect& rect)
+{
+ painter->setStandardEffect(QGL::LitMaterial);
+
+ painter->projectionMatrix().push();
+ painter->modelViewMatrix().push();
+
+ QGLSubsurface surface(painter->currentSurface(), rect);
+ painter->pushSurface(&surface);
+
+ painter->setCamera(&camera);
+ painter->modelViewMatrix().rotate(45.0f, 1.0f, 1.0f, 1.0f);
+
+ cube->draw(painter);
+
+ painter->projectionMatrix().pop();
+ painter->modelViewMatrix().pop();
+
+ painter->popSurface();
+
+ drawText(painter, rect, tr("Cube"));
+}
+
+void ShapesWidget::paintTeapot(QGLPainter *painter, const QRect& rect)
+{
+ painter->setStandardEffect(QGL::LitMaterial);
+
+ painter->projectionMatrix().push();
+ painter->modelViewMatrix().push();
+
+ QGLSubsurface surface(painter->currentSurface(), rect);
+ painter->pushSurface(&surface);
+
+ painter->setCamera(&camera);
+
+ // Need a one-sided lighting model for the teapot.
+ painter->setLightModel(&oneSidedModel);
+
+ teapot->draw(painter);
+
+ painter->setLightModel(&twoSidedModel);
+
+ painter->projectionMatrix().pop();
+ painter->modelViewMatrix().pop();
+
+ painter->popSurface();
+
+ drawText(painter, rect, tr("Teapot"));
+}
+
+// Draw text centered on the bottom of the "posn" rectangle.
+void ShapesWidget::drawText
+ (QGLPainter *painter, const QRect& posn, const QString& str)
+{
+ QFontMetrics metrics = fontMetrics();
+ QRect rect = metrics.boundingRect(str);
+ rect.adjust(0, 0, 1, 1);
+
+ QFont f = font();
+
+ QImage image(rect.size(), QImage::Format_ARGB32);
+ image.fill(0);
+ QPainter p2(&image);
+ p2.setFont(f);
+ p2.setPen(Qt::white);
+ p2.drawText(-rect.x(), metrics.ascent(), str);
+ p2.end();
+
+ QGLTexture2D texture;
+ texture.setImage(image);
+
+ int x = posn.x() + (posn.width() - rect.width()) / 2;
+ int y = posn.y() + posn.height() - metrics.ascent() - metrics.descent();
+ y -= 10;
+
+ QVector2DArray vertices;
+ vertices.append(x + rect.x(), y + metrics.ascent());
+ vertices.append(x + rect.x(), y - metrics.descent());
+ vertices.append(x + rect.x() + rect.width(), y - metrics.descent());
+ vertices.append(x + rect.x() + rect.width(), y + metrics.ascent());
+
+ QVector2DArray texCoord;
+ texCoord.append(0.0f, 0.0f);
+ texCoord.append(0.0f, 1.0f);
+ texCoord.append(1.0f, 1.0f);
+ texCoord.append(1.0f, 0.0f);
+
+ painter->clearAttributes();
+ painter->setStandardEffect(QGL::FlatReplaceTexture2D);
+ texture.bind();
+ painter->setVertexAttribute(QGL::Position, vertices);
+ painter->setVertexAttribute(QGL::TextureCoord0, texCoord);
+ painter->draw(QGL::TriangleFan, 4);
+ painter->setStandardEffect(QGL::FlatColor);
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ ShapesWidget w;
+ if (QApplication::arguments().contains(QLatin1String("-maximize")))
+ w.showMaximized();
+ else if (QApplication::arguments().contains(QLatin1String("-fullscreen")))
+ w.showFullScreen();
+ else
+ w.show();
+ return app.exec();
+}
+
+#include "shapes.moc"
diff --git a/demos/shapes/shapes.pro b/demos/shapes/shapes.pro
new file mode 100644
index 000000000..499c134c0
--- /dev/null
+++ b/demos/shapes/shapes.pro
@@ -0,0 +1,5 @@
+TEMPLATE = app
+TARGET = shapes
+CONFIG += qt warn_on qt3d
+SOURCES = shapes.cpp
+DESTDIR = ../../bin
diff --git a/demos/teaservice/README b/demos/teaservice/README
new file mode 100644
index 000000000..d7d71a617
--- /dev/null
+++ b/demos/teaservice/README
@@ -0,0 +1,7 @@
+
+This example demonstrates a view with multiple scene objects, plus material
+parameters. It shows a teapot, two teacups, and two teaspoons.
+
+The model source data came from "http://www.sjbaker.org/teapot/teaset.tgz".
+
+Note: the teacups have no bottoms in the original source data.
diff --git a/demos/teaservice/meshobject.cpp b/demos/teaservice/meshobject.cpp
new file mode 100644
index 000000000..1ff49d30b
--- /dev/null
+++ b/demos/teaservice/meshobject.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "meshobject.h"
+#include "qglview.h"
+
+MeshObject::MeshObject(QGLSceneNode *meshObject, QObject *parent)
+ : QObject(parent)
+{
+ m_mesh = 0;
+ m_meshObject = meshObject;
+ m_scale = 1.0f;
+ m_rotationAngle = 0.0f;
+ m_effect = 0;
+ m_objectId = -1;
+ m_hovering = false;
+ m_material = 0;
+ m_hoverMaterial = 0;
+}
+
+MeshObject::MeshObject(QGLAbstractScene *scene, QObject *parent)
+ : QObject(parent)
+{
+ scene->setParent(this);
+ m_mesh = 0;
+ m_meshObject = scene->mainNode();
+ m_scale = 1.0f;
+ m_rotationAngle = 0.0f;
+ m_effect = 0;
+ m_objectId = -1;
+ m_hovering = false;
+ m_material = 0;
+ m_hoverMaterial = 0;
+}
+
+MeshObject::~MeshObject()
+{
+ delete m_mesh;
+}
+
+void MeshObject::initialize(QGLView *view, QGLPainter *painter)
+{
+ Q_UNUSED(painter);
+ if (m_objectId != -1)
+ view->registerObject(m_objectId, this);
+}
+
+void MeshObject::draw(QGLPainter *painter)
+{
+ // Position the model at its designated position, scale, and orientation.
+ painter->modelViewMatrix().push();
+ painter->modelViewMatrix().translate(m_position);
+ if (m_scale != 1.0f)
+ painter->modelViewMatrix().scale(m_scale);
+ if (m_rotationAngle != 0.0f)
+ painter->modelViewMatrix().rotate(m_rotationAngle, m_rotationVector);
+
+ // Apply the material and effect to the painter.
+ QGLMaterial *material;
+ if (m_hovering)
+ material = m_hoverMaterial;
+ else
+ material = m_material;
+ painter->setColor(material->diffuseColor());
+ painter->setFaceMaterial(QGL::AllFaces, material);
+ if (m_effect)
+ painter->setUserEffect(m_effect);
+ else
+ painter->setStandardEffect(QGL::LitMaterial);
+
+ // Mark the object for object picking purposes.
+ int prevObjectId = painter->objectPickId();
+ if (m_objectId != -1)
+ painter->setObjectPickId(m_objectId);
+
+ // Draw the geometry mesh.
+ if (m_meshObject)
+ m_meshObject->draw(painter);
+ else
+ m_mesh->draw(painter);
+
+ // Turn off the user effect, if present.
+ if (m_effect)
+ painter->setStandardEffect(QGL::LitMaterial);
+
+ // Revert to the previous object identifier.
+ painter->setObjectPickId(prevObjectId);
+
+ // Restore the modelview matrix.
+ painter->modelViewMatrix().pop();
+}
+
+bool MeshObject::event(QEvent *e)
+{
+ // Convert the raw event into a signal representing the user's action.
+ if (e->type() == QEvent::MouseButtonPress) {
+ QMouseEvent *me = (QMouseEvent *)e;
+ if (me->button() == Qt::LeftButton)
+ emit pressed();
+ } else if (e->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent *me = (QMouseEvent *)e;
+ if (me->button() == Qt::LeftButton) {
+ emit released();
+ if (me->x() >= 0) // Positive: inside object, Negative: outside.
+ emit clicked();
+ }
+ } else if (e->type() == QEvent::MouseButtonDblClick) {
+ emit doubleClicked();
+ } else if (e->type() == QEvent::Enter) {
+ m_hovering = true;
+ emit hoverChanged();
+ } else if (e->type() == QEvent::Leave) {
+ m_hovering = false;
+ emit hoverChanged();
+ }
+ return QObject::event(e);
+}
diff --git a/demos/teaservice/meshobject.h b/demos/teaservice/meshobject.h
new file mode 100644
index 000000000..c0abb8813
--- /dev/null
+++ b/demos/teaservice/meshobject.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 MESHOBJECT_H
+#define MESHOBJECT_H
+
+#include <QtCore/qobject.h>
+#include <QtGui/qevent.h>
+
+#include "qglpainter.h"
+#include "qglabstractscene.h"
+
+class QGLView;
+class QGLSceneNode;
+
+class MeshObject : public QObject
+{
+ Q_OBJECT
+public:
+ explicit MeshObject(QGLSceneNode *meshObject, QObject *parent=0);
+ explicit MeshObject(QGLAbstractScene *scene, QObject *parent=0);
+ virtual ~MeshObject();
+
+ QVector3D position() const { return m_position; }
+ void setPosition(const QVector3D& value) { m_position = value; }
+
+ qreal scale() const { return m_scale; }
+ void setScale(qreal value) { m_scale = value; }
+
+ qreal rotationAngle() const { return m_rotationAngle; }
+ void setRotationAngle(qreal value) { m_rotationAngle = value; }
+
+ QVector3D rotationVector() const { return m_rotationVector; }
+ void setRotationVector(const QVector3D& value) { m_rotationVector = value; }
+
+ QGLMaterial *material() const { return m_material; }
+ void setMaterial(QGLMaterial *value)
+ { m_material = value; m_hoverMaterial = value; }
+
+ QGLMaterial *hoverMaterial() const { return m_hoverMaterial; }
+ void setHoverMaterial(QGLMaterial *value) { m_hoverMaterial = value; }
+
+ QGLAbstractEffect *effect() const { return m_effect; }
+ void setEffect(QGLAbstractEffect *value) { m_effect = value; }
+
+ int objectId() const { return m_objectId; }
+ void setObjectId(int id) { m_objectId = id; }
+
+ void initialize(QGLView *view, QGLPainter *painter);
+ void draw(QGLPainter *painter);
+
+signals:
+ void pressed();
+ void released();
+ void clicked();
+ void doubleClicked();
+ void hoverChanged();
+
+protected:
+ bool event(QEvent *e);
+
+private:
+ QGLSceneNode *m_mesh;
+ QGLSceneNode *m_meshObject;
+ QGLAbstractScene *m_scene;
+ QVector3D m_position;
+ qreal m_scale;
+ qreal m_rotationAngle;
+ QVector3D m_rotationVector;
+ QGLMaterial *m_material;
+ QGLMaterial *m_hoverMaterial;
+ QGLAbstractEffect *m_effect;
+ int m_objectId;
+ bool m_hovering;
+};
+
+#endif
diff --git a/demos/teaservice/per_pixel_lighting.fsh b/demos/teaservice/per_pixel_lighting.fsh
new file mode 100644
index 000000000..166c4d44b
--- /dev/null
+++ b/demos/teaservice/per_pixel_lighting.fsh
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+// Per-pixel lighting - fragment shader side.
+
+struct qt_MaterialParameters {
+ mediump vec4 emission;
+ mediump vec4 ambient;
+ mediump vec4 diffuse;
+ mediump vec4 specular;
+ mediump float shininess;
+};
+uniform qt_MaterialParameters qt_Material;
+
+struct qt_SingleLightParameters {
+ mediump vec4 position;
+ mediump vec3 spotDirection;
+ mediump float spotExponent;
+ mediump float spotCutoff;
+ mediump float spotCosCutoff;
+ mediump float constantAttenuation;
+ mediump float linearAttenuation;
+ mediump float quadraticAttenuation;
+};
+uniform qt_SingleLightParameters qt_Light;
+
+varying mediump vec3 qNormal;
+varying mediump vec3 qLightDirection;
+varying mediump vec3 qHalfVector;
+varying mediump vec3 qVertexToLight;
+varying mediump vec4 qAmbient;
+varying mediump vec4 qDiffuse;
+
+vec4 qLightPixel(vec4 ambient, vec4 diffuse)
+{
+ float angle, spot;
+ vec4 color;
+ vec4 component;
+ vec3 normal = normalize(qNormal);
+
+ // Start with the ambient color.
+ color = ambient;
+
+ // Determine the cosine of the angle between the normal and the
+ // vector from the vertex to the light.
+ angle = max(dot(normal, qLightDirection), 0.0);
+
+ // Calculate the diffuse light components.
+ component = angle * diffuse;
+
+ // Calculate the specular light components.
+ if (angle != 0.0) {
+ angle = max(dot(normal, qHalfVector), 0.0);
+ component += pow(angle, qt_Material.shininess) * qt_Material.specular;
+ }
+
+ // Apply the spotlight angle and exponent.
+ if (qt_Light.spotCutoff != 180.0) {
+ spot = max(dot(normalize(qVertexToLight),
+ normalize(qt_Light.spotDirection)), 0.0);
+ if (spot < qt_Light.spotCosCutoff)
+ spot = 0.0;
+ else
+ spot = pow(spot, qt_Light.spotExponent);
+ component *= spot;
+ }
+
+ return clamp(color + component, 0.0, 1.0);
+}
+
+void main(void)
+{
+ gl_FragColor = qLightPixel(qAmbient, qDiffuse);
+}
diff --git a/demos/teaservice/per_pixel_lighting.vsh b/demos/teaservice/per_pixel_lighting.vsh
new file mode 100644
index 000000000..c437652ef
--- /dev/null
+++ b/demos/teaservice/per_pixel_lighting.vsh
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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$
+**
+****************************************************************************/
+
+// Per-pixel lighting - vertex shader side.
+
+attribute highp vec4 qt_Vertex;
+attribute mediump vec3 qt_Normal;
+uniform mediump mat4 qt_ModelViewMatrix;
+uniform mediump mat4 qt_ModelViewProjectionMatrix;
+uniform mediump mat3 qt_NormalMatrix;
+
+struct qt_MaterialParameters {
+ mediump vec4 emission;
+ mediump vec4 ambient;
+ mediump vec4 diffuse;
+ mediump vec4 specular;
+ mediump float shininess;
+};
+uniform qt_MaterialParameters qt_Material;
+
+struct qt_SingleLightParameters {
+ mediump vec4 position;
+ mediump vec3 spotDirection;
+ mediump float spotExponent;
+ mediump float spotCutoff;
+ mediump float spotCosCutoff;
+ mediump float constantAttenuation;
+ mediump float linearAttenuation;
+ mediump float quadraticAttenuation;
+};
+uniform qt_SingleLightParameters qt_Light;
+
+varying mediump vec4 qAmbient;
+varying mediump vec4 qDiffuse;
+varying mediump vec3 qNormal;
+varying mediump vec3 qLightDirection;
+varying mediump vec3 qHalfVector;
+varying mediump vec3 qVertexToLight;
+
+void qLightVertex(vec4 vertex, vec3 normal)
+{
+ vec3 toEye;
+ qNormal = normal;
+ qAmbient = qt_Material.emission + qt_Material.ambient;
+ qDiffuse = qt_Material.diffuse;
+ qLightDirection = normalize(qt_Light.position.xyz);
+ toEye = vec3(0, 0, 1);
+ qHalfVector = normalize(qLightDirection + toEye);
+ qVertexToLight = vertex.xyz - qt_Light.position.xyz;
+}
+
+void main(void)
+{
+ gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;
+ vec4 vertex = qt_ModelViewMatrix * qt_Vertex;
+ vec3 normal = normalize(qt_NormalMatrix * qt_Normal);
+ qLightVertex(vertex, normal);
+}
diff --git a/demos/teaservice/perpixeleffect.cpp b/demos/teaservice/perpixeleffect.cpp
new file mode 100644
index 000000000..450f21396
--- /dev/null
+++ b/demos/teaservice/perpixeleffect.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "perpixeleffect.h"
+
+QT_BEGIN_NAMESPACE
+
+PerPixelEffect::PerPixelEffect()
+{
+ setVertexShaderFromFile(":per_pixel_lighting.vsh");
+ setFragmentShaderFromFile(":per_pixel_lighting.fsh");
+}
+
+PerPixelEffect::~PerPixelEffect()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/demos/teaservice/perpixeleffect.h b/demos/teaservice/perpixeleffect.h
new file mode 100644
index 000000000..cf015abdf
--- /dev/null
+++ b/demos/teaservice/perpixeleffect.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 PERPIXELEFFECT_H
+#define PERPIXELEFFECT_H
+
+#include "qglshaderprogrameffect.h"
+
+class PerPixelEffectPrivate;
+class QGLShader;
+
+class PerPixelEffect : public QGLShaderProgramEffect
+{
+ Q_DISABLE_COPY(PerPixelEffect);
+public:
+ PerPixelEffect();
+ virtual ~PerPixelEffect();
+};
+
+#endif
diff --git a/demos/teaservice/sceneobject.cpp b/demos/teaservice/sceneobject.cpp
new file mode 100644
index 000000000..438b6fa19
--- /dev/null
+++ b/demos/teaservice/sceneobject.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 "sceneobject.h"
+#include "meshobject.h"
+
+SceneObject::SceneObject(QObject *parent)
+ : QObject(parent)
+{
+}
+
+SceneObject::~SceneObject()
+{
+}
+
+void SceneObject::initialize(QGLView *view, QGLPainter *painter)
+{
+ // Initialize all of the mesh objects that we have as children.
+ foreach (QObject *obj, children()) {
+ MeshObject *meshobj = qobject_cast<MeshObject *>(obj);
+ if (meshobj)
+ meshobj->initialize(view, painter);
+ }
+}
+
+void SceneObject::draw(QGLPainter *painter)
+{
+ // Draw all of the mesh objects that we have as children.
+ foreach (QObject *obj, children()) {
+ MeshObject *meshobj = qobject_cast<MeshObject *>(obj);
+ if (meshobj)
+ meshobj->draw(painter);
+ }
+}
diff --git a/demos/teaservice/sceneobject.h b/demos/teaservice/sceneobject.h
new file mode 100644
index 000000000..edfaa82a6
--- /dev/null
+++ b/demos/teaservice/sceneobject.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 SCENEOBJECT_H
+#define SCENEOBJECT_H
+
+#include <QtCore/qobject.h>
+#include "qglpainter.h"
+
+class QGLView;
+
+class SceneObject : public QObject
+{
+ Q_OBJECT
+public:
+ explicit SceneObject(QObject *parent=0);
+ virtual ~SceneObject();
+
+ virtual void initialize(QGLView *view, QGLPainter *painter);
+ virtual void draw(QGLPainter *painter);
+};
+
+#endif
diff --git a/demos/teaservice/teacup.txt b/demos/teaservice/teacup.txt
new file mode 100644
index 000000000..f4dde3efd
--- /dev/null
+++ b/demos/teaservice/teacup.txt
@@ -0,0 +1,280 @@
+26
+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
+4,17,18,19,8,20,21,22,12,23,24,25,16,26,27,28
+19,29,30,31,22,32,33,34,25,35,36,37,28,38,39,40
+31,41,42,1,34,43,44,5,37,45,46,9,40,47,48,13
+13,14,15,16,49,50,51,52,53,54,55,56,57,58,59,60
+16,26,27,28,52,61,62,63,56,64,65,66,60,67,68,69
+28,38,39,40,63,70,71,72,66,73,74,75,69,76,77,78
+40,47,48,13,72,79,80,49,75,81,82,53,78,83,84,57
+193,194,195,196,197,198,199,200,201,202,203,204,1,2,3,4
+196,205,206,207,200,208,209,210,204,211,212,213,4,17,18,19
+207,214,215,216,210,217,218,219,213,220,221,222,19,29,30,31
+216,223,224,193,219,225,226,197,222,227,228,201,31,41,42,1
+229,230,231,28,232,233,234,235,236,237,238,239,240,241,242,243
+28,244,245,229,235,246,247,232,239,248,249,236,243,250,251,240
+57,58,59,60,85,86,87,88,89,90,91,92,93,94,95,96
+60,67,68,69,88,97,98,99,92,100,101,102,96,103,104,105
+69,76,77,78,99,106,107,108,102,109,110,111,105,112,113,114
+78,83,84,57,108,115,116,85,111,117,118,89,114,119,120,93
+93,94,95,96,121,122,123,124,125,126,127,128,129,130,131,132
+96,103,104,105,124,133,134,135,128,136,137,138,132,139,140,141
+105,112,113,114,135,142,143,144,138,145,146,147,141,148,149,150
+114,119,120,93,144,151,152,121,147,153,154,125,150,155,156,129
+129,130,131,132,157,158,159,160,161,162,163,164,165,166,167,168
+132,139,140,141,160,169,170,171,164,172,173,174,168,175,176,177
+141,148,149,150,171,178,179,180,174,181,182,183,177,184,185,186
+150,155,156,129,180,187,188,157,183,189,190,161,186,191,192,165
+251
+0.409091,0.772727,0.0
+0.409091,0.772727,-0.229091
+0.229091,0.772727,-0.409091
+0.0,0.772727,-0.409091
+0.409091,0.886364,0.0
+0.409091,0.886364,-0.229091
+0.229091,0.886364,-0.409091
+0.0,0.886364,-0.409091
+0.454545,0.886364,0.0
+0.454545,0.886364,-0.254545
+0.254545,0.886364,-0.454545
+0.0,0.886364,-0.454545
+0.454545,0.772727,0.0
+0.454545,0.772727,-0.254545
+0.254545,0.772727,-0.454545
+0.0,0.772727,-0.454545
+-0.229091,0.772727,-0.409091
+-0.409091,0.772727,-0.229091
+-0.409091,0.772727,0.0
+-0.229091,0.886364,-0.409091
+-0.409091,0.886364,-0.229091
+-0.409091,0.886364,0.0
+-0.254545,0.886364,-0.454545
+-0.454545,0.886364,-0.254545
+-0.454545,0.886364,0.0
+-0.254545,0.772727,-0.454545
+-0.454545,0.772727,-0.254545
+-0.454545,0.772727,0.0
+-0.409091,0.772727,0.229091
+-0.229091,0.772727,0.409091
+0.0,0.772727,0.409091
+-0.409091,0.886364,0.229091
+-0.229091,0.886364,0.409091
+0.0,0.886364,0.409091
+-0.454545,0.886364,0.254545
+-0.254545,0.886364,0.454545
+0.0,0.886364,0.454545
+-0.454545,0.772727,0.254545
+-0.254545,0.772727,0.454545
+0.0,0.772727,0.454545
+0.229091,0.772727,0.409091
+0.409091,0.772727,0.229091
+0.229091,0.886364,0.409091
+0.409091,0.886364,0.229091
+0.254545,0.886364,0.454545
+0.454545,0.886364,0.254545
+0.254545,0.772727,0.454545
+0.454545,0.772727,0.254545
+0.454545,0.545455,0.0
+0.454545,0.545455,-0.254545
+0.254545,0.545455,-0.454545
+0.0,0.545455,-0.454545
+0.454545,0.272727,0.0
+0.454545,0.272727,-0.254545
+0.254545,0.272727,-0.454545
+0.0,0.272727,-0.454545
+0.318182,0.0454545,0.0
+0.318182,0.0454545,-0.178182
+0.178182,0.0454545,-0.318182
+0.0,0.0454545,-0.318182
+-0.254545,0.545455,-0.454545
+-0.454545,0.545455,-0.254545
+-0.454545,0.545455,0.0
+-0.254545,0.272727,-0.454545
+-0.454545,0.272727,-0.254545
+-0.454545,0.272727,0.0
+-0.178182,0.0454545,-0.318182
+-0.318182,0.0454545,-0.178182
+-0.318182,0.0454545,0.0
+-0.454545,0.545455,0.254545
+-0.254545,0.545455,0.454545
+0.0,0.545455,0.454545
+-0.454545,0.272727,0.254545
+-0.254545,0.272727,0.454545
+0.0,0.272727,0.454545
+-0.318182,0.0454545,0.178182
+-0.178182,0.0454545,0.318182
+0.0,0.0454545,0.318182
+0.254545,0.545455,0.454545
+0.454545,0.545455,0.254545
+0.254545,0.272727,0.454545
+0.454545,0.272727,0.254545
+0.178182,0.0454545,0.318182
+0.318182,0.0454545,0.178182
+0.545455,0.0454545,0.0
+0.545455,0.0454545,-0.305455
+0.305455,0.0454545,-0.545455
+0.0,0.0454545,-0.545455
+0.727273,0.136364,0.0
+0.727273,0.136364,-0.407273
+0.407273,0.136364,-0.727273
+0.0,0.136364,-0.727273
+0.909091,0.136364,0.0
+0.909091,0.136364,-0.509091
+0.509091,0.136364,-0.909091
+0.0,0.136364,-0.909091
+-0.305455,0.0454545,-0.545455
+-0.545455,0.0454545,-0.305455
+-0.545455,0.0454545,0.0
+-0.407273,0.136364,-0.727273
+-0.727273,0.136364,-0.407273
+-0.727273,0.136364,0.0
+-0.509091,0.136364,-0.909091
+-0.909091,0.136364,-0.509091
+-0.909091,0.136364,0.0
+-0.545455,0.0454545,0.305455
+-0.305455,0.0454545,0.545455
+0.0,0.0454545,0.545455
+-0.727273,0.136364,0.407273
+-0.407273,0.136364,0.727273
+0.0,0.136364,0.727273
+-0.909091,0.136364,0.509091
+-0.509091,0.136364,0.909091
+0.0,0.136364,0.909091
+0.305455,0.0454545,0.545455
+0.545455,0.0454545,0.305455
+0.407273,0.136364,0.727273
+0.727273,0.136364,0.407273
+0.509091,0.136364,0.909091
+0.909091,0.136364,0.509091
+1.0,0.136364,0.0
+1.0,0.136364,-0.56
+0.56,0.136364,-1.0
+0.0,0.136364,-1.0
+1.0,0.0909091,0.0
+1.0,0.0909091,-0.56
+0.56,0.0909091,-1.0
+0.0,0.0909091,-1.0
+0.909091,0.0909091,0.0
+0.909091,0.0909091,-0.509091
+0.509091,0.0909091,-0.909091
+0.0,0.0909091,-0.909091
+-0.56,0.136364,-1.0
+-1.0,0.136364,-0.56
+-1.0,0.136364,0.0
+-0.56,0.0909091,-1.0
+-1.0,0.0909091,-0.56
+-1.0,0.0909091,0.0
+-0.509091,0.0909091,-0.909091
+-0.909091,0.0909091,-0.509091
+-0.909091,0.0909091,0.0
+-1.0,0.136364,0.56
+-0.56,0.136364,1.0
+0.0,0.136364,1.0
+-1.0,0.0909091,0.56
+-0.56,0.0909091,1.0
+0.0,0.0909091,1.0
+-0.909091,0.0909091,0.509091
+-0.509091,0.0909091,0.909091
+0.0,0.0909091,0.909091
+0.56,0.136364,1.0
+1.0,0.136364,0.56
+0.56,0.0909091,1.0
+1.0,0.0909091,0.56
+0.509091,0.0909091,0.909091
+0.909091,0.0909091,0.509091
+0.727273,0.0909091,0.0
+0.727273,0.0909091,-0.407273
+0.407273,0.0909091,-0.727273
+0.0,0.0909091,-0.727273
+0.545455,0.0,0.0
+0.545455,0.0,-0.305455
+0.305455,0.0,-0.545455
+0.0,0.0,-0.545455
+0.318182,0.0,0.0
+0.318182,0.0,-0.178182
+0.178182,0.0,-0.318182
+0.0,0.0,-0.318182
+-0.407273,0.0909091,-0.727273
+-0.727273,0.0909091,-0.407273
+-0.727273,0.0909091,0.0
+-0.305455,0.0,-0.545455
+-0.545455,0.0,-0.305455
+-0.545455,0.0,0.0
+-0.178182,0.0,-0.318182
+-0.318182,0.0,-0.178182
+-0.318182,0.0,0.0
+-0.727273,0.0909091,0.407273
+-0.407273,0.0909091,0.727273
+0.0,0.0909091,0.727273
+-0.545455,0.0,0.305455
+-0.305455,0.0,0.545455
+0.0,0.0,0.545455
+-0.318182,0.0,0.178182
+-0.178182,0.0,0.318182
+0.0,0.0,0.318182
+0.407273,0.0909091,0.727273
+0.727273,0.0909091,0.407273
+0.305455,0.0,0.545455
+0.545455,0.0,0.305455
+0.178182,0.0,0.318182
+0.318182,0.0,0.178182
+0.272727,0.0454545,0.0
+0.272727,0.0454545,-0.152727
+0.152727,0.0454545,-0.272727
+0.0,0.0454545,-0.272727
+0.409091,0.272727,0.0
+0.409091,0.272727,-0.229091
+0.229091,0.272727,-0.409091
+0.0,0.272727,-0.409091
+0.409091,0.545455,0.0
+0.409091,0.545455,-0.229091
+0.229091,0.545455,-0.409091
+0.0,0.545455,-0.409091
+-0.152727,0.0454545,-0.272727
+-0.272727,0.0454545,-0.152727
+-0.272727,0.0454545,0.0
+-0.229091,0.272727,-0.409091
+-0.409091,0.272727,-0.229091
+-0.409091,0.272727,0.0
+-0.229091,0.545455,-0.409091
+-0.409091,0.545455,-0.229091
+-0.409091,0.545455,0.0
+-0.272727,0.0454545,0.152727
+-0.152727,0.0454545,0.272727
+0.0,0.0454545,0.272727
+-0.409091,0.272727,0.229091
+-0.229091,0.272727,0.409091
+0.0,0.272727,0.409091
+-0.409091,0.545455,0.229091
+-0.229091,0.545455,0.409091
+0.0,0.545455,0.409091
+0.152727,0.0454545,0.272727
+0.272727,0.0454545,0.152727
+0.229091,0.272727,0.409091
+0.409091,0.272727,0.229091
+0.229091,0.545455,0.409091
+0.409091,0.545455,0.229091
+-0.454545,0.704545,0.0
+-0.454545,0.704545,-0.0454545
+-0.454545,0.772727,-0.0454545
+-0.772727,0.863636,0.0
+-0.772727,0.863636,-0.0454545
+-0.818182,0.954545,-0.0454545
+-0.818182,0.954545,0.0
+-0.772727,0.522727,0.0
+-0.772727,0.522727,-0.0454545
+-0.909091,0.477273,-0.0454545
+-0.909091,0.477273,0.0
+-0.409091,0.363636,0.0
+-0.409091,0.363636,-0.0454545
+-0.409091,0.295455,-0.0454545
+-0.409091,0.295455,0.0
+-0.454545,0.772727,0.0454545
+-0.454545,0.704545,0.0454545
+-0.818182,0.954545,0.0454545
+-0.772727,0.863636,0.0454545
+-0.909091,0.477273,0.0454545
+-0.772727,0.522727,0.0454545
+-0.409091,0.295455,0.0454545
+-0.409091,0.363636,0.0454545
+# reverse-patches
diff --git a/demos/teaservice/teaservice.cpp b/demos/teaservice/teaservice.cpp
new file mode 100644
index 000000000..8923fb3ae
--- /dev/null
+++ b/demos/teaservice/teaservice.cpp
@@ -0,0 +1,379 @@
+/****************************************************************************
+**
+** 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 QtQuick3D 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 <QMainWindow>
+#include <QMenu>
+#include <QMenuBar>
+#include <QKeyEvent>
+#include <QAction>
+#include <QDebug>
+#include "qglview.h"
+#include "meshobject.h"
+#include "sceneobject.h"
+#include "qglteapot.h"
+#include "qglbuilder.h"
+#include "perpixeleffect.h"
+
+enum {
+ ObjTeapot,
+ ObjTeacup1,
+ ObjTeacup2,
+ ObjTeaspoon1,
+ ObjTeaspoon2
+};
+
+class Teapot : public MeshObject
+{
+ Q_OBJECT
+public:
+ Teapot(QObject *parent=0);
+ ~Teapot() {}
+};
+
+static QGLSceneNode *createTeapot(QObject *parent)
+{
+ QGLBuilder builder;
+ builder << QGLTeapot();
+ QGLSceneNode *n = builder.finalizedSceneNode();
+ n->setParent(parent);
+ return n;
+}
+
+Teapot::Teapot(QObject *parent)
+ : MeshObject(createTeapot(parent), parent)
+{
+}
+
+class Teacup : public MeshObject
+{
+ Q_OBJECT
+public:
+ Teacup(QObject *parent=0);
+ ~Teacup() {}
+};
+
+static QGLAbstractScene *loadBezier(const QString& fileName)
+{
+ QGLAbstractScene *scene;
+ scene = QGLAbstractScene::loadScene(fileName, QLatin1String("bezier"));
+ if (!scene)
+ qFatal("Could not load %s, probably plugin could not be found",
+ fileName.toLatin1().constData());
+ return scene;
+}
+
+Teacup::Teacup(QObject *parent)
+ : MeshObject(loadBezier(QLatin1String(":/teacup.txt")), parent)
+{
+}
+
+class Teaspoon : public MeshObject
+{
+ Q_OBJECT
+public:
+ Teaspoon(QObject *parent=0);
+ ~Teaspoon() {}
+};
+
+Teaspoon::Teaspoon(QObject *parent)
+ : MeshObject(loadBezier(QLatin1String(":/teaspoon.txt")), parent)
+{
+}
+
+class TeaService : public QObject
+{
+ Q_OBJECT
+public:
+ TeaService(QObject *parent=0);
+ ~TeaService();
+
+ SceneObject *service;
+
+ Teapot *teapot;
+ Teacup *teacup1;
+ Teacup *teacup2;
+ Teaspoon *teaspoon1;
+ Teaspoon *teaspoon2;
+ PerPixelEffect *lighting;
+
+ void changeMaterials(bool perPixel);
+
+signals:
+ void changed();
+
+private slots:
+ void teapotClicked();
+ void teacup1Clicked();
+ void teacup2Clicked();
+ void teaspoon1Clicked();
+ void teaspoon2Clicked();
+
+private:
+ QGLMaterial *china;
+ QGLMaterial *chinaHighlight;
+ QGLMaterial *metal;
+ QGLMaterial *metalHighlight;
+};
+
+TeaService::TeaService(QObject *parent)
+ : QObject(parent)
+{
+ china = new QGLMaterial(this);
+ china->setAmbientColor(QColor(192, 150, 128));
+ china->setSpecularColor(QColor(60, 60, 60));
+ china->setShininess(128);
+
+ chinaHighlight = new QGLMaterial(this);
+ chinaHighlight->setAmbientColor(QColor(255, 192, 0));
+ chinaHighlight->setSpecularColor(QColor(60, 60, 0));
+ chinaHighlight->setShininess(128);
+
+ metal = new QGLMaterial(this);
+ metal->setAmbientColor(QColor(255, 255, 255));
+ metal->setDiffuseColor(QColor(150, 150, 150));
+ metal->setSpecularColor(QColor(255, 255, 255));
+ metal->setShininess(128);
+
+ metalHighlight = new QGLMaterial(this);
+ metalHighlight->setAmbientColor(QColor(255, 255, 96));
+ metalHighlight->setDiffuseColor(QColor(150, 150, 96));
+ metalHighlight->setSpecularColor(QColor(255, 255, 255));
+ metalHighlight->setShininess(128);
+
+ service = new SceneObject(this);
+ teapot = new Teapot(service);
+ teacup1 = new Teacup(service);
+ teacup2 = new Teacup(service);
+ teacup1->setPosition(QVector3D(-2.3f, -0.75f, 0.0f));
+ teacup2->setRotationAngle(180);
+ teacup2->setRotationVector(QVector3D(0, 1, 0));
+ teacup2->setPosition(QVector3D(2.3f, -0.75f, 0.0f));
+ teaspoon1 = new Teaspoon(service);
+ teaspoon2 = new Teaspoon(service);
+ teaspoon1->setRotationAngle(275);
+ teaspoon1->setRotationVector(QVector3D(1, 0, 0));
+ teaspoon1->setPosition(QVector3D(-1.7f, -0.58f, 0.0f));
+ teaspoon2->setRotationAngle(275);
+ teaspoon2->setRotationVector(QVector3D(1, 0, 0));
+ teaspoon2->setPosition(QVector3D(1.7f, -0.58f, 0.0f));
+
+ teapot->setObjectId(ObjTeapot);
+ teacup1->setObjectId(ObjTeacup1);
+ teacup2->setObjectId(ObjTeacup2);
+ teaspoon1->setObjectId(ObjTeaspoon1);
+ teaspoon2->setObjectId(ObjTeaspoon2);
+
+ lighting = new PerPixelEffect();
+ changeMaterials(false);
+
+ connect(teapot, SIGNAL(hoverChanged()), this, SIGNAL(changed()));
+ connect(teacup1, SIGNAL(hoverChanged()), this, SIGNAL(changed()));
+ connect(teacup2, SIGNAL(hoverChanged()), this, SIGNAL(changed()));
+ connect(teaspoon1, SIGNAL(hoverChanged()), this, SIGNAL(changed()));
+ connect(teaspoon2, SIGNAL(hoverChanged()), this, SIGNAL(changed()));
+
+ connect(teapot, SIGNAL(clicked()), this, SLOT(teapotClicked()));
+ connect(teacup1, SIGNAL(clicked()), this, SLOT(teacup1Clicked()));
+ connect(teacup2, SIGNAL(clicked()), this, SLOT(teacup2Clicked()));
+ connect(teaspoon1, SIGNAL(clicked()), this, SLOT(teaspoon1Clicked()));
+ connect(teaspoon2, SIGNAL(clicked()), this, SLOT(teaspoon2Clicked()));
+}
+
+TeaService::~TeaService()
+{
+ delete lighting;
+}
+
+void TeaService::changeMaterials(bool perPixel)
+{
+ teapot->setMaterial(china);
+ teapot->setHoverMaterial(chinaHighlight);
+ teacup1->setMaterial(china);
+ teacup1->setHoverMaterial(chinaHighlight);
+ teacup2->setMaterial(china);
+ teacup2->setHoverMaterial(chinaHighlight);
+ if (perPixel) {
+ teapot->setEffect(lighting);
+ teacup1->setEffect(lighting);
+ teacup2->setEffect(lighting);
+ } else
+ {
+ teapot->setEffect(0);
+ teacup1->setEffect(0);
+ teacup2->setEffect(0);
+ }
+
+ teaspoon1->setMaterial(metal);
+ teaspoon1->setHoverMaterial(metalHighlight);
+ teaspoon2->setMaterial(metal);
+ teaspoon2->setHoverMaterial(metalHighlight);
+ if (perPixel) {
+ teaspoon1->setEffect(lighting);
+ teaspoon2->setEffect(lighting);
+ } else
+ {
+ teaspoon1->setEffect(0);
+ teaspoon2->setEffect(0);
+ }
+}
+
+void TeaService::teapotClicked()
+{
+ qDebug("teapot clicked");
+}
+
+void TeaService::teacup1Clicked()
+{
+ qDebug("teacup1 clicked");
+}
+
+void TeaService::teacup2Clicked()
+{
+ qDebug("teacup2 clicked");
+}
+
+void TeaService::teaspoon1Clicked()
+{
+ qDebug("teaspoon1 clicked");
+}
+
+void TeaService::teaspoon2Clicked()
+{
+ qDebug("teaspoon2 clicked");
+}
+
+class TeaServiceView : public QGLView
+{
+ Q_OBJECT
+public:
+ TeaServiceView(QWidget *parent=0);
+
+public slots:
+ void standardLighting();
+ void perPixelLighting();
+
+protected:
+ void initializeGL(QGLPainter *painter);
+ void paintGL(QGLPainter *painter);
+ void keyPressEvent(QKeyEvent *e);
+
+private:
+ TeaService *teaService;
+};
+
+TeaServiceView::TeaServiceView(QWidget *parent)
+ : QGLView(parent)
+{
+ teaService = new TeaService(this);
+
+ setOption(QGLView::ObjectPicking, true);
+
+ connect(teaService, SIGNAL(changed()), this, SLOT(updateGL()));
+}
+
+void TeaServiceView::initializeGL(QGLPainter *painter)
+{
+ teaService->service->initialize(this, painter);
+}
+
+void TeaServiceView::paintGL(QGLPainter *painter)
+{
+ teaService->service->draw(painter);
+}
+
+void TeaServiceView::standardLighting()
+{
+ teaService->changeMaterials(false);
+ updateGL();
+}
+
+void TeaServiceView::perPixelLighting()
+{
+ teaService->changeMaterials(true);
+ updateGL();
+}
+
+void TeaServiceView::keyPressEvent(QKeyEvent *e)
+{
+ if (e->key() == Qt::Key_Tab) {
+ // The Tab key turns the ShowPicking option on and off,
+ // which helps show what the pick buffer looks like.
+ setOption(QGLView::ShowPicking, ((options() & QGLView::ShowPicking) == 0));
+ updateGL();
+ }
+ QGLView::keyPressEvent(e);
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+ QMainWindow mainw;
+ mainw.setMinimumSize(850, 480);
+ mainw.setWindowTitle(QLatin1String("Tea Service"));
+
+ TeaServiceView view;
+ mainw.setCentralWidget(&view);
+ view.setFocus();
+
+ view.camera()->setEye(QVector3D(0, 3, 10));
+
+ QMenu *menu = mainw.menuBar()->addMenu(QLatin1String("Effects"));
+
+ QAction *standardLighting = new QAction(QLatin1String("Standard lighting"), &mainw);
+ menu->addAction(standardLighting);
+ QObject::connect(standardLighting, SIGNAL(triggered()), &view, SLOT(standardLighting()));
+
+ QAction *perPixelLighting = new QAction(QLatin1String("Per-pixel lighting"), &mainw);
+ menu->addAction(perPixelLighting);
+ QObject::connect(perPixelLighting, SIGNAL(triggered()), &view, SLOT(perPixelLighting()));
+
+ menu->addSeparator();
+
+ QAction *exitAction = new QAction(QLatin1String("E&xit"), &mainw);
+ menu->addAction(exitAction);
+ QObject::connect(exitAction, SIGNAL(triggered()), &app, SLOT(quit()));
+
+ mainw.show();
+ return app.exec();
+}
+
+#include "teaservice.moc"
diff --git a/demos/teaservice/teaservice.pro b/demos/teaservice/teaservice.pro
new file mode 100644
index 000000000..e08325de1
--- /dev/null
+++ b/demos/teaservice/teaservice.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+TARGET = teaservice
+CONFIG += qt warn_on qt3d
+SOURCES = teaservice.cpp meshobject.cpp sceneobject.cpp perpixeleffect.cpp
+HEADERS = meshobject.h sceneobject.h perpixeleffect.h
+RESOURCES = teaservice.qrc
+DESTDIR = ../../bin
diff --git a/demos/teaservice/teaservice.qrc b/demos/teaservice/teaservice.qrc
new file mode 100644
index 000000000..ab55d88c0
--- /dev/null
+++ b/demos/teaservice/teaservice.qrc
@@ -0,0 +1,8 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>per_pixel_lighting.vsh</file>
+ <file>per_pixel_lighting.fsh</file>
+ <file>teacup.txt</file>
+ <file>teaspoon.txt</file>
+</qresource>
+</RCC>
diff --git a/demos/teaservice/teaspoon.txt b/demos/teaservice/teaspoon.txt
new file mode 100644
index 000000000..3c6a1b74b
--- /dev/null
+++ b/demos/teaservice/teaspoon.txt
@@ -0,0 +1,275 @@
+16
+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
+17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32
+33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48
+49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64
+65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80
+81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96
+97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112
+113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128
+129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144
+145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160
+161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176
+177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192
+193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208
+209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224
+225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240
+241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256
+256
+-0.000107143,0.205357,0.0
+0.0,0.196429,-0.0178571
+0.0,0.196429,-0.0178571
+0.000107143,0.205357,0.0
+-0.0535714,0.205357,0.0
+-0.0222714,0.178571,-0.0534286
+0.0222714,0.178571,-0.0534286
+0.0535714,0.205357,0.0
+-0.107143,0.0952429,-0.0178571
+-0.0446429,0.0952429,-0.0892857
+0.0446429,0.0952429,-0.0892857
+0.107143,0.0952429,-0.0178571
+-0.107143,0.0,-0.0178571
+-0.0446429,0.0,-0.0892857
+0.0446429,0.0,-0.0892857
+0.107143,0.0,-0.0178571
+0.000107143,0.205357,0.0
+0.000135714,0.207589,0.00446429
+0.000157143,0.216518,0.00446429
+0.000125,0.214286,0.0
+0.0535714,0.205357,0.0
+0.0613964,0.212054,0.0133571
+0.0714286,0.220982,0.015625
+0.0625,0.214286,0.0
+0.107143,0.0952429,-0.0178571
+0.122768,0.0952429,0.0
+0.142857,0.0952429,0.00446429
+0.125,0.0952429,-0.0178571
+0.107143,0.0,-0.0178571
+0.122768,0.0,0.0
+0.142857,0.0,0.00446429
+0.125,0.0,-0.0178571
+0.000125,0.214286,0.0
+0.0,0.205357,-0.0178571
+0.0,0.205357,-0.0178571
+-0.000125,0.214286,0.0
+0.0625,0.214286,0.0
+0.0267857,0.1875,-0.0625
+-0.0267857,0.1875,-0.0625
+-0.0625,0.214286,0.0
+0.125,0.0952429,-0.0178571
+0.0535714,0.0952429,-0.107143
+-0.0535714,0.0952429,-0.107143
+-0.125,0.0952429,-0.0178571
+0.125,0.0,-0.0178571
+0.0535714,0.0,-0.107143
+-0.0535714,0.0,-0.107143
+-0.125,0.0,-0.0178571
+-0.000125,0.214286,0.0
+-0.000157143,0.216518,0.00446429
+-0.000135714,0.207589,0.00446429
+-0.000107143,0.205357,0.0
+-0.0625,0.214286,0.0
+-0.0714286,0.220982,0.015625
+-0.0613964,0.212054,0.0133571
+-0.0535714,0.205357,0.0
+-0.125,0.0952429,-0.0178571
+-0.142857,0.0952429,0.00446429
+-0.122768,0.0952429,0.0
+-0.107143,0.0952429,-0.0178571
+-0.125,0.0,-0.0178571
+-0.142857,0.0,0.00446429
+-0.122768,0.0,0.0
+-0.107143,0.0,-0.0178571
+-0.107143,0.0,-0.0178571
+-0.0446429,0.0,-0.0892857
+0.0446429,0.0,-0.0892857
+0.107143,0.0,-0.0178571
+-0.107143,-0.142857,-0.0178571
+-0.0446429,-0.142857,-0.0892857
+0.0446429,-0.142857,-0.0892857
+0.107143,-0.142857,-0.0178571
+-0.0133929,-0.160714,0.0386893
+-0.00557857,-0.160714,0.0386893
+0.00557857,-0.160714,0.0386893
+0.0133929,-0.160714,0.0386893
+-0.0133929,-0.25,0.0535714
+-0.00557857,-0.25,0.0535714
+0.00557857,-0.25,0.0535714
+0.0133929,-0.25,0.0535714
+0.107143,0.0,-0.0178571
+0.122768,0.0,0.0
+0.142857,0.0,0.00446429
+0.125,0.0,-0.0178571
+0.107143,-0.142857,-0.0178571
+0.122768,-0.142857,0.0
+0.142857,-0.142857,0.00446429
+0.125,-0.142857,-0.0178571
+0.0133929,-0.160714,0.0386893
+0.0153464,-0.160714,0.0386893
+0.0178571,-0.160714,0.0314357
+0.015625,-0.160714,0.0297607
+0.0133929,-0.25,0.0535714
+0.0153464,-0.25,0.0535714
+0.0178571,-0.25,0.0463179
+0.015625,-0.25,0.0446429
+0.125,0.0,-0.0178571
+0.0535714,0.0,-0.107143
+-0.0535714,0.0,-0.107143
+-0.125,0.0,-0.0178571
+0.125,-0.142857,-0.0178571
+0.0535714,-0.142857,-0.107143
+-0.0535714,-0.142857,-0.107143
+-0.125,-0.142857,-0.0178571
+0.015625,-0.160714,0.0297607
+0.00669643,-0.160714,0.0230643
+-0.00781071,-0.160714,0.0208321
+-0.015625,-0.160714,0.0297607
+0.015625,-0.25,0.0446429
+0.00669643,-0.25,0.0379464
+-0.00781071,-0.25,0.0357143
+-0.015625,-0.25,0.0446429
+-0.125,0.0,-0.0178571
+-0.142857,0.0,0.00446429
+-0.122768,0.0,0.0
+-0.107143,0.0,-0.0178571
+-0.125,-0.142857,-0.0178571
+-0.142857,-0.142857,0.00446429
+-0.122768,-0.142857,0.0
+-0.107143,-0.142857,-0.0178571
+-0.015625,-0.160714,0.0297607
+-0.0175786,-0.160714,0.0319929
+-0.0153464,-0.160714,0.0386893
+-0.0133929,-0.160714,0.0386893
+-0.015625,-0.25,0.0446429
+-0.0175786,-0.25,0.046875
+-0.0153464,-0.25,0.0535714
+-0.0133929,-0.25,0.0535714
+-0.0133929,-0.25,0.0535714
+-0.00557857,-0.25,0.0535714
+0.00557857,-0.25,0.0535714
+0.0133929,-0.25,0.0535714
+-0.0133929,-0.46425,0.0892857
+-0.00557857,-0.46425,0.0892857
+0.00557857,-0.46425,0.0892857
+0.0133929,-0.46425,0.0892857
+-0.0446429,-0.678571,0.0535714
+-0.00892857,-0.678571,0.0625
+0.00892857,-0.678571,0.0625
+0.0446429,-0.678571,0.0535714
+-0.0446429,-0.857143,0.0357143
+-0.00892857,-0.857143,0.0446429
+0.00892857,-0.857143,0.0446429
+0.0446429,-0.857143,0.0357143
+0.0133929,-0.25,0.0535714
+0.0153464,-0.25,0.0535714
+0.0178571,-0.25,0.0463179
+0.015625,-0.25,0.0446429
+0.0133929,-0.46425,0.0892857
+0.0153464,-0.464286,0.0892857
+0.0178571,-0.46425,0.0820321
+0.015625,-0.46425,0.0803571
+0.0446429,-0.678571,0.0535714
+0.0535714,-0.678571,0.0513393
+0.0535714,-0.678571,0.0334821
+0.0446429,-0.678571,0.0357143
+0.0446429,-0.857143,0.0357143
+0.0535714,-0.857143,0.0334821
+0.0535714,-0.857143,0.015625
+0.0446429,-0.857143,0.0178571
+0.015625,-0.25,0.0446429
+0.00669643,-0.25,0.0379464
+-0.00781071,-0.25,0.0357143
+-0.015625,-0.25,0.0446429
+0.015625,-0.46425,0.0803571
+0.00669643,-0.464286,0.0736607
+-0.00781071,-0.46425,0.0714286
+-0.015625,-0.46425,0.0803571
+0.0446429,-0.678571,0.0357143
+0.00892857,-0.678571,0.0446429
+-0.00892857,-0.678571,0.0446429
+-0.0446429,-0.678571,0.0357143
+0.0446429,-0.857143,0.0178571
+0.00892857,-0.857143,0.0267857
+-0.00892857,-0.857143,0.0267857
+-0.0446429,-0.857143,0.0178571
+-0.015625,-0.25,0.0446429
+-0.0175786,-0.25,0.046875
+-0.0153464,-0.25,0.0535714
+-0.0133929,-0.25,0.0535714
+-0.015625,-0.46425,0.0803571
+-0.0175786,-0.464286,0.0825893
+-0.0153464,-0.464286,0.0892857
+-0.0133929,-0.46425,0.0892857
+-0.0446429,-0.678571,0.0357143
+-0.0535714,-0.678571,0.0334821
+-0.0535714,-0.678571,0.0513393
+-0.0446429,-0.678571,0.0535714
+-0.0446429,-0.857143,0.0178571
+-0.0535714,-0.857143,0.015625
+-0.0535714,-0.857143,0.0334821
+-0.0446429,-0.857143,0.0357143
+-0.0446429,-0.857143,0.0357143
+-0.00892857,-0.857143,0.0446429
+0.00892857,-0.857143,0.0446429
+0.0446429,-0.857143,0.0357143
+-0.0446429,-0.928571,0.0285714
+-0.00892857,-0.928571,0.0375
+0.00892857,-0.928571,0.0375
+0.0446429,-0.928571,0.0285714
+-0.0539286,-0.999643,0.0178571
+0.000357143,-0.999643,0.0178571
+0.0,-0.999643,0.0178571
+0.0535714,-0.999643,0.0178571
+-0.000357143,-1,0.0178571
+0.000357143,-1,0.0178571
+0.0,-1,0.0178571
+0.0,-1,0.0178571
+0.0446429,-0.857143,0.0357143
+0.0535714,-0.857143,0.0334821
+0.0535714,-0.857143,0.015625
+0.0446429,-0.857143,0.0178571
+0.0446429,-0.928571,0.0285714
+0.0535714,-0.928571,0.0263393
+0.0535714,-0.928571,0.00848214
+0.0446429,-0.928571,0.0107143
+0.0535714,-0.999643,0.0178571
+0.0669643,-0.999643,0.0178571
+0.0673214,-0.999643,0.0
+0.0539286,-0.999643,0.0
+0.0,-1,0.0178571
+0.0,-1,0.0178571
+0.000357143,-1,0.0
+0.000357143,-1,0.0
+0.0446429,-0.857143,0.0178571
+0.00892857,-0.857143,0.0267857
+-0.00892857,-0.857143,0.0267857
+-0.0446429,-0.857143,0.0178571
+0.0446429,-0.928571,0.0107143
+0.00892857,-0.928571,0.0196429
+-0.00892857,-0.928571,0.0196429
+-0.0446429,-0.928571,0.0107143
+0.0539286,-0.999643,0.0
+0.000357143,-0.999643,0.0
+-0.000357143,-0.999643,0.0
+-0.0539286,-0.999643,0.0
+0.000357143,-1,0.0
+0.000357143,-1,0.0
+-0.000357143,-1,0.0
+-0.000357143,-1,0.0
+-0.0446429,-0.857143,0.0178571
+-0.0535714,-0.857143,0.015625
+-0.0535714,-0.857143,0.0334821
+-0.0446429,-0.857143,0.0357143
+-0.0446429,-0.928571,0.0107143
+-0.0535714,-0.928571,0.00848214
+-0.0535714,-0.928571,0.0263393
+-0.0446429,-0.928571,0.0285714
+-0.0539286,-0.999643,0.0
+-0.0673214,-0.999643,0.0
+-0.0675,-0.999643,0.0178571
+-0.0539286,-0.999643,0.0178571
+-0.000357143,-1,0.0
+-0.000357143,-1,0.0
+-0.000535714,-1,0.0178571
+-0.000357143,-1,0.0178571
+# reverse-patches