From e0d5221957bf0d7857f924f1f2ae63d490de0a0a Mon Sep 17 00:00:00 2001 From: Casper van Donderen Date: Wed, 22 Jun 2011 13:54:56 +0200 Subject: Move all other demos in qtbase to examples. Change-Id: Iab0e7364d1f6b348d0e3033ea9304139f5bd6d0d Reviewed-on: http://codereview.qt.nokia.com/617 Reviewed-by: Qt Sanity Bot Reviewed-by: David Boddie --- examples/graphicsview/boxes/3rdparty/fbm.c | 207 ++++ examples/graphicsview/boxes/3rdparty/fbm.h | 40 + examples/graphicsview/boxes/basic.fsh | 73 ++ examples/graphicsview/boxes/basic.vsh | 61 ++ examples/graphicsview/boxes/boxes.pro | 49 + examples/graphicsview/boxes/boxes.qrc | 25 + examples/graphicsview/boxes/cubemap_negx.jpg | Bin 0 -> 41060 bytes examples/graphicsview/boxes/cubemap_negy.jpg | Bin 0 -> 15520 bytes examples/graphicsview/boxes/cubemap_negz.jpg | Bin 0 -> 68911 bytes examples/graphicsview/boxes/cubemap_posx.jpg | Bin 0 -> 74915 bytes examples/graphicsview/boxes/cubemap_posy.jpg | Bin 0 -> 24193 bytes examples/graphicsview/boxes/cubemap_posz.jpg | Bin 0 -> 57881 bytes examples/graphicsview/boxes/dotted.fsh | 66 ++ examples/graphicsview/boxes/fresnel.fsh | 79 ++ examples/graphicsview/boxes/glass.fsh | 76 ++ examples/graphicsview/boxes/glbuffers.cpp | 402 ++++++++ examples/graphicsview/boxes/glbuffers.h | 366 +++++++ examples/graphicsview/boxes/glextensions.cpp | 98 ++ examples/graphicsview/boxes/glextensions.h | 202 ++++ examples/graphicsview/boxes/gltrianglemesh.h | 91 ++ examples/graphicsview/boxes/granite.fsh | 76 ++ examples/graphicsview/boxes/main.cpp | 150 +++ examples/graphicsview/boxes/marble.fsh | 71 ++ examples/graphicsview/boxes/parameters.par | 5 + examples/graphicsview/boxes/qt-logo.jpg | Bin 0 -> 40886 bytes examples/graphicsview/boxes/qt-logo.png | Bin 0 -> 13923 bytes examples/graphicsview/boxes/qtbox.cpp | 480 +++++++++ examples/graphicsview/boxes/qtbox.h | 118 +++ examples/graphicsview/boxes/reflection.fsh | 54 + examples/graphicsview/boxes/refraction.fsh | 70 ++ examples/graphicsview/boxes/roundedbox.cpp | 161 +++ examples/graphicsview/boxes/roundedbox.h | 72 ++ examples/graphicsview/boxes/scene.cpp | 1085 ++++++++++++++++++++ examples/graphicsview/boxes/scene.h | 245 +++++ examples/graphicsview/boxes/smiley.png | Bin 0 -> 14508 bytes examples/graphicsview/boxes/square.jpg | Bin 0 -> 14542 bytes examples/graphicsview/boxes/trackball.cpp | 160 +++ examples/graphicsview/boxes/trackball.h | 79 ++ examples/graphicsview/boxes/wood.fsh | 70 ++ examples/graphicsview/chip/chip.cpp | 183 ++++ examples/graphicsview/chip/chip.h | 68 ++ examples/graphicsview/chip/chip.pro | 20 + examples/graphicsview/chip/fileprint.png | Bin 0 -> 1456 bytes examples/graphicsview/chip/images.qrc | 10 + examples/graphicsview/chip/main.cpp | 57 + examples/graphicsview/chip/mainwindow.cpp | 109 ++ examples/graphicsview/chip/mainwindow.h | 68 ++ examples/graphicsview/chip/qt4logo.png | Bin 0 -> 48333 bytes examples/graphicsview/chip/rotateleft.png | Bin 0 -> 1754 bytes examples/graphicsview/chip/rotateright.png | Bin 0 -> 1732 bytes examples/graphicsview/chip/view.cpp | 276 +++++ examples/graphicsview/chip/view.h | 104 ++ examples/graphicsview/chip/zoomin.png | Bin 0 -> 1622 bytes examples/graphicsview/chip/zoomout.png | Bin 0 -> 1601 bytes .../embeddeddialogs/No-Ones-Laughing-3.jpg | Bin 0 -> 30730 bytes .../graphicsview/embeddeddialogs/customproxy.cpp | 167 +++ .../graphicsview/embeddeddialogs/customproxy.h | 76 ++ .../embeddeddialogs/embeddeddialog.cpp | 106 ++ .../graphicsview/embeddeddialogs/embeddeddialog.h | 66 ++ .../graphicsview/embeddeddialogs/embeddeddialog.ui | 87 ++ .../embeddeddialogs/embeddeddialogs.pro | 19 + .../embeddeddialogs/embeddeddialogs.qrc | 5 + examples/graphicsview/embeddeddialogs/main.cpp | 83 ++ 63 files changed, 6235 insertions(+) create mode 100644 examples/graphicsview/boxes/3rdparty/fbm.c create mode 100644 examples/graphicsview/boxes/3rdparty/fbm.h create mode 100644 examples/graphicsview/boxes/basic.fsh create mode 100644 examples/graphicsview/boxes/basic.vsh create mode 100644 examples/graphicsview/boxes/boxes.pro create mode 100644 examples/graphicsview/boxes/boxes.qrc create mode 100644 examples/graphicsview/boxes/cubemap_negx.jpg create mode 100644 examples/graphicsview/boxes/cubemap_negy.jpg create mode 100644 examples/graphicsview/boxes/cubemap_negz.jpg create mode 100644 examples/graphicsview/boxes/cubemap_posx.jpg create mode 100644 examples/graphicsview/boxes/cubemap_posy.jpg create mode 100644 examples/graphicsview/boxes/cubemap_posz.jpg create mode 100644 examples/graphicsview/boxes/dotted.fsh create mode 100644 examples/graphicsview/boxes/fresnel.fsh create mode 100644 examples/graphicsview/boxes/glass.fsh create mode 100644 examples/graphicsview/boxes/glbuffers.cpp create mode 100644 examples/graphicsview/boxes/glbuffers.h create mode 100644 examples/graphicsview/boxes/glextensions.cpp create mode 100644 examples/graphicsview/boxes/glextensions.h create mode 100644 examples/graphicsview/boxes/gltrianglemesh.h create mode 100644 examples/graphicsview/boxes/granite.fsh create mode 100644 examples/graphicsview/boxes/main.cpp create mode 100644 examples/graphicsview/boxes/marble.fsh create mode 100644 examples/graphicsview/boxes/parameters.par create mode 100644 examples/graphicsview/boxes/qt-logo.jpg create mode 100644 examples/graphicsview/boxes/qt-logo.png create mode 100644 examples/graphicsview/boxes/qtbox.cpp create mode 100644 examples/graphicsview/boxes/qtbox.h create mode 100644 examples/graphicsview/boxes/reflection.fsh create mode 100644 examples/graphicsview/boxes/refraction.fsh create mode 100644 examples/graphicsview/boxes/roundedbox.cpp create mode 100644 examples/graphicsview/boxes/roundedbox.h create mode 100644 examples/graphicsview/boxes/scene.cpp create mode 100644 examples/graphicsview/boxes/scene.h create mode 100644 examples/graphicsview/boxes/smiley.png create mode 100644 examples/graphicsview/boxes/square.jpg create mode 100644 examples/graphicsview/boxes/trackball.cpp create mode 100644 examples/graphicsview/boxes/trackball.h create mode 100644 examples/graphicsview/boxes/wood.fsh create mode 100644 examples/graphicsview/chip/chip.cpp create mode 100644 examples/graphicsview/chip/chip.h create mode 100644 examples/graphicsview/chip/chip.pro create mode 100644 examples/graphicsview/chip/fileprint.png create mode 100644 examples/graphicsview/chip/images.qrc create mode 100644 examples/graphicsview/chip/main.cpp create mode 100644 examples/graphicsview/chip/mainwindow.cpp create mode 100644 examples/graphicsview/chip/mainwindow.h create mode 100644 examples/graphicsview/chip/qt4logo.png create mode 100644 examples/graphicsview/chip/rotateleft.png create mode 100644 examples/graphicsview/chip/rotateright.png create mode 100644 examples/graphicsview/chip/view.cpp create mode 100644 examples/graphicsview/chip/view.h create mode 100644 examples/graphicsview/chip/zoomin.png create mode 100644 examples/graphicsview/chip/zoomout.png create mode 100644 examples/graphicsview/embeddeddialogs/No-Ones-Laughing-3.jpg create mode 100644 examples/graphicsview/embeddeddialogs/customproxy.cpp create mode 100644 examples/graphicsview/embeddeddialogs/customproxy.h create mode 100644 examples/graphicsview/embeddeddialogs/embeddeddialog.cpp create mode 100644 examples/graphicsview/embeddeddialogs/embeddeddialog.h create mode 100644 examples/graphicsview/embeddeddialogs/embeddeddialog.ui create mode 100644 examples/graphicsview/embeddeddialogs/embeddeddialogs.pro create mode 100644 examples/graphicsview/embeddeddialogs/embeddeddialogs.qrc create mode 100644 examples/graphicsview/embeddeddialogs/main.cpp (limited to 'examples/graphicsview') diff --git a/examples/graphicsview/boxes/3rdparty/fbm.c b/examples/graphicsview/boxes/3rdparty/fbm.c new file mode 100644 index 0000000000..98eb87a33b --- /dev/null +++ b/examples/graphicsview/boxes/3rdparty/fbm.c @@ -0,0 +1,207 @@ +/***************************************************************** + + Implementation of the fractional Brownian motion algorithm. These + functions were originally the work of F. Kenton Musgrave. + For documentation of the different functions please refer to the + book: + "Texturing and modeling: a procedural approach" + by David S. Ebert et. al. + +******************************************************************/ + +#if defined (_MSC_VER) +#include +#endif + +#include +#include +#include "fbm.h" + +#if defined(Q_CC_MSVC) +#pragma warning(disable:4244) +#endif + +/* Definitions used by the noise2() functions */ + +//#define B 0x100 +//#define BM 0xff +#define B 0x20 +#define BM 0x1f + +#define N 0x1000 +#define NP 12 /* 2^N */ +#define NM 0xfff + +static int p[B + B + 2]; +static float g3[B + B + 2][3]; +static float g2[B + B + 2][2]; +static float g1[B + B + 2]; +static int start = 1; + +static void init(void); + +#define s_curve(t) ( t * t * (3. - 2. * t) ) + +#define lerp(t, a, b) ( a + t * (b - a) ) + +#define setup(i,b0,b1,r0,r1)\ + t = vec[i] + N;\ + b0 = ((int)t) & BM;\ + b1 = (b0+1) & BM;\ + r0 = t - (int)t;\ + r1 = r0 - 1.; +#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] ) + +/* Fractional Brownian Motion function */ + +double fBm( Vector point, double H, double lacunarity, double octaves, + int init ) +{ + + double value, frequency, remainder; + int i; + static double exponent_array[10]; + float vec[3]; + + /* precompute and store spectral weights */ + if ( init ) { + start = 1; + srand( time(0) ); + /* seize required memory for exponent_array */ + frequency = 1.0; + for (i=0; i<=octaves; i++) { + /* compute weight for each frequency */ + exponent_array[i] = pow( frequency, -H ); + frequency *= lacunarity; + } + } + + value = 0.0; /* initialize vars to proper values */ + frequency = 1.0; + vec[0]=point.x; + vec[1]=point.y; + vec[2]=point.z; + + + /* inner loop of spectral construction */ + for (i=0; i + +#ifdef __cplusplus +extern "C" { +#endif + +//#define TRUE 1 +//#define FALSE 0 + +typedef struct { + double x; + double y; + double z; +} Vector; + +float noise3(float vec[]); +double fBm( Vector point, double H, double lacunarity, double octaves, + int init ); +#endif + +#ifdef __cplusplus +} +#endif + + + + diff --git a/examples/graphicsview/boxes/basic.fsh b/examples/graphicsview/boxes/basic.fsh new file mode 100644 index 0000000000..faf3601606 --- /dev/null +++ b/examples/graphicsview/boxes/basic.fsh @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform vec4 basicColor; + +void main() +{ + vec3 N = normalize(normal); + // assume directional light + + gl_MaterialParameters M = gl_FrontMaterial; + + float NdotL = dot(N, lightDirection.xyz); + float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz); + + vec3 absN = abs(gl_TexCoord[1].xyz); + vec3 texCoord; + if (absN.x > absN.y && absN.x > absN.z) + texCoord = gl_TexCoord[1].yzx; + else if (absN.y > absN.z) + texCoord = gl_TexCoord[1].zxy; + else + texCoord = gl_TexCoord[1].xyz; + texCoord.y *= -sign(texCoord.z); + texCoord += 0.5; + + vec4 texColor = texture2D(tex, texCoord.xy); + vec4 unlitColor = gl_Color * mix(basicColor, vec4(texColor.xyz, 1.0), texColor.w); + gl_FragColor = (ambient + diffuse * max(NdotL, 0.0)) * unlitColor + + M.specular * specular * pow(max(RdotL, 0.0), M.shininess); +} diff --git a/examples/graphicsview/boxes/basic.vsh b/examples/graphicsview/boxes/basic.vsh new file mode 100644 index 0000000000..31acc4224a --- /dev/null +++ b/examples/graphicsview/boxes/basic.vsh @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform mat4 view; + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[1] = gl_Vertex; + specular = gl_LightSource[0].specular; + ambient = gl_LightSource[0].ambient; + diffuse = gl_LightSource[0].diffuse; + lightDirection = view * gl_LightSource[0].position; + + normal = gl_NormalMatrix * gl_Normal; + position = (gl_ModelViewMatrix * gl_Vertex).xyz; + + gl_FrontColor = gl_Color; + gl_Position = ftransform(); +} diff --git a/examples/graphicsview/boxes/boxes.pro b/examples/graphicsview/boxes/boxes.pro new file mode 100644 index 0000000000..d599a3a0ac --- /dev/null +++ b/examples/graphicsview/boxes/boxes.pro @@ -0,0 +1,49 @@ +###################################################################### +# Automatically generated by qmake (2.01a) ma 3. nov 17:33:30 2008 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +HEADERS += 3rdparty/fbm.h \ + glbuffers.h \ + glextensions.h \ + gltrianglemesh.h \ + qtbox.h \ + roundedbox.h \ + scene.h \ + trackball.h +SOURCES += 3rdparty/fbm.c \ + glbuffers.cpp \ + glextensions.cpp \ + main.cpp \ + qtbox.cpp \ + roundedbox.cpp \ + scene.cpp \ + trackball.cpp + +RESOURCES += boxes.qrc + +QT += opengl + +# install +target.path = $$[QT_INSTALL_DEMOS]/qtbase/boxes +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro *.html *.jpg *.png *.fsh *.vsh *.par +sources.files -= 3rdparty/fbm.h 3rdparty/fbm.c +sources.files += 3rdparty +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/boxes +INSTALLS += target sources + +wince*: { + DEPLOYMENT_PLUGIN += qjpeg +} + +win32-msvc* { + QMAKE_CXXFLAGS -= -Zm200 + QMAKE_CFLAGS -= -Zm200 + QMAKE_CXXFLAGS += -Zm500 + QMAKE_CFLAGS += -Zm500 +} diff --git a/examples/graphicsview/boxes/boxes.qrc b/examples/graphicsview/boxes/boxes.qrc new file mode 100644 index 0000000000..d27506dc5a --- /dev/null +++ b/examples/graphicsview/boxes/boxes.qrc @@ -0,0 +1,25 @@ + + + cubemap_negx.jpg + cubemap_negy.jpg + cubemap_negz.jpg + cubemap_posx.jpg + cubemap_posy.jpg + cubemap_posz.jpg + square.jpg + basic.vsh + basic.fsh + dotted.fsh + fresnel.fsh + glass.fsh + granite.fsh + marble.fsh + reflection.fsh + refraction.fsh + wood.fsh + parameters.par + qt-logo.png + smiley.png + qt-logo.jpg + + diff --git a/examples/graphicsview/boxes/cubemap_negx.jpg b/examples/graphicsview/boxes/cubemap_negx.jpg new file mode 100644 index 0000000000..07c282eab9 Binary files /dev/null and b/examples/graphicsview/boxes/cubemap_negx.jpg differ diff --git a/examples/graphicsview/boxes/cubemap_negy.jpg b/examples/graphicsview/boxes/cubemap_negy.jpg new file mode 100644 index 0000000000..46cd2f9cf3 Binary files /dev/null and b/examples/graphicsview/boxes/cubemap_negy.jpg differ diff --git a/examples/graphicsview/boxes/cubemap_negz.jpg b/examples/graphicsview/boxes/cubemap_negz.jpg new file mode 100644 index 0000000000..40c01ddff3 Binary files /dev/null and b/examples/graphicsview/boxes/cubemap_negz.jpg differ diff --git a/examples/graphicsview/boxes/cubemap_posx.jpg b/examples/graphicsview/boxes/cubemap_posx.jpg new file mode 100644 index 0000000000..0b42e8a1b1 Binary files /dev/null and b/examples/graphicsview/boxes/cubemap_posx.jpg differ diff --git a/examples/graphicsview/boxes/cubemap_posy.jpg b/examples/graphicsview/boxes/cubemap_posy.jpg new file mode 100644 index 0000000000..2aca9b1e98 Binary files /dev/null and b/examples/graphicsview/boxes/cubemap_posy.jpg differ diff --git a/examples/graphicsview/boxes/cubemap_posz.jpg b/examples/graphicsview/boxes/cubemap_posz.jpg new file mode 100644 index 0000000000..2e49173848 Binary files /dev/null and b/examples/graphicsview/boxes/cubemap_posz.jpg differ diff --git a/examples/graphicsview/boxes/dotted.fsh b/examples/graphicsview/boxes/dotted.fsh new file mode 100644 index 0000000000..a9f1bcbefb --- /dev/null +++ b/examples/graphicsview/boxes/dotted.fsh @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; + +void main() +{ + vec3 N = normalize(normal); + + gl_MaterialParameters M = gl_FrontMaterial; + + // assume directional light + float NdotL = dot(N, lightDirection.xyz); + float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz); + + float r1 = length(fract(7.0 * gl_TexCoord[1].xyz) - 0.5); + float r2 = length(fract(5.0 * gl_TexCoord[1].xyz + 0.2) - 0.5); + float r3 = length(fract(11.0 * gl_TexCoord[1].xyz + 0.7) - 0.5); + vec4 rs = vec4(r1, r2, r3, 0.0); + + vec4 unlitColor = gl_Color * (0.8 - clamp(10.0 * (0.4 - rs), 0.0, 0.2)); + unlitColor.w = 1.0; + gl_FragColor = (ambient + diffuse * max(NdotL, 0.0)) * unlitColor + + M.specular * specular * pow(max(RdotL, 0.0), M.shininess); +} diff --git a/examples/graphicsview/boxes/fresnel.fsh b/examples/graphicsview/boxes/fresnel.fsh new file mode 100644 index 0000000000..462f9674f4 --- /dev/null +++ b/examples/graphicsview/boxes/fresnel.fsh @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform samplerCube env; +uniform mat4 view; +uniform vec4 basicColor; + +void main() +{ + vec3 N = normalize(normal); + // assume directional light + + gl_MaterialParameters M = gl_FrontMaterial; + + float NdotL = dot(N, lightDirection.xyz); + float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz); + + vec3 absN = abs(gl_TexCoord[1].xyz); + vec3 texCoord; + if (absN.x > absN.y && absN.x > absN.z) + texCoord = gl_TexCoord[1].yzx; + else if (absN.y > absN.z) + texCoord = gl_TexCoord[1].zxy; + else + texCoord = gl_TexCoord[1].xyz; + texCoord.y *= -sign(texCoord.z); + texCoord += 0.5; + + vec4 texColor = texture2D(tex, texCoord.xy); + vec4 unlitColor = gl_Color * mix(basicColor, vec4(texColor.xyz, 1.0), texColor.w); + vec4 litColor = (ambient + diffuse * max(NdotL, 0.0)) * unlitColor + + M.specular * specular * pow(max(RdotL, 0.0), M.shininess); + + vec3 R = 2.0 * dot(-position, N) * N + position; + vec4 reflectedColor = textureCube(env, R * mat3(view[0].xyz, view[1].xyz, view[2].xyz)); + gl_FragColor = mix(litColor, reflectedColor, 0.2 + 0.8 * pow(1.0 + dot(N, normalize(position)), 2.0)); +} diff --git a/examples/graphicsview/boxes/glass.fsh b/examples/graphicsview/boxes/glass.fsh new file mode 100644 index 0000000000..aeac2c2fed --- /dev/null +++ b/examples/graphicsview/boxes/glass.fsh @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform samplerCube env; +uniform mat4 view; + +// Some arbitrary values +// Arrays don't work here on glsl < 120, apparently. +//const float coeffs[6] = float[6](1.0/4.0, 1.0/4.1, 1.0/4.2, 1.0/4.3, 1.0/4.4, 1.0/4.5); +float coeffs(int i) +{ + return 1.0 / (3.0 + 0.1 * float(i)); +} + +void main() +{ + vec3 N = normalize(normal); + vec3 I = -normalize(position); + mat3 V = mat3(view[0].xyz, view[1].xyz, view[2].xyz); + float IdotN = dot(I, N); + float scales[6]; + vec3 C[6]; + for (int i = 0; i < 6; ++i) { + scales[i] = (IdotN - sqrt(1.0 - coeffs(i) + coeffs(i) * (IdotN * IdotN))); + C[i] = textureCube(env, (-I + coeffs(i) * N) * V).xyz; + } + vec4 refractedColor = 0.25 * vec4(C[5].x + 2.0*C[0].x + C[1].x, C[1].y + 2.0*C[2].y + C[3].y, + C[3].z + 2.0*C[4].z + C[5].z, 4.0); + + vec3 R = 2.0 * dot(-position, N) * N + position; + vec4 reflectedColor = textureCube(env, R * V); + + gl_FragColor = mix(refractedColor, reflectedColor, 0.4 + 0.6 * pow(1.0 - IdotN, 2.0)); +} diff --git a/examples/graphicsview/boxes/glbuffers.cpp b/examples/graphicsview/boxes/glbuffers.cpp new file mode 100644 index 0000000000..e12132b4cd --- /dev/null +++ b/examples/graphicsview/boxes/glbuffers.cpp @@ -0,0 +1,402 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "glbuffers.h" +#include + + +void qgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar) +{ + const GLdouble ymax = zNear * tan(fovy * M_PI / 360.0); + const GLdouble ymin = -ymax; + const GLdouble xmin = ymin * aspect; + const GLdouble xmax = ymax * aspect; + glFrustum(xmin, xmax, ymin, ymax, zNear, zFar); +} + +//============================================================================// +// GLTexture // +//============================================================================// + +GLTexture::GLTexture() : m_texture(0), m_failed(false) +{ + glGenTextures(1, &m_texture); +} + +GLTexture::~GLTexture() +{ + glDeleteTextures(1, &m_texture); +} + +//============================================================================// +// GLTexture2D // +//============================================================================// + +GLTexture2D::GLTexture2D(int width, int height) +{ + glBindTexture(GL_TEXTURE_2D, m_texture); + glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, + GL_BGRA, GL_UNSIGNED_BYTE, 0); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + //glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + glBindTexture(GL_TEXTURE_2D, 0); +} + + +GLTexture2D::GLTexture2D(const QString& fileName, int width, int height) +{ + // TODO: Add error handling. + QImage image(fileName); + + if (image.isNull()) { + m_failed = true; + return; + } + + image = image.convertToFormat(QImage::Format_ARGB32); + + //qDebug() << "Image size:" << image.width() << "x" << image.height(); + if (width <= 0) + width = image.width(); + if (height <= 0) + height = image.height(); + if (width != image.width() || height != image.height()) + image = image.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + + glBindTexture(GL_TEXTURE_2D, m_texture); + + // Works on x86, so probably works on all little-endian systems. + // Does it work on big-endian systems? + glTexImage2D(GL_TEXTURE_2D, 0, 4, image.width(), image.height(), 0, + GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + //glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + glBindTexture(GL_TEXTURE_2D, 0); +} + +void GLTexture2D::load(int width, int height, QRgb *data) +{ + glBindTexture(GL_TEXTURE_2D, m_texture); + glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, + GL_BGRA, GL_UNSIGNED_BYTE, data); + glBindTexture(GL_TEXTURE_2D, 0); +} + +void GLTexture2D::bind() +{ + glBindTexture(GL_TEXTURE_2D, m_texture); + glEnable(GL_TEXTURE_2D); +} + +void GLTexture2D::unbind() +{ + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); +} + + +//============================================================================// +// GLTexture3D // +//============================================================================// + +GLTexture3D::GLTexture3D(int width, int height, int depth) +{ + GLBUFFERS_ASSERT_OPENGL("GLTexture3D::GLTexture3D", glTexImage3D, return) + + glBindTexture(GL_TEXTURE_3D, m_texture); + glTexImage3D(GL_TEXTURE_3D, 0, 4, width, height, depth, 0, + GL_BGRA, GL_UNSIGNED_BYTE, 0); + + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_REPEAT); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + //glTexParameteri(GL_TEXTURE_3D, GL_GENERATE_MIPMAP, GL_TRUE); + glBindTexture(GL_TEXTURE_3D, 0); +} + +void GLTexture3D::load(int width, int height, int depth, QRgb *data) +{ + GLBUFFERS_ASSERT_OPENGL("GLTexture3D::load", glTexImage3D, return) + + glBindTexture(GL_TEXTURE_3D, m_texture); + glTexImage3D(GL_TEXTURE_3D, 0, 4, width, height, depth, 0, + GL_BGRA, GL_UNSIGNED_BYTE, data); + glBindTexture(GL_TEXTURE_3D, 0); +} + +void GLTexture3D::bind() +{ + glBindTexture(GL_TEXTURE_3D, m_texture); + glEnable(GL_TEXTURE_3D); +} + +void GLTexture3D::unbind() +{ + glBindTexture(GL_TEXTURE_3D, 0); + glDisable(GL_TEXTURE_3D); +} + +//============================================================================// +// GLTextureCube // +//============================================================================// + +GLTextureCube::GLTextureCube(int size) +{ + glBindTexture(GL_TEXTURE_CUBE_MAP, m_texture); + + for (int i = 0; i < 6; ++i) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 4, size, size, 0, + GL_BGRA, GL_UNSIGNED_BYTE, 0); + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + //glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +GLTextureCube::GLTextureCube(const QStringList& fileNames, int size) +{ + // TODO: Add error handling. + + glBindTexture(GL_TEXTURE_CUBE_MAP, m_texture); + + int index = 0; + foreach (QString file, fileNames) { + QImage image(file); + if (image.isNull()) { + m_failed = true; + break; + } + + image = image.convertToFormat(QImage::Format_ARGB32); + + //qDebug() << "Image size:" << image.width() << "x" << image.height(); + if (size <= 0) + size = image.width(); + if (size != image.width() || size != image.height()) + image = image.scaled(size, size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + + // Works on x86, so probably works on all little-endian systems. + // Does it work on big-endian systems? + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index, 0, 4, image.width(), image.height(), 0, + GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); + + if (++index == 6) + break; + } + + // Clear remaining faces. + while (index < 6) { + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + index, 0, 4, size, size, 0, + GL_BGRA, GL_UNSIGNED_BYTE, 0); + ++index; + } + + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + //glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_GENERATE_MIPMAP, GL_TRUE); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +void GLTextureCube::load(int size, int face, QRgb *data) +{ + glBindTexture(GL_TEXTURE_CUBE_MAP, m_texture); + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, 4, size, size, 0, + GL_BGRA, GL_UNSIGNED_BYTE, data); + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); +} + +void GLTextureCube::bind() +{ + glBindTexture(GL_TEXTURE_CUBE_MAP, m_texture); + glEnable(GL_TEXTURE_CUBE_MAP); +} + +void GLTextureCube::unbind() +{ + glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + glDisable(GL_TEXTURE_CUBE_MAP); +} + +//============================================================================// +// GLFrameBufferObject // +//============================================================================// + +GLFrameBufferObject::GLFrameBufferObject(int width, int height) + : m_fbo(0) + , m_depthBuffer(0) + , m_width(width) + , m_height(height) + , m_failed(false) +{ + GLBUFFERS_ASSERT_OPENGL("GLFrameBufferObject::GLFrameBufferObject", + glGenFramebuffersEXT && glGenRenderbuffersEXT && glBindRenderbufferEXT && glRenderbufferStorageEXT, return) + + // TODO: share depth buffers of same size + glGenFramebuffersEXT(1, &m_fbo); + //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + glGenRenderbuffersEXT(1, &m_depthBuffer); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthBuffer); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, m_width, m_height); + //glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthBuffer); + //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); +} + +GLFrameBufferObject::~GLFrameBufferObject() +{ + GLBUFFERS_ASSERT_OPENGL("GLFrameBufferObject::~GLFrameBufferObject", + glDeleteFramebuffersEXT && glDeleteRenderbuffersEXT, return) + + glDeleteFramebuffersEXT(1, &m_fbo); + glDeleteRenderbuffersEXT(1, &m_depthBuffer); +} + +void GLFrameBufferObject::setAsRenderTarget(bool state) +{ + GLBUFFERS_ASSERT_OPENGL("GLFrameBufferObject::setAsRenderTarget", glBindFramebufferEXT, return) + + if (state) { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, m_width, m_height); + } else { + glPopAttrib(); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } +} + +bool GLFrameBufferObject::isComplete() +{ + GLBUFFERS_ASSERT_OPENGL("GLFrameBufferObject::isComplete", glCheckFramebufferStatusEXT, return false) + + return GL_FRAMEBUFFER_COMPLETE_EXT == glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); +} + +//============================================================================// +// GLRenderTargetCube // +//============================================================================// + +GLRenderTargetCube::GLRenderTargetCube(int size) + : GLTextureCube(size) + , m_fbo(size, size) +{ +} + +void GLRenderTargetCube::begin(int face) +{ + GLBUFFERS_ASSERT_OPENGL("GLRenderTargetCube::begin", + glFramebufferTexture2DEXT && glFramebufferRenderbufferEXT, return) + + m_fbo.setAsRenderTarget(true); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, m_texture, 0); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_fbo.m_depthBuffer); +} + +void GLRenderTargetCube::end() +{ + m_fbo.setAsRenderTarget(false); +} + +void GLRenderTargetCube::getViewMatrix(QMatrix4x4& mat, int face) +{ + if (face < 0 || face >= 6) { + qWarning("GLRenderTargetCube::getViewMatrix: 'face' must be in the range [0, 6). (face == %d)", face); + return; + } + + static int perm[6][3] = { + {2, 1, 0}, + {2, 1, 0}, + {0, 2, 1}, + {0, 2, 1}, + {0, 1, 2}, + {0, 1, 2}, + }; + + static float signs[6][3] = { + {-1.0f, -1.0f, -1.0f}, + {+1.0f, -1.0f, +1.0f}, + {+1.0f, +1.0f, -1.0f}, + {+1.0f, -1.0f, +1.0f}, + {+1.0f, -1.0f, -1.0f}, + {-1.0f, -1.0f, +1.0f}, + }; + + mat.fill(0.0f); + for (int i = 0; i < 3; ++i) + mat(i, perm[face][i]) = signs[face][i]; + mat(3, 3) = 1.0f; +} + +void GLRenderTargetCube::getProjectionMatrix(QMatrix4x4& mat, float nearZ, float farZ) +{ + static const QMatrix4x4 reference( + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, -1.0f, 0.0f); + + mat = reference; + mat(2, 2) = (nearZ+farZ)/(nearZ-farZ); + mat(2, 3) = 2.0f*nearZ*farZ/(nearZ-farZ); +} diff --git a/examples/graphicsview/boxes/glbuffers.h b/examples/graphicsview/boxes/glbuffers.h new file mode 100644 index 0000000000..6b18d3f128 --- /dev/null +++ b/examples/graphicsview/boxes/glbuffers.h @@ -0,0 +1,366 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GLBUFFERS_H +#define GLBUFFERS_H + +//#include +#include "glextensions.h" + +#include +#include + +#define BUFFER_OFFSET(i) ((char*)0 + (i)) +#define SIZE_OF_MEMBER(cls, member) sizeof(static_cast(0)->member) + +#define GLBUFFERS_ASSERT_OPENGL(prefix, assertion, returnStatement) \ +if (m_failed || !(assertion)) { \ + if (!m_failed) qCritical(prefix ": The necessary OpenGL functions are not available."); \ + m_failed = true; \ + returnStatement; \ +} + +void qgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar); + +QT_BEGIN_NAMESPACE +class QMatrix4x4; +QT_END_NAMESPACE + +class GLTexture +{ +public: + GLTexture(); + virtual ~GLTexture(); + virtual void bind() = 0; + virtual void unbind() = 0; + virtual bool failed() const {return m_failed;} +protected: + GLuint m_texture; + bool m_failed; +}; + +class GLFrameBufferObject +{ +public: + friend class GLRenderTargetCube; + // friend class GLRenderTarget2D; + + GLFrameBufferObject(int width, int height); + virtual ~GLFrameBufferObject(); + bool isComplete(); + virtual bool failed() const {return m_failed;} +protected: + void setAsRenderTarget(bool state = true); + GLuint m_fbo; + GLuint m_depthBuffer; + int m_width, m_height; + bool m_failed; +}; + +class GLTexture2D : public GLTexture +{ +public: + GLTexture2D(int width, int height); + GLTexture2D(const QString& fileName, int width = 0, int height = 0); + void load(int width, int height, QRgb *data); + virtual void bind(); + virtual void unbind(); +}; + +class GLTexture3D : public GLTexture +{ +public: + GLTexture3D(int width, int height, int depth); + // TODO: Implement function below + //GLTexture3D(const QString& fileName, int width = 0, int height = 0); + void load(int width, int height, int depth, QRgb *data); + virtual void bind(); + virtual void unbind(); +}; + +class GLTextureCube : public GLTexture +{ +public: + GLTextureCube(int size); + GLTextureCube(const QStringList& fileNames, int size = 0); + void load(int size, int face, QRgb *data); + virtual void bind(); + virtual void unbind(); +}; + +// TODO: Define and implement class below +//class GLRenderTarget2D : public GLTexture2D + +class GLRenderTargetCube : public GLTextureCube +{ +public: + GLRenderTargetCube(int size); + // begin rendering to one of the cube's faces. 0 <= face < 6 + void begin(int face); + // end rendering + void end(); + virtual bool failed() {return m_failed || m_fbo.failed();} + + static void getViewMatrix(QMatrix4x4& mat, int face); + static void getProjectionMatrix(QMatrix4x4& mat, float nearZ, float farZ); +private: + GLFrameBufferObject m_fbo; +}; + +struct VertexDescription +{ + enum + { + Null = 0, // Terminates a VertexDescription array + Position, + TexCoord, + Normal, + Color, + }; + int field; // Position, TexCoord, Normal, Color + int type; // GL_FLOAT, GL_UNSIGNED_BYTE + int count; // number of elements + int offset; // field's offset into vertex struct + int index; // 0 (unused at the moment) +}; + +// Implementation of interleaved buffers. +// 'T' is a struct which must include a null-terminated static array +// 'VertexDescription* description'. +// Example: +/* +struct Vertex +{ + GLfloat position[3]; + GLfloat texCoord[2]; + GLfloat normal[3]; + GLbyte color[4]; + static VertexDescription description[]; +}; + +VertexDescription Vertex::description[] = { + {VertexDescription::Position, GL_FLOAT, SIZE_OF_MEMBER(Vertex, position) / sizeof(GLfloat), offsetof(Vertex, position), 0}, + {VertexDescription::TexCoord, GL_FLOAT, SIZE_OF_MEMBER(Vertex, texCoord) / sizeof(GLfloat), offsetof(Vertex, texCoord), 0}, + {VertexDescription::Normal, GL_FLOAT, SIZE_OF_MEMBER(Vertex, normal) / sizeof(GLfloat), offsetof(Vertex, normal), 0}, + {VertexDescription::Color, GL_BYTE, SIZE_OF_MEMBER(Vertex, color) / sizeof(GLbyte), offsetof(Vertex, color), 0}, + {VertexDescription::Null, 0, 0, 0, 0}, +}; +*/ +template +class GLVertexBuffer +{ +public: + GLVertexBuffer(int length, const T *data = 0, int mode = GL_STATIC_DRAW) + : m_length(0) + , m_mode(mode) + , m_buffer(0) + , m_failed(false) + { + GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::GLVertexBuffer", glGenBuffers && glBindBuffer && glBufferData, return) + + glGenBuffers(1, &m_buffer); + glBindBuffer(GL_ARRAY_BUFFER, m_buffer); + glBufferData(GL_ARRAY_BUFFER, (m_length = length) * sizeof(T), data, mode); + } + + ~GLVertexBuffer() + { + GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::~GLVertexBuffer", glDeleteBuffers, return) + + glDeleteBuffers(1, &m_buffer); + } + + void bind() + { + GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::bind", glBindBuffer, return) + + glBindBuffer(GL_ARRAY_BUFFER, m_buffer); + for (VertexDescription *desc = T::description; desc->field != VertexDescription::Null; ++desc) { + switch (desc->field) { + case VertexDescription::Position: + glVertexPointer(desc->count, desc->type, sizeof(T), BUFFER_OFFSET(desc->offset)); + glEnableClientState(GL_VERTEX_ARRAY); + break; + case VertexDescription::TexCoord: + glTexCoordPointer(desc->count, desc->type, sizeof(T), BUFFER_OFFSET(desc->offset)); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + break; + case VertexDescription::Normal: + glNormalPointer(desc->type, sizeof(T), BUFFER_OFFSET(desc->offset)); + glEnableClientState(GL_NORMAL_ARRAY); + break; + case VertexDescription::Color: + glColorPointer(desc->count, desc->type, sizeof(T), BUFFER_OFFSET(desc->offset)); + glEnableClientState(GL_COLOR_ARRAY); + break; + default: + break; + } + } + } + + void unbind() + { + GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::unbind", glBindBuffer, return) + + glBindBuffer(GL_ARRAY_BUFFER, 0); + for (VertexDescription *desc = T::description; desc->field != VertexDescription::Null; ++desc) { + switch (desc->field) { + case VertexDescription::Position: + glDisableClientState(GL_VERTEX_ARRAY); + break; + case VertexDescription::TexCoord: + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + break; + case VertexDescription::Normal: + glDisableClientState(GL_NORMAL_ARRAY); + break; + case VertexDescription::Color: + glDisableClientState(GL_COLOR_ARRAY); + break; + default: + break; + } + } + } + + int length() const {return m_length;} + + T *lock() + { + GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::lock", glBindBuffer && glMapBuffer, return 0) + + glBindBuffer(GL_ARRAY_BUFFER, m_buffer); + //glBufferData(GL_ARRAY_BUFFER, m_length, NULL, m_mode); + GLvoid* buffer = glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE); + m_failed = (buffer == 0); + return reinterpret_cast(buffer); + } + + void unlock() + { + GLBUFFERS_ASSERT_OPENGL("GLVertexBuffer::unlock", glBindBuffer && glUnmapBuffer, return) + + glBindBuffer(GL_ARRAY_BUFFER, m_buffer); + glUnmapBuffer(GL_ARRAY_BUFFER); + } + + bool failed() + { + return m_failed; + } + +private: + int m_length, m_mode; + GLuint m_buffer; + bool m_failed; +}; + +template +class GLIndexBuffer +{ +public: + GLIndexBuffer(int length, const T *data = 0, int mode = GL_STATIC_DRAW) + : m_length(0) + , m_mode(mode) + , m_buffer(0) + , m_failed(false) + { + GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::GLIndexBuffer", glGenBuffers && glBindBuffer && glBufferData, return) + + glGenBuffers(1, &m_buffer); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, (m_length = length) * sizeof(T), data, mode); + } + + ~GLIndexBuffer() + { + GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::~GLIndexBuffer", glDeleteBuffers, return) + + glDeleteBuffers(1, &m_buffer); + } + + void bind() + { + GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::bind", glBindBuffer, return) + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer); + } + + void unbind() + { + GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::unbind", glBindBuffer, return) + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + + int length() const {return m_length;} + + T *lock() + { + GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::lock", glBindBuffer && glMapBuffer, return 0) + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer); + GLvoid* buffer = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_READ_WRITE); + m_failed = (buffer == 0); + return reinterpret_cast(buffer); + } + + void unlock() + { + GLBUFFERS_ASSERT_OPENGL("GLIndexBuffer::unlock", glBindBuffer && glUnmapBuffer, return) + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffer); + glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + } + + bool failed() + { + return m_failed; + } + +private: + int m_length, m_mode; + GLuint m_buffer; + bool m_failed; +}; + +#endif diff --git a/examples/graphicsview/boxes/glextensions.cpp b/examples/graphicsview/boxes/glextensions.cpp new file mode 100644 index 0000000000..b712efe38b --- /dev/null +++ b/examples/graphicsview/boxes/glextensions.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "glextensions.h" + +#define RESOLVE_GL_FUNC(f) ok &= bool((f = (_gl##f) context->getProcAddress(QLatin1String("gl" #f)))); + +bool GLExtensionFunctions::resolve(const QGLContext *context) +{ + bool ok = true; + + RESOLVE_GL_FUNC(GenFramebuffersEXT) + RESOLVE_GL_FUNC(GenRenderbuffersEXT) + RESOLVE_GL_FUNC(BindRenderbufferEXT) + RESOLVE_GL_FUNC(RenderbufferStorageEXT) + RESOLVE_GL_FUNC(DeleteFramebuffersEXT) + RESOLVE_GL_FUNC(DeleteRenderbuffersEXT) + RESOLVE_GL_FUNC(BindFramebufferEXT) + RESOLVE_GL_FUNC(FramebufferTexture2DEXT) + RESOLVE_GL_FUNC(FramebufferRenderbufferEXT) + RESOLVE_GL_FUNC(CheckFramebufferStatusEXT) + + RESOLVE_GL_FUNC(ActiveTexture) + RESOLVE_GL_FUNC(TexImage3D) + + RESOLVE_GL_FUNC(GenBuffers) + RESOLVE_GL_FUNC(BindBuffer) + RESOLVE_GL_FUNC(BufferData) + RESOLVE_GL_FUNC(DeleteBuffers) + RESOLVE_GL_FUNC(MapBuffer) + RESOLVE_GL_FUNC(UnmapBuffer) + + return ok; +} + +bool GLExtensionFunctions::fboSupported() { + return GenFramebuffersEXT + && GenRenderbuffersEXT + && BindRenderbufferEXT + && RenderbufferStorageEXT + && DeleteFramebuffersEXT + && DeleteRenderbuffersEXT + && BindFramebufferEXT + && FramebufferTexture2DEXT + && FramebufferRenderbufferEXT + && CheckFramebufferStatusEXT; +} + +bool GLExtensionFunctions::openGL15Supported() { + return ActiveTexture + && TexImage3D + && GenBuffers + && BindBuffer + && BufferData + && DeleteBuffers + && MapBuffer + && UnmapBuffer; +} + +#undef RESOLVE_GL_FUNC diff --git a/examples/graphicsview/boxes/glextensions.h b/examples/graphicsview/boxes/glextensions.h new file mode 100644 index 0000000000..54de548cd7 --- /dev/null +++ b/examples/graphicsview/boxes/glextensions.h @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GLEXTENSIONS_H +#define GLEXTENSIONS_H + +#include + +/* +Functions resolved: + +glGenFramebuffersEXT +glGenRenderbuffersEXT +glBindRenderbufferEXT +glRenderbufferStorageEXT +glDeleteFramebuffersEXT +glDeleteRenderbuffersEXT +glBindFramebufferEXT +glFramebufferTexture2DEXT +glFramebufferRenderbufferEXT +glCheckFramebufferStatusEXT + +glActiveTexture +glTexImage3D + +glGenBuffers +glBindBuffer +glBufferData +glDeleteBuffers +glMapBuffer +glUnmapBuffer +*/ + +#ifndef Q_WS_MAC +# ifndef APIENTRYP +# ifdef APIENTRY +# define APIENTRYP APIENTRY * +# else +# define APIENTRY +# define APIENTRYP * +# endif +# endif +#else +# define APIENTRY +# define APIENTRYP * +#endif + +#ifndef GL_VERSION_1_2 +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_BGRA 0x80E1 +#endif + +#ifndef GL_VERSION_1_3 +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +//#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +//#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +//#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +//#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +//#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#endif + +#ifndef GL_ARB_vertex_buffer_object +typedef ptrdiff_t GLsizeiptrARB; +#endif + +#ifndef GL_VERSION_1_5 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_READ_WRITE 0x88BA +#define GL_STATIC_DRAW 0x88E4 +#endif + +#ifndef GL_EXT_framebuffer_object +#define GL_RENDERBUFFER_EXT 0x8D41 +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#endif + +typedef void (APIENTRY *_glGenFramebuffersEXT) (GLsizei, GLuint *); +typedef void (APIENTRY *_glGenRenderbuffersEXT) (GLsizei, GLuint *); +typedef void (APIENTRY *_glBindRenderbufferEXT) (GLenum, GLuint); +typedef void (APIENTRY *_glRenderbufferStorageEXT) (GLenum, GLenum, GLsizei, GLsizei); +typedef void (APIENTRY *_glDeleteFramebuffersEXT) (GLsizei, const GLuint*); +typedef void (APIENTRY *_glDeleteRenderbuffersEXT) (GLsizei, const GLuint*); +typedef void (APIENTRY *_glBindFramebufferEXT) (GLenum, GLuint); +typedef void (APIENTRY *_glFramebufferTexture2DEXT) (GLenum, GLenum, GLenum, GLuint, GLint); +typedef void (APIENTRY *_glFramebufferRenderbufferEXT) (GLenum, GLenum, GLenum, GLuint); +typedef GLenum (APIENTRY *_glCheckFramebufferStatusEXT) (GLenum); + +typedef void (APIENTRY *_glActiveTexture) (GLenum); +typedef void (APIENTRY *_glTexImage3D) (GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); + +typedef void (APIENTRY *_glGenBuffers) (GLsizei, GLuint *); +typedef void (APIENTRY *_glBindBuffer) (GLenum, GLuint); +typedef void (APIENTRY *_glBufferData) (GLenum, GLsizeiptrARB, const GLvoid *, GLenum); +typedef void (APIENTRY *_glDeleteBuffers) (GLsizei, const GLuint *); +typedef void *(APIENTRY *_glMapBuffer) (GLenum, GLenum); +typedef GLboolean (APIENTRY *_glUnmapBuffer) (GLenum); + +struct GLExtensionFunctions +{ + bool resolve(const QGLContext *context); + + bool fboSupported(); + bool openGL15Supported(); // the rest: multi-texture, 3D-texture, vertex buffer objects + + _glGenFramebuffersEXT GenFramebuffersEXT; + _glGenRenderbuffersEXT GenRenderbuffersEXT; + _glBindRenderbufferEXT BindRenderbufferEXT; + _glRenderbufferStorageEXT RenderbufferStorageEXT; + _glDeleteFramebuffersEXT DeleteFramebuffersEXT; + _glDeleteRenderbuffersEXT DeleteRenderbuffersEXT; + _glBindFramebufferEXT BindFramebufferEXT; + _glFramebufferTexture2DEXT FramebufferTexture2DEXT; + _glFramebufferRenderbufferEXT FramebufferRenderbufferEXT; + _glCheckFramebufferStatusEXT CheckFramebufferStatusEXT; + + _glActiveTexture ActiveTexture; + _glTexImage3D TexImage3D; + + _glGenBuffers GenBuffers; + _glBindBuffer BindBuffer; + _glBufferData BufferData; + _glDeleteBuffers DeleteBuffers; + _glMapBuffer MapBuffer; + _glUnmapBuffer UnmapBuffer; +}; + +inline GLExtensionFunctions &getGLExtensionFunctions() +{ + static GLExtensionFunctions funcs; + return funcs; +} + +#define glGenFramebuffersEXT getGLExtensionFunctions().GenFramebuffersEXT +#define glGenRenderbuffersEXT getGLExtensionFunctions().GenRenderbuffersEXT +#define glBindRenderbufferEXT getGLExtensionFunctions().BindRenderbufferEXT +#define glRenderbufferStorageEXT getGLExtensionFunctions().RenderbufferStorageEXT +#define glDeleteFramebuffersEXT getGLExtensionFunctions().DeleteFramebuffersEXT +#define glDeleteRenderbuffersEXT getGLExtensionFunctions().DeleteRenderbuffersEXT +#define glBindFramebufferEXT getGLExtensionFunctions().BindFramebufferEXT +#define glFramebufferTexture2DEXT getGLExtensionFunctions().FramebufferTexture2DEXT +#define glFramebufferRenderbufferEXT getGLExtensionFunctions().FramebufferRenderbufferEXT +#define glCheckFramebufferStatusEXT getGLExtensionFunctions().CheckFramebufferStatusEXT + +#define glActiveTexture getGLExtensionFunctions().ActiveTexture +#define glTexImage3D getGLExtensionFunctions().TexImage3D + +#define glGenBuffers getGLExtensionFunctions().GenBuffers +#define glBindBuffer getGLExtensionFunctions().BindBuffer +#define glBufferData getGLExtensionFunctions().BufferData +#define glDeleteBuffers getGLExtensionFunctions().DeleteBuffers +#define glMapBuffer getGLExtensionFunctions().MapBuffer +#define glUnmapBuffer getGLExtensionFunctions().UnmapBuffer + +#endif diff --git a/examples/graphicsview/boxes/gltrianglemesh.h b/examples/graphicsview/boxes/gltrianglemesh.h new file mode 100644 index 0000000000..ecf6531d85 --- /dev/null +++ b/examples/graphicsview/boxes/gltrianglemesh.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GLTRIANGLEMESH_H +#define GLTRIANGLEMESH_H + +//#include +#include "glextensions.h" + +#include +#include + +#include "glbuffers.h" + +template +class GLTriangleMesh +{ +public: + GLTriangleMesh(int vertexCount, int indexCount) : m_vb(vertexCount), m_ib(indexCount) + { + } + + virtual ~GLTriangleMesh() + { + } + + virtual void draw() + { + if (failed()) + return; + + int type = GL_UNSIGNED_INT; + if (sizeof(TIndex) == sizeof(char)) type = GL_UNSIGNED_BYTE; + if (sizeof(TIndex) == sizeof(short)) type = GL_UNSIGNED_SHORT; + + m_vb.bind(); + m_ib.bind(); + glDrawElements(GL_TRIANGLES, m_ib.length(), type, BUFFER_OFFSET(0)); + m_vb.unbind(); + m_ib.unbind(); + } + + bool failed() + { + return m_vb.failed() || m_ib.failed(); + } +protected: + GLVertexBuffer m_vb; + GLIndexBuffer m_ib; +}; + + +#endif diff --git a/examples/graphicsview/boxes/granite.fsh b/examples/graphicsview/boxes/granite.fsh new file mode 100644 index 0000000000..abaeeb97bc --- /dev/null +++ b/examples/graphicsview/boxes/granite.fsh @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform sampler3D noise; + +//const vec4 graniteColors[3] = {vec4(0.0, 0.0, 0.0, 1), vec4(0.30, 0.15, 0.10, 1), vec4(0.80, 0.70, 0.75, 1)}; +uniform vec4 graniteColors[3]; + +float steep(float x) +{ + return clamp(5.0 * x - 2.0, 0.0, 1.0); +} + +void main() +{ + vec2 turbulence = vec2(0, 0); + float scale = 1.0; + for (int i = 0; i < 4; ++i) { + turbulence += scale * (texture3D(noise, gl_TexCoord[1].xyz / scale).xy - 0.5); + scale *= 0.5; + } + + vec3 N = normalize(normal); + // assume directional light + + gl_MaterialParameters M = gl_FrontMaterial; + + float NdotL = dot(N, lightDirection.xyz); + float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz); + + vec4 unlitColor = mix(graniteColors[1], mix(graniteColors[0], graniteColors[2], steep(0.5 + turbulence.y)), 4.0 * abs(turbulence.x)); + gl_FragColor = (ambient + diffuse * max(NdotL, 0.0)) * unlitColor + + M.specular * specular * pow(max(RdotL, 0.0), M.shininess); +} diff --git a/examples/graphicsview/boxes/main.cpp b/examples/graphicsview/boxes/main.cpp new file mode 100644 index 0000000000..483170801f --- /dev/null +++ b/examples/graphicsview/boxes/main.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//#include +#include "glextensions.h" + +#include "scene.h" + +#include +#include + +class GraphicsView : public QGraphicsView +{ +public: + GraphicsView() + { + setWindowTitle(tr("Boxes")); + setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + //setRenderHints(QPainter::SmoothPixmapTransform); + } + +protected: + void resizeEvent(QResizeEvent *event) { + if (scene()) + scene()->setSceneRect(QRect(QPoint(0, 0), event->size())); + QGraphicsView::resizeEvent(event); + } +}; + +inline bool matchString(const char *extensionString, const char *subString) +{ + int subStringLength = strlen(subString); + return (strncmp(extensionString, subString, subStringLength) == 0) + && ((extensionString[subStringLength] == ' ') || (extensionString[subStringLength] == '\0')); +} + +bool necessaryExtensionsSupported() +{ + const char *extensionString = reinterpret_cast(glGetString(GL_EXTENSIONS)); + const char *p = extensionString; + + const int GL_EXT_FBO = 1; + const int GL_ARB_VS = 2; + const int GL_ARB_FS = 4; + const int GL_ARB_SO = 8; + int extensions = 0; + + while (*p) { + if (matchString(p, "GL_EXT_framebuffer_object")) + extensions |= GL_EXT_FBO; + else if (matchString(p, "GL_ARB_vertex_shader")) + extensions |= GL_ARB_VS; + else if (matchString(p, "GL_ARB_fragment_shader")) + extensions |= GL_ARB_FS; + else if (matchString(p, "GL_ARB_shader_objects")) + extensions |= GL_ARB_SO; + while ((*p != ' ') && (*p != '\0')) + ++p; + if (*p == ' ') + ++p; + } + return (extensions == 15); +} + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + if ((QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_5) == 0) { + QMessageBox::critical(0, "OpenGL features missing", + "OpenGL version 1.5 or higher is required to run this demo.\n" + "The program will now exit."); + return -1; + } + + int maxTextureSize = 1024; + QGLWidget *widget = new QGLWidget(QGLFormat(QGL::SampleBuffers)); + widget->makeCurrent(); + + if (!necessaryExtensionsSupported()) { + QMessageBox::critical(0, "OpenGL features missing", + "The OpenGL extensions required to run this demo are missing.\n" + "The program will now exit."); + delete widget; + return -2; + } + + // Check if all the necessary functions are resolved. + if (!getGLExtensionFunctions().resolve(widget->context())) { + QMessageBox::critical(0, "OpenGL features missing", + "Failed to resolve OpenGL functions required to run this demo.\n" + "The program will now exit."); + delete widget; + return -3; + } + + // TODO: Make conditional for final release + QMessageBox::information(0, "For your information", + "This demo can be GPU and CPU intensive and may\n" + "work poorly or not at all on your system."); + + widget->makeCurrent(); // The current context must be set before calling Scene's constructor + Scene scene(1024, 768, maxTextureSize); + GraphicsView view; + view.setViewport(widget); + view.setViewportUpdateMode(QGraphicsView::FullViewportUpdate); + view.setScene(&scene); + view.show(); + + return app.exec(); +} + diff --git a/examples/graphicsview/boxes/marble.fsh b/examples/graphicsview/boxes/marble.fsh new file mode 100644 index 0000000000..170ec3abef --- /dev/null +++ b/examples/graphicsview/boxes/marble.fsh @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform sampler3D noise; + +//const vec4 marbleColors[2] = {vec4(0.9, 0.9, 0.9, 1), vec4(0.6, 0.5, 0.5, 1)}; +uniform vec4 marbleColors[2]; + +void main() +{ + float turbulence = 0.0; + float scale = 1.0; + for (int i = 0; i < 4; ++i) { + turbulence += scale * (texture3D(noise, 0.125 * gl_TexCoord[1].xyz / scale).x - 0.5); + scale *= 0.5; + } + + vec3 N = normalize(normal); + // assume directional light + + gl_MaterialParameters M = gl_FrontMaterial; + + float NdotL = dot(N, lightDirection.xyz); + float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz); + + vec4 unlitColor = mix(marbleColors[0], marbleColors[1], exp(-4.0 * abs(turbulence))); + gl_FragColor = (ambient + diffuse * max(NdotL, 0.0)) * unlitColor + + M.specular * specular * pow(max(RdotL, 0.0), M.shininess); +} diff --git a/examples/graphicsview/boxes/parameters.par b/examples/graphicsview/boxes/parameters.par new file mode 100644 index 0000000000..50e20739b9 --- /dev/null +++ b/examples/graphicsview/boxes/parameters.par @@ -0,0 +1,5 @@ +color basicColor ff0e3d0e +color woodColors ff5e3d33 ffcc9966 +float woodTubulence 0.1 +color graniteColors ff000000 ff4d261a ffccb3bf +color marbleColors ffe6e6e6 ff998080 diff --git a/examples/graphicsview/boxes/qt-logo.jpg b/examples/graphicsview/boxes/qt-logo.jpg new file mode 100644 index 0000000000..4014b4659c Binary files /dev/null and b/examples/graphicsview/boxes/qt-logo.jpg differ diff --git a/examples/graphicsview/boxes/qt-logo.png b/examples/graphicsview/boxes/qt-logo.png new file mode 100644 index 0000000000..7d3e97eb36 Binary files /dev/null and b/examples/graphicsview/boxes/qt-logo.png differ diff --git a/examples/graphicsview/boxes/qtbox.cpp b/examples/graphicsview/boxes/qtbox.cpp new file mode 100644 index 0000000000..d24116578c --- /dev/null +++ b/examples/graphicsview/boxes/qtbox.cpp @@ -0,0 +1,480 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtbox.h" + +const qreal ROTATE_SPEED_X = 30.0 / 1000.0; +const qreal ROTATE_SPEED_Y = 20.0 / 1000.0; +const qreal ROTATE_SPEED_Z = 40.0 / 1000.0; +const int MAX_ITEM_SIZE = 512; +const int MIN_ITEM_SIZE = 16; + +//============================================================================// +// ItemBase // +//============================================================================// + +ItemBase::ItemBase(int size, int x, int y) : m_size(size), m_isResizing(false) +{ + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIsSelectable, true); + setFlag(QGraphicsItem::ItemIsFocusable, true); + setAcceptHoverEvents(true); + setPos(x, y); + m_startTime = QTime::currentTime(); +} + +ItemBase::~ItemBase() +{ +} + +QRectF ItemBase::boundingRect() const +{ + return QRectF(-m_size / 2, -m_size / 2, m_size, m_size); +} + +void ItemBase::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *) +{ + if (option->state & QStyle::State_Selected) { + painter->setRenderHint(QPainter::Antialiasing, true); + if (option->state & QStyle::State_HasFocus) + painter->setPen(Qt::yellow); + else + painter->setPen(Qt::white); + painter->drawRect(boundingRect()); + + painter->drawLine(m_size / 2 - 9, m_size / 2, m_size / 2, m_size / 2 - 9); + painter->drawLine(m_size / 2 - 6, m_size / 2, m_size / 2, m_size / 2 - 6); + painter->drawLine(m_size / 2 - 3, m_size / 2, m_size / 2, m_size / 2 - 3); + + painter->setRenderHint(QPainter::Antialiasing, false); + } +} + +void ItemBase::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) +{ + if (!isSelected() && scene()) { + scene()->clearSelection(); + setSelected(true); + } + + QMenu menu; + QAction *delAction = menu.addAction("Delete"); + QAction *newAction = menu.addAction("New"); + QAction *growAction = menu.addAction("Grow"); + QAction *shrinkAction = menu.addAction("Shrink"); + + QAction *selectedAction = menu.exec(event->screenPos()); + + if (selectedAction == delAction) + deleteSelectedItems(scene()); + else if (selectedAction == newAction) + duplicateSelectedItems(scene()); + else if (selectedAction == growAction) + growSelectedItems(scene()); + else if (selectedAction == shrinkAction) + shrinkSelectedItems(scene()); +} + +void ItemBase::duplicateSelectedItems(QGraphicsScene *scene) +{ + if (!scene) + return; + + QList selected; + selected = scene->selectedItems(); + + foreach (QGraphicsItem *item, selected) { + ItemBase *itemBase = qgraphicsitem_cast(item); + if (itemBase) + scene->addItem(itemBase->createNew(itemBase->m_size, itemBase->pos().x() + itemBase->m_size, itemBase->pos().y())); + } +} + +void ItemBase::deleteSelectedItems(QGraphicsScene *scene) +{ + if (!scene) + return; + + QList selected; + selected = scene->selectedItems(); + + foreach (QGraphicsItem *item, selected) { + ItemBase *itemBase = qgraphicsitem_cast(item); + if (itemBase) + delete itemBase; + } +} + +void ItemBase::growSelectedItems(QGraphicsScene *scene) +{ + if (!scene) + return; + + QList selected; + selected = scene->selectedItems(); + + foreach (QGraphicsItem *item, selected) { + ItemBase *itemBase = qgraphicsitem_cast(item); + if (itemBase) { + itemBase->prepareGeometryChange(); + itemBase->m_size *= 2; + if (itemBase->m_size > MAX_ITEM_SIZE) + itemBase->m_size = MAX_ITEM_SIZE; + } + } +} + +void ItemBase::shrinkSelectedItems(QGraphicsScene *scene) +{ + if (!scene) + return; + + QList selected; + selected = scene->selectedItems(); + + foreach (QGraphicsItem *item, selected) { + ItemBase *itemBase = qgraphicsitem_cast(item); + if (itemBase) { + itemBase->prepareGeometryChange(); + itemBase->m_size /= 2; + if (itemBase->m_size < MIN_ITEM_SIZE) + itemBase->m_size = MIN_ITEM_SIZE; + } + } +} + +void ItemBase::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (m_isResizing) { + int dx = int(2.0 * event->pos().x()); + int dy = int(2.0 * event->pos().y()); + prepareGeometryChange(); + m_size = (dx > dy ? dx : dy); + if (m_size < MIN_ITEM_SIZE) + m_size = MIN_ITEM_SIZE; + else if (m_size > MAX_ITEM_SIZE) + m_size = MAX_ITEM_SIZE; + } else { + QGraphicsItem::mouseMoveEvent(event); + } +} + +void ItemBase::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + if (m_isResizing || (isInResizeArea(event->pos()) && isSelected())) + setCursor(Qt::SizeFDiagCursor); + else + setCursor(Qt::ArrowCursor); + QGraphicsItem::hoverMoveEvent(event); +} + +void ItemBase::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + static qreal z = 0.0; + setZValue(z += 1.0); + if (event->button() == Qt::LeftButton && isInResizeArea(event->pos())) { + m_isResizing = true; + } else { + QGraphicsItem::mousePressEvent(event); + } +} + +void ItemBase::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->button() == Qt::LeftButton && m_isResizing) { + m_isResizing = false; + } else { + QGraphicsItem::mouseReleaseEvent(event); + } +} + +void ItemBase::keyPressEvent(QKeyEvent *event) +{ + switch (event->key()) { + case Qt::Key_Delete: + deleteSelectedItems(scene()); + break; + case Qt::Key_Insert: + duplicateSelectedItems(scene()); + break; + case Qt::Key_Plus: + growSelectedItems(scene()); + break; + case Qt::Key_Minus: + shrinkSelectedItems(scene()); + break; + default: + QGraphicsItem::keyPressEvent(event); + break; + } +} + +void ItemBase::wheelEvent(QGraphicsSceneWheelEvent *event) +{ + prepareGeometryChange(); + m_size = int(m_size * exp(-event->delta() / 600.0)); + if (m_size > MAX_ITEM_SIZE) + m_size = MAX_ITEM_SIZE; + else if (m_size < MIN_ITEM_SIZE) + m_size = MIN_ITEM_SIZE; +} + +int ItemBase::type() const +{ + return Type; +} + + +bool ItemBase::isInResizeArea(const QPointF &pos) +{ + return (-pos.y() < pos.x() - m_size + 9); +} + +//============================================================================// +// QtBox // +//============================================================================// + +QtBox::QtBox(int size, int x, int y) : ItemBase(size, x, y), m_texture(0) +{ + for (int i = 0; i < 8; ++i) { + m_vertices[i].setX(i & 1 ? 0.5f : -0.5f); + m_vertices[i].setY(i & 2 ? 0.5f : -0.5f); + m_vertices[i].setZ(i & 4 ? 0.5f : -0.5f); + } + for (int i = 0; i < 4; ++i) { + m_texCoords[i].setX(i & 1 ? 1.0f : 0.0f); + m_texCoords[i].setY(i & 2 ? 1.0f : 0.0f); + } + m_normals[0] = QVector3D(-1.0f, 0.0f, 0.0f); + m_normals[1] = QVector3D(1.0f, 0.0f, 0.0f); + m_normals[2] = QVector3D(0.0f, -1.0f, 0.0f); + m_normals[3] = QVector3D(0.0f, 1.0f, 0.0f); + m_normals[4] = QVector3D(0.0f, 0.0f, -1.0f); + m_normals[5] = QVector3D(0.0f, 0.0f, 1.0f); +} + +QtBox::~QtBox() +{ + if (m_texture) + delete m_texture; +} + +ItemBase *QtBox::createNew(int size, int x, int y) +{ + return new QtBox(size, x, y); +} + +void QtBox::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + QRectF rect = boundingRect().translated(pos()); + float width = float(painter->device()->width()); + float height = float(painter->device()->height()); + + float left = 2.0f * float(rect.left()) / width - 1.0f; + float right = 2.0f * float(rect.right()) / width - 1.0f; + float top = 1.0f - 2.0f * float(rect.top()) / height; + float bottom = 1.0f - 2.0f * float(rect.bottom()) / height; + float moveToRectMatrix[] = { + 0.5f * (right - left), 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f * (bottom - top), 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.5f * (right + left), 0.5f * (bottom + top), 0.0f, 1.0f + }; + + painter->beginNativePainting(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadMatrixf(moveToRectMatrix); + qgluPerspective(60.0, 1.0, 0.01, 10.0); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + //glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + glEnable(GL_NORMALIZE); + + if(m_texture == 0) + m_texture = new GLTexture2D(":/res/boxes/qt-logo.jpg", 64, 64); + m_texture->bind(); + glEnable(GL_TEXTURE_2D); + + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + float lightColour[] = {1.0f, 1.0f, 1.0f, 1.0f}; + float lightDir[] = {0.0f, 0.0f, 1.0f, 0.0f}; + glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColour); + glLightfv(GL_LIGHT0, GL_POSITION, lightDir); + glEnable(GL_LIGHT0); + + glTranslatef(0.0f, 0.0f, -1.5f); + glRotatef(ROTATE_SPEED_X * m_startTime.msecsTo(QTime::currentTime()), 1.0f, 0.0f, 0.0f); + glRotatef(ROTATE_SPEED_Y * m_startTime.msecsTo(QTime::currentTime()), 0.0f, 1.0f, 0.0f); + glRotatef(ROTATE_SPEED_Z * m_startTime.msecsTo(QTime::currentTime()), 0.0f, 0.0f, 1.0f); + int dt = m_startTime.msecsTo(QTime::currentTime()); + if (dt < 500) + glScalef(dt / 500.0f, dt / 500.0f, dt / 500.0f); + + for (int dir = 0; dir < 3; ++dir) { + glColor4f(1.0f, 1.0f, 1.0f, 1.0); + + glBegin(GL_TRIANGLE_STRIP); + glNormal3fv(reinterpret_cast(&m_normals[2 * dir + 0])); + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 2; ++j) { + glTexCoord2fv(reinterpret_cast(&m_texCoords[(j << 1) | i])); + glVertex3fv(reinterpret_cast(&m_vertices[(i << ((dir + 2) % 3)) | (j << ((dir + 1) % 3))])); + } + } + glEnd(); + + glBegin(GL_TRIANGLE_STRIP); + glNormal3fv(reinterpret_cast(&m_normals[2 * dir + 1])); + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 2; ++j) { + glTexCoord2fv(reinterpret_cast(&m_texCoords[(j << 1) | i])); + glVertex3fv(reinterpret_cast(&m_vertices[(1 << dir) | (i << ((dir + 1) % 3)) | (j << ((dir + 2) % 3))])); + } + } + glEnd(); + } + m_texture->unbind(); + + //glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHT0); + glDisable(GL_NORMALIZE); + + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + painter->endNativePainting(); + + ItemBase::paint(painter, option, widget); +} + +//============================================================================// +// CircleItem // +//============================================================================// + +CircleItem::CircleItem(int size, int x, int y) : ItemBase(size, x, y) +{ + m_color = QColor::fromHsv(rand() % 360, 255, 255); +} + +void CircleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + int dt = m_startTime.msecsTo(QTime::currentTime()); + + qreal r0 = 0.5 * m_size * (1.0 - exp(-0.001 * ((dt + 3800) % 4000))); + qreal r1 = 0.5 * m_size * (1.0 - exp(-0.001 * ((dt + 0) % 4000))); + qreal r2 = 0.5 * m_size * (1.0 - exp(-0.001 * ((dt + 1800) % 4000))); + qreal r3 = 0.5 * m_size * (1.0 - exp(-0.001 * ((dt + 2000) % 4000))); + + if (r0 > r1) + r0 = 0.0; + if (r2 > r3) + r2 = 0.0; + + QPainterPath path; + path.moveTo(r1, 0.0); + path.arcTo(-r1, -r1, 2 * r1, 2 * r1, 0.0, 360.0); + path.lineTo(r0, 0.0); + path.arcTo(-r0, -r0, 2 * r0, 2 * r0, 0.0, -360.0); + path.closeSubpath(); + path.moveTo(r3, 0.0); + path.arcTo(-r3, -r3, 2 * r3, 2 * r3, 0.0, 360.0); + path.lineTo(r0, 0.0); + path.arcTo(-r2, -r2, 2 * r2, 2 * r2, 0.0, -360.0); + path.closeSubpath(); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->setBrush(QBrush(m_color)); + painter->setPen(Qt::NoPen); + painter->drawPath(path); + painter->setBrush(Qt::NoBrush); + painter->setPen(Qt::SolidLine); + painter->setRenderHint(QPainter::Antialiasing, false); + + ItemBase::paint(painter, option, widget); +} + +ItemBase *CircleItem::createNew(int size, int x, int y) +{ + return new CircleItem(size, x, y); +} + +//============================================================================// +// SquareItem // +//============================================================================// + +SquareItem::SquareItem(int size, int x, int y) : ItemBase(size, x, y) +{ + m_image = QPixmap(":/res/boxes/square.jpg"); +} + +void SquareItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + int dt = m_startTime.msecsTo(QTime::currentTime()); + QTransform oldTransform = painter->worldTransform(); + int dtMod = dt % 2000; + qreal amp = 0.002 * (dtMod < 1000 ? dtMod : 2000 - dtMod) - 1.0; + + qreal scale = 0.6 + 0.2 * amp * amp; + painter->setWorldTransform(QTransform().rotate(15.0 * amp).scale(scale, scale), true); + + painter->drawPixmap(-m_size / 2, -m_size / 2, m_size, m_size, m_image); + + painter->setWorldTransform(oldTransform, false); + ItemBase::paint(painter, option, widget); +} + +ItemBase *SquareItem::createNew(int size, int x, int y) +{ + return new SquareItem(size, x, y); +} diff --git a/examples/graphicsview/boxes/qtbox.h b/examples/graphicsview/boxes/qtbox.h new file mode 100644 index 0000000000..56b86a55bb --- /dev/null +++ b/examples/graphicsview/boxes/qtbox.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTBOX_H +#define QTBOX_H + +#include + +#include +#include "glbuffers.h" + +class ItemBase : public QGraphicsItem +{ +public: + enum { Type = UserType + 1 }; + + ItemBase(int size, int x, int y); + virtual ~ItemBase(); + virtual QRectF boundingRect() const; + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); +protected: + virtual ItemBase *createNew(int size, int x, int y) = 0; + virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + virtual void hoverMoveEvent(QGraphicsSceneHoverEvent *event); + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void keyPressEvent(QKeyEvent *event); + virtual void wheelEvent(QGraphicsSceneWheelEvent *event); + virtual int type() const; + bool isInResizeArea(const QPointF &pos); + + static void duplicateSelectedItems(QGraphicsScene *scene); + static void deleteSelectedItems(QGraphicsScene *scene); + static void growSelectedItems(QGraphicsScene *scene); + static void shrinkSelectedItems(QGraphicsScene *scene); + + int m_size; + QTime m_startTime; + bool m_isResizing; +}; + +class QtBox : public ItemBase +{ +public: + QtBox(int size, int x, int y); + virtual ~QtBox(); + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); +protected: + virtual ItemBase *createNew(int size, int x, int y); +private: + QVector3D m_vertices[8]; + QVector3D m_texCoords[4]; + QVector3D m_normals[6]; + GLTexture *m_texture; +}; + +class CircleItem : public ItemBase +{ +public: + CircleItem(int size, int x, int y); + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); +protected: + virtual ItemBase *createNew(int size, int x, int y); + + QColor m_color; +}; + +class SquareItem : public ItemBase +{ +public: + SquareItem(int size, int x, int y); + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); +protected: + virtual ItemBase *createNew(int size, int x, int y); + + QPixmap m_image; +}; + +#endif diff --git a/examples/graphicsview/boxes/reflection.fsh b/examples/graphicsview/boxes/reflection.fsh new file mode 100644 index 0000000000..576c522bbb --- /dev/null +++ b/examples/graphicsview/boxes/reflection.fsh @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform samplerCube env; +uniform mat4 view; + +void main() +{ + vec3 N = normalize(normal); + vec3 R = 2.0 * dot(-position, N) * N + position; + gl_FragColor = textureCube(env, R * mat3(view[0].xyz, view[1].xyz, view[2].xyz)); +} diff --git a/examples/graphicsview/boxes/refraction.fsh b/examples/graphicsview/boxes/refraction.fsh new file mode 100644 index 0000000000..10ab38a54c --- /dev/null +++ b/examples/graphicsview/boxes/refraction.fsh @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform samplerCube env; +uniform mat4 view; + +// Arrays don't work here on glsl < 120, apparently. +//const float coeffs[6] = float[6](1.0/2.0, 1.0/2.1, 1.0/2.2, 1.0/2.3, 1.0/2.4, 1.0/2.5); +float coeffs(int i) +{ + return 1.0 / (2.0 + 0.1 * float(i)); +} + +void main() +{ + vec3 N = normalize(normal); + vec3 I = -normalize(position); + float IdotN = dot(I, N); + float scales[6]; + vec3 C[6]; + for (int i = 0; i < 6; ++i) { + scales[i] = (IdotN - sqrt(1.0 - coeffs(i) + coeffs(i) * (IdotN * IdotN))); + C[i] = textureCube(env, (-I + coeffs(i) * N) * mat3(view[0].xyz, view[1].xyz, view[2].xyz)).xyz; + } + + gl_FragColor = 0.25 * vec4(C[5].x + 2.0*C[0].x + C[1].x, C[1].y + 2.0*C[2].y + C[3].y, + C[3].z + 2.0*C[4].z + C[5].z, 4.0); +} diff --git a/examples/graphicsview/boxes/roundedbox.cpp b/examples/graphicsview/boxes/roundedbox.cpp new file mode 100644 index 0000000000..5058043707 --- /dev/null +++ b/examples/graphicsview/boxes/roundedbox.cpp @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "roundedbox.h" + +//============================================================================// +// P3T2N3Vertex // +//============================================================================// + +VertexDescription P3T2N3Vertex::description[] = { + {VertexDescription::Position, GL_FLOAT, SIZE_OF_MEMBER(P3T2N3Vertex, position) / sizeof(float), 0, 0}, + {VertexDescription::TexCoord, GL_FLOAT, SIZE_OF_MEMBER(P3T2N3Vertex, texCoord) / sizeof(float), sizeof(QVector3D), 0}, + {VertexDescription::Normal, GL_FLOAT, SIZE_OF_MEMBER(P3T2N3Vertex, normal) / sizeof(float), sizeof(QVector3D) + sizeof(QVector2D), 0}, + + {VertexDescription::Null, 0, 0, 0, 0}, +}; + +//============================================================================// +// GLRoundedBox // +//============================================================================// + +float lerp(float a, float b, float t) +{ + return a * (1.0f - t) + b * t; +} + +GLRoundedBox::GLRoundedBox(float r, float scale, int n) + : GLTriangleMesh((n+2)*(n+3)*4, (n+1)*(n+1)*24+36+72*(n+1)) +{ + int vidx = 0, iidx = 0; + int vertexCountPerCorner = (n + 2) * (n + 3) / 2; + + P3T2N3Vertex *vp = m_vb.lock(); + unsigned short *ip = m_ib.lock(); + + if (!vp || !ip) { + qWarning("GLRoundedBox::GLRoundedBox: Failed to lock vertex buffer and/or index buffer."); + m_ib.unlock(); + m_vb.unlock(); + return; + } + + for (int corner = 0; corner < 8; ++corner) { + QVector3D centre(corner & 1 ? 1.0f : -1.0f, + corner & 2 ? 1.0f : -1.0f, + corner & 4 ? 1.0f : -1.0f); + int winding = (corner & 1) ^ ((corner >> 1) & 1) ^ (corner >> 2); + int offsX = ((corner ^ 1) - corner) * vertexCountPerCorner; + int offsY = ((corner ^ 2) - corner) * vertexCountPerCorner; + int offsZ = ((corner ^ 4) - corner) * vertexCountPerCorner; + + // Face polygons + if (winding) { + ip[iidx++] = vidx; + ip[iidx++] = vidx + offsX; + ip[iidx++] = vidx + offsY; + + ip[iidx++] = vidx + vertexCountPerCorner - n - 2; + ip[iidx++] = vidx + vertexCountPerCorner - n - 2 + offsY; + ip[iidx++] = vidx + vertexCountPerCorner - n - 2 + offsZ; + + ip[iidx++] = vidx + vertexCountPerCorner - 1; + ip[iidx++] = vidx + vertexCountPerCorner - 1 + offsZ; + ip[iidx++] = vidx + vertexCountPerCorner - 1 + offsX; + } + + for (int i = 0; i < n + 2; ++i) { + + // Edge polygons + if (winding && i < n + 1) { + ip[iidx++] = vidx + i + 1; + ip[iidx++] = vidx; + ip[iidx++] = vidx + offsY + i + 1; + ip[iidx++] = vidx + offsY; + ip[iidx++] = vidx + offsY + i + 1; + ip[iidx++] = vidx; + + ip[iidx++] = vidx + i; + ip[iidx++] = vidx + 2 * i + 2; + ip[iidx++] = vidx + i + offsX; + ip[iidx++] = vidx + 2 * i + offsX + 2; + ip[iidx++] = vidx + i + offsX; + ip[iidx++] = vidx + 2 * i + 2; + + ip[iidx++] = (corner + 1) * vertexCountPerCorner - 1 - i; + ip[iidx++] = (corner + 1) * vertexCountPerCorner - 2 - i; + ip[iidx++] = (corner + 1) * vertexCountPerCorner - 1 - i + offsZ; + ip[iidx++] = (corner + 1) * vertexCountPerCorner - 2 - i + offsZ; + ip[iidx++] = (corner + 1) * vertexCountPerCorner - 1 - i + offsZ; + ip[iidx++] = (corner + 1) * vertexCountPerCorner - 2 - i; + } + + for (int j = 0; j <= i; ++j) { + QVector3D normal = QVector3D(i - j, j, n + 1 - i).normalized(); + QVector3D offset(0.5f - r, 0.5f - r, 0.5f - r); + QVector3D pos = centre * (offset + r * normal); + + vp[vidx].position = scale * pos; + vp[vidx].normal = centre * normal; + vp[vidx].texCoord = QVector2D(pos.x() + 0.5f, pos.y() + 0.5f); + + // Corner polygons + if (i < n + 1) { + ip[iidx++] = vidx; + ip[iidx++] = vidx + i + 2 - winding; + ip[iidx++] = vidx + i + 1 + winding; + } + if (i < n) { + ip[iidx++] = vidx + i + 1 + winding; + ip[iidx++] = vidx + i + 2 - winding; + ip[iidx++] = vidx + 2 * i + 4; + } + + ++vidx; + } + } + + } + + m_ib.unlock(); + m_vb.unlock(); +} + diff --git a/examples/graphicsview/boxes/roundedbox.h b/examples/graphicsview/boxes/roundedbox.h new file mode 100644 index 0000000000..54dda82000 --- /dev/null +++ b/examples/graphicsview/boxes/roundedbox.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ROUNDEDBOX_H +#define ROUNDEDBOX_H + +//#include +#include "glextensions.h" + +#include +#include + +#include "gltrianglemesh.h" +#include +#include +#include "glbuffers.h" + +struct P3T2N3Vertex +{ + QVector3D position; + QVector2D texCoord; + QVector3D normal; + static VertexDescription description[]; +}; + +class GLRoundedBox : public GLTriangleMesh +{ +public: + // 0 < r < 0.5, 0 <= n <= 125 + GLRoundedBox(float r = 0.25f, float scale = 1.0f, int n = 10); +}; + + +#endif diff --git a/examples/graphicsview/boxes/scene.cpp b/examples/graphicsview/boxes/scene.cpp new file mode 100644 index 0000000000..39cd0fcafd --- /dev/null +++ b/examples/graphicsview/boxes/scene.cpp @@ -0,0 +1,1085 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "scene.h" +#include +#include + +#include "3rdparty/fbm.h" + +void checkGLErrors(const QString& prefix) +{ + switch (glGetError()) { + case GL_NO_ERROR: + //qDebug() << prefix << tr("No error."); + break; + case GL_INVALID_ENUM: + qDebug() << prefix << QObject::tr("Invalid enum."); + break; + case GL_INVALID_VALUE: + qDebug() << prefix << QObject::tr("Invalid value."); + break; + case GL_INVALID_OPERATION: + qDebug() << prefix << QObject::tr("Invalid operation."); + break; + case GL_STACK_OVERFLOW: + qDebug() << prefix << QObject::tr("Stack overflow."); + break; + case GL_STACK_UNDERFLOW: + qDebug() << prefix << QObject::tr("Stack underflow."); + break; + case GL_OUT_OF_MEMORY: + qDebug() << prefix << QObject::tr("Out of memory."); + break; + default: + qDebug() << prefix << QObject::tr("Unknown error."); + break; + } +} + +//============================================================================// +// ColorEdit // +//============================================================================// + +ColorEdit::ColorEdit(QRgb initialColor, int id) + : m_color(initialColor), m_id(id) +{ + QHBoxLayout *layout = new QHBoxLayout; + setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); + + m_lineEdit = new QLineEdit(QString::number(m_color, 16)); + layout->addWidget(m_lineEdit); + + m_button = new QFrame; + QPalette palette = m_button->palette(); + palette.setColor(QPalette::Window, QColor(m_color)); + m_button->setPalette(palette); + m_button->setAutoFillBackground(true); + m_button->setMinimumSize(32, 0); + m_button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); + m_button->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); + layout->addWidget(m_button); + + connect(m_lineEdit, SIGNAL(editingFinished()), this, SLOT(editDone())); +} + +void ColorEdit::editDone() +{ + bool ok; + QRgb newColor = m_lineEdit->text().toUInt(&ok, 16); + if (ok) + setColor(newColor); +} + +void ColorEdit::mousePressEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + QColor color(m_color); + QColorDialog dialog(color, 0); + dialog.setOption(QColorDialog::ShowAlphaChannel, true); +// The ifdef block is a workaround for the beta, TODO: remove when bug 238525 is fixed +#ifdef Q_WS_MAC + dialog.setOption(QColorDialog::DontUseNativeDialog, true); +#endif + dialog.move(280, 120); + if (dialog.exec() == QDialog::Rejected) + return; + QRgb newColor = dialog.selectedColor().rgba(); + if (newColor == m_color) + return; + setColor(newColor); + } +} + +void ColorEdit::setColor(QRgb color) +{ + m_color = color; + m_lineEdit->setText(QString::number(m_color, 16)); // "Clean up" text + QPalette palette = m_button->palette(); + palette.setColor(QPalette::Window, QColor(m_color)); + m_button->setPalette(palette); + emit colorChanged(m_color, m_id); +} + +//============================================================================// +// FloatEdit // +//============================================================================// + +FloatEdit::FloatEdit(float initialValue, int id) + : m_value(initialValue), m_id(id) +{ + QHBoxLayout *layout = new QHBoxLayout; + setLayout(layout); + layout->setContentsMargins(0, 0, 0, 0); + + m_lineEdit = new QLineEdit(QString::number(m_value)); + layout->addWidget(m_lineEdit); + + connect(m_lineEdit, SIGNAL(editingFinished()), this, SLOT(editDone())); +} + +void FloatEdit::editDone() +{ + bool ok; + float newValue = m_lineEdit->text().toFloat(&ok); + if (ok) { + m_value = newValue; + m_lineEdit->setText(QString::number(m_value)); // "Clean up" text + emit valueChanged(m_value, m_id); + } +} + +//============================================================================// +// TwoSidedGraphicsWidget // +//============================================================================// + +TwoSidedGraphicsWidget::TwoSidedGraphicsWidget(QGraphicsScene *scene) + : QObject(scene) + , m_current(0) + , m_angle(0) + , m_delta(0) +{ + for (int i = 0; i < 2; ++i) + m_proxyWidgets[i] = 0; +} + +void TwoSidedGraphicsWidget::setWidget(int index, QWidget *widget) +{ + if (index < 0 || index >= 2) + { + qWarning("TwoSidedGraphicsWidget::setWidget: Index out of bounds, index == %d", index); + return; + } + + GraphicsWidget *proxy = new GraphicsWidget; + proxy->setWidget(widget); + + if (m_proxyWidgets[index]) + delete m_proxyWidgets[index]; + m_proxyWidgets[index] = proxy; + + proxy->setCacheMode(QGraphicsItem::ItemCoordinateCache); + proxy->setZValue(1e30); // Make sure the dialog is drawn on top of all other (OpenGL) items + + if (index != m_current) + proxy->setVisible(false); + + qobject_cast(parent())->addItem(proxy); +} + +QWidget *TwoSidedGraphicsWidget::widget(int index) +{ + if (index < 0 || index >= 2) + { + qWarning("TwoSidedGraphicsWidget::widget: Index out of bounds, index == %d", index); + return 0; + } + return m_proxyWidgets[index]->widget(); +} + +void TwoSidedGraphicsWidget::flip() +{ + m_delta = (m_current == 0 ? 9 : -9); + animateFlip(); +} + +void TwoSidedGraphicsWidget::animateFlip() +{ + m_angle += m_delta; + if (m_angle == 90) { + int old = m_current; + m_current ^= 1; + m_proxyWidgets[old]->setVisible(false); + m_proxyWidgets[m_current]->setVisible(true); + m_proxyWidgets[m_current]->setGeometry(m_proxyWidgets[old]->geometry()); + } + + QRectF r = m_proxyWidgets[m_current]->boundingRect(); + m_proxyWidgets[m_current]->setTransform(QTransform() + .translate(r.width() / 2, r.height() / 2) + .rotate(m_angle - 180 * m_current, Qt::YAxis) + .translate(-r.width() / 2, -r.height() / 2)); + + if ((m_current == 0 && m_angle > 0) || (m_current == 1 && m_angle < 180)) + QTimer::singleShot(25, this, SLOT(animateFlip())); +} + +QVariant GraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemPositionChange && scene()) { + QRectF rect = boundingRect(); + QPointF pos = value.toPointF(); + QRectF sceneRect = scene()->sceneRect(); + if (pos.x() + rect.left() < sceneRect.left()) + pos.setX(sceneRect.left() - rect.left()); + else if (pos.x() + rect.right() >= sceneRect.right()) + pos.setX(sceneRect.right() - rect.right()); + if (pos.y() + rect.top() < sceneRect.top()) + pos.setY(sceneRect.top() - rect.top()); + else if (pos.y() + rect.bottom() >= sceneRect.bottom()) + pos.setY(sceneRect.bottom() - rect.bottom()); + return pos; + } + return QGraphicsProxyWidget::itemChange(change, value); +} + +void GraphicsWidget::resizeEvent(QGraphicsSceneResizeEvent *event) +{ + setCacheMode(QGraphicsItem::NoCache); + setCacheMode(QGraphicsItem::ItemCoordinateCache); + QGraphicsProxyWidget::resizeEvent(event); +} + +void GraphicsWidget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + painter->setRenderHint(QPainter::Antialiasing, false); + QGraphicsProxyWidget::paint(painter, option, widget); + //painter->setRenderHint(QPainter::Antialiasing, true); +} + +//============================================================================// +// RenderOptionsDialog // +//============================================================================// + +RenderOptionsDialog::RenderOptionsDialog() + : QDialog(0, Qt::CustomizeWindowHint | Qt::WindowTitleHint) +{ + setWindowOpacity(0.75); + setWindowTitle(tr("Options (double click to flip)")); + QGridLayout *layout = new QGridLayout; + setLayout(layout); + layout->setColumnStretch(1, 1); + + int row = 0; + + QCheckBox *check = new QCheckBox(tr("Dynamic cube map")); + check->setCheckState(Qt::Unchecked); + // Dynamic cube maps are only enabled when multi-texturing and render to texture are available. + check->setEnabled(glActiveTexture && glGenFramebuffersEXT); + connect(check, SIGNAL(stateChanged(int)), this, SIGNAL(dynamicCubemapToggled(int))); + layout->addWidget(check, 0, 0, 1, 2); + ++row; + + QPalette palette; + + // Load all .par files + // .par files have a simple syntax for specifying user adjustable uniform variables. + QSet uniforms; + QList filter = QStringList("*.par"); + QList files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable); + + foreach (QFileInfo fileInfo, files) { + QFile file(fileInfo.absoluteFilePath()); + if (file.open(QIODevice::ReadOnly)) { + while (!file.atEnd()) { + QList tokens = file.readLine().simplified().split(' '); + QList::const_iterator it = tokens.begin(); + if (it == tokens.end()) + continue; + QByteArray type = *it; + if (++it == tokens.end()) + continue; + QByteArray name = *it; + bool singleElement = (tokens.size() == 3); // type, name and one value + char counter[10] = "000000000"; + int counterPos = 8; // position of last digit + while (++it != tokens.end()) { + m_parameterNames << name; + if (!singleElement) { + m_parameterNames.back() += "["; + m_parameterNames.back() += counter + counterPos; + m_parameterNames.back() += "]"; + int j = 8; // position of last digit + ++counter[j]; + while (j > 0 && counter[j] > '9') { + counter[j] = '0'; + ++counter[--j]; + } + if (j < counterPos) + counterPos = j; + } + + if (type == "color") { + layout->addWidget(new QLabel(m_parameterNames.back())); + bool ok; + ColorEdit *colorEdit = new ColorEdit(it->toUInt(&ok, 16), m_parameterNames.size() - 1); + m_parameterEdits << colorEdit; + layout->addWidget(colorEdit); + connect(colorEdit, SIGNAL(colorChanged(QRgb,int)), this, SLOT(setColorParameter(QRgb,int))); + ++row; + } else if (type == "float") { + layout->addWidget(new QLabel(m_parameterNames.back())); + bool ok; + FloatEdit *floatEdit = new FloatEdit(it->toFloat(&ok), m_parameterNames.size() - 1); + m_parameterEdits << floatEdit; + layout->addWidget(floatEdit); + connect(floatEdit, SIGNAL(valueChanged(float,int)), this, SLOT(setFloatParameter(float,int))); + ++row; + } + } + } + file.close(); + } + } + + layout->addWidget(new QLabel(tr("Texture:"))); + m_textureCombo = new QComboBox; + connect(m_textureCombo, SIGNAL(currentIndexChanged(int)), this, SIGNAL(textureChanged(int))); + layout->addWidget(m_textureCombo); + ++row; + + layout->addWidget(new QLabel(tr("Shader:"))); + m_shaderCombo = new QComboBox; + connect(m_shaderCombo, SIGNAL(currentIndexChanged(int)), this, SIGNAL(shaderChanged(int))); + layout->addWidget(m_shaderCombo); + ++row; + + layout->setRowStretch(row, 1); +} + +int RenderOptionsDialog::addTexture(const QString &name) +{ + m_textureCombo->addItem(name); + return m_textureCombo->count() - 1; +} + +int RenderOptionsDialog::addShader(const QString &name) +{ + m_shaderCombo->addItem(name); + return m_shaderCombo->count() - 1; +} + +void RenderOptionsDialog::emitParameterChanged() +{ + foreach (ParameterEdit *edit, m_parameterEdits) + edit->emitChange(); +} + +void RenderOptionsDialog::setColorParameter(QRgb color, int id) +{ + emit colorParameterChanged(m_parameterNames[id], color); +} + +void RenderOptionsDialog::setFloatParameter(float value, int id) +{ + emit floatParameterChanged(m_parameterNames[id], value); +} + +void RenderOptionsDialog::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) + emit doubleClicked(); +} + +//============================================================================// +// ItemDialog // +//============================================================================// + +ItemDialog::ItemDialog() + : QDialog(0, Qt::CustomizeWindowHint | Qt::WindowTitleHint) +{ + setWindowTitle(tr("Items (double click to flip)")); + setWindowOpacity(0.75); + resize(160, 100); + + QVBoxLayout *layout = new QVBoxLayout; + setLayout(layout); + QPushButton *button; + + button = new QPushButton(tr("Add Qt box")); + layout->addWidget(button); + connect(button, SIGNAL(clicked()), this, SLOT(triggerNewQtBox())); + + button = new QPushButton(tr("Add circle")); + layout->addWidget(button); + connect(button, SIGNAL(clicked()), this, SLOT(triggerNewCircleItem())); + + button = new QPushButton(tr("Add square")); + layout->addWidget(button); + connect(button, SIGNAL(clicked()), this, SLOT(triggerNewSquareItem())); + + layout->addStretch(1); +} + +void ItemDialog::triggerNewQtBox() +{ + emit newItemTriggered(QtBoxItem); +} + +void ItemDialog::triggerNewCircleItem() +{ + emit newItemTriggered(CircleItem); +} + +void ItemDialog::triggerNewSquareItem() +{ + emit newItemTriggered(SquareItem); +} + +void ItemDialog::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) + emit doubleClicked(); +} + +//============================================================================// +// Scene // +//============================================================================// + +const static char environmentShaderText[] = + "uniform samplerCube env;" + "void main() {" + "gl_FragColor = textureCube(env, gl_TexCoord[1].xyz);" + "}"; + +Scene::Scene(int width, int height, int maxTextureSize) + : m_distExp(600) + , m_frame(0) + , m_maxTextureSize(maxTextureSize) + , m_currentShader(0) + , m_currentTexture(0) + , m_dynamicCubemap(false) + , m_updateAllCubemaps(true) + , m_box(0) + , m_vertexShader(0) + , m_environmentShader(0) + , m_environmentProgram(0) +{ + setSceneRect(0, 0, width, height); + + m_trackBalls[0] = TrackBall(0.05f, QVector3D(0, 1, 0), TrackBall::Sphere); + m_trackBalls[1] = TrackBall(0.005f, QVector3D(0, 0, 1), TrackBall::Sphere); + m_trackBalls[2] = TrackBall(0.0f, QVector3D(0, 1, 0), TrackBall::Plane); + + m_renderOptions = new RenderOptionsDialog; + m_renderOptions->move(20, 120); + m_renderOptions->resize(m_renderOptions->sizeHint()); + + connect(m_renderOptions, SIGNAL(dynamicCubemapToggled(int)), this, SLOT(toggleDynamicCubemap(int))); + connect(m_renderOptions, SIGNAL(colorParameterChanged(QString,QRgb)), this, SLOT(setColorParameter(QString,QRgb))); + connect(m_renderOptions, SIGNAL(floatParameterChanged(QString,float)), this, SLOT(setFloatParameter(QString,float))); + connect(m_renderOptions, SIGNAL(textureChanged(int)), this, SLOT(setTexture(int))); + connect(m_renderOptions, SIGNAL(shaderChanged(int)), this, SLOT(setShader(int))); + + m_itemDialog = new ItemDialog; + connect(m_itemDialog, SIGNAL(newItemTriggered(ItemDialog::ItemType)), this, SLOT(newItem(ItemDialog::ItemType))); + + TwoSidedGraphicsWidget *twoSided = new TwoSidedGraphicsWidget(this); + twoSided->setWidget(0, m_renderOptions); + twoSided->setWidget(1, m_itemDialog); + + connect(m_renderOptions, SIGNAL(doubleClicked()), twoSided, SLOT(flip())); + connect(m_itemDialog, SIGNAL(doubleClicked()), twoSided, SLOT(flip())); + + addItem(new QtBox(64, width - 64, height - 64)); + addItem(new QtBox(64, width - 64, 64)); + addItem(new QtBox(64, 64, height - 64)); + addItem(new QtBox(64, 64, 64)); + + initGL(); + + m_timer = new QTimer(this); + m_timer->setInterval(20); + connect(m_timer, SIGNAL(timeout()), this, SLOT(update())); + m_timer->start(); + + m_time.start(); +} + +Scene::~Scene() +{ + if (m_box) + delete m_box; + foreach (GLTexture *texture, m_textures) + if (texture) delete texture; + if (m_mainCubemap) + delete m_mainCubemap; + foreach (QGLShaderProgram *program, m_programs) + if (program) delete program; + if (m_vertexShader) + delete m_vertexShader; + foreach (QGLShader *shader, m_fragmentShaders) + if (shader) delete shader; + foreach (GLRenderTargetCube *rt, m_cubemaps) + if (rt) delete rt; + if (m_environmentShader) + delete m_environmentShader; + if (m_environmentProgram) + delete m_environmentProgram; +} + +void Scene::initGL() +{ + m_box = new GLRoundedBox(0.25f, 1.0f, 10); + + m_vertexShader = new QGLShader(QGLShader::Vertex); + m_vertexShader->compileSourceFile(QLatin1String(":/res/boxes/basic.vsh")); + + QStringList list; + list << ":/res/boxes/cubemap_posx.jpg" << ":/res/boxes/cubemap_negx.jpg" << ":/res/boxes/cubemap_posy.jpg" + << ":/res/boxes/cubemap_negy.jpg" << ":/res/boxes/cubemap_posz.jpg" << ":/res/boxes/cubemap_negz.jpg"; + m_environment = new GLTextureCube(list, qMin(1024, m_maxTextureSize)); + m_environmentShader = new QGLShader(QGLShader::Fragment); + m_environmentShader->compileSourceCode(environmentShaderText); + m_environmentProgram = new QGLShaderProgram; + m_environmentProgram->addShader(m_vertexShader); + m_environmentProgram->addShader(m_environmentShader); + m_environmentProgram->link(); + + const int NOISE_SIZE = 128; // for a different size, B and BM in fbm.c must also be changed + m_noise = new GLTexture3D(NOISE_SIZE, NOISE_SIZE, NOISE_SIZE); + QRgb *data = new QRgb[NOISE_SIZE * NOISE_SIZE * NOISE_SIZE]; + memset(data, 0, NOISE_SIZE * NOISE_SIZE * NOISE_SIZE * sizeof(QRgb)); + QRgb *p = data; + float pos[3]; + for (int k = 0; k < NOISE_SIZE; ++k) { + pos[2] = k * (0x20 / (float)NOISE_SIZE); + for (int j = 0; j < NOISE_SIZE; ++j) { + for (int i = 0; i < NOISE_SIZE; ++i) { + for (int byte = 0; byte < 4; ++byte) { + pos[0] = (i + (byte & 1) * 16) * (0x20 / (float)NOISE_SIZE); + pos[1] = (j + (byte & 2) * 8) * (0x20 / (float)NOISE_SIZE); + *p |= (int)(128.0f * (noise3(pos) + 1.0f)) << (byte * 8); + } + ++p; + } + } + } + m_noise->load(NOISE_SIZE, NOISE_SIZE, NOISE_SIZE, data); + delete[] data; + + m_mainCubemap = new GLRenderTargetCube(512); + + QStringList filter; + QList files; + + // Load all .png files as textures + m_currentTexture = 0; + filter = QStringList("*.png"); + files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable); + + foreach (QFileInfo file, files) { + GLTexture *texture = new GLTexture2D(file.absoluteFilePath(), qMin(256, m_maxTextureSize), qMin(256, m_maxTextureSize)); + if (texture->failed()) { + delete texture; + continue; + } + m_textures << texture; + m_renderOptions->addTexture(file.baseName()); + } + + if (m_textures.size() == 0) + m_textures << new GLTexture2D(qMin(64, m_maxTextureSize), qMin(64, m_maxTextureSize)); + + // Load all .fsh files as fragment shaders + m_currentShader = 0; + filter = QStringList("*.fsh"); + files = QDir(":/res/boxes/").entryInfoList(filter, QDir::Files | QDir::Readable); + foreach (QFileInfo file, files) { + QGLShaderProgram *program = new QGLShaderProgram; + QGLShader* shader = new QGLShader(QGLShader::Fragment); + shader->compileSourceFile(file.absoluteFilePath()); + // The program does not take ownership over the shaders, so store them in a vector so they can be deleted afterwards. + program->addShader(m_vertexShader); + program->addShader(shader); + if (!program->link()) { + qWarning("Failed to compile and link shader program"); + qWarning("Vertex shader log:"); + qWarning() << m_vertexShader->log(); + qWarning() << "Fragment shader log ( file =" << file.absoluteFilePath() << "):"; + qWarning() << shader->log(); + qWarning("Shader program log:"); + qWarning() << program->log(); + + delete shader; + delete program; + continue; + } + + m_fragmentShaders << shader; + m_programs << program; + m_renderOptions->addShader(file.baseName()); + + program->bind(); + m_cubemaps << ((program->uniformLocation("env") != -1) ? new GLRenderTargetCube(qMin(256, m_maxTextureSize)) : 0); + program->release(); + } + + if (m_programs.size() == 0) + m_programs << new QGLShaderProgram; + + m_renderOptions->emitParameterChanged(); +} + +static void loadMatrix(const QMatrix4x4& m) +{ + // static to prevent glLoadMatrixf to fail on certain drivers + static GLfloat mat[16]; + const qreal *data = m.constData(); + for (int index = 0; index < 16; ++index) + mat[index] = data[index]; + glLoadMatrixf(mat); +} + +static void multMatrix(const QMatrix4x4& m) +{ + // static to prevent glMultMatrixf to fail on certain drivers + static GLfloat mat[16]; + const qreal *data = m.constData(); + for (int index = 0; index < 16; ++index) + mat[index] = data[index]; + glMultMatrixf(mat); +} + +// If one of the boxes should not be rendered, set excludeBox to its index. +// If the main box should not be rendered, set excludeBox to -1. +void Scene::renderBoxes(const QMatrix4x4 &view, int excludeBox) +{ + QMatrix4x4 invView = view.inverted(); + + // If multi-texturing is supported, use three saplers. + if (glActiveTexture) { + glActiveTexture(GL_TEXTURE0); + m_textures[m_currentTexture]->bind(); + glActiveTexture(GL_TEXTURE2); + m_noise->bind(); + glActiveTexture(GL_TEXTURE1); + } else { + m_textures[m_currentTexture]->bind(); + } + + glDisable(GL_LIGHTING); + glDisable(GL_CULL_FACE); + + QMatrix4x4 viewRotation(view); + viewRotation(3, 0) = viewRotation(3, 1) = viewRotation(3, 2) = 0.0f; + viewRotation(0, 3) = viewRotation(1, 3) = viewRotation(2, 3) = 0.0f; + viewRotation(3, 3) = 1.0f; + loadMatrix(viewRotation); + glScalef(20.0f, 20.0f, 20.0f); + + // Don't render the environment if the environment texture can't be set for the correct sampler. + if (glActiveTexture) { + m_environment->bind(); + m_environmentProgram->bind(); + m_environmentProgram->setUniformValue("tex", GLint(0)); + m_environmentProgram->setUniformValue("env", GLint(1)); + m_environmentProgram->setUniformValue("noise", GLint(2)); + m_box->draw(); + m_environmentProgram->release(); + m_environment->unbind(); + } + + loadMatrix(view); + + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + + for (int i = 0; i < m_programs.size(); ++i) { + if (i == excludeBox) + continue; + + glPushMatrix(); + QMatrix4x4 m; + m.rotate(m_trackBalls[1].rotation()); + multMatrix(m); + + glRotatef(360.0f * i / m_programs.size(), 0.0f, 0.0f, 1.0f); + glTranslatef(2.0f, 0.0f, 0.0f); + glScalef(0.3f, 0.6f, 0.6f); + + if (glActiveTexture) { + if (m_dynamicCubemap && m_cubemaps[i]) + m_cubemaps[i]->bind(); + else + m_environment->bind(); + } + m_programs[i]->bind(); + m_programs[i]->setUniformValue("tex", GLint(0)); + m_programs[i]->setUniformValue("env", GLint(1)); + m_programs[i]->setUniformValue("noise", GLint(2)); + m_programs[i]->setUniformValue("view", view); + m_programs[i]->setUniformValue("invView", invView); + m_box->draw(); + m_programs[i]->release(); + + if (glActiveTexture) { + if (m_dynamicCubemap && m_cubemaps[i]) + m_cubemaps[i]->unbind(); + else + m_environment->unbind(); + } + glPopMatrix(); + } + + if (-1 != excludeBox) { + QMatrix4x4 m; + m.rotate(m_trackBalls[0].rotation()); + multMatrix(m); + + if (glActiveTexture) { + if (m_dynamicCubemap) + m_mainCubemap->bind(); + else + m_environment->bind(); + } + + m_programs[m_currentShader]->bind(); + m_programs[m_currentShader]->setUniformValue("tex", GLint(0)); + m_programs[m_currentShader]->setUniformValue("env", GLint(1)); + m_programs[m_currentShader]->setUniformValue("noise", GLint(2)); + m_programs[m_currentShader]->setUniformValue("view", view); + m_programs[m_currentShader]->setUniformValue("invView", invView); + m_box->draw(); + m_programs[m_currentShader]->release(); + + if (glActiveTexture) { + if (m_dynamicCubemap) + m_mainCubemap->unbind(); + else + m_environment->unbind(); + } + } + + if (glActiveTexture) { + glActiveTexture(GL_TEXTURE2); + m_noise->unbind(); + glActiveTexture(GL_TEXTURE0); + } + m_textures[m_currentTexture]->unbind(); +} + +void Scene::setStates() +{ + //glClearColor(0.25f, 0.25f, 0.5f, 1.0f); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + //glEnable(GL_COLOR_MATERIAL); + glEnable(GL_TEXTURE_2D); + glEnable(GL_NORMALIZE); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + setLights(); + + float materialSpecular[] = {0.5f, 0.5f, 0.5f, 1.0f}; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, materialSpecular); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 32.0f); +} + +void Scene::setLights() +{ + glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); + //float lightColour[] = {1.0f, 1.0f, 1.0f, 1.0f}; + float lightDir[] = {0.0f, 0.0f, 1.0f, 0.0f}; + //glLightfv(GL_LIGHT0, GL_DIFFUSE, lightColour); + //glLightfv(GL_LIGHT0, GL_SPECULAR, lightColour); + glLightfv(GL_LIGHT0, GL_POSITION, lightDir); + glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, 1.0f); + glEnable(GL_LIGHT0); +} + +void Scene::defaultStates() +{ + //glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_LIGHTING); + //glDisable(GL_COLOR_MATERIAL); + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHT0); + glDisable(GL_NORMALIZE); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, 0.0f); + float defaultMaterialSpecular[] = {0.0f, 0.0f, 0.0f, 1.0f}; + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, defaultMaterialSpecular); + glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f); +} + +void Scene::renderCubemaps() +{ + // To speed things up, only update the cubemaps for the small cubes every N frames. + const int N = (m_updateAllCubemaps ? 1 : 3); + + QMatrix4x4 mat; + GLRenderTargetCube::getProjectionMatrix(mat, 0.1f, 100.0f); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + loadMatrix(mat); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + QVector3D center; + + for (int i = m_frame % N; i < m_cubemaps.size(); i += N) { + if (0 == m_cubemaps[i]) + continue; + + float angle = 2.0f * PI * i / m_cubemaps.size(); + + center = m_trackBalls[1].rotation().rotatedVector(QVector3D(cos(angle), sin(angle), 0.0f)); + + for (int face = 0; face < 6; ++face) { + m_cubemaps[i]->begin(face); + + GLRenderTargetCube::getViewMatrix(mat, face); + QVector4D v = QVector4D(-center.x(), -center.y(), -center.z(), 1.0); + mat.setColumn(3, mat * v); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + renderBoxes(mat, i); + + m_cubemaps[i]->end(); + } + } + + for (int face = 0; face < 6; ++face) { + m_mainCubemap->begin(face); + GLRenderTargetCube::getViewMatrix(mat, face); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + renderBoxes(mat, -1); + + m_mainCubemap->end(); + } + + glPopMatrix(); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + m_updateAllCubemaps = false; +} + +void Scene::drawBackground(QPainter *painter, const QRectF &) +{ + float width = float(painter->device()->width()); + float height = float(painter->device()->height()); + + painter->beginNativePainting(); + setStates(); + + if (m_dynamicCubemap) + renderCubemaps(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_PROJECTION); + qgluPerspective(60.0, width / height, 0.01, 15.0); + + glMatrixMode(GL_MODELVIEW); + + QMatrix4x4 view; + view.rotate(m_trackBalls[2].rotation()); + view(2, 3) -= 2.0f * exp(m_distExp / 1200.0f); + renderBoxes(view); + + defaultStates(); + ++m_frame; + + painter->endNativePainting(); +} + +QPointF Scene::pixelPosToViewPos(const QPointF& p) +{ + return QPointF(2.0 * float(p.x()) / width() - 1.0, + 1.0 - 2.0 * float(p.y()) / height()); +} + +void Scene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsScene::mouseMoveEvent(event); + if (event->isAccepted()) + return; + + if (event->buttons() & Qt::LeftButton) { + m_trackBalls[0].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + event->accept(); + } else { + m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + } + + if (event->buttons() & Qt::RightButton) { + m_trackBalls[1].move(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + event->accept(); + } else { + m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + } + + if (event->buttons() & Qt::MidButton) { + m_trackBalls[2].move(pixelPosToViewPos(event->scenePos()), QQuaternion()); + event->accept(); + } else { + m_trackBalls[2].release(pixelPosToViewPos(event->scenePos()), QQuaternion()); + } +} + +void Scene::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsScene::mousePressEvent(event); + if (event->isAccepted()) + return; + + if (event->buttons() & Qt::LeftButton) { + m_trackBalls[0].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + event->accept(); + } + + if (event->buttons() & Qt::RightButton) { + m_trackBalls[1].push(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + event->accept(); + } + + if (event->buttons() & Qt::MidButton) { + m_trackBalls[2].push(pixelPosToViewPos(event->scenePos()), QQuaternion()); + event->accept(); + } +} + +void Scene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsScene::mouseReleaseEvent(event); + if (event->isAccepted()) + return; + + if (event->button() == Qt::LeftButton) { + m_trackBalls[0].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + event->accept(); + } + + if (event->button() == Qt::RightButton) { + m_trackBalls[1].release(pixelPosToViewPos(event->scenePos()), m_trackBalls[2].rotation().conjugate()); + event->accept(); + } + + if (event->button() == Qt::MidButton) { + m_trackBalls[2].release(pixelPosToViewPos(event->scenePos()), QQuaternion()); + event->accept(); + } +} + +void Scene::wheelEvent(QGraphicsSceneWheelEvent * event) +{ + QGraphicsScene::wheelEvent(event); + if (!event->isAccepted()) { + m_distExp += event->delta(); + if (m_distExp < -8 * 120) + m_distExp = -8 * 120; + if (m_distExp > 10 * 120) + m_distExp = 10 * 120; + event->accept(); + } +} + +void Scene::setShader(int index) +{ + if (index >= 0 && index < m_fragmentShaders.size()) + m_currentShader = index; +} + +void Scene::setTexture(int index) +{ + if (index >= 0 && index < m_textures.size()) + m_currentTexture = index; +} + +void Scene::toggleDynamicCubemap(int state) +{ + if ((m_dynamicCubemap = (state == Qt::Checked))) + m_updateAllCubemaps = true; +} + +void Scene::setColorParameter(const QString &name, QRgb color) +{ + // set the color in all programs + foreach (QGLShaderProgram *program, m_programs) { + program->bind(); + program->setUniformValue(program->uniformLocation(name), QColor(color)); + program->release(); + } +} + +void Scene::setFloatParameter(const QString &name, float value) +{ + // set the color in all programs + foreach (QGLShaderProgram *program, m_programs) { + program->bind(); + program->setUniformValue(program->uniformLocation(name), value); + program->release(); + } +} + +void Scene::newItem(ItemDialog::ItemType type) +{ + QSize size = sceneRect().size().toSize(); + switch (type) { + case ItemDialog::QtBoxItem: + addItem(new QtBox(64, rand() % (size.width() - 64) + 32, rand() % (size.height() - 64) + 32)); + break; + case ItemDialog::CircleItem: + addItem(new CircleItem(64, rand() % (size.width() - 64) + 32, rand() % (size.height() - 64) + 32)); + break; + case ItemDialog::SquareItem: + addItem(new SquareItem(64, rand() % (size.width() - 64) + 32, rand() % (size.height() - 64) + 32)); + break; + default: + break; + } +} diff --git a/examples/graphicsview/boxes/scene.h b/examples/graphicsview/boxes/scene.h new file mode 100644 index 0000000000..96ee908d58 --- /dev/null +++ b/examples/graphicsview/boxes/scene.h @@ -0,0 +1,245 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SCENE_H +#define SCENE_H + +//#include +#include "glextensions.h" + +#include +#include + +#include "roundedbox.h" +#include "gltrianglemesh.h" +#include "trackball.h" +#include "glbuffers.h" +#include "qtbox.h" + +#define PI 3.14159265358979 + +QT_BEGIN_NAMESPACE +class QMatrix4x4; +QT_END_NAMESPACE + +class ParameterEdit : public QWidget +{ +public: + virtual void emitChange() = 0; +}; + +class ColorEdit : public ParameterEdit +{ + Q_OBJECT +public: + ColorEdit(QRgb initialColor, int id); + QRgb color() const {return m_color;} + virtual void emitChange() {emit colorChanged(m_color, m_id);} +public slots: + void editDone(); +signals: + void colorChanged(QRgb color, int id); +protected: + virtual void mousePressEvent(QMouseEvent *event); + void setColor(QRgb color); // also emits colorChanged() +private: + QGraphicsScene *m_dialogParentScene; + QLineEdit *m_lineEdit; + QFrame *m_button; + QRgb m_color; + int m_id; +}; + +class FloatEdit : public ParameterEdit +{ + Q_OBJECT +public: + FloatEdit(float initialValue, int id); + float value() const {return m_value;} + virtual void emitChange() {emit valueChanged(m_value, m_id);} +public slots: + void editDone(); +signals: + void valueChanged(float value, int id); +private: + QGraphicsScene *m_dialogParentScene; + QLineEdit *m_lineEdit; + float m_value; + int m_id; +}; + +class GraphicsWidget : public QGraphicsProxyWidget +{ +public: + GraphicsWidget() : QGraphicsProxyWidget(0, Qt::Window) {} +protected: + virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); + virtual void resizeEvent(QGraphicsSceneResizeEvent *event); + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); +}; + +class TwoSidedGraphicsWidget : public QObject +{ + Q_OBJECT +public: + TwoSidedGraphicsWidget(QGraphicsScene *scene); + void setWidget(int index, QWidget *widget); + QWidget *widget(int index); +public slots: + void flip(); +protected slots: + void animateFlip(); +private: + GraphicsWidget *m_proxyWidgets[2]; + int m_current; + int m_angle; // angle in degrees + int m_delta; +}; + +class RenderOptionsDialog : public QDialog +{ + Q_OBJECT +public: + RenderOptionsDialog(); + int addTexture(const QString &name); + int addShader(const QString &name); + void emitParameterChanged(); +protected slots: + void setColorParameter(QRgb color, int id); + void setFloatParameter(float value, int id); +signals: + void dynamicCubemapToggled(int); + void colorParameterChanged(const QString &, QRgb); + void floatParameterChanged(const QString &, float); + void textureChanged(int); + void shaderChanged(int); + void doubleClicked(); +protected: + virtual void mouseDoubleClickEvent(QMouseEvent *event); + + QVector m_parameterNames; + QComboBox *m_textureCombo; + QComboBox *m_shaderCombo; + QVector m_parameterEdits; +}; + +class ItemDialog : public QDialog +{ + Q_OBJECT +public: + enum ItemType { + QtBoxItem, + CircleItem, + SquareItem, + }; + + ItemDialog(); +public slots: + void triggerNewQtBox(); + void triggerNewCircleItem(); + void triggerNewSquareItem(); +signals: + void doubleClicked(); + void newItemTriggered(ItemDialog::ItemType type); +protected: + virtual void mouseDoubleClickEvent(QMouseEvent *event); +}; + +class Scene : public QGraphicsScene +{ + Q_OBJECT +public: + Scene(int width, int height, int maxTextureSize); + ~Scene(); + virtual void drawBackground(QPainter *painter, const QRectF &rect); + +public slots: + void setShader(int index); + void setTexture(int index); + void toggleDynamicCubemap(int state); + void setColorParameter(const QString &name, QRgb color); + void setFloatParameter(const QString &name, float value); + void newItem(ItemDialog::ItemType type); +protected: + void renderBoxes(const QMatrix4x4 &view, int excludeBox = -2); + void setStates(); + void setLights(); + void defaultStates(); + void renderCubemaps(); + + virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + virtual void wheelEvent(QGraphicsSceneWheelEvent * event); +private: + void initGL(); + QPointF pixelPosToViewPos(const QPointF& p); + + QTime m_time; + int m_lastTime; + int m_mouseEventTime; + int m_distExp; + int m_frame; + int m_maxTextureSize; + + int m_currentShader; + int m_currentTexture; + bool m_dynamicCubemap; + bool m_updateAllCubemaps; + + RenderOptionsDialog *m_renderOptions; + ItemDialog *m_itemDialog; + QTimer *m_timer; + GLRoundedBox *m_box; + TrackBall m_trackBalls[3]; + QVector m_textures; + GLTextureCube *m_environment; + GLTexture3D *m_noise; + GLRenderTargetCube *m_mainCubemap; + QVector m_cubemaps; + QVector m_programs; + QGLShader *m_vertexShader; + QVector m_fragmentShaders; + QGLShader *m_environmentShader; + QGLShaderProgram *m_environmentProgram; +}; + +#endif diff --git a/examples/graphicsview/boxes/smiley.png b/examples/graphicsview/boxes/smiley.png new file mode 100644 index 0000000000..41cfda6b23 Binary files /dev/null and b/examples/graphicsview/boxes/smiley.png differ diff --git a/examples/graphicsview/boxes/square.jpg b/examples/graphicsview/boxes/square.jpg new file mode 100644 index 0000000000..03f53bd530 Binary files /dev/null and b/examples/graphicsview/boxes/square.jpg differ diff --git a/examples/graphicsview/boxes/trackball.cpp b/examples/graphicsview/boxes/trackball.cpp new file mode 100644 index 0000000000..1bb864ce90 --- /dev/null +++ b/examples/graphicsview/boxes/trackball.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "trackball.h" +#include "scene.h" + +//============================================================================// +// TrackBall // +//============================================================================// + +TrackBall::TrackBall(TrackMode mode) + : m_angularVelocity(0) + , m_paused(false) + , m_pressed(false) + , m_mode(mode) +{ + m_axis = QVector3D(0, 1, 0); + m_rotation = QQuaternion(); + m_lastTime = QTime::currentTime(); +} + +TrackBall::TrackBall(float angularVelocity, const QVector3D& axis, TrackMode mode) + : m_axis(axis) + , m_angularVelocity(angularVelocity) + , m_paused(false) + , m_pressed(false) + , m_mode(mode) +{ + m_rotation = QQuaternion(); + m_lastTime = QTime::currentTime(); +} + +void TrackBall::push(const QPointF& p, const QQuaternion &) +{ + m_rotation = rotation(); + m_pressed = true; + m_lastTime = QTime::currentTime(); + m_lastPos = p; + m_angularVelocity = 0.0f; +} + +void TrackBall::move(const QPointF& p, const QQuaternion &transformation) +{ + if (!m_pressed) + return; + + QTime currentTime = QTime::currentTime(); + int msecs = m_lastTime.msecsTo(currentTime); + if (msecs <= 20) + return; + + switch (m_mode) { + case Plane: + { + QLineF delta(m_lastPos, p); + m_angularVelocity = 180*delta.length() / (PI*msecs); + m_axis = QVector3D(-delta.dy(), delta.dx(), 0.0f).normalized(); + m_axis = transformation.rotatedVector(m_axis); + m_rotation = QQuaternion::fromAxisAndAngle(m_axis, 180 / PI * delta.length()) * m_rotation; + } + break; + case Sphere: + { + QVector3D lastPos3D = QVector3D(m_lastPos.x(), m_lastPos.y(), 0.0f); + float sqrZ = 1 - QVector3D::dotProduct(lastPos3D, lastPos3D); + if (sqrZ > 0) + lastPos3D.setZ(sqrt(sqrZ)); + else + lastPos3D.normalize(); + + QVector3D currentPos3D = QVector3D(p.x(), p.y(), 0.0f); + sqrZ = 1 - QVector3D::dotProduct(currentPos3D, currentPos3D); + if (sqrZ > 0) + currentPos3D.setZ(sqrt(sqrZ)); + else + currentPos3D.normalize(); + + m_axis = QVector3D::crossProduct(lastPos3D, currentPos3D); + float angle = 180 / PI * asin(sqrt(QVector3D::dotProduct(m_axis, m_axis))); + + m_angularVelocity = angle / msecs; + m_axis.normalize(); + m_axis = transformation.rotatedVector(m_axis); + m_rotation = QQuaternion::fromAxisAndAngle(m_axis, angle) * m_rotation; + } + break; + } + + + m_lastPos = p; + m_lastTime = currentTime; +} + +void TrackBall::release(const QPointF& p, const QQuaternion &transformation) +{ + // Calling move() caused the rotation to stop if the framerate was too low. + move(p, transformation); + m_pressed = false; +} + +void TrackBall::start() +{ + m_lastTime = QTime::currentTime(); + m_paused = false; +} + +void TrackBall::stop() +{ + m_rotation = rotation(); + m_paused = true; +} + +QQuaternion TrackBall::rotation() const +{ + if (m_paused || m_pressed) + return m_rotation; + + QTime currentTime = QTime::currentTime(); + float angle = m_angularVelocity * m_lastTime.msecsTo(currentTime); + return QQuaternion::fromAxisAndAngle(m_axis, angle) * m_rotation; +} + diff --git a/examples/graphicsview/boxes/trackball.h b/examples/graphicsview/boxes/trackball.h new file mode 100644 index 0000000000..097851a42c --- /dev/null +++ b/examples/graphicsview/boxes/trackball.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TRACKBALL_H +#define TRACKBALL_H + +#include + +#include +#include + +class TrackBall +{ +public: + enum TrackMode + { + Plane, + Sphere, + }; + TrackBall(TrackMode mode = Sphere); + TrackBall(float angularVelocity, const QVector3D& axis, TrackMode mode = Sphere); + // coordinates in [-1,1]x[-1,1] + void push(const QPointF& p, const QQuaternion &transformation); + void move(const QPointF& p, const QQuaternion &transformation); + void release(const QPointF& p, const QQuaternion &transformation); + void start(); // starts clock + void stop(); // stops clock + QQuaternion rotation() const; +private: + QQuaternion m_rotation; + QVector3D m_axis; + float m_angularVelocity; + + QPointF m_lastPos; + QTime m_lastTime; + bool m_paused; + bool m_pressed; + TrackMode m_mode; +}; + +#endif diff --git a/examples/graphicsview/boxes/wood.fsh b/examples/graphicsview/boxes/wood.fsh new file mode 100644 index 0000000000..19950b252c --- /dev/null +++ b/examples/graphicsview/boxes/wood.fsh @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +varying vec3 position, normal; +varying vec4 specular, ambient, diffuse, lightDirection; + +uniform sampler2D tex; +uniform sampler3D noise; + +//const vec4 woodColors[2] = {vec4(0.37,0.24,0.20,1), vec4(0.8,0.6,0.4,1)}; +uniform vec4 woodColors[2]; +//const float woodTubulence = 0.1; +uniform float woodTubulence; + +void main() +{ + float r = length(gl_TexCoord[1].yz); + r += woodTubulence * texture3D(noise, 0.25 * gl_TexCoord[1].xyz).x; + + vec3 N = normalize(normal); + // assume directional light + + gl_MaterialParameters M = gl_FrontMaterial; + + float NdotL = dot(N, lightDirection.xyz); + float RdotL = dot(reflect(normalize(position), N), lightDirection.xyz); + + float f = fract(16.0 * r); + vec4 unlitColor = mix(woodColors[0], woodColors[1], min(1.25 * f, 5.0 - 5.0 * f)); + gl_FragColor = (ambient + diffuse * max(NdotL, 0.0)) * unlitColor + + M.specular * specular * pow(max(RdotL, 0.0), M.shininess); +} diff --git a/examples/graphicsview/chip/chip.cpp b/examples/graphicsview/chip/chip.cpp new file mode 100644 index 0000000000..21b63bae2c --- /dev/null +++ b/examples/graphicsview/chip/chip.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "chip.h" + +#include + +Chip::Chip(const QColor &color, int x, int y) +{ + this->x = x; + this->y = y; + this->color = color; + setZValue((x + y) % 2); + + setFlags(ItemIsSelectable | ItemIsMovable); + setAcceptsHoverEvents(true); +} + +QRectF Chip::boundingRect() const +{ + return QRectF(0, 0, 110, 70); +} + +QPainterPath Chip::shape() const +{ + QPainterPath path; + path.addRect(14, 14, 82, 42); + return path; +} + +void Chip::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(widget); + + QColor fillColor = (option->state & QStyle::State_Selected) ? color.dark(150) : color; + if (option->state & QStyle::State_MouseOver) + fillColor = fillColor.light(125); + + const qreal lod = option->levelOfDetailFromTransform(painter->worldTransform()); + if (lod < 0.2) { + if (lod < 0.125) { + painter->fillRect(QRectF(0, 0, 110, 70), fillColor); + return; + } + + QBrush b = painter->brush(); + painter->setBrush(fillColor); + painter->drawRect(13, 13, 97, 57); + painter->setBrush(b); + return; + } + + QPen oldPen = painter->pen(); + QPen pen = oldPen; + int width = 0; + if (option->state & QStyle::State_Selected) + width += 2; + + pen.setWidth(width); + QBrush b = painter->brush(); + painter->setBrush(QBrush(fillColor.dark(option->state & QStyle::State_Sunken ? 120 : 100))); + + painter->drawRect(QRect(14, 14, 79, 39)); + painter->setBrush(b); + + if (lod >= 1) { + painter->setPen(QPen(Qt::gray, 1)); + painter->drawLine(15, 54, 94, 54); + painter->drawLine(94, 53, 94, 15); + painter->setPen(QPen(Qt::black, 0)); + } + + // Draw text + if (lod >= 2) { + QFont font("Times", 10); + font.setStyleStrategy(QFont::ForceOutline); + painter->setFont(font); + painter->save(); + painter->scale(0.1, 0.1); + painter->drawText(170, 180, QString("Model: VSC-2000 (Very Small Chip) at %1x%2").arg(x).arg(y)); + painter->drawText(170, 200, QString("Serial number: DLWR-WEER-123L-ZZ33-SDSJ")); + painter->drawText(170, 220, QString("Manufacturer: Chip Manufacturer")); + painter->restore(); + } + + // Draw lines + QVarLengthArray lines; + if (lod >= 0.5) { + for (int i = 0; i <= 10; i += (lod > 0.5 ? 1 : 2)) { + lines.append(QLineF(18 + 7 * i, 13, 18 + 7 * i, 5)); + lines.append(QLineF(18 + 7 * i, 54, 18 + 7 * i, 62)); + } + for (int i = 0; i <= 6; i += (lod > 0.5 ? 1 : 2)) { + lines.append(QLineF(5, 18 + i * 5, 13, 18 + i * 5)); + lines.append(QLineF(94, 18 + i * 5, 102, 18 + i * 5)); + } + } + if (lod >= 0.4) { + const QLineF lineData[] = { + QLineF(25, 35, 35, 35), + QLineF(35, 30, 35, 40), + QLineF(35, 30, 45, 35), + QLineF(35, 40, 45, 35), + QLineF(45, 30, 45, 40), + QLineF(45, 35, 55, 35) + }; + lines.append(lineData, 6); + } + painter->drawLines(lines.data(), lines.size()); + + // Draw red ink + if (stuff.size() > 1) { + QPen p = painter->pen(); + painter->setPen(QPen(Qt::red, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + painter->setBrush(Qt::NoBrush); + QPainterPath path; + path.moveTo(stuff.first()); + for (int i = 1; i < stuff.size(); ++i) + path.lineTo(stuff.at(i)); + painter->drawPath(path); + painter->setPen(p); + } +} + +void Chip::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsItem::mousePressEvent(event); + update(); +} + +void Chip::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->modifiers() & Qt::ShiftModifier) { + stuff << event->pos(); + update(); + return; + } + QGraphicsItem::mouseMoveEvent(event); +} + +void Chip::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + QGraphicsItem::mouseReleaseEvent(event); + update(); +} diff --git a/examples/graphicsview/chip/chip.h b/examples/graphicsview/chip/chip.h new file mode 100644 index 0000000000..ff9f636843 --- /dev/null +++ b/examples/graphicsview/chip/chip.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CHIP_H +#define CHIP_H + +#include +#include + +class Chip : public QGraphicsItem +{ +public: + Chip(const QColor &color, int x, int y); + + QRectF boundingRect() const; + QPainterPath shape() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + +private: + int x, y; + QColor color; + QList stuff; +}; + +#endif diff --git a/examples/graphicsview/chip/chip.pro b/examples/graphicsview/chip/chip.pro new file mode 100644 index 0000000000..1e1a7de735 --- /dev/null +++ b/examples/graphicsview/chip/chip.pro @@ -0,0 +1,20 @@ +RESOURCES += images.qrc + +HEADERS += mainwindow.h view.h chip.h +SOURCES += main.cpp +SOURCES += mainwindow.cpp view.cpp chip.cpp + +contains(QT_CONFIG, opengl):QT += opengl + +build_all:!build_pass { + CONFIG -= build_all + CONFIG += release +} + +# install +target.path = $$[QT_INSTALL_DEMOS]/qtbase/chip +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.png *.pro *.html *.doc images +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/chip +INSTALLS += target sources + +symbian: CONFIG += qt_demo diff --git a/examples/graphicsview/chip/fileprint.png b/examples/graphicsview/chip/fileprint.png new file mode 100644 index 0000000000..ba7c02dc18 Binary files /dev/null and b/examples/graphicsview/chip/fileprint.png differ diff --git a/examples/graphicsview/chip/images.qrc b/examples/graphicsview/chip/images.qrc new file mode 100644 index 0000000000..c7cdf0c4c0 --- /dev/null +++ b/examples/graphicsview/chip/images.qrc @@ -0,0 +1,10 @@ + + + qt4logo.png + zoomin.png + zoomout.png + rotateleft.png + rotateright.png + fileprint.png + + diff --git a/examples/graphicsview/chip/main.cpp b/examples/graphicsview/chip/main.cpp new file mode 100644 index 0000000000..e983e4cca6 --- /dev/null +++ b/examples/graphicsview/chip/main.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" + +#include + +int main(int argc, char **argv) +{ + Q_INIT_RESOURCE(images); + + QApplication app(argc, argv); + app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + + MainWindow window; + window.show(); + + return app.exec(); +} diff --git a/examples/graphicsview/chip/mainwindow.cpp b/examples/graphicsview/chip/mainwindow.cpp new file mode 100644 index 0000000000..7476c00ab1 --- /dev/null +++ b/examples/graphicsview/chip/mainwindow.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" +#include "view.h" +#include "chip.h" + +#include + +MainWindow::MainWindow(QWidget *parent) + : QWidget(parent) +{ + populateScene(); + + h1Splitter = new QSplitter; + h2Splitter = new QSplitter; + + QSplitter *vSplitter = new QSplitter; + vSplitter->setOrientation(Qt::Vertical); + vSplitter->addWidget(h1Splitter); + vSplitter->addWidget(h2Splitter); + + View *view = new View("Top left view"); + view->view()->setScene(scene); + h1Splitter->addWidget(view); + + view = new View("Top right view"); + view->view()->setScene(scene); + h1Splitter->addWidget(view); + + view = new View("Bottom left view"); + view->view()->setScene(scene); + h2Splitter->addWidget(view); + + view = new View("Bottom right view"); + view->view()->setScene(scene); + h2Splitter->addWidget(view); + + QHBoxLayout *layout = new QHBoxLayout; + layout->addWidget(vSplitter); + setLayout(layout); + + setWindowTitle(tr("Chip Demo")); +} + +void MainWindow::populateScene() +{ + scene = new QGraphicsScene; + + QImage image(":/qt4logo.png"); + + // Populate scene + int xx = 0; + int nitems = 0; + for (int i = -11000; i < 11000; i += 110) { + ++xx; + int yy = 0; + for (int j = -7000; j < 7000; j += 70) { + ++yy; + qreal x = (i + 11000) / 22000.0; + qreal y = (j + 7000) / 14000.0; + + QColor color(image.pixel(int(image.width() * x), int(image.height() * y))); + QGraphicsItem *item = new Chip(color, xx, yy); + item->setPos(QPointF(i, j)); + scene->addItem(item); + + ++nitems; + } + } +} diff --git a/examples/graphicsview/chip/mainwindow.h b/examples/graphicsview/chip/mainwindow.h new file mode 100644 index 0000000000..650e1f1f3c --- /dev/null +++ b/examples/graphicsview/chip/mainwindow.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +QT_FORWARD_DECLARE_CLASS(QGraphicsScene) +QT_FORWARD_DECLARE_CLASS(QGraphicsView) +QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QSlider) +QT_FORWARD_DECLARE_CLASS(QSplitter) + +class MainWindow : public QWidget +{ + Q_OBJECT +public: + MainWindow(QWidget *parent = 0); + +private: + void setupMatrix(); + void populateScene(); + + QGraphicsScene *scene; + QSplitter *h1Splitter; + QSplitter *h2Splitter; +}; + +#endif diff --git a/examples/graphicsview/chip/qt4logo.png b/examples/graphicsview/chip/qt4logo.png new file mode 100644 index 0000000000..157e86ed64 Binary files /dev/null and b/examples/graphicsview/chip/qt4logo.png differ diff --git a/examples/graphicsview/chip/rotateleft.png b/examples/graphicsview/chip/rotateleft.png new file mode 100644 index 0000000000..8cfa931986 Binary files /dev/null and b/examples/graphicsview/chip/rotateleft.png differ diff --git a/examples/graphicsview/chip/rotateright.png b/examples/graphicsview/chip/rotateright.png new file mode 100644 index 0000000000..ec5e8664a1 Binary files /dev/null and b/examples/graphicsview/chip/rotateright.png differ diff --git a/examples/graphicsview/chip/view.cpp b/examples/graphicsview/chip/view.cpp new file mode 100644 index 0000000000..5634f85d98 --- /dev/null +++ b/examples/graphicsview/chip/view.cpp @@ -0,0 +1,276 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "view.h" + +#include +#ifndef QT_NO_OPENGL +#include +#endif + +#include + +void GraphicsView::wheelEvent(QWheelEvent *e) +{ + if (e->modifiers() & Qt::ControlModifier) { + if (e->delta() > 0) + view->zoomIn(6); + else + view->zoomOut(6); + e->accept(); + } else { + QGraphicsView::wheelEvent(e); + } +} + +View::View(const QString &name, QWidget *parent) + : QFrame(parent) +{ + setFrameStyle(Sunken | StyledPanel); + graphicsView = new GraphicsView(this); + graphicsView->setRenderHint(QPainter::Antialiasing, false); + graphicsView->setDragMode(QGraphicsView::RubberBandDrag); + graphicsView->setOptimizationFlags(QGraphicsView::DontSavePainterState); + graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); + graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); + + int size = style()->pixelMetric(QStyle::PM_ToolBarIconSize); + QSize iconSize(size, size); + + QToolButton *zoomInIcon = new QToolButton; + zoomInIcon->setAutoRepeat(true); + zoomInIcon->setAutoRepeatInterval(33); + zoomInIcon->setAutoRepeatDelay(0); + zoomInIcon->setIcon(QPixmap(":/zoomin.png")); + zoomInIcon->setIconSize(iconSize); + QToolButton *zoomOutIcon = new QToolButton; + zoomOutIcon->setAutoRepeat(true); + zoomOutIcon->setAutoRepeatInterval(33); + zoomOutIcon->setAutoRepeatDelay(0); + zoomOutIcon->setIcon(QPixmap(":/zoomout.png")); + zoomOutIcon->setIconSize(iconSize); + zoomSlider = new QSlider; + zoomSlider->setMinimum(0); + zoomSlider->setMaximum(500); + zoomSlider->setValue(250); + zoomSlider->setTickPosition(QSlider::TicksRight); + + // Zoom slider layout + QVBoxLayout *zoomSliderLayout = new QVBoxLayout; + zoomSliderLayout->addWidget(zoomInIcon); + zoomSliderLayout->addWidget(zoomSlider); + zoomSliderLayout->addWidget(zoomOutIcon); + + QToolButton *rotateLeftIcon = new QToolButton; + rotateLeftIcon->setIcon(QPixmap(":/rotateleft.png")); + rotateLeftIcon->setIconSize(iconSize); + QToolButton *rotateRightIcon = new QToolButton; + rotateRightIcon->setIcon(QPixmap(":/rotateright.png")); + rotateRightIcon->setIconSize(iconSize); + rotateSlider = new QSlider; + rotateSlider->setOrientation(Qt::Horizontal); + rotateSlider->setMinimum(-360); + rotateSlider->setMaximum(360); + rotateSlider->setValue(0); + rotateSlider->setTickPosition(QSlider::TicksBelow); + + // Rotate slider layout + QHBoxLayout *rotateSliderLayout = new QHBoxLayout; + rotateSliderLayout->addWidget(rotateLeftIcon); + rotateSliderLayout->addWidget(rotateSlider); + rotateSliderLayout->addWidget(rotateRightIcon); + + resetButton = new QToolButton; + resetButton->setText(tr("0")); + resetButton->setEnabled(false); + + // Label layout + QHBoxLayout *labelLayout = new QHBoxLayout; + label = new QLabel(name); + label2 = new QLabel(tr("Pointer Mode")); + selectModeButton = new QToolButton; + selectModeButton->setText(tr("Select")); + selectModeButton->setCheckable(true); + selectModeButton->setChecked(true); + dragModeButton = new QToolButton; + dragModeButton->setText(tr("Drag")); + dragModeButton->setCheckable(true); + dragModeButton->setChecked(false); + antialiasButton = new QToolButton; + antialiasButton->setText(tr("Antialiasing")); + antialiasButton->setCheckable(true); + antialiasButton->setChecked(false); + openGlButton = new QToolButton; + openGlButton->setText(tr("OpenGL")); + openGlButton->setCheckable(true); +#ifndef QT_NO_OPENGL + openGlButton->setEnabled(QGLFormat::hasOpenGL()); +#else + openGlButton->setEnabled(false); +#endif + printButton = new QToolButton; + printButton->setIcon(QIcon(QPixmap(":/fileprint.png"))); + + QButtonGroup *pointerModeGroup = new QButtonGroup; + pointerModeGroup->setExclusive(true); + pointerModeGroup->addButton(selectModeButton); + pointerModeGroup->addButton(dragModeButton); + + labelLayout->addWidget(label); + labelLayout->addStretch(); + labelLayout->addWidget(label2); + labelLayout->addWidget(selectModeButton); + labelLayout->addWidget(dragModeButton); + labelLayout->addStretch(); + labelLayout->addWidget(antialiasButton); + labelLayout->addWidget(openGlButton); + labelLayout->addWidget(printButton); + + QGridLayout *topLayout = new QGridLayout; + topLayout->addLayout(labelLayout, 0, 0); + topLayout->addWidget(graphicsView, 1, 0); + topLayout->addLayout(zoomSliderLayout, 1, 1); + topLayout->addLayout(rotateSliderLayout, 2, 0); + topLayout->addWidget(resetButton, 2, 1); + setLayout(topLayout); + + connect(resetButton, SIGNAL(clicked()), this, SLOT(resetView())); + connect(zoomSlider, SIGNAL(valueChanged(int)), this, SLOT(setupMatrix())); + connect(rotateSlider, SIGNAL(valueChanged(int)), this, SLOT(setupMatrix())); + connect(graphicsView->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setResetButtonEnabled())); + connect(graphicsView->horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(setResetButtonEnabled())); + connect(selectModeButton, SIGNAL(toggled(bool)), this, SLOT(togglePointerMode())); + connect(dragModeButton, SIGNAL(toggled(bool)), this, SLOT(togglePointerMode())); + connect(antialiasButton, SIGNAL(toggled(bool)), this, SLOT(toggleAntialiasing())); + connect(openGlButton, SIGNAL(toggled(bool)), this, SLOT(toggleOpenGL())); + connect(rotateLeftIcon, SIGNAL(clicked()), this, SLOT(rotateLeft())); + connect(rotateRightIcon, SIGNAL(clicked()), this, SLOT(rotateRight())); + connect(zoomInIcon, SIGNAL(clicked()), this, SLOT(zoomIn())); + connect(zoomOutIcon, SIGNAL(clicked()), this, SLOT(zoomOut())); + connect(printButton, SIGNAL(clicked()), this, SLOT(print())); + + setupMatrix(); +} + +QGraphicsView *View::view() const +{ + return static_cast(graphicsView); +} + +void View::resetView() +{ + zoomSlider->setValue(250); + rotateSlider->setValue(0); + setupMatrix(); + graphicsView->ensureVisible(QRectF(0, 0, 0, 0)); + + resetButton->setEnabled(false); +} + +void View::setResetButtonEnabled() +{ + resetButton->setEnabled(true); +} + +void View::setupMatrix() +{ + qreal scale = qPow(qreal(2), (zoomSlider->value() - 250) / qreal(50)); + + QMatrix matrix; + matrix.scale(scale, scale); + matrix.rotate(rotateSlider->value()); + + graphicsView->setMatrix(matrix); + setResetButtonEnabled(); +} + +void View::togglePointerMode() +{ + graphicsView->setDragMode(selectModeButton->isChecked() + ? QGraphicsView::RubberBandDrag + : QGraphicsView::ScrollHandDrag); + graphicsView->setInteractive(selectModeButton->isChecked()); +} + +void View::toggleOpenGL() +{ +#ifndef QT_NO_OPENGL + graphicsView->setViewport(openGlButton->isChecked() ? new QGLWidget(QGLFormat(QGL::SampleBuffers)) : new QWidget); +#endif +} + +void View::toggleAntialiasing() +{ + graphicsView->setRenderHint(QPainter::Antialiasing, antialiasButton->isChecked()); +} + +void View::print() +{ +#ifndef QT_NO_PRINTER + QPrinter printer; + QPrintDialog dialog(&printer, this); + if (dialog.exec() == QDialog::Accepted) { + QPainter painter(&printer); + graphicsView->render(&painter); + } +#endif +} + +void View::zoomIn(int level) +{ + zoomSlider->setValue(zoomSlider->value() + level); +} + +void View::zoomOut(int level) +{ + zoomSlider->setValue(zoomSlider->value() - level); +} + +void View::rotateLeft() +{ + rotateSlider->setValue(rotateSlider->value() - 10); +} + +void View::rotateRight() +{ + rotateSlider->setValue(rotateSlider->value() + 10); +} + diff --git a/examples/graphicsview/chip/view.h b/examples/graphicsview/chip/view.h new file mode 100644 index 0000000000..7c587d4147 --- /dev/null +++ b/examples/graphicsview/chip/view.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VIEW_H +#define VIEW_H + +#include +#include + +QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QSlider) +QT_FORWARD_DECLARE_CLASS(QToolButton) + +class View; + +class GraphicsView : public QGraphicsView +{ + Q_OBJECT +public: + GraphicsView(View *v) : QGraphicsView(), view(v) { } + +protected: + void wheelEvent(QWheelEvent *); + +private: + View *view; +}; + +class View : public QFrame +{ + Q_OBJECT +public: + View(const QString &name, QWidget *parent = 0); + + QGraphicsView *view() const; + +public slots: + void zoomIn(int level = 1); + void zoomOut(int level = 1); + +private slots: + void resetView(); + void setResetButtonEnabled(); + void setupMatrix(); + void togglePointerMode(); + void toggleOpenGL(); + void toggleAntialiasing(); + void print(); + void rotateLeft(); + void rotateRight(); + +private: + GraphicsView *graphicsView; + QLabel *label; + QLabel *label2; + QToolButton *selectModeButton; + QToolButton *dragModeButton; + QToolButton *openGlButton; + QToolButton *antialiasButton; + QToolButton *printButton; + QToolButton *resetButton; + QSlider *zoomSlider; + QSlider *rotateSlider; +}; + +#endif diff --git a/examples/graphicsview/chip/zoomin.png b/examples/graphicsview/chip/zoomin.png new file mode 100644 index 0000000000..8b0daeea48 Binary files /dev/null and b/examples/graphicsview/chip/zoomin.png differ diff --git a/examples/graphicsview/chip/zoomout.png b/examples/graphicsview/chip/zoomout.png new file mode 100644 index 0000000000..1575dd24f6 Binary files /dev/null and b/examples/graphicsview/chip/zoomout.png differ diff --git a/examples/graphicsview/embeddeddialogs/No-Ones-Laughing-3.jpg b/examples/graphicsview/embeddeddialogs/No-Ones-Laughing-3.jpg new file mode 100644 index 0000000000..445567fbda Binary files /dev/null and b/examples/graphicsview/embeddeddialogs/No-Ones-Laughing-3.jpg differ diff --git a/examples/graphicsview/embeddeddialogs/customproxy.cpp b/examples/graphicsview/embeddeddialogs/customproxy.cpp new file mode 100644 index 0000000000..cbc622a34f --- /dev/null +++ b/examples/graphicsview/embeddeddialogs/customproxy.cpp @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "customproxy.h" + +#include + +CustomProxy::CustomProxy(QGraphicsItem *parent, Qt::WindowFlags wFlags) + : QGraphicsProxyWidget(parent, wFlags), popupShown(false), currentPopup(0) +{ + timeLine = new QTimeLine(250, this); + connect(timeLine, SIGNAL(valueChanged(qreal)), + this, SLOT(updateStep(qreal))); + connect(timeLine, SIGNAL(stateChanged(QTimeLine::State)), + this, SLOT(stateChanged(QTimeLine::State))); +} + +QRectF CustomProxy::boundingRect() const +{ + return QGraphicsProxyWidget::boundingRect().adjusted(0, 0, 10, 10); +} + +void CustomProxy::paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget) +{ + const QColor color(0, 0, 0, 64); + + QRectF r = windowFrameRect(); + QRectF right(r.right(), r.top() + 10, 10, r.height() - 10); + QRectF bottom(r.left() + 10, r.bottom(), r.width(), 10); + bool intersectsRight = right.intersects(option->exposedRect); + bool intersectsBottom = bottom.intersects(option->exposedRect); + if (intersectsRight && intersectsBottom) { + QPainterPath path; + path.addRect(right); + path.addRect(bottom); + painter->setPen(Qt::NoPen); + painter->setBrush(color); + painter->drawPath(path); + } else if (intersectsBottom) { + painter->fillRect(bottom, color); + } else if (intersectsRight) { + painter->fillRect(right, color); + } + + QGraphicsProxyWidget::paintWindowFrame(painter, option, widget); +} + +void CustomProxy::hoverEnterEvent(QGraphicsSceneHoverEvent *event) +{ + QGraphicsProxyWidget::hoverEnterEvent(event); + scene()->setActiveWindow(this); + if (timeLine->currentValue() != 1) + zoomIn(); +} + +void CustomProxy::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + QGraphicsProxyWidget::hoverLeaveEvent(event); + if (!popupShown && (timeLine->direction() != QTimeLine::Backward || timeLine->currentValue() != 0)) + zoomOut(); +} + +bool CustomProxy::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + if (watched->isWindow() && (event->type() == QEvent::UngrabMouse || event->type() == QEvent::GrabMouse)) { + popupShown = watched->isVisible(); + if (!popupShown && !isUnderMouse()) + zoomOut(); + } + return QGraphicsProxyWidget::sceneEventFilter(watched, event); +} + +QVariant CustomProxy::itemChange(GraphicsItemChange change, const QVariant &value) +{ + if (change == ItemChildAddedChange || change == ItemChildRemovedChange) { + if (change == ItemChildAddedChange) { + currentPopup = qvariant_cast(value); + currentPopup->setCacheMode(ItemCoordinateCache); + if (scene()) + currentPopup->installSceneEventFilter(this); + } else if (scene()) { + currentPopup->removeSceneEventFilter(this); + currentPopup = 0; + } + } else if (currentPopup && change == ItemSceneHasChanged) { + currentPopup->installSceneEventFilter(this); + } + return QGraphicsProxyWidget::itemChange(change, value); +} + +void CustomProxy::updateStep(qreal step) +{ + QRectF r = boundingRect(); + setTransform(QTransform() + .translate(r.width() / 2, r.height() / 2) + .rotate(step * 30, Qt::XAxis) + .rotate(step * 10, Qt::YAxis) + .rotate(step * 5, Qt::ZAxis) + .scale(1 + 1.5 * step, 1 + 1.5 * step) + .translate(-r.width() / 2, -r.height() / 2)); +} + +void CustomProxy::stateChanged(QTimeLine::State state) +{ + if (state == QTimeLine::Running) { + if (timeLine->direction() == QTimeLine::Forward) + setCacheMode(ItemCoordinateCache); + } else if (state == QTimeLine::NotRunning) { + if (timeLine->direction() == QTimeLine::Backward) + setCacheMode(DeviceCoordinateCache); + } +} + +void CustomProxy::zoomIn() +{ + if (timeLine->direction() != QTimeLine::Forward) + timeLine->setDirection(QTimeLine::Forward); + if (timeLine->state() == QTimeLine::NotRunning) + timeLine->start(); +} + +void CustomProxy::zoomOut() +{ + if (timeLine->direction() != QTimeLine::Backward) + timeLine->setDirection(QTimeLine::Backward); + if (timeLine->state() == QTimeLine::NotRunning) + timeLine->start(); +} diff --git a/examples/graphicsview/embeddeddialogs/customproxy.h b/examples/graphicsview/embeddeddialogs/customproxy.h new file mode 100644 index 0000000000..1ceaa06bb3 --- /dev/null +++ b/examples/graphicsview/embeddeddialogs/customproxy.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CUSTOMPROXY_H +#define CUSTOMPROXY_H + +#include +#include + +class CustomProxy : public QGraphicsProxyWidget +{ + Q_OBJECT +public: + CustomProxy(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); + + QRectF boundingRect() const; + void paintWindowFrame(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget); + +protected: + void hoverEnterEvent(QGraphicsSceneHoverEvent *event); + void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); + bool sceneEventFilter(QGraphicsItem *watched, QEvent *event); + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + +private slots: + void updateStep(qreal step); + void stateChanged(QTimeLine::State); + void zoomIn(); + void zoomOut(); + +private: + QTimeLine *timeLine; + bool popupShown; + QGraphicsItem *currentPopup; +}; + +#endif diff --git a/examples/graphicsview/embeddeddialogs/embeddeddialog.cpp b/examples/graphicsview/embeddeddialogs/embeddeddialog.cpp new file mode 100644 index 0000000000..f932307925 --- /dev/null +++ b/examples/graphicsview/embeddeddialogs/embeddeddialog.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "embeddeddialog.h" +#include "ui_embeddeddialog.h" + +#include + +EmbeddedDialog::EmbeddedDialog(QWidget *parent) + : QDialog(parent) +{ + ui = new Ui_embeddedDialog; + ui->setupUi(this); + ui->layoutDirection->setCurrentIndex(layoutDirection() != Qt::LeftToRight); + + foreach (QString styleName, QStyleFactory::keys()) { + ui->style->addItem(styleName); + if (style()->objectName().toLower() == styleName.toLower()) + ui->style->setCurrentIndex(ui->style->count() - 1); + } + + connect(ui->layoutDirection, SIGNAL(activated(int)), + this, SLOT(layoutDirectionChanged(int))); + connect(ui->spacing, SIGNAL(valueChanged(int)), + this, SLOT(spacingChanged(int))); + connect(ui->fontComboBox, SIGNAL(currentFontChanged(QFont)), + this, SLOT(fontChanged(QFont))); + connect(ui->style, SIGNAL(activated(QString)), + this, SLOT(styleChanged(QString))); +} + +EmbeddedDialog::~EmbeddedDialog() +{ + delete ui; +} + +void EmbeddedDialog::layoutDirectionChanged(int index) +{ + setLayoutDirection(index == 0 ? Qt::LeftToRight : Qt::RightToLeft); +} + +void EmbeddedDialog::spacingChanged(int spacing) +{ + layout()->setSpacing(spacing); + adjustSize(); +} + +void EmbeddedDialog::fontChanged(const QFont &font) +{ + setFont(font); +} + +static void setStyleHelper(QWidget *widget, QStyle *style) +{ + widget->setStyle(style); + widget->setPalette(style->standardPalette()); + foreach (QObject *child, widget->children()) { + if (QWidget *childWidget = qobject_cast(child)) + setStyleHelper(childWidget, style); + } +} + +void EmbeddedDialog::styleChanged(const QString &styleName) +{ + QStyle *style = QStyleFactory::create(styleName); + if (style) + setStyleHelper(this, style); +} diff --git a/examples/graphicsview/embeddeddialogs/embeddeddialog.h b/examples/graphicsview/embeddeddialogs/embeddeddialog.h new file mode 100644 index 0000000000..b7f8da085e --- /dev/null +++ b/examples/graphicsview/embeddeddialogs/embeddeddialog.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EMBEDDEDDIALOG_H +#define EMBEDDEDDIALOG_H + +#include + +QT_FORWARD_DECLARE_CLASS(Ui_embeddedDialog); + +class EmbeddedDialog : public QDialog +{ + Q_OBJECT +public: + EmbeddedDialog(QWidget *parent = 0); + ~EmbeddedDialog(); + +private slots: + void layoutDirectionChanged(int index); + void spacingChanged(int spacing); + void fontChanged(const QFont &font); + void styleChanged(const QString &styleName); + +private: + Ui_embeddedDialog *ui; +}; + +#endif diff --git a/examples/graphicsview/embeddeddialogs/embeddeddialog.ui b/examples/graphicsview/embeddeddialogs/embeddeddialog.ui new file mode 100644 index 0000000000..f967b10085 --- /dev/null +++ b/examples/graphicsview/embeddeddialogs/embeddeddialog.ui @@ -0,0 +1,87 @@ + + embeddedDialog + + + + 0 + 0 + 407 + 134 + + + + Embedded Dialog + + + + + + Layout Direction: + + + layoutDirection + + + + + + + + Left to Right + + + + + Right to Left + + + + + + + + Select Font: + + + fontComboBox + + + + + + + + + + Style: + + + style + + + + + + + + + + Layout spacing: + + + spacing + + + + + + + Qt::Horizontal + + + + + + + + diff --git a/examples/graphicsview/embeddeddialogs/embeddeddialogs.pro b/examples/graphicsview/embeddeddialogs/embeddeddialogs.pro new file mode 100644 index 0000000000..675a9889a2 --- /dev/null +++ b/examples/graphicsview/embeddeddialogs/embeddeddialogs.pro @@ -0,0 +1,19 @@ +SOURCES += main.cpp +SOURCES += customproxy.cpp embeddeddialog.cpp +HEADERS += customproxy.h embeddeddialog.h + +FORMS += embeddeddialog.ui +RESOURCES += embeddeddialogs.qrc + +build_all:!build_pass { + CONFIG -= build_all + CONFIG += release +} + +# install +target.path = $$[QT_INSTALL_DEMOS]/qtbase/embeddeddialogs +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS *.png *.jpg *.plist *.icns *.ico *.rc *.pro *.html *.doc images +sources.path = $$[QT_INSTALL_DEMOS]/qtbase/embeddeddialogs +INSTALLS += target sources + +symbian: CONFIG += qt_demo diff --git a/examples/graphicsview/embeddeddialogs/embeddeddialogs.qrc b/examples/graphicsview/embeddeddialogs/embeddeddialogs.qrc new file mode 100644 index 0000000000..33be5038da --- /dev/null +++ b/examples/graphicsview/embeddeddialogs/embeddeddialogs.qrc @@ -0,0 +1,5 @@ + + + No-Ones-Laughing-3.jpg + + diff --git a/examples/graphicsview/embeddeddialogs/main.cpp b/examples/graphicsview/embeddeddialogs/main.cpp new file mode 100644 index 0000000000..bca81b8c79 --- /dev/null +++ b/examples/graphicsview/embeddeddialogs/main.cpp @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the demonstration applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "customproxy.h" +#include "embeddeddialog.h" + +#include + +int main(int argc, char *argv[]) +{ + Q_INIT_RESOURCE(embeddeddialogs); + QApplication app(argc, argv); + + QGraphicsScene scene; + scene.setStickyFocus(true); +#ifndef Q_OS_WINCE + const int gridSize = 10; +#else + const int gridSize = 5; +#endif + + for (int y = 0; y < gridSize; ++y) { + for (int x = 0; x < gridSize; ++x) { + CustomProxy *proxy = new CustomProxy(0, Qt::Window); + proxy->setWidget(new EmbeddedDialog); + + QRectF rect = proxy->boundingRect(); + + proxy->setPos(x * rect.width() * 1.05, y * rect.height() * 1.05); + proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache); + + scene.addItem(proxy); + } + } + scene.setSceneRect(scene.itemsBoundingRect()); + + QGraphicsView view(&scene); + view.scale(0.5, 0.5); + view.setRenderHints(view.renderHints() | QPainter::Antialiasing | QPainter::SmoothPixmapTransform); + view.setBackgroundBrush(QPixmap(":/No-Ones-Laughing-3.jpg")); + view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + view.show(); + view.setWindowTitle("Embedded Dialogs Demo"); + return app.exec(); +} -- cgit v1.2.3