summaryrefslogtreecommitdiffstats
path: root/examples/demo/opengl
diff options
context:
space:
mode:
authorTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:24:15 -0500
committerTimothy Pearson <kb9vqf@pearsoncomputing.net>2011-07-10 15:24:15 -0500
commitbd0f3345a938b35ce6a12f6150373b0955b8dd12 (patch)
tree7a520322212d48ebcb9fbe1087e7fca28b76185c /examples/demo/opengl
downloadqt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.tar.gz
qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.zip
Add Qt3 development HEAD version
Diffstat (limited to 'examples/demo/opengl')
-rw-r--r--examples/demo/opengl/fbm.c207
-rw-r--r--examples/demo/opengl/fbm.h39
-rw-r--r--examples/demo/opengl/gear.xpm304
-rw-r--r--examples/demo/opengl/glbox.cpp142
-rw-r--r--examples/demo/opengl/glbox.h43
-rw-r--r--examples/demo/opengl/glcontrolwidget.cpp195
-rw-r--r--examples/demo/opengl/glcontrolwidget.h56
-rw-r--r--examples/demo/opengl/glgear.cpp271
-rw-r--r--examples/demo/opengl/glgear.h26
-rw-r--r--examples/demo/opengl/glinfo.h26
-rw-r--r--examples/demo/opengl/glinfo_x11.cpp257
-rw-r--r--examples/demo/opengl/glinfotext.h23
-rw-r--r--examples/demo/opengl/gllandscape.cpp880
-rw-r--r--examples/demo/opengl/gllandscape.h98
-rw-r--r--examples/demo/opengl/gllandscapeviewer.ui623
-rw-r--r--examples/demo/opengl/gllandscapeviewer.ui.h37
-rw-r--r--examples/demo/opengl/gllogo.bmpbin0 -> 17462 bytes
-rw-r--r--examples/demo/opengl/gltexobj.cpp210
-rw-r--r--examples/demo/opengl/gltexobj.h44
-rw-r--r--examples/demo/opengl/glworkspace.cpp212
-rw-r--r--examples/demo/opengl/glworkspace.h37
-rw-r--r--examples/demo/opengl/nurbs.xpm305
-rw-r--r--examples/demo/opengl/printpreview.ui277
-rw-r--r--examples/demo/opengl/printpreview.ui.h70
-rw-r--r--examples/demo/opengl/qtlogo.bmpbin0 -> 17462 bytes
-rw-r--r--examples/demo/opengl/qtlogo.pngbin0 -> 5206 bytes
-rw-r--r--examples/demo/opengl/snapshot.xpm238
-rw-r--r--examples/demo/opengl/texture.xpm130
-rw-r--r--examples/demo/opengl/wirebox.xpm155
29 files changed, 4905 insertions, 0 deletions
diff --git a/examples/demo/opengl/fbm.c b/examples/demo/opengl/fbm.c
new file mode 100644
index 0000000..47d5a61
--- /dev/null
+++ b/examples/demo/opengl/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 <qglobal.h>
+#endif
+
+#include <time.h>
+#include <stdlib.h>
+#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 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] )
+
+static float noise3(float vec[3]);
+
+/* 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<octaves; i++) {
+ /* value += noise3( vec ) * exponent_array[i];*/
+ value += noise3( vec ) * exponent_array[i];
+ vec[0] *= lacunarity;
+ vec[1] *= lacunarity;
+ vec[2] *= lacunarity;
+ } /* for */
+
+ remainder = octaves - (int)octaves;
+ if ( remainder ) /* add in ``octaves'' remainder */
+ /* ``i'' and spatial freq. are preset in loop above */
+ value += remainder * noise3( vec ) * exponent_array[i];
+
+ return( value );
+
+} /* fBm() */
+
+
+float noise3(float vec[3])
+{
+ int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
+ register int i, j;
+
+ if (start) {
+ start = 0;
+ init();
+ }
+
+ setup(0, bx0,bx1, rx0,rx1);
+ setup(1, by0,by1, ry0,ry1);
+ setup(2, bz0,bz1, rz0,rz1);
+
+ i = p[ bx0 ];
+ j = p[ bx1 ];
+
+ b00 = p[ i + by0 ];
+ b10 = p[ j + by0 ];
+ b01 = p[ i + by1 ];
+ b11 = p[ j + by1 ];
+
+ t = s_curve(rx0);
+ sy = s_curve(ry0);
+ sz = s_curve(rz0);
+
+
+ q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
+ q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
+ a = lerp(t, u, v);
+
+ q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
+ q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
+ b = lerp(t, u, v);
+
+ c = lerp(sy, a, b);
+
+ q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
+ q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
+ a = lerp(t, u, v);
+
+ q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
+ q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
+ b = lerp(t, u, v);
+
+ d = lerp(sy, a, b);
+
+ return lerp(sz, c, d);
+}
+
+static void normalize2(float v[2])
+{
+ float s;
+
+ s = sqrt(v[0] * v[0] + v[1] * v[1]);
+ v[0] = v[0] / s;
+ v[1] = v[1] / s;
+}
+
+static void normalize3(float v[3])
+{
+ float s;
+
+ s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+ v[0] = v[0] / s;
+ v[1] = v[1] / s;
+ v[2] = v[2] / s;
+}
+
+static void init(void)
+{
+ int i, j, k;
+
+ for (i = 0 ; i < B ; i++) {
+ p[i] = i;
+
+ g1[i] = (float)((rand() % (B + B)) - B) / B;
+
+ for (j = 0 ; j < 2 ; j++)
+ g2[i][j] = (float)((rand() % (B + B)) - B) / B;
+ normalize2(g2[i]);
+
+ for (j = 0 ; j < 3 ; j++)
+ g3[i][j] = (float)((rand() % (B + B)) - B) / B;
+ normalize3(g3[i]);
+ }
+
+ while (--i) {
+ k = p[i];
+ p[i] = p[j = rand() % B];
+ p[j] = k;
+ }
+
+ for (i = 0 ; i < B + 2 ; i++) {
+ p[B + i] = p[i];
+ g1[B + i] = g1[i];
+ for (j = 0 ; j < 2 ; j++)
+ g2[B + i][j] = g2[i][j];
+ for (j = 0 ; j < 3 ; j++)
+ g3[B + i][j] = g3[i][j];
+ }
+}
diff --git a/examples/demo/opengl/fbm.h b/examples/demo/opengl/fbm.h
new file mode 100644
index 0000000..474cd3c
--- /dev/null
+++ b/examples/demo/opengl/fbm.h
@@ -0,0 +1,39 @@
+/*****************************************************************
+
+ Prototypes for 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.
+
+******************************************************************/
+
+#ifndef _fbm_h
+#define _fbm_h
+
+#include <math.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TRUE 1
+#define FALSE 0
+
+typedef struct {
+ double x;
+ double y;
+ double z;
+} Vector;
+
+double fBm( Vector point, double H, double lacunarity, double octaves,
+ int init );
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+
+
+
diff --git a/examples/demo/opengl/gear.xpm b/examples/demo/opengl/gear.xpm
new file mode 100644
index 0000000..ccba9ec
--- /dev/null
+++ b/examples/demo/opengl/gear.xpm
@@ -0,0 +1,304 @@
+/* XPM */
+static char *gear[] = {
+/* width height num_colors chars_per_pixel */
+" 48 48 249 2",
+/* colors */
+".. c #7a7a7b",
+".# c #afafaf",
+".a c #adadad",
+".b c #727273",
+".c c #a7a7a7",
+".d c #a5a5a5",
+".e c #9d9f9d",
+".f c #9d9d9d",
+".g c #9b9b9b",
+".h c #656666",
+".i c #9a999a",
+".j c #626463",
+".k c #979797",
+".l c #969796",
+".m c #5e5e5f",
+".n c #5e5c5f",
+".o c #5c5e5d",
+".p c #919191",
+".q c #c6c6c5",
+".r c #8d8d8d",
+".s c #535454",
+".t c #bdbcbc",
+".u c #bbbaba",
+".v c #838383",
+".w c #818181",
+".x c #8e8f91",
+".y c #484849",
+".z c #797979",
+".A c #aeaead",
+".B c #777777",
+".C c #acacab",
+".D c #abaaaa",
+".E c #747574",
+".F c #a8a8a7",
+".G c #706f70",
+".H c #b1b2b3",
+".I c #323233",
+".J c #9b9a9a",
+".K c #656565",
+".L c #9a9a99",
+".M c #cfcdcd",
+".N c #999898",
+".O c #dedfdf",
+".P c #2b2c2c",
+".Q c #959694",
+".R c #5f5f5f",
+".S c #5f5d5f",
+".T c #939292",
+".U c #5c5b5c",
+".V c #a0a0a2",
+".W c #242425",
+".X c #595959",
+".Y c #8e8e8d",
+".Z c #575757",
+".0 c #555555",
+".1 c #c0bfbe",
+".2 c #545554",
+".3 c #8a8889",
+".4 c #888887",
+".5 c #cdcdce",
+".6 c #858484",
+".7 c #cacbcb",
+".8 c #161617",
+".9 c #807e7f",
+"#. c #131414",
+"## c #8d8e8f",
+"#a c #7b7a7a",
+"#b c #454545",
+"#c c #c0c1c1",
+"#d c #444344",
+"#e c #bfbfc0",
+"#f c #424342",
+"#g c #f2f2f2",
+"#h c #757674",
+"#i c #403f40",
+"#j c #3f3f3f",
+"#k c #3d3d3d",
+"#l c #6a6a69",
+"#m c #696868",
+"#n c #e2e2e2",
+"#o c #2f2f2f",
+"#p c #a8a9a9",
+"#q c #626261",
+"#r c #616060",
+"#s c #d8d8d8",
+"#t c #5a5a59",
+"#u c #232323",
+"#v c #9e9f9f",
+"#w c #1d1d1d",
+"#x c #1c1b1c",
+"#y c #cdcccd",
+"#z c #1a1b1a",
+"#A c #191919",
+"#B c #cacaca",
+"#C c #949595",
+"#D c #151515",
+"#E c #121312",
+"#F c #c2c2c2",
+"#G c #8c8d8d",
+"#H c #0f0f0f",
+"#I c #444443",
+"#J c #434242",
+"#K c #414040",
+"#L c #b9bab9",
+"#M c #b6b6b6",
+"#N c #b5b4b5",
+"#O c #b4b4b4",
+"#P c #6d6b6b",
+"#Q c #7a7b7b",
+"#R c #343433",
+"#S c #696767",
+"#T c #acacac",
+"#U c None",
+"#V c #dedddd",
+"#W c #717172",
+"#X c #a6a6a6",
+"#Y c #707171",
+"#Z c #292828",
+"#0 c #a4a4a4",
+"#1 c #6e6f6f",
+"#2 c #6a6b6b",
+"#3 c #9d9c9d",
+"#4 c #d0d1cf",
+"#5 c #c8c7c7",
+"#6 c #929092",
+"#7 c #c6c5c5",
+"#8 c #141413",
+"#9 c #131412",
+"a. c #c5c3c4",
+"a# c #9fa0a2",
+"aa c #d2d3d4",
+"ab c #8b8c8b",
+"ac c #8a8a8a",
+"ad c #bfbfbe",
+"ae c #bfbdbe",
+"af c #515352",
+"ag c #878687",
+"ah c #828282",
+"ai c #b7b7b6",
+"aj c #fbfcfc",
+"ak c #494b4a",
+"al c #49494a",
+"am c #7e7e7e",
+"an c #484949",
+"ao c #f9fafa",
+"ap c #474748",
+"aq c #f7f8f8",
+"ar c #797a79",
+"as c #787878",
+"at c #aaa9a9",
+"au c #737473",
+"av c #a8a9a7",
+"aw c #ececed",
+"ax c #39393a",
+"ay c #6d6c6d",
+"az c #6b6c6b",
+"aA c #e5e6e6",
+"aB c #afb1b1",
+"aC c #9f9f9e",
+"aD c #323333",
+"aE c #676667",
+"aF c #2f3130",
+"aG c #646464",
+"aH c #636463",
+"aI c #949393",
+"aJ c #181716",
+"aK c #141312",
+"aL c #d3d2d4",
+"aM c #212122",
+"aN c #565656",
+"aO c #1e1f1f",
+"aP c #525452",
+"aQ c #888787",
+"aR c #515251",
+"aS c #858584",
+"aT c #4e4e4e",
+"aU c #ffffff",
+"aV c #4d4e4d",
+"aW c #828181",
+"aX c #5c5c5f",
+"aY c #151516",
+"aZ c #5a5c5d",
+"a0 c #141515",
+"a1 c #8f8f91",
+"a2 c #111112",
+"a3 c #464646",
+"a4 c #101111",
+"a5 c #c1c2c2",
+"a6 c #f5f5f5",
+"a7 c #bfc0c0",
+"a8 c #414241",
+"a9 c #3f403f",
+"b. c #3e3e3e",
+"b# c #727171",
+"ba c #3b3c3b",
+"bb c #716f70",
+"bc c #e9e9e9",
+"bd c #363636",
+"be c #353435",
+"bf c #afb0b0",
+"bg c #686767",
+"bh c #313031",
+"bi c #e1e1e1",
+"bj c #2e2e2e",
+"bk c #626361",
+"bl c #2c2c2c",
+"bm c #605f5f",
+"bn c #dadbda",
+"bo c #a2a2a3",
+"bp c #262626",
+"bq c #6b6d6d",
+"br c #a1a0a2",
+"bs c #5a5b59",
+"bt c #242424",
+"bu c #d5d5d5",
+"bv c #595758",
+"bw c #575556",
+"bx c #8c8a8a",
+"by c #d1d1d1",
+"bz c #1e1e1e",
+"bA c #cfcfcf",
+"bB c #535352",
+"bC c #979898",
+"bD c #515150",
+"bE c #1b1a1b",
+"bF c #504f4f",
+"bG c #181a18",
+"bH c #848282",
+"bI c #c9c9c9",
+"bJ c #4e4b4d",
+"bK c #161616",
+"bL c #151415",
+"bM c #141414",
+"bN c #c5c5c5",
+"bO c #111011",
+"bP c #bdbdbd",
+"bQ c #777675",
+"bR c #0b0a0b",
+"bS c #bbbbbb",
+"bT c #858686",
+"bU c #848685",
+"bV c #b8b9b8",
+"bW c #4b4b4d",
+"bX c #808081",
+"bY c #4a4b4c",
+"bZ c #b5b5b5",
+"b0 c #393738",
+"b1 c #7c7e7d",
+"b2 c #b3b1b3",
+/* pixels */
+"#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#G.Rbpab#UboaEb.axb0b0aNbU#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#WbWbM#8#.b0.Gbp.8aK#.bM#.#.bMbzak#C#U#U#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U#U#U#U#U#Uar.WbMbMbMbM#zaO#.bMbMbMbMbMbMbMbMaJaO.o#U#U#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U#U#Uad.wbp#.#.bMbM#uaN#zbMbMbMbMbMbMbMbMbKaO#xaY.U#U#U#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U#Ba6aj.6.8bMbMbMbMacaUaL#PbLbMbMbMbM#D#wbzbKbMbM.G#U#U#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#Uadbcajaqbc.5.IbMbMbMbM#nawbcao#g.NbFbMbEaO.8bMbMbMaK.6#U#U#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U.OaUaoawbcaA#nb#bMbMbM#KaUbi#4.M#sawajbb#zbMbMbMbMbM#9#z.B#U#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#Uaa#ebcaA#nbi.OaQbMbMa0#QaUby.M.7#5#7.5.KbMbMbMbMbMbMbM#.#x.B#U#hbh.W.N#U#U#U#U#U#U#U",
+"#U#U#U#U#U#Ubo.oaA#n.O#VbnbnaS.vaQa7aA.7#5#7#F#c.1#RbMbMbMbMbMbMbMbM#.bl#d#z#.a4#I#v#U#U#U#U#U#U",
+"#U#U#U#U#U#U.zaF.Y.O#Vbn#sbuaa#4bA#y.7#5bNa5#caeat#wbMbMbMbMbMbMbM#D#xbz#DbMbMbM#A.G#U#U#U#U#U#U",
+"#U#U#U#U.rbdbO#E.d#n#sbuaabybA.M.7#5bN#F#cad.t.u.g#wbMbMbMbMbMbMbGbz.8bMbMbMbMbM#8bp.N#U#U#U#U#U",
+"#U#UbZ#e.vbhbMaza6#saaby#4.5.5bI#5bNa5.1ae.u#L#M#O.6bpbLbM#u#aaNbEbMbMbMbMbMbMbMbMbMax#U#U#U#U#U",
+"#U#Ubcaoaqbi#Paobnaa#4bA.M.7#5#7a5#cad.t.ubV#O.Hbf.a.T#f.I#7aoaIbEbMbMbMbMbMbMbMbMbMbKay#U#U#U#U",
+"#U#UaU.Obna6aU#nby#4.5.7bI.q#F#cadbP.ubV#N#Obf.A#T.D.c#Xbfaobf#3a3.8bMbMbMbMbMbMbMbMbGbm#U#U#U#U",
+"#Uadajbu#sbu#n#4.M#y#B#5bNa5a7adbS#Lai#O.H.#.a.Cat#Xbo.VaC.f.gbC.Ybl#DbMbMbMbMbMbLbp.X#U#U#U#U#U",
+"#UbAawaaaabybA.M.7bI#7#F#cad.t.u#LbZ#Obf.##T#Tav.dboa##v.g.L.laI#6ar#xbMbMbMbMbG.PaS#U#U#U#U#U#U",
+"#Ubcbiby#4bA.7bI.qa.a5.1ad.u#L#M#OaB.#.a.Dav.dbr.V#v.f.g.k#C.T#6.YabaP#AbM#Dbz#waK.z#U#U#U#U#U#U",
+"#UbP#0bA#y.7#5#7a5a7aebS.uai#O.Hbf.a.C#p.cbobr#v.f.J.N.laIa1.x#G.3.4bTbJbzaObKbM#9a9#U#U#U#U#U#U",
+"#U..bM.X#O#7a.a5a7aebS#L#M#Obf.#.f#2.saf.w.V#v#3.LbCaI.Ta1.xab.3aQbTaW.X#AbMbMbM#D#x#v#U#U#U#U#U",
+"#U#U#abhbMa5#eadbS#Lai#O.H.#.a.Qb.bdbl.W.I.Z.l.N.QaIa1.x.rac.4bT.vay#RbLbMbMbMbMbM#9#Y#U#U#U#U#U",
+"#U#U#U#U#bad.t.ubVbZ#Obf.a.C.CbJ#RbEbMbMbK#RazaI#6.x#Gbx.4bT.6.wambhbMbMbMbMbMbMbM#8a4#HaKar#U#U",
+"#U#U#U#U#bbS#Lai#Obfbf.a.Dav.pbd.WbMbMbMbMbMb#.f##ab.3.4bTah.9am#QblbMbMbMbMbMbMbMbMbMbM#9.o#U#U",
+"#U#U#U#U#6#B#N.Hbf.a#Tat.c.dagbd#wbMbMbMbMbMa8#Mab.4bT.v.wamb1aras#I#.bMbMbMbMbMbMbMbMbM#D.o#U#U",
+"#U#UbZaAa6#cbf.##T#Tav.dbr.V.Bbd#wbMbV.Na2aKbM.L#MaS.wbXb1#aas#h.E.Za2bMbMbMbMbMbMbMbM#z#Z.o#U#U",
+"#UbZa6aw.ubf#T.Dav.c#0.V#v.f.vbd#wbFac#oaObRbMa8#g.vb1#Q.zbQ#h.b.G#1aYbMbMbMbMbMbM.8#ubdaT.o#U#U",
+"#Uadaobf.A#Tat.c.dbra#.f#3.N.Tba#ibMbfaDbj#HbMbMaU.Y#aasbQau#Y.Gbq#2aX#obtaO#DbLaJbpbabWaP.o#U#U",
+"#UbZaU.t.Dav#Xbo.V#v#3.JbC.Q#6aN.0bMbk#0aObRbMbMbN#ObQ#hb#.Gbqaz#m.haH#r.S.XbjaM.P#JbFbB.y.o#U#U",
+"#U#Ua6.5.F#0br#v.e.g.N.laI#6.x#Q.m.IbM#Z#HbRbMbMac.c.bbb#1az#lbg.Kbk#r.n.Ubs.Ib0.yaPaTbY.W.r#U#U",
+"#U#Ubn#Vbr.V.f.g.L.kaI.T.x.Yab.4.iasbMbMbMbMbMbMbS.a.Gay#2bg.hbk#r.naX#t.Z.2bd#faRaVapbt#Y#U#U#U",
+"#U#Uad#g.d.f.LbC.l.T.p.x#GacaQbT.TaabhbMbMbMbMaRa6.waz#maEaH#qbmaXaZbvaN.saRbe.yak#dbt#Y#U#U#U#U",
+"#U#U#UaU#v.N.laI.T.x##ab.4aQ.6.w.9.c#n.nbMbM.n#Vbn#lbg.K.j#r.n.U.Xbw.0aPaRaTbjal#i#u.r#U#U#U#U#U",
+"#U#U#UaibhbMbMbMakab.3.4aSaW.wb1#a.zb2aqaUaUaUbPb#.haH#r.RaX#tbv.0.saRbWalan.Pb0#8#i#U#U#U#U#U#U",
+"#U#U#U.V.6.6.6#a.WaragbH.wamb1aras#hau.G.T.p#Q.haG#qbm.naXbvaN.2aPbFap#k#i#j.W#8#.a4.y#U#U#U#U#U",
+"#U#U#U#U#U#U#U#UbgaVaW.9b1#Q.zbQ.E#W.Gayaz#m.K.j#q.SaXbsbv.0bBaRbF.yb.#Rbpbt#A#.bM#8#H#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#Ua8aub1.z.B.Eb#.G#1#2#maEaGbk.RaXbsbvaN.saRbFaTak#K.I#zbMbMbMaYa2aK#Y#U#U#U#U#U",
+"#U#U#U#U#U#U#U#UbN#s.Eas#h.Ebb.Gbq#l#S.KaH#r.maZ.X.Z.2aPbDaTbYan#IbdbEbMbMbMbMbObO#Y#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#UawbSbQ.E#Y.Gbq#2#m.KaH#r.S.n#tbv.0bBaRbFbJana3#d#fbl#AbMbMbMbOa4#Y#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#Ua6au.b.G#1az#lbg.K#qbm.nbsbv.0.2bBbFaTbYana3#da8#jbdbp#Aa2bOa2.b#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#UbV#d.nbq#2bg.haH#r.SaXbsbv.0.sbDbFbWaka3#d#f#ib.bab0aD#uaJa2.b#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U.vbla9aGaH.Xb..0#t.X.0.saRbFbJakap#b#I#K#i#kaxb0be.IbjaO.k#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U#U#GbWbtbF.Wbp#daOa9aPbDaTbY.ya3#da9bebj#kaxbe#RaFblaM.Y#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U#U#U#0bQblbz#a#U.kax#IbJakap#b#fbdaO#zbM#wax.IaF.WaO.Y#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#Ubmb.apa3#da8#i#ibMbMbMbMaJbl#o#dbr#U#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#Ubm#o#d#f#i#k#k#ibMbMbMbMbMbpaS#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#lbpaxbabaaxba#ibzbzbM#daS#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#db0b0b0#Z#wbjbg#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U",
+"#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U#U"
+};
diff --git a/examples/demo/opengl/glbox.cpp b/examples/demo/opengl/glbox.cpp
new file mode 100644
index 0000000..6e9e686
--- /dev/null
+++ b/examples/demo/opengl/glbox.cpp
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+/****************************************************************************
+**
+** This is a simple QGLWidget displaying an openGL wireframe box
+**
+** The OpenGL code is mostly borrowed from Brian Pauls "spin" example
+** in the Mesa distribution
+**
+****************************************************************************/
+
+#include "glbox.h"
+
+#if defined(Q_CC_MSVC)
+#pragma warning(disable:4305) // init: truncation from const double to float
+#endif
+
+/*!
+ Create a GLBox widget
+*/
+
+GLBox::GLBox( QWidget* parent, const char* name, WFlags f )
+ : GLControlWidget( parent, name, 0, f )
+{
+ setAnimationDelay( -1 );
+ xRot = yRot = zRot = 0.0; // default object rotation
+ scale = 1.25; // default object scale
+ object = 0;
+}
+
+
+/*!
+ Release allocated resources
+*/
+
+GLBox::~GLBox()
+{
+ makeCurrent();
+ glDeleteLists( object, 1 );
+}
+
+
+/*!
+ Paint the box. The actual openGL commands for drawing the box are
+ performed here.
+*/
+
+void GLBox::paintGL()
+{
+ glClear( GL_COLOR_BUFFER_BIT );
+
+ glLoadIdentity();
+ transform();
+ glCallList( object );
+ drawText();
+ qglColor( green );
+ glLineWidth( 1.0 );
+ glBegin( GL_LINES );
+ {
+ glVertex3f( 0.0, 0.0, 0.0 );
+ glVertex3f( 0.98, 0.98, 0.98 );
+ }
+ glEnd();
+ renderText( 1.0, 1.0, 1.0, "Wirebox", QFont( "helvetica", 12, QFont::Bold, TRUE ) );
+}
+
+
+/*!
+ Set up the OpenGL rendering state, and define display list
+*/
+
+void GLBox::initializeGL()
+{
+ qglClearColor( black ); // Let OpenGL clear to black
+ object = makeObject(); // Generate an OpenGL display list
+ glShadeModel( GL_FLAT );
+}
+
+
+
+/*!
+ Set up the OpenGL view port, matrix mode, etc.
+*/
+
+void GLBox::resizeGL( int w, int h )
+{
+ glViewport( 0, 0, (GLint)w, (GLint)h );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 15.0 );
+ glMatrixMode( GL_MODELVIEW );
+}
+
+
+/*!
+ Generate an OpenGL display list for the object to be shown, i.e. the box
+*/
+
+GLuint GLBox::makeObject()
+{
+ GLuint list;
+
+ list = glGenLists( 1 );
+
+ glNewList( list, GL_COMPILE );
+
+ qglColor( white ); // Shorthand for glColor3f or glIndex
+
+ glLineWidth( 2.0 );
+
+ glBegin( GL_LINE_LOOP );
+ glVertex3f( 1.0, 0.5, -0.4 );
+ glVertex3f( 1.0, -0.5, -0.4 );
+ glVertex3f( -1.0, -0.5, -0.4 );
+ glVertex3f( -1.0, 0.5, -0.4 );
+ glEnd();
+
+ glBegin( GL_LINE_LOOP );
+ glVertex3f( 1.0, 0.5, 0.4 );
+ glVertex3f( 1.0, -0.5, 0.4 );
+ glVertex3f( -1.0, -0.5, 0.4 );
+ glVertex3f( -1.0, 0.5, 0.4 );
+ glEnd();
+
+ glBegin( GL_LINES );
+ glVertex3f( 1.0, 0.5, -0.4 ); glVertex3f( 1.0, 0.5, 0.4 );
+ glVertex3f( 1.0, -0.5, -0.4 ); glVertex3f( 1.0, -0.5, 0.4 );
+ glVertex3f( -1.0, -0.5, -0.4 ); glVertex3f( -1.0, -0.5, 0.4 );
+ glVertex3f( -1.0, 0.5, -0.4 ); glVertex3f( -1.0, 0.5, 0.4 );
+ glEnd();
+
+ glEndList();
+
+ return list;
+}
diff --git a/examples/demo/opengl/glbox.h b/examples/demo/opengl/glbox.h
new file mode 100644
index 0000000..6f5089b
--- /dev/null
+++ b/examples/demo/opengl/glbox.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+/****************************************************************************
+**
+** This is a simple QGLWidget displaying an openGL wireframe box
+**
+****************************************************************************/
+
+#ifndef GLBOX_H
+#define GLBOX_H
+
+#include "glcontrolwidget.h"
+
+class GLBox : public GLControlWidget
+{
+ Q_OBJECT
+
+public:
+
+ GLBox( QWidget* parent = 0, const char* name = 0, WFlags f = 0 );
+ ~GLBox();
+
+protected:
+
+ void initializeGL();
+ void paintGL();
+ void resizeGL( int w, int h );
+
+ virtual GLuint makeObject();
+
+private:
+ GLuint object;
+};
+
+
+#endif // GLBOX_H
diff --git a/examples/demo/opengl/glcontrolwidget.cpp b/examples/demo/opengl/glcontrolwidget.cpp
new file mode 100644
index 0000000..d81d328
--- /dev/null
+++ b/examples/demo/opengl/glcontrolwidget.cpp
@@ -0,0 +1,195 @@
+#include "glcontrolwidget.h"
+
+#include <qcursor.h>
+#include <qtimer.h>
+
+#include <math.h>
+
+GLControlWidget::GLControlWidget( QWidget *parent, const char *name, QGLWidget *share, WFlags f )
+: QGLWidget( parent, name, share, f ),
+ xRot(0),yRot(0),zRot(0),xTrans(0),yTrans(0),zTrans(-10.0),scale(5.0), animation(TRUE), wasAnimated(FALSE), delay( 50 )
+{
+ setCursor( pointingHandCursor );
+ timer = new QTimer( this );
+ connect( timer, SIGNAL(timeout()), SLOT(animate()) );
+ timer->start( delay );
+}
+
+void GLControlWidget::transform()
+{
+ glTranslatef( xTrans, yTrans, zTrans );
+ glScalef( scale, scale, scale );
+
+ glRotatef( xRot, 1.0, 0.0, 0.0 );
+ glRotatef( yRot, 0.0, 1.0, 0.0 );
+ glRotatef( zRot, 0.0, 0.0, 1.0 );
+}
+
+void GLControlWidget::drawText()
+{
+ glPushAttrib( GL_LIGHTING_BIT | GL_TEXTURE_BIT );
+ glDisable( GL_LIGHTING );
+ glDisable( GL_TEXTURE_2D );
+ qglColor( white );
+ QString str( "Rendering text in OpenGL is easy with Qt" );
+ QFontMetrics fm( font() );
+ renderText( (width() - fm.width( str )) / 2, 15, str );
+ QFont f( "courier", 8 );
+ QFontMetrics fmc( f );
+ qglColor( QColor("skyblue") );
+ int x, y, z;
+ x = (xRot >= 0) ? (int) xRot % 360 : 359 - (QABS((int) xRot) % 360);
+ y = (yRot >= 0) ? (int) yRot % 360 : 359 - (QABS((int) yRot) % 360);
+ z = (zRot >= 0) ? (int) zRot % 360 : 359 - (QABS((int) zRot) % 360);
+ str.sprintf( "Rot X: %03d - Rot Y: %03d - Rot Z: %03d", x, y, z );
+ renderText( (width() - fmc.width( str )) / 2, height() - 15, str, f );
+ glPopAttrib();
+}
+
+/*!
+ Set the rotation angle of the object to \e degrees around the X axis.
+*/
+void GLControlWidget::setXRotation( double degrees )
+{
+ xRot = (GLfloat)fmod(degrees, 360.0);
+ updateGL();
+}
+
+/*!
+ Set the rotation angle of the object to \e degrees around the Y axis.
+*/
+void GLControlWidget::setYRotation( double degrees )
+{
+ yRot = (GLfloat)fmod(degrees, 360.0);
+ updateGL();
+}
+
+
+/*!
+ Set the rotation angle of the object to \e degrees around the Z axis.
+*/
+void GLControlWidget::setZRotation( double degrees )
+{
+ zRot = (GLfloat)fmod(degrees, 360.0);
+ updateGL();
+}
+
+void GLControlWidget::setScale( double s )
+{
+ scale = s;
+ updateGL();
+}
+
+void GLControlWidget::setXTrans( double x )
+{
+ xTrans = x;
+ updateGL();
+}
+
+void GLControlWidget::setYTrans( double y )
+{
+ yTrans = y;
+ updateGL();
+}
+
+void GLControlWidget::setZTrans( double z )
+{
+ zTrans = z;
+ updateGL();
+}
+
+void GLControlWidget::setRotationImpulse( double x, double y, double z )
+{
+ setXRotation( xRot + 180*x );
+ setYRotation( yRot + 180*y );
+ setZRotation( zRot - 180*z );
+}
+
+void GLControlWidget::setTranslationImpulse( double x, double y, double z )
+{
+ setXTrans( xTrans + 2*x );
+ setYTrans( yTrans - 2*y );
+ setZTrans( zTrans + 2*z );
+}
+
+void GLControlWidget::mousePressEvent( QMouseEvent *e )
+{
+ e->accept();
+ oldPos = e->pos();
+}
+
+void GLControlWidget::mouseReleaseEvent( QMouseEvent *e )
+{
+ e->accept();
+ oldPos = e->pos();
+}
+
+void GLControlWidget::mouseMoveEvent( QMouseEvent *e )
+{
+ e->accept();
+ double dx = e->x() - oldPos.x();
+ double dy = e->y() - oldPos.y();
+
+ oldPos = e->pos();
+
+ double rx = dx / width();
+ double ry = dy / height();
+
+ if ( e->state() == LeftButton )
+ setRotationImpulse( ry, rx, 0 );
+ else if ( e->state() == RightButton )
+ setRotationImpulse( ry, 0, rx );
+ else if ( e->state() == MidButton )
+ setTranslationImpulse( rx, ry, 0 );
+ else if ( e->state() == ( LeftButton | RightButton ) )
+ setTranslationImpulse( rx, 0, ry );
+}
+
+void GLControlWidget::wheelEvent( QWheelEvent *e )
+{
+ e->accept();
+ if ( scale <= ( (double)e->delta() / 1000 ) )
+ return;
+ setScale( scale - ( (double)e->delta() / 1000 ));
+}
+
+void GLControlWidget::mouseDoubleClickEvent( QMouseEvent * )
+{
+ if ( delay <= 0 )
+ return;
+
+ animation = !animation;
+ if ( animation )
+ timer->start( delay );
+ else
+ timer->stop();
+}
+
+void GLControlWidget::showEvent( QShowEvent *e )
+{
+ if ( wasAnimated && !timer->isActive() )
+ timer->start( delay );
+
+ QGLWidget::showEvent( e );
+}
+
+void GLControlWidget::hideEvent( QHideEvent *e )
+{
+ wasAnimated = timer->isActive();
+ timer->stop();
+ QGLWidget::hideEvent( e );
+}
+
+void GLControlWidget::animate()
+{
+}
+
+void GLControlWidget::setAnimationDelay( int ms )
+{
+ timer->stop();
+ delay = ms;
+ if ( animation ) {
+ wasAnimated = TRUE;
+ timer->start( delay );
+ }
+}
diff --git a/examples/demo/opengl/glcontrolwidget.h b/examples/demo/opengl/glcontrolwidget.h
new file mode 100644
index 0000000..05d026f
--- /dev/null
+++ b/examples/demo/opengl/glcontrolwidget.h
@@ -0,0 +1,56 @@
+#ifndef GLCONTROLWIDGET_H
+#define GLCONTROLWIDGET_H
+
+#include <qgl.h>
+
+class GLControlWidget : public QGLWidget
+{
+ Q_OBJECT
+
+public:
+ GLControlWidget( QWidget *parent, const char *name = 0, QGLWidget *share = 0, WFlags f = 0 );
+
+ virtual void transform();
+
+public slots:
+ void setXRotation( double degrees );
+ void setYRotation( double degrees );
+ void setZRotation( double degrees );
+
+ void setScale( double s );
+
+ void setXTrans( double x );
+ void setYTrans( double y );
+ void setZTrans( double z );
+
+ virtual void setRotationImpulse( double x, double y, double z );
+ virtual void setTranslationImpulse( double x, double y, double z );
+ void drawText();
+
+protected:
+ void setAnimationDelay( int ms );
+ void mousePressEvent( QMouseEvent *e );
+ void mouseReleaseEvent( QMouseEvent *e );
+ void mouseMoveEvent( QMouseEvent * );
+ void mouseDoubleClickEvent( QMouseEvent * );
+ void wheelEvent( QWheelEvent * );
+
+ void showEvent( QShowEvent * );
+ void hideEvent( QHideEvent * );
+
+ GLfloat xRot, yRot, zRot;
+ GLfloat xTrans, yTrans, zTrans;
+ GLfloat scale;
+ bool animation;
+
+protected slots:
+ virtual void animate();
+
+private:
+ bool wasAnimated;
+ QPoint oldPos;
+ QTimer* timer;
+ int delay;
+};
+
+#endif
diff --git a/examples/demo/opengl/glgear.cpp b/examples/demo/opengl/glgear.cpp
new file mode 100644
index 0000000..e9b837b
--- /dev/null
+++ b/examples/demo/opengl/glgear.cpp
@@ -0,0 +1,271 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+//
+// Draws a gear.
+//
+// Portions of this code have been borrowed from Brian Paul's Mesa
+// distribution.
+//
+
+#include "glgear.h"
+
+#include <math.h>
+
+#if defined(Q_CC_MSVC)
+#pragma warning(disable:4305) // init: truncation from const double to float
+#endif
+
+/*
+ * Draw a gear wheel. You'll probably want to call this function when
+ * building a display list since we do a lot of trig here.
+ *
+ * Input: inner_radius - radius of hole at center
+ * outer_radius - radius at center of teeth
+ * width - width of gear
+ * teeth - number of teeth
+ * tooth_depth - depth of tooth
+ */
+static void gear( GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
+ GLint teeth, GLfloat tooth_depth )
+{
+ GLint i;
+ GLfloat r0, r1, r2;
+ GLfloat angle, da;
+ GLfloat u, v, len;
+
+ r0 = inner_radius;
+ r1 = outer_radius - tooth_depth/2.0;
+ r2 = outer_radius + tooth_depth/2.0;
+
+ const double pi = 3.14159264;
+ da = 2.0*pi / teeth / 4.0;
+
+ glShadeModel( GL_FLAT );
+
+ glNormal3f( 0.0, 0.0, 1.0 );
+
+ /* draw front face */
+ glBegin( GL_QUAD_STRIP );
+ for (i=0;i<=teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+ glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
+ glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
+ glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
+ glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
+ }
+ glEnd();
+
+ /* draw front sides of teeth */
+ glBegin( GL_QUADS );
+ da = 2.0*pi / teeth / 4.0;
+ for (i=0;i<teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+
+ glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
+ glVertex3f( r2*cos(angle+da), r2*sin(angle+da), width*0.5 );
+ glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5 );
+ glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
+ }
+ glEnd();
+
+
+ glNormal3f( 0.0, 0.0, -1.0 );
+
+ /* draw back face */
+ glBegin( GL_QUAD_STRIP );
+ for (i=0;i<=teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+ glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
+ glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
+ glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
+ glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
+ }
+ glEnd();
+
+ /* draw back sides of teeth */
+ glBegin( GL_QUADS );
+ da = 2.0*pi / teeth / 4.0;
+ for (i=0;i<teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+
+ glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
+ glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5 );
+ glVertex3f( r2*cos(angle+da), r2*sin(angle+da), -width*0.5 );
+ glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
+ }
+ glEnd();
+
+
+ /* draw outward faces of teeth */
+ glBegin( GL_QUAD_STRIP );
+ for (i=0;i<teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+
+ glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 );
+ glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 );
+ u = r2*cos(angle+da) - r1*cos(angle);
+ v = r2*sin(angle+da) - r1*sin(angle);
+ len = sqrt( u*u + v*v );
+ u /= len;
+ v /= len;
+ glNormal3f( v, -u, 0.0 );
+ glVertex3f( r2*cos(angle+da), r2*sin(angle+da), width*0.5 );
+ glVertex3f( r2*cos(angle+da), r2*sin(angle+da), -width*0.5 );
+ glNormal3f( cos(angle), sin(angle), 0.0 );
+ glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5 );
+ glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5 );
+ u = r1*cos(angle+3*da) - r2*cos(angle+2*da);
+ v = r1*sin(angle+3*da) - r2*sin(angle+2*da);
+ glNormal3f( v, -u, 0.0 );
+ glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
+ glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 );
+ glNormal3f( cos(angle), sin(angle), 0.0 );
+ }
+
+ glVertex3f( r1*cos(0.0), r1*sin(0.0), width*0.5 );
+ glVertex3f( r1*cos(0.0), r1*sin(0.0), -width*0.5 );
+
+ glEnd();
+
+
+ glShadeModel( GL_SMOOTH );
+
+ /* draw inside radius cylinder */
+ glBegin( GL_QUAD_STRIP );
+ for (i=0;i<=teeth;i++) {
+ angle = i * 2.0*pi / teeth;
+ glNormal3f( -cos(angle), -sin(angle), 0.0 );
+ glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
+ glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
+ }
+ glEnd();
+
+}
+
+void GLGear::draw()
+{
+ glPushMatrix();
+ glRotatef( view_rotx, 1.0, 0.0, 0.0 );
+ glRotatef( view_roty, 0.0, 1.0, 0.0 );
+ glRotatef( view_rotz, 0.0, 0.0, 1.0 );
+
+ glPushMatrix();
+ glTranslatef( -3.0, -2.0, 0.0 );
+ glRotatef( angle, 0.0, 0.0, 1.0 );
+ glCallList(gear1);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef( 3.1, -2.0, 0.0 );
+ glRotatef( -2.0*angle-9.0, 0.0, 0.0, 1.0 );
+ glCallList(gear2);
+ glPopMatrix();
+
+ glPushMatrix();
+ glTranslatef( -3.1, 2.2, -1.8 );
+ glRotatef( 90.0, 1.0, 0.0, 0.0 );
+ glRotatef( 2.0*angle-2.0, 0.0, 0.0, 1.0 );
+ glCallList(gear3);
+ glPopMatrix();
+
+ glPopMatrix();
+}
+
+GLGear::GLGear( QWidget *parent, const char *name, WFlags f )
+ : GLControlWidget( parent, name, 0, f )
+{
+ scale = 1.0;
+ setAnimationDelay( 15 );
+ view_rotx = 20.0;
+ view_roty = 30.0;
+ view_rotz = 0.0;
+ angle = 0.0;
+}
+
+void GLGear::initializeGL()
+{
+ static GLfloat pos[4] = {5.0, 5.0, 10.0, 1.0 };
+ static GLfloat ared[4] = {0.8, 0.1, 0.0, 1.0 };
+ static GLfloat agreen[4] = {0.0, 0.8, 0.2, 1.0 };
+ static GLfloat ablue[4] = {0.2, 0.2, 1.0, 1.0 };
+
+ glLightfv( GL_LIGHT0, GL_POSITION, pos );
+ glEnable( GL_CULL_FACE );
+ glEnable( GL_LIGHTING );
+ glEnable( GL_LIGHT0 );
+ glEnable( GL_DEPTH_TEST );
+
+ /* make the gears */
+ gear1 = glGenLists(1);
+ glNewList(gear1, GL_COMPILE);
+ glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ared );
+ gear( 1.0, 4.0, 1.0, 20, 0.7 );
+ glEndList();
+
+ gear2 = glGenLists(1);
+ glNewList(gear2, GL_COMPILE);
+ glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, agreen );
+ gear( 0.5, 2.0, 2.0, 10, 0.7 );
+ glEndList();
+
+ gear3 = glGenLists(1);
+ glNewList(gear3, GL_COMPILE);
+ glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, ablue );
+ gear( 1.3, 2.0, 0.5, 10, 0.7 );
+ glEndList();
+
+ glEnable( GL_NORMALIZE );
+}
+
+
+void GLGear::resizeGL( int width, int height )
+{
+ GLfloat w = (float) width / (float) height;
+ GLfloat h = 1.0;
+
+ glViewport( 0, 0, width, height );
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum( -w, w, -h, h, 5.0, 60.0 );
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef( 0.0, 0.0, -40.0 );
+}
+
+
+void GLGear::paintGL()
+{
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ glPushMatrix();
+ transform();
+ draw();
+ drawText();
+
+ glPushAttrib( GL_LIGHTING_BIT | GL_TEXTURE_BIT );
+ glDisable( GL_LIGHTING );
+ glDisable( GL_TEXTURE_2D );
+ qglColor( green );
+ glLineWidth( 1.0 );
+ glBegin( GL_LINES );
+ {
+ glVertex3f( 0.0, 0.0, 0.0 );
+ glVertex3f( 2.98, 2.98, 2.98 );
+ }
+ glEnd();
+ renderText( 3.0, 3.0, 3.0, "Gears", QFont( "helvetica", 12, QFont::Bold, TRUE ) );
+ glPopMatrix();
+ glPopAttrib();
+}
+
+void GLGear::animate()
+{
+ angle += 2.0;
+ view_roty += 1.0;
+ updateGL();
+}
diff --git a/examples/demo/opengl/glgear.h b/examples/demo/opengl/glgear.h
new file mode 100644
index 0000000..e728765
--- /dev/null
+++ b/examples/demo/opengl/glgear.h
@@ -0,0 +1,26 @@
+#ifndef GLGEAR_H
+#define GLGEAR_H
+
+#include "glcontrolwidget.h"
+
+class GLGear : public GLControlWidget
+{
+ Q_OBJECT
+
+public:
+ GLGear( QWidget *parent = 0, const char *name = 0, WFlags f = 0 );
+
+protected:
+ void draw();
+ void animate();
+ void initializeGL();
+ void resizeGL( int, int );
+ void paintGL();
+
+private:
+ GLfloat view_rotx, view_roty, view_rotz;
+ GLint gear1, gear2, gear3;
+ GLfloat angle;
+};
+
+#endif // GLGEAR_H
diff --git a/examples/demo/opengl/glinfo.h b/examples/demo/opengl/glinfo.h
new file mode 100644
index 0000000..1e1d1dd
--- /dev/null
+++ b/examples/demo/opengl/glinfo.h
@@ -0,0 +1,26 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef GLINFO_H
+#define GLINFO_H
+
+#include <qstring.h>
+
+class GLInfo
+{
+public:
+ GLInfo();
+ QString info();//extensions();
+/* QString configs(); */
+
+protected:
+ QString infotext;
+/* QString config; */
+};
+#endif
diff --git a/examples/demo/opengl/glinfo_x11.cpp b/examples/demo/opengl/glinfo_x11.cpp
new file mode 100644
index 0000000..1137ef9
--- /dev/null
+++ b/examples/demo/opengl/glinfo_x11.cpp
@@ -0,0 +1,257 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#define QT_CLEAN_NAMESPACE // avoid clashes with Xmd.h
+
+#include <qstringlist.h>
+#include <qgl.h>
+#include "glinfo.h"
+
+#include <GL/glx.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#ifndef GLX_NONE_EXT
+#define GLX_NONE_EXT 0x8000
+#endif
+
+typedef struct visualAttribs {
+ /* X visual attribs */
+ int id;
+ int c_class;
+ int depth;
+ int redMask, greenMask, blueMask;
+ int colormapSize;
+ int bitsPerRGB;
+ /* GL visual attribs */
+ int supportsGL;
+ int transparent;
+ int bufferSize;
+ int level;
+ int rgba;
+ int doubleBuffer;
+ int stereo;
+ int auxBuffers;
+ int redSize, greenSize, blueSize, alphaSize;
+ int depthSize;
+ int stencilSize;
+ int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
+ int numSamples, numMultisample;
+ int visualCaveat;
+} VisualAttribs;
+
+static void screenInfo( Display *dpy, int scrnum, QString &infotext )
+{
+ const char *serverVendor = glXQueryServerString( dpy, scrnum, GLX_VENDOR );
+ const char *serverVersion = glXQueryServerString( dpy, scrnum, GLX_VERSION );
+ const char *serverExtensions = glXQueryServerString( dpy, scrnum, GLX_EXTENSIONS );
+ const char *clientVendor = glXGetClientString( dpy, GLX_VENDOR );
+ const char *clientVersion = glXGetClientString( dpy, GLX_VERSION );
+ const char *clientExtensions = glXGetClientString( dpy, GLX_EXTENSIONS );
+ const char *glxExtensions = glXQueryExtensionsString( dpy, scrnum );
+ const char *glVendor = (const char *) glGetString( GL_VENDOR );
+ const char *glRenderer = (const char *) glGetString( GL_RENDERER );
+ const char *glVersion = (const char *) glGetString( GL_VERSION );
+ const char *glExtensions = (const char *) glGetString( GL_EXTENSIONS );
+ const char *gluVersion = (const char *) gluGetString( (GLenum) GLU_VERSION );
+ const char *gluExtensions = (const char *) gluGetString( (GLenum) GLU_EXTENSIONS );
+
+ infotext.sprintf( "%sServer GLX vendor string: %s\n", infotext.ascii(), serverVendor );
+ infotext.sprintf( "%sServer GLX version string: %s\n", infotext.ascii(), serverVersion );
+ infotext.sprintf( "%sServer GLX extensions:\n", infotext.ascii() );
+
+ infotext += QString( serverExtensions ).replace( ' ', '\n' ) + "\n\n";
+
+ infotext.sprintf( "%sClient GLX vendor string: %s\n", infotext.ascii(), clientVendor );
+ infotext.sprintf( "%sClient GLX version string: %s\n", infotext.ascii(), clientVersion );
+ infotext.sprintf( "%sClient GLX extensions:\n", infotext.ascii() );
+
+ infotext += QString( clientExtensions ).replace( ' ', '\n' ) + "\n\n";
+
+ infotext.sprintf( "%sGLX extensions:\n", infotext.ascii() );
+
+ infotext += QString( glxExtensions ).replace( ' ', '\n' ) + "\n\n";
+
+ infotext.sprintf( "%sOpenGL vendor string: %s\n", infotext.ascii(), glVendor );
+ infotext.sprintf( "%sOpenGL renderer string: %s\n", infotext.ascii(), glRenderer );
+ infotext.sprintf( "%sOpenGL version string: %s\n", infotext.ascii(), glVersion );
+ infotext.sprintf( "%sOpenGL extensions:\n", infotext.ascii() );
+
+ infotext += QString( glExtensions ).replace( ' ', '\n' ) + "\n\n";
+
+ infotext.sprintf( "%sGLU version: %s\n", infotext.ascii(), gluVersion );
+ infotext.sprintf( "%sGLU extensions:\n", infotext.ascii() );
+
+ infotext += QString( gluExtensions ).replace( ' ', '\n' ) + "\n\n";
+}
+
+static const char * visualClassName( int cls )
+{
+ switch ( cls ) {
+ case StaticColor:
+ return "StaticColor";
+ case PseudoColor:
+ return "PseudoColor";
+ case StaticGray:
+ return "StaticGray";
+ case GrayScale:
+ return "GrayScale";
+ case TrueColor:
+ return "TrueColor";
+ case DirectColor:
+ return "DirectColor";
+ default:
+ return "";
+ }
+}
+
+static const char * caveatString( int caveat )
+{
+ switch ( caveat ) {
+#if defined(GLX_EXT_visual_rating)
+ case GLX_NONE_EXT:
+ return "None";
+ case GLX_SLOW_VISUAL_EXT:
+ return "Slow";
+ case GLX_NON_CONFORMANT_VISUAL_EXT:
+ return "Nonconformant";
+#endif
+ default:
+ return "<none>";
+ }
+}
+
+static void visualAttribs( Display * dpy, XVisualInfo * vi, VisualAttribs * attribs )
+{
+ memset( attribs, 0, sizeof( VisualAttribs ) );
+
+ attribs->id = vi->visualid;
+ attribs->c_class = vi->c_class;
+ attribs->depth = vi->depth;
+ attribs->redMask = vi->red_mask;
+ attribs->greenMask = vi->green_mask;
+ attribs->blueMask = vi->blue_mask;
+ attribs->colormapSize = vi->colormap_size;
+ attribs->bitsPerRGB = vi->bits_per_rgb;
+
+ if ( glXGetConfig( dpy, vi, GLX_USE_GL, &attribs->supportsGL ) != 0 )
+ return;
+ attribs->accumAlphaSize = 0;
+ glXGetConfig( dpy, vi, GLX_BUFFER_SIZE, &attribs->bufferSize );
+ glXGetConfig( dpy, vi, GLX_LEVEL, &attribs->level );
+ glXGetConfig( dpy, vi, GLX_RGBA, &attribs->rgba );
+ glXGetConfig( dpy, vi, GLX_DOUBLEBUFFER, &attribs->doubleBuffer );
+ glXGetConfig( dpy, vi, GLX_STEREO, &attribs->stereo );
+ glXGetConfig( dpy, vi, GLX_AUX_BUFFERS, &attribs->auxBuffers );
+ glXGetConfig( dpy, vi, GLX_RED_SIZE, &attribs->redSize );
+ glXGetConfig( dpy, vi, GLX_GREEN_SIZE, &attribs->greenSize );
+ glXGetConfig( dpy, vi, GLX_BLUE_SIZE, &attribs->blueSize );
+ glXGetConfig( dpy, vi, GLX_ALPHA_SIZE, &attribs->alphaSize );
+ glXGetConfig( dpy, vi, GLX_DEPTH_SIZE, &attribs->depthSize );
+ glXGetConfig( dpy, vi, GLX_STENCIL_SIZE, &attribs->stencilSize );
+ glXGetConfig( dpy, vi, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize );
+ glXGetConfig( dpy, vi, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize );
+ glXGetConfig( dpy, vi, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize );
+ glXGetConfig( dpy, vi, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize );
+
+ attribs->transparent = 0; // transparent pixel missing
+ attribs->numSamples = 0; // multisample tests missing
+ attribs->numMultisample = 0;
+
+#if defined(GLX_EXT_visual_rating)
+ const char *ext = glXQueryExtensionsString( dpy, vi->screen );
+ if ( ext && strstr( ext, "GLX_EXT_visual_rating" ) )
+ glXGetConfig(dpy, vi, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
+ else
+ attribs->visualCaveat = GLX_NONE_EXT;
+#else
+ attribs->visualCaveat = 0;
+#endif
+}
+
+static void visualInfo( Display *dpy, int scrnum, QString &configs )
+{
+ QString str;
+ XVisualInfo *visuals, temp;
+ int numVisuals;
+ long mask;
+ int i;
+
+ /* get list of all visuals on this screen */
+ temp.screen = scrnum;
+ mask = VisualScreenMask;
+ visuals = XGetVisualInfo( dpy, mask, &temp, &numVisuals );
+
+ VisualAttribs attribs;
+ configs.append( "Vis Vis Visual Trans buff lev render DB ste r g b a aux dep ste accum buffers MS MS\n"
+ " ID Depth Type parent size el type reo sz sz sz sz buf th ncl r g b a num bufs Caveat\n"
+ "-----------------------------------------------------------------------------------------------------------\n" );
+ for ( i = 0; i < numVisuals; i++ ) {
+ visualAttribs( dpy, &visuals[i], &attribs );
+ str.sprintf( "0x%2x %2d %-12s %d %2d %d %-4s %d %d %d %d %d %d"
+ " %d %2d %d %2d %2d %2d %2d %d %d %s\n",
+ attribs.id,
+ attribs.depth,
+ visualClassName( attribs.c_class ),
+ attribs.transparent,
+ attribs.bufferSize,
+ attribs.level,
+ attribs.rgba ? "rgba" : "ci",
+ attribs.doubleBuffer,
+ attribs.stereo,
+ attribs.redSize,
+ attribs.greenSize,
+ attribs.blueSize,
+ attribs.alphaSize,
+ attribs.auxBuffers,
+ attribs.depthSize,
+ attribs.stencilSize,
+ attribs.accumRedSize,
+ attribs.accumGreenSize,
+ attribs.accumBlueSize,
+ attribs.accumAlphaSize,
+ attribs.numSamples,
+ attribs.numMultisample,
+ caveatString( attribs.visualCaveat ) );
+ configs.append( str );
+ }
+
+
+ XFree( visuals );
+}
+
+GLInfo::GLInfo()
+{
+ QGLWidget gl((QWidget *) 0);
+ gl.makeCurrent();
+ Display *dpy;
+ char *displayName = 0;
+ int numScreens, scrNum;
+
+ dpy = gl.x11Display();
+ if ( !dpy ) {
+ qWarning( "Error: unable to open display %s\n", displayName );
+ }
+
+ numScreens = ScreenCount( dpy );
+ infotext.sprintf( "Display name: %s\nDirect rendering: %s\n", DisplayString( dpy ),
+ gl.format().directRendering() ? "Yes" : "No" );
+
+ for ( scrNum = 0; scrNum < numScreens; scrNum++ ) {
+ screenInfo( dpy, scrNum, infotext );
+ visualInfo( dpy, scrNum, infotext );
+ if ( scrNum + 1 < numScreens )
+ infotext.append( "\n\n" );
+ }
+}
+
+QString GLInfo::info()
+{
+ return infotext;
+}
diff --git a/examples/demo/opengl/glinfotext.h b/examples/demo/opengl/glinfotext.h
new file mode 100644
index 0000000..7d7b656
--- /dev/null
+++ b/examples/demo/opengl/glinfotext.h
@@ -0,0 +1,23 @@
+#include <qlayout.h>
+#include <qtextview.h>
+#include <qfont.h>
+#include "glinfo.h"
+
+class GLInfoText : public QWidget
+{
+public:
+ GLInfoText(QWidget *parent)
+ : QWidget(parent)
+ {
+ view = new QTextView(this);
+ view->setFont(QFont("courier", 10));
+ view->setWordWrap(QTextEdit::NoWrap);
+ QHBoxLayout *l = new QHBoxLayout(this);
+ l->addWidget(view);
+ GLInfo info;
+ view->setText(info.info());
+ }
+
+private:
+ QTextView *view;
+};
diff --git a/examples/demo/opengl/gllandscape.cpp b/examples/demo/opengl/gllandscape.cpp
new file mode 100644
index 0000000..e11c8c9
--- /dev/null
+++ b/examples/demo/opengl/gllandscape.cpp
@@ -0,0 +1,880 @@
+#include <qimage.h>
+#include "gllandscape.h"
+
+
+#include <math.h>
+
+#include "fbm.h"
+
+#ifndef PI
+#define PI 3.14159
+#endif
+
+#if defined(Q_CC_MSVC)
+#pragma warning(disable:4305) // init: truncation from const double to float
+#pragma warning(disable:4244) // init: truncation from const double to float
+#endif
+
+GLLandscape::GLLandscape( QWidget * parent, const char * name )
+ : QGLWidget( parent, name )
+{
+ mouseButtonDown = FALSE;
+ animationRunning = FALSE;
+ oldX = oldY = oldZ = 0.0;
+ landscape = 0;
+ vertexNormals = 0;
+ normals = 0;
+ wave = 0;
+ wt = 0;
+ cubeRot = 0;
+ createGrid( 50 );
+ setWireframe( 0 );
+}
+
+GLLandscape::~GLLandscape()
+{
+ destroyGrid();
+}
+
+void GLLandscape::initializeGL()
+{
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ glGetFloatv( GL_MODELVIEW_MATRIX,(GLfloat *) views[AxisView].model );
+
+ glTranslatef( 0.0, 0.0, -50.0 );
+ glRotatef( -45, 1, 0, 0 );
+ glRotatef( -45, 0, 0, 1 );
+ glGetFloatv( GL_MODELVIEW_MATRIX,(GLfloat *) views[CurrentView].model );
+ glGetFloatv( GL_MODELVIEW_MATRIX,(GLfloat *) views[DefaultView].model );
+
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ /* Use GL utility library function to obtain desired view */
+ gluPerspective( 60, 1, 1, 250 );
+ glGetFloatv( GL_PROJECTION_MATRIX, (GLfloat *)views[CurrentView].projection );
+ glGetFloatv( GL_PROJECTION_MATRIX, (GLfloat *)views[DefaultView].projection );
+
+ qglClearColor( black );
+ glDepthFunc( GL_LESS );
+ calculateVertexNormals();
+
+ QImage tex;
+ tex.load("opengl/qtlogo.png");
+ tex = QGLWidget::convertToGLFormat(tex); // flipped 32bit RGBA
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+ glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());
+ initDisplayLists();
+}
+
+void GLLandscape::resizeGL( int width, int height )
+{
+ glViewport( 0, 0, width, height );
+}
+
+void GLLandscape::paintGL()
+{
+ QString str;
+ GLboolean lighting;
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ switch ( mode ) {
+ case Wireframe:
+ drawWireframe();
+ str = tr( "Wireframe" );
+ break;
+ case Filled:
+ drawFilled();
+ str = tr( "Flat shaded" );
+ break;
+ case SmoothShaded:
+ str = tr( "Smooth shaded" );
+ drawSmoothShaded();
+ break;
+ case Landscape:
+ drawSmoothShaded();
+ str = tr( "Landscape" );
+ break;
+ }
+ glGetBooleanv( GL_LIGHTING, &lighting );
+ if ( lighting )
+ glDisable( GL_LIGHTING );
+ qglColor( white );
+ renderText(15, height() - 15, str);
+ drawAxis();
+ drawCube();
+ if ( lighting )
+ glEnable( GL_LIGHTING );
+}
+
+void GLLandscape::drawAxis()
+{
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glViewport(15, 20, 50, 50);
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(-1.1, 1.1, -1.1, 1.1, 0.1, 10);
+ glTranslatef(0, 0, -1.2);
+ glRotatef(-45, 1, 0, 0);
+ glRotatef(-45, 0, 0, 1);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadMatrixf((GLfloat *) views[AxisView].model);
+
+ glCallList(axisList);
+ qglColor(white);
+ renderText(1.1f, 0, 0, "x");
+ renderText(0, 1.1f, 0, "y");
+ renderText(0, 0, 1.1f, "z");
+
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glPopAttrib();
+}
+
+void GLLandscape::drawCube()
+{
+ glPushAttrib(GL_ALL_ATTRIB_BITS);
+ glViewport(width()-75, 0, 75, 75);
+ glMatrixMode( GL_PROJECTION );
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(-1.1, 1.1, -1.1, 1.1, 0.1, 10);
+ glTranslatef(0, 0, -1.2);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+ glRotatef(cubeRot, 1, 0, 0);
+ glRotatef(cubeRot, 0, 1, 0);
+ glRotatef(cubeRot, 0, 0, 1);
+ glTranslatef(-0.5, -0.5, -0.5);
+
+ glCallList(cubeList);
+
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glPopAttrib();
+}
+
+void GLLandscape::drawWireframe()
+{
+ qglColor( white );
+ glBegin( GL_LINES );
+ {
+ for ( int y = 0; y < (gridSize-1); y++ )
+ for ( int x = 0; x < (gridSize-1); x++) {
+ glVertex3f( x-gridHalf, y-gridHalf, landscape[x][y] );
+ glVertex3f( x+1-gridHalf, y-gridHalf, landscape[x+1][y] );
+ glVertex3f( x-gridHalf, y-gridHalf, landscape[x][y] );
+ glVertex3f( x+1-gridHalf, y+1-gridHalf, landscape[x+1][y+1] );
+
+ glVertex3f( x-gridHalf, y-gridHalf, landscape[x][y] );
+ glVertex3f( x-gridHalf, y+1-gridHalf, landscape[x][y+1] );
+ }
+ }
+ glEnd();
+ glBegin( GL_LINE_STRIP );
+ {
+ for ( int x = 0; x < gridSize; x++ ) {
+ glVertex3f( x-gridHalf, gridHalf-1, landscape[x][gridSize-1] );
+ }
+ }
+ glEnd();
+ glBegin( GL_LINE_STRIP );
+ {
+ for ( int y = 0; y < gridSize; y++ ) {
+ glVertex3f( gridHalf-1, y-gridHalf, landscape[gridSize-1][y] );
+ }
+ }
+ glEnd();
+}
+
+void GLLandscape::drawFilled()
+{
+ for ( int y = 0; y < gridSize-1; y++ )
+ for ( int x = 0; x < gridSize-1; x++ ) {
+ qglColor( red );
+ glBegin( GL_TRIANGLE_STRIP );
+ {
+ glVertex3f(x-gridHalf,y-gridHalf, landscape[x][y]);
+ glVertex3f(x+1-gridHalf,y-gridHalf, landscape[x+1][y]);
+ glVertex3f(x-gridHalf,y+1-gridHalf, landscape[x][y+1]);
+ }
+ glEnd();
+ qglColor( white );
+ glBegin( GL_TRIANGLE_STRIP );
+ {
+ glVertex3f(x+1-gridHalf,y-gridHalf, landscape[x+1][y]);
+ glVertex3f(x+1-gridHalf,y+1-gridHalf, landscape[x+1][y+1]);
+ glVertex3f(x-gridHalf,y+1-gridHalf, landscape[x][y+1]);
+ }
+ glEnd();
+ }
+}
+
+void GLLandscape::drawSmoothShaded()
+{
+ if ( mode == SmoothShaded ) {
+ GLfloat materialAmbient[] = { 0.00, 0.00, 1.0, 0.0 };
+ GLfloat materialShininess[] = { 128.0 };
+ GLfloat materialSpecular[] = { 1.0, 1.0, 1.0, 0.0 };
+
+ glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular );
+ glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient );
+ glMaterialfv( GL_FRONT, GL_SHININESS, materialShininess );
+ } else {
+ GLfloat materialAmbient[] = { 0.20, 0.33, 0.20, 0.0 };
+ GLfloat materialShininess[] = { 1.0 };
+ GLfloat materialSpecular[] = { 0.1, 0.1, 0.1, 0.1 };
+
+ glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular );
+ glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient );
+ glMaterialfv( GL_FRONT, GL_SHININESS, materialShininess );
+ }
+
+ for ( int y = 0; y < gridSize-1; y++ )
+ for ( int x = 0; x < gridSize-1; x++ ) {
+ glBegin( GL_POLYGON );
+ {
+ glNormal3dv(vertexNormals[x][y].n);
+ glVertex3f(x-gridHalf,y-gridHalf,landscape[x][y]);
+
+ glNormal3dv(vertexNormals[x+1][y].n);
+ glVertex3f(x+1-gridHalf, y-gridHalf, landscape[x+1][y]);
+
+ glNormal3dv(vertexNormals[x+1][y+1].n);
+ glVertex3f(x+1-gridHalf, y+1-gridHalf, landscape[x+1][y+1]);
+ }
+ glEnd();
+
+ glBegin( GL_POLYGON );
+ {
+ glNormal3dv(vertexNormals[x][y].n);
+ glVertex3f(x-gridHalf,y-gridHalf, landscape[x][y]);
+
+ glNormal3dv(vertexNormals[x+1][y+1].n);
+ glVertex3f(x+1-gridHalf,y+1-gridHalf, landscape[x+1][y+1]);
+
+ glNormal3dv(vertexNormals[x][y+1].n);
+ glVertex3f(x-gridHalf,y+1-gridHalf, landscape[x][y+1]);
+ }
+ glEnd();
+ }
+
+ // Draw water
+ if ( mode == Landscape ) {
+ GLfloat materialAmbient[] = { 0.00, 0.00, 1.0, 0.0 };
+ GLfloat materialShininess[] = { 128.0 };
+ GLfloat materialSpecular[] = { 1.0, 1.0, 1.0, 0.0 };
+
+ glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular );
+ glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient );
+ glMaterialfv( GL_FRONT, GL_SHININESS, materialShininess );
+
+ glEnable( GL_BLEND );
+ glBegin( GL_POLYGON );
+ {
+ glNormal3f( 0, 0, 1 );
+ glVertex3f( -gridHalf, -gridHalf, .2 );
+ glNormal3f( 0, 0, 1 );
+ glVertex3f( -gridHalf, gridHalf, .2 );
+ glNormal3f( 0, 0, 1 );
+ glVertex3f( gridHalf, gridHalf, .2 );
+ glNormal3f( 0, 0, 1 );
+ glVertex3f( gridHalf, -gridHalf, .2 );
+
+ }
+ glEnd();
+ glDisable( GL_BLEND );
+ }
+}
+
+void GLLandscape::setGridSize( int size )
+{
+ destroyGrid(); // destroy old grid
+ createGrid( size ); // create new grid
+ initializeGL();
+ updateGL();
+}
+
+void GLLandscape::createGrid( int size )
+{
+ if ( (size % 2) != 0 )
+ size++;
+ gridSize = size;
+ gridHalf = gridSize / 2;
+ initFractals = TRUE;
+ landscape = new double*[gridSize];
+ normals = new gridNormals*[gridSize];
+ vertexNormals = new avgNormals*[gridSize];
+ wt = new double*[gridSize];
+ wave = new double*[gridSize];
+ for ( int i = 0; i < gridSize; i++ ) {
+ landscape[i] = new double[gridSize];
+ normals[i] = new gridNormals[gridSize];
+ vertexNormals[i] = new avgNormals[gridSize];
+ wt[i] = new double[gridSize];
+ wave[i] = new double[gridSize];
+
+ memset( landscape[i], 0, gridSize*sizeof(double) );
+ memset( normals[i], 0, gridSize*sizeof(gridNormals) );
+ memset( vertexNormals[i], 0, gridSize*sizeof(avgNormals) );
+ memset( wt[i], 0, gridSize*sizeof(double) );
+ memset( wave[i], 0, gridSize*sizeof(double) );
+ }
+}
+
+void GLLandscape::destroyGrid()
+{
+ if ( landscape != NULL ) {
+ for( int i = 0; i < gridSize; i++ ) {
+ delete[] landscape[i];
+ delete[] normals[i];
+ delete[] vertexNormals[i];
+ delete[] wt[i];
+ delete[] wave[i];
+ }
+ delete[] landscape;
+ delete[] normals;
+ delete[] vertexNormals;
+ delete[] wt;
+ delete[] wave;
+ }
+ landscape = 0;
+}
+
+void GLLandscape::rotate( GLfloat deg, Axis axis )
+{
+ makeCurrent();
+ glMatrixMode( GL_MODELVIEW );
+ for ( int i = DefaultView; i <= AxisView; i++ ) {
+ glLoadMatrixf((GLfloat *) views[i].model);
+ if ( axis == XAxis )
+ glRotatef( deg, 1, 0, 0 );
+ else if ( axis == YAxis )
+ glRotatef( deg, 0, 1, 0 );
+ else
+ glRotatef( deg, 0, 0, 1 );
+ glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) views[i].model);
+ }
+ glLoadMatrixf((GLfloat *) views[CurrentView].model);
+}
+
+void GLLandscape::rotateX( int deg )
+{
+ static int oldDeg = 0;
+
+ rotate( deg-oldDeg, XAxis );
+ oldDeg = deg;
+ updateGL();
+}
+
+void GLLandscape::rotateY( int deg )
+{
+ static int oldDeg = 0;
+
+ rotate( deg-oldDeg, YAxis );
+ oldDeg = deg;
+ updateGL();
+}
+
+void GLLandscape::rotateZ( int deg )
+{
+ static int oldDeg = 0;
+
+ rotate( deg-oldDeg, ZAxis );
+ oldDeg = deg;
+ updateGL();
+}
+
+void GLLandscape::zoom( int z )
+{
+ float zoom;
+ if ( z < 100 ) {
+ zoom = 1 + 4.99 - (z*5.0 / 100.0);
+ } else {
+ z = 200 - z;
+ zoom = z / 100.0;
+ }
+ makeCurrent();
+ glMatrixMode( GL_MODELVIEW );
+ // Always scale the original model matrix
+ glLoadMatrixf((GLfloat *) views[DefaultView].model);
+ glScalef( zoom, zoom, zoom );
+ glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) views[CurrentView].model);
+ updateGL();
+}
+
+void GLLandscape::resetGrid()
+{
+ setGridSize( gridSize );
+}
+
+void GLLandscape::fractalize()
+{
+ Vector p;
+ double value;
+ double roughness = 0.5;
+ int frequency = 50;
+
+ p.x = p.y = p.z = 0;
+ // Initialise fbm routine
+ if ( initFractals ) {
+ initFractals = FALSE;
+ value = fBm( p, roughness, 2.0, 8.0, 1 );
+ }
+
+ // Fractalize grid
+ for ( int x = 0; x < gridSize; x++ ) {
+ for ( int y = 0; y < gridSize; y++ ) {
+ p.x = (double) x / (101 - frequency);
+ p.y = (double) y / (101 - frequency);
+ p.z = (double) landscape[x][y] / (101 - frequency);
+ value = fBm(p, roughness, 2.0, 8.0, 0);
+ landscape[x][y] += value;
+ }
+ }
+ calculateVertexNormals();
+ updateGL();
+}
+
+
+//
+// Calculate the vector cross product of v and w, store result in n.
+//
+static void crossProduct( double v[3], double w[3], double n[3] )
+{
+ n[0] = v[1]*w[2]-w[1]*v[2];
+ n[1] = w[0]*v[2]-v[0]*w[2];
+ n[2] = v[0]*w[1]-w[0]*v[1];
+}
+
+void GLLandscape::calculateVertexNormals()
+{
+ double len, v[3], v2[3], w[3], w2[3], n[3], n2[3];
+
+ // Calculate the surface normals for all polygons in the
+ // height field
+ for ( int i = 0; i < (gridSize-1); i++ )
+ for ( int k = 0; k < (gridSize-1); k++ ) {
+ /* Lower poly normal */
+ v[0] = 1; // (i+1)-i
+ v[1] = 0; // k-k
+ v[2] = landscape[i+1][k]-landscape[i][k];
+ w[0] = 1; // (i+1)-i
+ w[1] = 1; // (k+1)-k
+ w[2] = landscape[i+1][k+1]-landscape[i][k];
+ crossProduct( v, w, n );
+ len = sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);
+ normals[i][k].l[0] = n[0]/len;
+ normals[i][k].l[1] = n[1]/len;
+ normals[i][k].l[2] = n[2]/len;
+
+ /* Upper poly normal */
+ v2[0] = -1.0; // i-(i+1);
+ v2[1] = 0.0; // (k+1)-(k+1);
+ v2[2] = landscape[i][k+1]-landscape[i+1][k+1];
+ w2[0] = -1.0; // i-(i+1);
+ w2[1] = -1.0; // k-(k+1);
+ w2[2] = landscape[i][k]-landscape[i+1][k+1];
+ crossProduct( v2, w2, n2 );
+ len = sqrt(n2[0]*n2[0]+n2[1]*n2[1]+n2[2]*n2[2]);
+ normals[i][k].u[0] = n2[0]/len;
+ normals[i][k].u[1] = n2[1]/len;
+ normals[i][k].u[2] = n2[2]/len;
+ }
+
+ // Calculate proper vertex normals
+ averageNormals();
+}
+
+void GLLandscape::averageNormals()
+{
+ // Calculate the average surface normal for a vertex based on
+ // the normals of the surrounding polygons
+ for ( int i = 0; i < gridSize; i++ )
+ for ( int k = 0; k < gridSize; k++ ) {
+ if ( i > 0 && k > 0 && i < (gridSize-1) && k < (gridSize-1) ) {
+ // For vertices that are *not* on the edge of the height field
+ for ( int t = 0; t < 3; t++ ) // X, Y and Z components
+ vertexNormals[i][k].n[t] = ( normals[i][k].u[t] +
+ normals[i][k].l[t] +
+ normals[i][k-1].u[t] +
+ normals[i-1][k-1].u[t] +
+ normals[i-1][k-1].l[t] +
+ normals[i-1][k].l[t] )/6.0;
+ } else {
+ // Vertices that are on the edge of the height field require
+ // special attention..
+ if ( i == 0 && k == 0 ) {
+ for ( int t = 0; t < 3; t++ )
+ vertexNormals[i][k].n[t] = ( normals[i][k].u[t] +
+ normals[i][k].l[t] )/2.0;
+ } else if ( i == gridSize-1 && k == gridSize-1 ) {
+ for ( int t = 0; t < 3; t++ )
+ vertexNormals[i][k].n[t] = ( normals[i][k].u[t] +
+ normals[i][k].l[t] )/2.0;
+ } else if ( i == gridSize-1) {
+ for ( int t = 0; t < 3; t++ )
+ vertexNormals[i][k].n[t] = vertexNormals[i-1][k].n[t];
+ } else if ( k == gridSize-1 ) {
+ for ( int t = 0; t < 3; t++ )
+ vertexNormals[i][k].n[t] = vertexNormals[i][k-1].n[t];
+ } else if ( k > 0 ) {
+ for ( int t = 0; t < 3; t++ )
+ vertexNormals[i][k].n[t] = (normals[i][k].u[t] +
+ normals[i][k].l[t] +
+ normals[i][k-1].u[t])/3.0;
+ } else if ( i > 0 ) {
+ for ( int t = 0; t < 3; t++ )
+ vertexNormals[i][k].n[t] = (normals[i][k].u[t] +
+ normals[i][k].l[t] +
+ normals[i-1][k].l[t])/3.0;
+ }
+ }
+ }
+}
+
+void GLLandscape::setWireframe( int state )
+{
+ if ( state != 1 ) {
+ // Enable line antialiasing
+ makeCurrent();
+ glEnable( GL_LINE_SMOOTH );
+ glEnable( GL_BLEND );
+ glDisable( GL_DEPTH_TEST );
+ glDisable( GL_LIGHTING );
+ glDisable( GL_NORMALIZE );
+
+ glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+ glHint( GL_LINE_SMOOTH_HINT, GL_DONT_CARE );
+
+ mode = Wireframe;
+ updateGL();
+ }
+}
+
+void GLLandscape::setFilled( int state )
+{
+ if ( state != 1 ) {
+ makeCurrent();
+ glEnable( GL_DEPTH_TEST );
+ glDisable( GL_LINE_SMOOTH );
+ glDisable( GL_BLEND );
+ glDisable( GL_LIGHTING );
+ glDisable( GL_NORMALIZE );
+
+ mode = Filled;
+ updateGL();
+ }
+}
+
+void GLLandscape::setSmoothShaded( int state )
+{
+ if ( state != 1 ) {
+ makeCurrent();
+ glEnable( GL_DEPTH_TEST );
+ glEnable( GL_LIGHTING );
+ glEnable( GL_LIGHT0 );
+ glEnable( GL_NORMALIZE );
+ glDisable( GL_LINE_SMOOTH );
+ glDisable( GL_BLEND );
+
+ glShadeModel( GL_SMOOTH );
+ glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE );
+
+ // Setup lighting and material properties
+ GLfloat position[] = { 15.0, -15.0, 15.0, 0.0 };
+ GLfloat ambient[] = { 0.50, 0.50, 0.50, 0.0 };
+ GLfloat diffuse[] = { 1.00, 1.00, 1.00, 0.0 };
+ GLfloat specular[] = { 1.0, 1.0, 1.0, 0.0 };
+ GLfloat materialAmbient[] = { 0.00, 0.00, 1.0, 0.0 };
+ // GLfloat materialDiffuse[] = { 1.00, 1.00, 1.0, 0.0 };
+ GLfloat materialShininess[] = { 128.0 };
+ GLfloat materialSpecular[] = { 1.0, 1.0, 1.0, 0.0 };
+
+ glMaterialfv( GL_FRONT, GL_SPECULAR, materialSpecular );
+ // glMaterialfv( GL_FRONT, GL_DIFFUSE, materialDiffuse );
+ glMaterialfv( GL_FRONT, GL_AMBIENT, materialAmbient );
+ glMaterialfv( GL_FRONT, GL_SHININESS, materialShininess );
+
+ glLightfv( GL_LIGHT0, GL_POSITION, position );
+ glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
+ glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
+ glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
+
+ mode = SmoothShaded;
+ calculateVertexNormals();
+ updateGL();
+ }
+}
+
+void GLLandscape::setLandscape( int state )
+{
+ if ( state != 1 ) {
+ makeCurrent();
+ glEnable( GL_DEPTH_TEST );
+ glEnable( GL_LIGHTING );
+ glEnable( GL_LIGHT0 );
+ glEnable( GL_NORMALIZE );
+ glDisable( GL_LINE_SMOOTH );
+ glDisable( GL_BLEND );
+
+ glShadeModel( GL_SMOOTH );
+ glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE );
+
+ // Setup lighting and material properties
+ GLfloat position[] = { 15.0, -15.0, 15.0, 0.0 };
+ GLfloat ambient[] = { 0.50, 0.50, 0.50, 0.0 };
+ GLfloat diffuse[] = { 1.00, 1.00, 1.00, 0.0 };
+ GLfloat specular[] = { 1.0, 1.0, 1.0, 0.0 };
+
+ glLightfv( GL_LIGHT0, GL_POSITION, position );
+ glLightfv( GL_LIGHT0, GL_AMBIENT, ambient );
+ glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse );
+ glLightfv( GL_LIGHT0, GL_SPECULAR, specular );
+
+ glBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR );
+
+ mode = Landscape;
+ calculateVertexNormals();
+ updateGL();
+ }
+}
+
+void GLLandscape::mousePressEvent( QMouseEvent *e )
+{
+ oldPos = e->pos();
+ mouseButtonDown = TRUE;
+}
+
+void GLLandscape::mouseReleaseEvent( QMouseEvent *e )
+{
+ oldPos = e->pos();
+ mouseButtonDown = FALSE;
+}
+
+void GLLandscape::mouseMoveEvent( QMouseEvent *e )
+{
+ GLfloat rx = (GLfloat) (e->x() - oldPos.x()) / width();
+ GLfloat ry = (GLfloat) (e->y() - oldPos.y()) / height();
+
+ if ( e->state() == LeftButton ) {
+ // Left button down - rotate around X and Y axes
+ oldX = 180*ry;
+ oldY = 180*rx;
+ rotate( oldX, XAxis );
+ rotate( oldY, YAxis );
+ updateGL();
+ } else if ( e->state() == RightButton ) {
+ // Right button down - rotate around X and Z axes
+ oldX = 180*ry;
+ oldZ = 180*rx;
+ rotate( oldX, XAxis );
+ rotate( oldZ, ZAxis );
+ updateGL();
+ }
+ oldPos = e->pos();
+}
+
+void GLLandscape::timerEvent( QTimerEvent *e )
+{
+ if (e->timerId() == cubeTimer) {
+ cubeRot += 1;
+ if (!animationRunning)
+ updateGL();
+ return;
+ }
+
+ int dx, dy; // disturbance point
+ float s, v, W, t;
+ int i, j;
+
+ if ( mode == Landscape ) {
+ dx = dy = 0;
+ } else {
+ dx = dy = gridSize >> 1;
+ }
+ W = 0.3;
+ v = -4; // wave speed
+
+ for ( i = 0; i < gridSize; i++ )
+ for ( j = 0; j < gridSize; j++ )
+ {
+ s = sqrt( (double) ( (j - dx) * (j - dx) + (i - dy) * (i - dy) ) );
+ wt[i][j] += 0.1;
+ t = s / v;
+
+ if ( mode == Landscape ) {
+ if ( (landscape[i][j] + wave[i][j]) < 0 )
+ landscape[i][j] -= wave[i][j];
+ if ( (dy - j != 0) || (dx - i != 0) )
+ wave[i][j] = (3 * sin( 2 * PI * W * (wt[i][j] + t ))) /
+ (0.2*(sqrt( pow((double)(dx-i), 2) + pow((double)(dy-j), 2))+2));
+ else
+ wave[i][j] = ( 3 * sin( 2 * PI * W * ( wt[i][j] + t ) ) );
+ if ( landscape[i][j] + wave[i][j] < 0 )
+ landscape[i][j] += wave[i][j];
+
+ } else {
+ landscape[i][j] -= wave[i][j];
+
+ if ( s != 0 )
+ wave[i][j] = 2 * sin(2 * PI * W * ( wt[i][j] + t )) /
+ (0.2*(s + 2));
+ else
+ wave[i][j] = 2 * sin( 2 * PI * W * ( wt[i][j] + t ) );
+ landscape[i][j] += wave[i][j];
+ }
+
+ }
+ if ( mode == SmoothShaded || mode == Landscape )
+ calculateVertexNormals();
+ updateGL();
+}
+
+void GLLandscape::toggleWaveAnimation( bool state )
+{
+ if (state) {
+ animTimer = startTimer(20);
+ animationRunning = TRUE;
+ } else {
+ killTimer(animTimer);
+ animationRunning = FALSE;
+ }
+}
+
+void GLLandscape::showEvent( QShowEvent * )
+{
+ if (animationRunning)
+ animTimer = startTimer(20);
+ cubeTimer = startTimer(50);
+}
+
+void GLLandscape::hideEvent( QHideEvent * )
+{
+ if (animationRunning)
+ killTimer(animTimer);
+ killTimer(cubeTimer);
+}
+
+void GLLandscape::initDisplayLists()
+{
+ // axisList
+ axisList = glGenLists(1);
+ glNewList(axisList, GL_COMPILE);
+
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_DEPTH_TEST);
+ glColor3f(1.0, 0.0, 0.0);
+ glBegin(GL_LINES);
+ {
+ glColor3f(1.0, 0.0, 0.0);
+ glVertex3f(-1.0f, 0, 0); // x axis
+ glVertex3f(1.0f, 0, 0);
+
+ glVertex3f(1.0f, 0, 0);
+ glVertex3f(0.8f, 0.2f, 0);
+ glVertex3f(1.0f, 0, 0);
+ glVertex3f(0.8f, -.2f, 0);
+
+ glColor3f(0.0, 1.0, 0.0);
+ glVertex3f(0, -1.0f, 0); // y axis
+ glVertex3f(0, 1.0f, 0);
+
+ glVertex3f(0, 1.0f, 0);
+ glVertex3f(0.2f, 0.8f, 0);
+ glVertex3f(0, 1.0f, 0);
+ glVertex3f(-0.2f, 0.8f, 0);
+
+ glColor3f(0.5, 0.5, 1.0);
+ glVertex3f(0, 0, -1.0f); // z axis
+ glVertex3f(0, 0, 1.0f);
+
+ glVertex3f(0, 0, 1.0f);
+ glVertex3f(0, 0.2f, 0.8f);
+ glVertex3f(0, 0, 1.0f);
+ glVertex3f(0,-0.2f, 0.8f);
+ }
+ glEnd();
+
+ glEndList();
+
+ // cubeList
+ cubeList = glGenLists(1);
+ glNewList(cubeList, GL_COMPILE);
+
+ glEnable(GL_TEXTURE_2D);
+ glEnable(GL_DEPTH_TEST);
+ glEnable(GL_CULL_FACE);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR);
+
+ glBegin( GL_QUADS );
+ {
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 0.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 0.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 0.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 0.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( 0.0, 1.0, 0.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( 0.0, 1.0, 0.0 );
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 );
+
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 1.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( 0.0, 1.0, 1.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( 0.0, 1.0, 1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 1.0 );
+
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 0.0, 0.0, 1.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 0.0, 0.0, 1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, 1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 0.0, 1.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 0.0, 0.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 0.0, 0.0 );
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 );
+
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 0.0, 1.0, 0.0 );
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, 1.0, 0.0 );
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, 1.0, 0.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 0.0, 1.0, 1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 0.0, 1.0, 1.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 0.0, 1.0, 0.0 );
+
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, 0.0, 0.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, 0.0, 1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 0.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( 1.0, 1.0, 0.0 );
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( 1.0, 0.0, 0.0 );
+
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 );
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 1.0, 0.0 );
+ glTexCoord2f( 0.0, 0.0 ); glVertex3f( 0.0, 1.0, 0.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( 0.0, 1.0, 1.0 );
+ glTexCoord2f( 0.0, 1.0 ); glVertex3f( 0.0, 1.0, 1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 0.0, 0.0, 1.0 );
+ glTexCoord2f( 1.0, 1.0 ); glVertex3f( 0.0, 0.0, 1.0 );
+ glTexCoord2f( 1.0, 0.0 ); glVertex3f( 0.0, 0.0, 0.0 );
+ }
+ glEnd();
+ glDisable(GL_TEXTURE_2D);
+
+ glEndList();
+}
diff --git a/examples/demo/opengl/gllandscape.h b/examples/demo/opengl/gllandscape.h
new file mode 100644
index 0000000..ca87676
--- /dev/null
+++ b/examples/demo/opengl/gllandscape.h
@@ -0,0 +1,98 @@
+#ifndef GLLANDSCAPE_H
+#define GLLANDSCAPE_H
+
+#include <qgl.h>
+
+class GLLandscape : public QGLWidget
+{
+ Q_OBJECT
+
+public:
+ GLLandscape( QWidget * parent = 0, const char * name = 0 );
+ ~GLLandscape();
+
+public slots:
+ void rotateX( int );
+ void rotateY( int );
+ void rotateZ( int );
+ void zoom( int );
+ void fractalize();
+ void resetGrid();
+
+ void setWireframe( int );
+ void setFilled( int );
+ void setSmoothShaded( int );
+ void setLandscape( int );
+ void setGridSize( int );
+
+ void toggleWaveAnimation( bool );
+
+signals:
+ void rotatedX( int );
+ void rotatedY( int );
+ void rotatedZ( int );
+
+protected:
+ void paintGL();
+ void initializeGL();
+ void resizeGL( int w, int h );
+ void mousePressEvent( QMouseEvent * );
+ void mouseReleaseEvent( QMouseEvent * );
+ void mouseMoveEvent( QMouseEvent * );
+ void timerEvent( QTimerEvent * );
+ void showEvent( QShowEvent * );
+ void hideEvent( QHideEvent * );
+
+ void drawWireframe();
+ void drawFilled();
+ void drawSmoothShaded();
+ void drawAxis();
+ void drawCube();
+
+private:
+ enum Axis { XAxis, YAxis, ZAxis };
+ enum RenderModes { Wireframe, Filled, SmoothShaded, Landscape };
+ enum Views { DefaultView, CurrentView, AxisView };
+
+ void rotate( GLfloat deg, Axis axis );
+ void calculateVertexNormals();
+ void averageNormals();
+ void createGrid( int size );
+ void destroyGrid();
+ void initDisplayLists();
+
+ RenderModes mode;
+
+ typedef struct grid_normals {
+ double u[3], l[3];
+ } gridNormals;
+
+ // Structure used to store the vertex normals for the landscape
+ typedef struct avg_normals {
+ double n[3];
+ } avgNormals;
+
+ typedef struct viewMatrix {
+ GLfloat model[4][4]; // OpenGL model view matrix for the view
+ GLfloat projection[4][4]; // OpenGL projection matrix for the view
+ } viewMatrix;
+
+ double ** landscape; // Height field data
+ double ** wave; // Wave data
+ double ** wt; // Parameterized wave data
+ gridNormals ** normals;
+ avgNormals ** vertexNormals;
+ viewMatrix views[3];
+
+ QPoint oldPos;
+ GLfloat oldX, oldY, oldZ;
+ bool initFractals;
+ int gridSize, gridHalf;
+ bool animationRunning;
+ bool mouseButtonDown;
+ int cubeTimer, animTimer;
+ GLfloat cubeRot;
+ GLint axisList, cubeList;
+};
+
+#endif
diff --git a/examples/demo/opengl/gllandscapeviewer.ui b/examples/demo/opengl/gllandscapeviewer.ui
new file mode 100644
index 0000000..558cc35
--- /dev/null
+++ b/examples/demo/opengl/gllandscapeviewer.ui
@@ -0,0 +1,623 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>GLLandscapeViewer</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>GLLandscapeViewer</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>731</width>
+ <height>519</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Qt/OpenGL example</string>
+ </property>
+ <property name="layoutMargin" stdset="0">
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>Layout9</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>18</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>X-rotation</string>
+ </property>
+ </widget>
+ <widget class="QThumbWheel">
+ <property name="name">
+ <cstring>wheelX</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>30</height>
+ </size>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout6</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Y-rotation</string>
+ </property>
+ </widget>
+ <widget class="QThumbWheel">
+ <property name="name">
+ <cstring>wheelY</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>30</height>
+ </size>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout7</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1_3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Z-rotation</string>
+ </property>
+ </widget>
+ <widget class="QThumbWheel">
+ <property name="name">
+ <cstring>wheelZ</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>100</width>
+ <height>30</height>
+ </size>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>Layout15</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>ButtonGroup2</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Rendering mode</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>RadioButton1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Wireframe</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="1">
+ <property name="name">
+ <cstring>RadioButton1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Fl&amp;at shaded</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="2">
+ <property name="name">
+ <cstring>RadioButton1_3</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Smooth shaded</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="3">
+ <property name="name">
+ <cstring>RadioButton1_3_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Landscape</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout14</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>fractalize_btn_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Fractalize</string>
+ </property>
+ <property name="autoRepeat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="2">
+ <property name="name">
+ <cstring>reset_btn</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Reset grid</string>
+ </property>
+ <property name="autoRepeat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="0">
+ <property name="name">
+ <cstring>animate_btn</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Animate</string>
+ </property>
+ <property name="toggleButton">
+ <bool>true</bool>
+ </property>
+ <property name="autoRepeat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>Layout19</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout18</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Zoom</string>
+ </property>
+ </widget>
+ <widget class="QThumbWheel">
+ <property name="name">
+ <cstring>wheelZoom</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Size</string>
+ </property>
+ </widget>
+ <widget class="QThumbWheel">
+ <property name="name">
+ <cstring>wheelSize</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>30</width>
+ <height>0</height>
+ </size>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QFrame">
+ <property name="name">
+ <cstring>Frame5</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>1</number>
+ </property>
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <widget class="GLLandscape">
+ <property name="name">
+ <cstring>landscape</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>GLLandscape</class>
+ <header location="local">gllandscape.h</header>
+ <sizehint>
+ <width>100</width>
+ <height>100</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>3</hordata>
+ <verdata>3</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ <signal>rotatedX(int)</signal>
+ <slot access="public" specifier="">rotateZ(int)</slot>
+ <slot access="public" specifier="">rotateY(int)</slot>
+ <slot access="public" specifier="">rotateX(int)</slot>
+ <slot access="public" specifier="">zoom(int)</slot>
+ <slot access="public" specifier="">fractalize()</slot>
+ <slot access="public" specifier="">setWireframe(int)</slot>
+ <slot access="public" specifier="">setFilled(int)</slot>
+ <slot access="public" specifier="">setGridSize(int)</slot>
+ <slot access="public" specifier="">toggleWaveAnimation(bool)</slot>
+ <slot access="public" specifier="">setSmoothShaded(int)</slot>
+ <slot access="public" specifier="">setLandscape(int)</slot>
+ <slot access="public" specifier="">resetGrid()</slot>
+ </customwidget>
+ <customwidget>
+ <class>QThumbWheel</class>
+ <header location="local">qthumbwheel.h</header>
+ <sizehint>
+ <width>100</width>
+ <height>16</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>7</hordata>
+ <verdata>0</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ <signal>valueChanged(int)</signal>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="646">789c6dd2c10ac2300c00d07bbf2234b722ddac1741fc04c5a3201e6615f43085390f22febbb65dd6666dd821dda36996b552b0df6d4055e2d937fdcd82bd361da8f3ab6ddf87e3fa23a431e01e98cb99901a2c6c1ff78bcbf19fe372713275ed6908f441ab51300617649108624641d22a9427c21a192405241a256e08e4850311172a3b95d87159742e98ef09bda403e03271f6a5bc663e9d8214279afd05eaa048f11e242f753c27bb21ee9cef4afc00c1c26728</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>RadioButton1</sender>
+ <signal>stateChanged(int)</signal>
+ <receiver>landscape</receiver>
+ <slot>setWireframe(int)</slot>
+ </connection>
+ <connection>
+ <sender>RadioButton1_2</sender>
+ <signal>stateChanged(int)</signal>
+ <receiver>landscape</receiver>
+ <slot>setFilled(int)</slot>
+ </connection>
+ <connection>
+ <sender>animate_btn</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>landscape</receiver>
+ <slot>toggleWaveAnimation(bool)</slot>
+ </connection>
+ <connection>
+ <sender>RadioButton1_3</sender>
+ <signal>stateChanged(int)</signal>
+ <receiver>landscape</receiver>
+ <slot>setSmoothShaded(int)</slot>
+ </connection>
+ <connection>
+ <sender>wheelY</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>landscape</receiver>
+ <slot>rotateY(int)</slot>
+ </connection>
+ <connection>
+ <sender>wheelZ</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>landscape</receiver>
+ <slot>rotateZ(int)</slot>
+ </connection>
+ <connection>
+ <sender>wheelSize</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>landscape</receiver>
+ <slot>setGridSize(int)</slot>
+ </connection>
+ <connection>
+ <sender>wheelZoom</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>landscape</receiver>
+ <slot>zoom(int)</slot>
+ </connection>
+ <connection>
+ <sender>wheelX</sender>
+ <signal>valueChanged(int)</signal>
+ <receiver>landscape</receiver>
+ <slot>rotateX(int)</slot>
+ </connection>
+ <connection>
+ <sender>RadioButton1_3_2</sender>
+ <signal>stateChanged(int)</signal>
+ <receiver>landscape</receiver>
+ <slot>setLandscape(int)</slot>
+ </connection>
+ <connection>
+ <sender>reset_btn</sender>
+ <signal>clicked()</signal>
+ <receiver>landscape</receiver>
+ <slot>resetGrid()</slot>
+ </connection>
+ <connection>
+ <sender>fractalize_btn_2</sender>
+ <signal>clicked()</signal>
+ <receiver>landscape</receiver>
+ <slot>fractalize()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>RadioButton1</tabstop>
+ <tabstop>RadioButton1_2</tabstop>
+ <tabstop>RadioButton1_3</tabstop>
+ <tabstop>RadioButton1_3_2</tabstop>
+ <tabstop>fractalize_btn_2</tabstop>
+ <tabstop>reset_btn</tabstop>
+ <tabstop>animate_btn</tabstop>
+</tabstops>
+<includes>
+ <include location="local" impldecl="in implementation">gllandscapeviewer.ui.h</include>
+</includes>
+<slots>
+ <slot access="protected">init()</slot>
+ <slot access="protected">destroy()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/demo/opengl/gllandscapeviewer.ui.h b/examples/demo/opengl/gllandscapeviewer.ui.h
new file mode 100644
index 0000000..395519d
--- /dev/null
+++ b/examples/demo/opengl/gllandscapeviewer.ui.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename slots use Qt Designer which will
+** update this file, preserving your code. Create an init() slot in place of
+** a constructor, and a destroy() slot in place of a destructor.
+*****************************************************************************/
+
+
+void GLLandscapeViewer::init()
+{
+ wheelX->setOrientation( Horizontal );
+ wheelY->setOrientation( Horizontal );
+ wheelZ->setOrientation( Horizontal );
+
+ wheelZoom->setOrientation( Vertical );
+ wheelZoom->setRange( 0, 200 );
+ wheelZoom->setValue( 100 );
+
+ wheelSize->setOrientation( Vertical );
+ wheelSize->setRange( 25, 200 );
+ wheelSize->setValue( 50 );
+ wheelSize->setSteps( 10, 10 );
+
+ wheelX->setRange( 0, 360 );
+ wheelY->setRange( 0, 360 );
+ wheelZ->setRange( 0, 360 );
+
+ wheelX->setTransmissionRatio( 0.5 );
+ wheelY->setTransmissionRatio( 0.5 );
+ wheelZ->setTransmissionRatio( 0.5 );
+}
+
+void GLLandscapeViewer::destroy()
+{
+
+}
diff --git a/examples/demo/opengl/gllogo.bmp b/examples/demo/opengl/gllogo.bmp
new file mode 100644
index 0000000..ee64a10
--- /dev/null
+++ b/examples/demo/opengl/gllogo.bmp
Binary files differ
diff --git a/examples/demo/opengl/gltexobj.cpp b/examples/demo/opengl/gltexobj.cpp
new file mode 100644
index 0000000..60627da
--- /dev/null
+++ b/examples/demo/opengl/gltexobj.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+/****************************************************************************
+**
+** This is a simple QGLWidget demonstrating the use of QImages for textures.
+**
+** Much of the GL code is inspired by the 'spectex' and 'texcyl'
+** public domain demo programs by Brian Paul.
+**
+****************************************************************************/
+
+#include "gltexobj.h"
+#include <qimage.h>
+
+/*!
+ Create a GLTexobj widget
+*/
+
+GLTexobj::GLTexobj( QWidget* parent, const char* name, WFlags f )
+ : GLControlWidget( parent, name, 0, f ), impX( -2 ), impY( 0.5 ), impZ( 1 )
+{
+ object = 0;
+}
+
+/*!
+ Release allocated resources
+*/
+
+GLTexobj::~GLTexobj()
+{
+ makeCurrent();
+ glDeleteLists( object, 1 );
+}
+
+
+/*!
+ Paint the texobj. The actual openGL commands for drawing the texobj are
+ performed here.
+*/
+
+void GLTexobj::paintGL()
+{
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ glPushMatrix();
+ transform();
+ glCallList( object );
+ drawText();
+ glPushAttrib( GL_LIGHTING_BIT | GL_TEXTURE_BIT );
+ glDisable( GL_LIGHTING );
+ glDisable( GL_TEXTURE_2D );
+ qglColor( green );
+ glLineWidth( 1.0 );
+ glBegin( GL_LINES );
+ {
+ glVertex3f( 0.0f, 0.0f, 1.0f );
+ glVertex3f( 0.98f, 0.98f, 0.98f );
+ }
+ glEnd();
+ renderText( 1.0, 1.0, 1.0, "Can", QFont( "helvetica", 12, QFont::Bold, TRUE ) );
+ glPopAttrib();
+ glPopMatrix();
+}
+
+
+/*!
+ Set up the OpenGL rendering state, and define display list
+*/
+
+void GLTexobj::initializeGL()
+{
+ // Set up the lights
+
+ GLfloat whiteDir[4] = {2.0, 2.0, 2.0, 1.0};
+ GLfloat whiteAmb[4] = {1.0, 1.0, 1.0, 1.0};
+ GLfloat lightPos[4] = {30.0, 30.0, 30.0, 1.0};
+
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glEnable(GL_DEPTH_TEST);
+ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, whiteAmb);
+
+ glMaterialfv(GL_FRONT, GL_DIFFUSE, whiteDir);
+ glMaterialfv(GL_FRONT, GL_SPECULAR, whiteDir);
+ glMaterialf(GL_FRONT, GL_SHININESS, 20.0);
+
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, whiteDir); // enable diffuse
+ glLightfv(GL_LIGHT0, GL_SPECULAR, whiteDir); // enable specular
+ glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
+
+ // Set up the textures
+
+ QImage tex1, tex2, buf;
+
+ if ( !buf.load( "opengl/gllogo.bmp" ) ) { // Load first image from file
+ qWarning( "Could not read image file, using single-color instead." );
+ QImage dummy( 128, 128, 32 );
+ dummy.fill( Qt::green.rgb() );
+ buf = dummy;
+ }
+ tex1 = QGLWidget::convertToGLFormat( buf ); // flipped 32bit RGBA
+
+ if ( !buf.load( "opengl/qtlogo.bmp" ) ) { // Load first image from file
+ qWarning( "Could not read image file, using single-color instead." );
+ QImage dummy( 128, 128, 32 );
+ dummy.fill( Qt::red.rgb() );
+ buf = dummy;
+ }
+ tex2 = QGLWidget::convertToGLFormat( buf ); // flipped 32bit RGBA
+
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+ glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+ glEnable( GL_TEXTURE_2D );
+
+ // Set up various other stuff
+
+ glClearColor( 0.0, 0.0, 0.0, 0.0 ); // Let OpenGL clear to black
+ glEnable( GL_CULL_FACE ); // don't need Z testing for convex objects
+ glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
+
+ // Make the object display list
+
+ object = makeObject( tex1, tex2 ); // Generate an OpenGL display list
+}
+
+
+
+/*!
+ Set up the OpenGL view port, matrix mode, etc.
+*/
+
+void GLTexobj::resizeGL( int w, int h )
+{
+ glViewport( 0, 0, w, h );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+ glTranslatef( 0.0, 0.0, -70.0 );
+}
+
+
+/*!
+ Generate an OpenGL display list for the object to be shown, i.e. the texobj
+*/
+
+GLuint GLTexobj::makeObject( const QImage& tex1, const QImage& tex2 )
+{
+ GLUquadricObj* q = gluNewQuadric();
+ GLuint cylinderObj = glGenLists(1);
+ glNewList( cylinderObj, GL_COMPILE );
+
+ glTranslatef( 0.0, 0.0, -1.0 );
+
+ // cylinder
+ glTexImage2D( GL_TEXTURE_2D, 0, 3, tex1.width(), tex1.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, tex1.bits() );
+ gluQuadricTexture( q, GL_TRUE );
+ gluCylinder(q, 0.6, 0.6, 2.0, 24, 1);
+
+ // end cap
+ glTexImage2D( GL_TEXTURE_2D, 0, 3, tex2.width(), tex2.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, tex2.bits() );
+ glTranslatef( 0.0, 0.0, 2.0 );
+ gluDisk( q, 0.0, 0.6, 24, 1 );
+
+ // other end cap
+ glTranslatef( 0.0, 0.0, -2.0 );
+ gluQuadricOrientation( q, (GLenum)GLU_INSIDE );
+ gluDisk( q, 0.0, 0.6, 24, 1 );
+
+ glEndList();
+ gluDeleteQuadric( q );
+
+ return cylinderObj;
+}
+
+void GLTexobj::animate()
+{
+ xRot += impX;
+ yRot += impY;
+ zRot -= impZ;
+
+ impX -= impX * 0.05;
+ impY -= impY * 0.05;
+ impZ -= impZ * 0.05;
+
+ if ( impX > 0.1 || impY > 0.1 || impZ > 0.1 ||
+ impX < -0.1 || impY < -0.1 || impZ < -0.1 )
+ updateGL();
+}
+
+void GLTexobj::setRotationImpulse( double x, double y, double z )
+{
+ if ( animation ) {
+ impX += 180*x;
+ impY += 180*y;
+ impZ += 180*z;
+ } else {
+ GLControlWidget::setRotationImpulse( x, y, z );
+ }
+}
diff --git a/examples/demo/opengl/gltexobj.h b/examples/demo/opengl/gltexobj.h
new file mode 100644
index 0000000..e621627
--- /dev/null
+++ b/examples/demo/opengl/gltexobj.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+/****************************************************************************
+**
+** This is a simple QGLWidget displaying an openGL wireframe box
+**
+****************************************************************************/
+
+#ifndef GLTEXOBJ_H
+#define GLTEXOBJ_H
+
+#include "glcontrolwidget.h"
+
+class GLTexobj : public GLControlWidget
+{
+ Q_OBJECT
+
+public:
+ GLTexobj( QWidget* parent, const char* name = 0, WFlags f = 0 );
+ ~GLTexobj();
+
+protected:
+ void animate();
+ void initializeGL();
+ void paintGL();
+ void resizeGL( int w, int h );
+
+ virtual GLuint makeObject( const QImage& tex1, const QImage& tex2 );
+
+ void setRotationImpulse( double x, double y, double z );
+
+private:
+ GLuint object;
+ double impX, impY, impZ;
+};
+
+#endif // GLTEXOBJ_H
diff --git a/examples/demo/opengl/glworkspace.cpp b/examples/demo/opengl/glworkspace.cpp
new file mode 100644
index 0000000..4670582
--- /dev/null
+++ b/examples/demo/opengl/glworkspace.cpp
@@ -0,0 +1,212 @@
+#include "glworkspace.h"
+#include "glbox.h"
+#include "glgear.h"
+#include "gltexobj.h"
+
+#include <qworkspace.h>
+#include <qdialog.h>
+#include <qtoolbar.h>
+#include <qpopupmenu.h>
+#include <qmenubar.h>
+#include <qaction.h>
+#include <qprinter.h>
+#include <qpainter.h>
+#include <qcheckbox.h>
+#include <qvbox.h>
+#include <qimage.h>
+#include "printpreview.h"
+
+
+GLWorkspace::GLWorkspace( QWidget *parent, const char *name, WFlags f )
+: QMainWindow( parent, name, f ), printer( 0 )
+{
+ setupSceneActions();
+
+ QVBox *vbox = new QVBox( this );
+ vbox->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken );
+ vbox->setMargin( 1 );
+ vbox->setLineWidth( 1 );
+
+ workspace = new QWorkspace( vbox );
+ workspace->setBackgroundMode( PaletteMid );
+ setCentralWidget( vbox );
+}
+
+GLWorkspace::~GLWorkspace()
+{
+}
+
+void GLWorkspace::setupSceneActions()
+{
+ QToolBar *tb = new QToolBar( "Scene", this );
+ QPopupMenu *menu = new QPopupMenu( this );
+ menuBar()->insertItem( tr( "&Scene" ), menu );
+
+ QAction *a;
+ QActionGroup *newGroup = new QActionGroup( this );
+ newGroup->setMenuText( tr( "&New" ) );
+ newGroup->setText( tr( "New" ) );
+ newGroup->setUsesDropDown( TRUE );
+ newGroup->setExclusive( FALSE );
+ newGroup->setIconSet( QPixmap( "textdrawing/filenew.png" ) );
+ a = new QAction( tr( "Wirebox" ), QPixmap( "opengl/wirebox.xpm" ), tr( "&Wirebox" ), 0, newGroup );
+ connect( a, SIGNAL( activated() ), this, SLOT( newWirebox() ) );
+ a = new QAction( tr( "Gear" ), QPixmap( "opengl/gear.xpm" ), tr( "&Gears" ), 0, newGroup );
+ connect( a, SIGNAL( activated() ), this, SLOT( newGear() ) );
+ a = new QAction( tr( "Texture" ), QPixmap( "opengl/texture.xpm" ), tr( "&Texture" ), 0, newGroup );
+ connect( a, SIGNAL( activated() ), this, SLOT( newTexture() ) );
+/* a = new QAction( tr( "Nurbs" ), QPixmap( "opengl/nurbs.xpm" ), tr( "&Nurbs" ), 0, newGroup );
+ connect( a, SIGNAL( activated() ), this, SLOT( newNurbs() ) );*/
+ newGroup->addTo( tb );
+ newGroup->addTo( menu );
+
+ menu->insertSeparator();
+ QActionGroup *printGroup = new QActionGroup( this );
+ printGroup->setMenuText( tr( "&Print" ) );
+ printGroup->setText( tr( "Print" ) );
+ printGroup->setUsesDropDown( TRUE );
+ printGroup->setExclusive( FALSE );
+ printGroup->setIconSet( QPixmap( "textdrawing/print.png" ) );
+ QAction *da = new QAction( tr( "Window Size" ), QPixmap( "textdrawing/print.png" ), tr( "&Window Size" ), CTRL + Key_P, printGroup );
+ connect( da, SIGNAL( activated() ), this, SLOT( filePrintWindowRes() ) );
+ a = new QAction( tr( "Low Resolution" ), tr( "&Low Resolution" ), 0, printGroup );
+ connect( a, SIGNAL( activated() ), this, SLOT( filePrintLowRes() ) );
+ a = new QAction( tr( "Medium Resolution" ), tr( "&Medium Resolution" ), 0, printGroup );
+ connect( a, SIGNAL( activated() ), this, SLOT( filePrintMedRes() ) );
+ a = new QAction( tr( "High Resolution" ), tr( "&High Resolution" ), 0, printGroup );
+ connect( a, SIGNAL( activated() ), this, SLOT( filePrintHighRes() ) );
+ printGroup->addSeparator();
+ a = new QAction( tr( "Setup" ), tr( "&Setup..." ), 0, printGroup );
+ connect( a, SIGNAL( activated() ), this, SLOT( filePrintSetup() ) );
+ da->addTo( tb );
+ printGroup->addTo( menu );
+
+ a = new QAction( tr( "Close" ), QPixmap(), tr( "&Close" ), 0, this );
+ connect( a, SIGNAL( activated() ), this, SLOT( fileClose() ) );
+ a->addTo( menu );
+}
+
+void GLWorkspace::newWirebox()
+{
+ GLBox *gl = new GLBox( workspace, 0, WDestructiveClose );
+ gl->setIcon( QPixmap( "opengl/wirebox.xpm" ) );
+ gl->setCaption( tr( "Wirebox" ) );
+ gl->resize( 320, 240 );
+ gl->show();
+}
+
+void GLWorkspace::newGear()
+{
+ GLGear *gl = new GLGear( workspace, 0, WDestructiveClose );
+ gl->setIcon( QPixmap( "opengl/gear.xpm" ) );
+ gl->setCaption( tr( "Gear" ) );
+ gl->resize( 320, 240 );
+ gl->show();
+}
+
+void GLWorkspace::newTexture()
+{
+ GLTexobj *gl = new GLTexobj( workspace, 0, WDestructiveClose );
+ gl->setIcon( QPixmap( "opengl/texture.xpm" ) );
+ gl->setCaption( tr( "Texture" ) );
+ gl->resize( 320, 240 );
+ gl->show();
+}
+
+void GLWorkspace::newNurbs()
+{
+ GLGear *gl = new GLGear ( workspace, 0, WDestructiveClose );
+ gl->setIcon( QPixmap( "opengl/nurbs.xpm" ) );
+ gl->setCaption( tr( "Nurbs" ) );
+ gl->resize( 320, 240 );
+ gl->show();
+}
+
+void GLWorkspace::filePrint( int x, int y )
+{
+ bool print = printer || filePrintSetup();
+ if ( !print || !printer )
+ return;
+
+ QWidget *widget = workspace->activeWindow();
+ if ( !widget || !widget->inherits( "QGLWidget" ) )
+ return;
+ QGLWidget *gl = (QGLWidget *)widget;
+ QPixmap pm = gl->renderPixmap( x, y );
+
+ PrintPreview view( this );
+ QImage temp = pm.convertToImage();
+ temp = temp.smoothScale( 400, 300 );
+ QPixmap temppix;
+ temppix.convertFromImage( temp );
+ view.setPixmap( temppix );
+ view.setIcon( QPixmap( "opengl/snapshot.xpm" ) );
+ view.setCaption( gl->caption() + " - Print preview" );
+ if ( view.exec() ) {
+ QImage img = pm.convertToImage();
+ if ( view.checkInvert->isChecked() ) {
+ img.invertPixels();
+ }
+ if ( view.checkMirror->isChecked() ) {
+ img = img.mirror( TRUE, FALSE );
+ }
+ if ( view.checkFlip->isChecked() ) {
+ img = img.mirror( FALSE, TRUE );
+ }
+ if ( view.checkLeft->isEnabled() && view.checkLeft->isChecked() ) {
+ }
+ if ( view.checkRight->isEnabled() && view.checkRight->isChecked() ) {
+ }
+ pm.convertFromImage( img );
+
+ QPainter painter;
+ if ( !painter.begin( printer ) )
+ return;
+
+ painter.drawPixmap( QPoint( 0, 0 ), pm );
+
+ painter.end();
+ }
+}
+
+void GLWorkspace::filePrintWindowRes()
+{
+ filePrint( 0, 0 );
+}
+
+void GLWorkspace::filePrintLowRes()
+{
+ filePrint( 640, 480 );
+}
+
+void GLWorkspace::filePrintMedRes()
+{
+ filePrint( 1024, 768 );
+}
+
+void GLWorkspace::filePrintHighRes()
+{
+ filePrint( 2048, 1536 );
+}
+
+bool GLWorkspace::filePrintSetup()
+{
+ bool newPrinter = !printer;
+
+ if ( !printer )
+ printer = new QPrinter;
+ if ( printer->setup() ) {
+ return TRUE;
+ } else {
+ if ( newPrinter ) {
+ delete printer;
+ printer = 0;
+ }
+ return FALSE;
+ }
+}
+
+void GLWorkspace::fileClose()
+{
+ workspace->closeActiveWindow();
+}
diff --git a/examples/demo/opengl/glworkspace.h b/examples/demo/opengl/glworkspace.h
new file mode 100644
index 0000000..36e1a23
--- /dev/null
+++ b/examples/demo/opengl/glworkspace.h
@@ -0,0 +1,37 @@
+#ifndef GLWORKSPACE_H
+#define GLWORKSPACE_H
+
+#include <qmainwindow.h>
+
+class QWorkspace;
+class QPrinter;
+
+class GLWorkspace : public QMainWindow
+{
+ Q_OBJECT
+public:
+ GLWorkspace( QWidget *parent = 0, const char *name = 0, WFlags f = 0 );
+ ~GLWorkspace();
+
+protected:
+ void setupSceneActions();
+
+protected slots:
+ void newWirebox();
+ void newGear();
+ void newTexture();
+ void newNurbs();
+ void filePrint( int x, int y );
+ void filePrintWindowRes();
+ void filePrintLowRes();
+ void filePrintMedRes();
+ void filePrintHighRes();
+ bool filePrintSetup();
+ void fileClose();
+
+private:
+ QWorkspace *workspace;
+ QPrinter *printer;
+};
+
+#endif //GLWORKSPACE_H
diff --git a/examples/demo/opengl/nurbs.xpm b/examples/demo/opengl/nurbs.xpm
new file mode 100644
index 0000000..946d081
--- /dev/null
+++ b/examples/demo/opengl/nurbs.xpm
@@ -0,0 +1,305 @@
+/* XPM */
+static char *nest[] = {
+/* width height num_colors chars_per_pixel */
+" 48 48 202 2",
+/* colors */
+".. c None",
+".# c #1f1000",
+".a c #200800",
+".b c #201000",
+".c c #201700",
+".d c #20170f",
+".e c #201800",
+".f c #201f0f",
+".g c #2f1f00",
+".h c #2f2710",
+".i c #301700",
+".j c #301f00",
+".k c #30200f",
+".l c #302810",
+".m c #3f2000",
+".n c #3f270f",
+".o c #3f2f10",
+".p c #402700",
+".q c #40270f",
+".r c #402f0f",
+".s c #402f10",
+".t c #40371f",
+".u c #403720",
+".v c #40382f",
+".w c #4f3000",
+".x c #4f3010",
+".y c #4f371f",
+".z c #4f3f1f",
+".A c #4f3f3f",
+".B c #4f402f",
+".C c #4f403f",
+".D c #503700",
+".E c #50370f",
+".F c #503f10",
+".G c #50401f",
+".H c #504020",
+".I c #504030",
+".J c #50403f",
+".K c #504730",
+".L c #50473f",
+".M c #5f3f10",
+".N c #5f4000",
+".O c #5f401f",
+".P c #5f471f",
+".Q c #5f481f",
+".R c #5f482f",
+".S c #5f5030",
+".T c #5f5040",
+".U c #5f5750",
+".V c #604010",
+".W c #60481f",
+".X c #604830",
+".Y c #604f20",
+".Z c #604f3f",
+".0 c #605730",
+".1 c #60584f",
+".2 c #6f4000",
+".3 c #6f4810",
+".4 c #6f5730",
+".5 c #6f5740",
+".6 c #6f5f30",
+".7 c #6f5f3f",
+".8 c #6f6040",
+".9 c #6f6850",
+"#. c #704f10",
+"## c #70501f",
+"#a c #705020",
+"#b c #705710",
+"#c c #70581f",
+"#d c #705830",
+"#e c #705f2f",
+"#f c #705f3f",
+"#g c #705f4f",
+"#h c #705f50",
+"#i c #70683f",
+"#j c #706840",
+"#k c #70706f",
+"#l c #7f5000",
+"#m c #7f5f2f",
+"#n c #7f6030",
+"#o c #7f673f",
+"#p c #7f6840",
+"#q c #7f685f",
+"#r c #805820",
+"#s c #805f10",
+"#t c #80602f",
+"#u c #80673f",
+"#v c #80684f",
+"#w c #806f40",
+"#x c #806f50",
+"#y c #806f5f",
+"#z c #80704f",
+"#A c #80786f",
+"#B c #807f5f",
+"#C c #8f6020",
+"#D c #8f6f3f",
+"#E c #8f6f50",
+"#F c #8f7040",
+"#G c #8f784f",
+"#H c #906010",
+"#I c #906720",
+"#J c #90682f",
+"#K c #906f3f",
+"#L c #90702f",
+"#M c #907060",
+"#N c #90773f",
+"#O c #907840",
+"#P c #90786f",
+"#Q c #907f6f",
+"#R c #908050",
+"#S c #90875f",
+"#T c #90886f",
+"#U c #908f70",
+"#V c #909080",
+"#W c #9f701f",
+"#X c #9f702f",
+"#Y c #9f7840",
+"#Z c #9f804f",
+"#0 c #9f8050",
+"#1 c #a0680f",
+"#2 c #a0783f",
+"#3 c #a0804f",
+"#4 c #a0806f",
+"#5 c #a0874f",
+"#6 c #a0875f",
+"#7 c #a08f50",
+"#8 c #a08f5f",
+"#9 c #a0906f",
+"a. c #a09770",
+"a# c #a0977f",
+"aa c #af701f",
+"ab c #af782f",
+"ac c #af7f3f",
+"ad c #af803f",
+"ae c #af876f",
+"af c #af884f",
+"ag c #af8f5f",
+"ah c #af8f6f",
+"ai c #af8f7f",
+"aj c #af9070",
+"ak c #af907f",
+"al c #af9880",
+"am c #af9f70",
+"an c #afa080",
+"ao c #b06f0f",
+"ap c #b0802f",
+"aq c #b0904f",
+"ar c #b0975f",
+"as c #b09780",
+"at c #b0a06f",
+"au c #b0a890",
+"av c #bf8f3f",
+"aw c #bf907f",
+"ax c #bf974f",
+"ay c #bf977f",
+"az c #bf985f",
+"aA c #bf9860",
+"aB c #bf9f6f",
+"aC c #bfa080",
+"aD c #bfa870",
+"aE c #bfa880",
+"aF c #bfa890",
+"aG c #c09750",
+"aH c #c09f80",
+"aI c #c0a760",
+"aJ c #c0a76f",
+"aK c #c0b080",
+"aL c #c0b790",
+"aM c #cf9740",
+"aN c #cfa78f",
+"aO c #cfa87f",
+"aP c #cfaf6f",
+"aQ c #cfaf90",
+"aR c #d09f80",
+"aS c #d0a860",
+"aT c #d0b770",
+"aU c #d0b88f",
+"aV c #d0b890",
+"aW c #dfa750",
+"aX c #dfaf90",
+"aY c #dfb79f",
+"aZ c #dfb8a0",
+"a0 c #dfc08f",
+"a1 c #e0a780",
+"a2 c #e0b790",
+"a3 c #e0b79f",
+"a4 c #e0b870",
+"a5 c #e0bfa0",
+"a6 c #e0c8a0",
+"a7 c #e0cf9f",
+"a8 c #efb090",
+"a9 c #efbf90",
+"b. c #efd7af",
+"b# c #f0bf9f",
+"ba c #f0c0a0",
+"bb c #f0cfb0",
+"bc c #ffc8af",
+"bd c #ffd7b0",
+"be c #ffd7bf",
+"bf c #ffd8bf",
+"bg c #ffdfc0",
+"bh c #ffe7c0",
+/* pixels */
+"............................#8#8#9.Y..........#8#8#2#2..........................................",
+"..........................au#3#3a.aD#T#8aIa.#8........#8..#8#8..................................",
+"......................#Z#2aOaPar#PaLalaD#8#8....aD..#2......#8#8................................",
+"....................#8#Aajam#xa.........aE#x#e#t#p#O#8.G#3aV#Z#9#8#2#o..........................",
+"..................a#.....p#0....aE#P.p.i.2ab.P#aat#K.Y#F.4.x#ZazaV....#2aL......................",
+"............#F#D....aE#TaA#FaI#D#b#D.E.Y#3ad#D.H.s.l.k.q.E.z.f.O#Y#7an#0#SanaL..................",
+"..........#o#v....aBaKaua##2#.#C#C#m#2.w#t#I.P.M.n.k.i##.c.d.q.p.b.6#daI....#b..................",
+"..........#q..#2#FaAalaB#s#J#n.W#K##.R.z.k.x.s.d.n.o.r.Q.c.g.E#a.P.c.f#da##8..aI................",
+"........#3..#2.1..#D#tad#Zag#w#d#n.n.u.d.#.k.#.c.c.n.b.#.d.F#L.f##.f.c.c#7#D..a7................",
+"......aD#9a..Q..#LaW#maTaIa4#6.d.c.d.c.f.c.s.s.c.#.b.o.P.r.r.W.##a.M.#.e.k.4#eaKaOaL............",
+"......aD#8aL..#F.2#X.0.Y#e.Y.u.d.c.c.j.#.c.y.j.n#Mak#M#v.W#L.##d#K#c.s.f.l#R.caDa0..a0..........",
+"....#Ta.#F#A..#l#W#N.W#s.z.d.k.n.k.y.o.g.t.aawbdb#a3aQ#4#f.Z.y.x#aad#a.O.R.#aD.eaLaz..#F........",
+"....#2alal#8#t#n#Z.W.V.g.e.f.t.o.s.g.k.y.E#4babab#a1aRae#M.L.K.N.zaMac.W.4.u.c.c.RaD#8aD........",
+"....aU#8#m#Q#L#K#c.M.c.c.e.l.t.f.#.b.Y#a.Obfbfbhbaa5aNas#Q.T.C#a#e#m#X#m#f.S.c.c#j..a0#2#2......",
+"..#2#2..#8#s#r#l.w.i.c.t.z.H.t.#.o#x#F.MaRbfbhbgbca9aQas#Q.1.C.H.2.B#u#Y.4.H.S.B.e..#2b.au......",
+"....#FaDaO#5.p#W#J.i.#.f.o.H.l.R#v#u#t.waZbfbgbgbca3aQak#E.T.L.H.F#K#f#Y#a#a.R.0.l.Z#T..#W......",
+"....aV#9#e#0.pap#C.c.f.#.z.t.4.4.G.3.r.maXbhbgbga6aZaNaj#Q.J.L.K#w.V.3#Y#u.W#d.S.c.taD..aA#2....",
+"..azauaL.2ag#2#C.3.g.c.z.G.b.G.n.4.w.q.baXbfbcb#a5aQas#Q.5.I.J.H#.###b.O#Iab.W.e.c.kaD....aU....",
+"..#Z..#l#2#7aA.N.F.c.c.c.#aha5bbaZai#y.P.0bba2a2aXawai#y.L.I.A#t.M.Q#L#naa#8.p.D.#.z#FaD..au#8..",
+"..#Wa.ab#c.2aG#t.x.c.h.cbebaa8baaYaH#E.Z.WaNaQaNayai#M.1.J.C.K#H#I.P#e.v#s#D.D.n#z.h.Ba7..a.#2..",
+"....aF#l#L#2#L#6.P.#.caZbgbgbaa1aXaw#4#g.A.Vaeai#4#y.T.A.C.B#J#L#H#c#S.4.DaI#b.F.4#6ataO..aEa...",
+"aA#o#pab#lag#a#r.n.c.vaZbhbgbbbaaXasai#q.J.B#K#E.5.A.A.J.H.W.Vacad#N#R#o.j#C#7##.n#8.c#6aE..aE..",
+"....#t#Lao#5#mazag.caebhbhbgbba2aXaC#U#h.C.u#u#K.Y.7#K#K#2.3.k#m.4.Q.0aB.o.xaq#m.c#0.7.R....aE..",
+"....az#NaoaMaTaqaA.#aXbhbdbbbaaXaQak#M.1.I.L.u.y.z###5#racad#5#7.k.s#raI#Z.R#s#6.#.0#F.9..#Z....",
+"....aI.Nac#5aq#l#I.faNbfbcbba5aQaw#4#y.L.I.L.K.k.E.i.i.D.3aa#Hac.E.l#m#Oah.O#raf.z.c#wauaD#Z....",
+"an...X#naS#cap#Y#1.N#gbbbaa5a5aCak#M.1.I.I.I#J.V#faXbbaYas#E#J#I.3.k.4ad#2.4#s.D#f.#.R#GaJ#T....",
+"#T#9#oag#saa#J#F#b.m.cbbaXaNaHak#Q#h.C.I.J.B#lahaTbca8a3aHak.U#a#a.G.B#5#w.TaG#K.G#6.laAaAa.....",
+"..auaDaI#u#WaxaS.P#b.#.CaQaw#4#M#q.L.C.I.A.M#EaTbcbca1a2aHah#x.X#d.y.G#maq.8ap#X.z#G.g#2aE#8aL..",
+"..#Fan#laE#HaWaxat#w.m.c#x#P#y.5.C.L.J.C#u#caAbcbhbeb#aRay#4#P.T.C.s.k#DaS.7.E.baB.c.7aIaK..#9..",
+"....aE#q#2.6#a#I#taK.YaP.c.j.X.K.X.H.H.X#taJbcbfbgbfbaaYaHak#P.U.J.G#F#ma4aq#N.Q.c.#.7ar........",
+"....a.aG.D#6.p.Dac#d#2.6#z.a.j.O#n.D.E.#.cawbdbdbebba5aRaC#4#y.L.C.S#mafar#d#N.0.h.#az#V#8..#D..",
+"aL..aDaG.X#N#o.M#I#u#X.S.E.4.c.f.r.i.3#c.cawbdbcbeb#aXaNak#Q.5.L.L.B#2#mar#m.M.6.c.B#Z.RaT..#Za.",
+"#8auaE..#F.w#3ar#a#9ab#o.N###j.c.x.k.g.M.r#EbfbcbaaZaQas#4#y.I.C.A.0#5#m#Z#t#o.h.caA.t#e....al.8",
+"....aEaI..aA#r#F#oat#i#oac.2.c.c#J.x.G.P.p.jbca2aXaNaFai#P.5.I.I.v#2#Y#O#Y#C.7.c.caT.c#2..aAaAaG",
+"......#8a.am#k#Yag#F#w#FaD.V.#am#m.q.k.G.P.r#gaXawawae#M#g.C.L.A#dac#d#3#o.O.x.caP.c.#aA..aT#S..",
+"......#S....#T#i.uaI#n.D#jam.r.aag.W.W.E.W#a.p#gai#Q#y.T.C.C.A.5acaq#o#v.O.o.c.c.c.c.F..aB#OaT#B",
+"........#R....#T.w#faj.m.i#n#G#o.zag.O#u#m.F.j.0.K.L.I.I.C.Z#u#5aTaJ.H.E.G.f.#aP.d.##3a.#Z..a...",
+"........a#....#T..#e#F#6.O.a#O.w.6#i#8.G.O.6#X#i.O.x.H.X.H#aaxavaA.l.k.x.t.##S#w.c.lazaA#Z#T....",
+"..............am....ag#D#i#z.Q.o.#.w#e#0.m.Y#d.W.E.x.x#e#t#e#K#2.p.j.#.c.h.##9.7.#.SaD#DaE......",
+"................#N....aC.R.6.4#6.7.F.q.Y#0#e.n.F.O.O#a#w#v.E.E.b.j.c.e.d.#.H#B.#.7#7#U..........",
+"................aA#8#2#T#7.X.7.7.0.0.6ag#o#R#f.r.0#n#p.#.c.#.c.#.#.c.c.#.c#G#R#S#i#0............",
+"..................aL#8#Zaq#8.0.#.4#n.t.c.##waJ#0.G.z.R.r.o.f.d.c.e.#.4.0#o#8#F.#.o........#U....",
+"......................#8#8#DaDaD.T.h.t#8#z.h#Z.0.R.g.m#G#n.l.h.c.##z.0.##G#j.#.UaS#3#8#T#q......",
+"....................aE......#8aK#N#R#6.O.#.B#0#6#o.7#G.u.d.#.c.c.#.#.h#v#v#j#z#8#S#T#UaD........",
+"......................#Z....#NaL#8#jam#B.6#w.7#i.u#7araT#z#z#p#iaTaPat#p#R.#a....Y..............",
+"..........................#R..aEaja#.1#7#A#0.6.c.c.S#6.f.#.d#R.#.e.c.#.7#T......................",
+"................................#F#8#6........#o#o.c.c#K#n#u.o.Y#v#R#k..aI..a.a.................",
+"..............................#9#9....an#Z............#8#0..#0#RaE....#U#Sa....................."
+};
+SIMPLE = T
+BITPIX = 8
+NAXIS = 2
+NAXIS1 = 48
+NAXIS2 = 48
+HISTORY Written by XV 3.10
+END
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+SSSSSSSSSSSSSSSSS ƒSSSSSSƒSƒ~ŠSSŠƒ”SSSSSSSSSSSSSSSSSSSSSSSSSSs‰SSSSiirci/M
+l~oS¤S””SSSSSSSSSSSSSSSSSSSSS~SŠ•–Y‹yƒ]P‰~_†SSSSSSSSSSSSSSSSSSSSSSƒSSv´
+dz]m_d6‹–´ppid´°i~”SMSSSSSSSSSSSSSSSSSŠSSSŽv~‰EBƒ‰i_y6&lldpƒ†Š§SSSS
+SSSSSSSSSSSr§§R&6p&ƒTL%yc'&pTydXރ†nSSSSSSSSSSSS´ƒTYc6mŚƒ@?L//
+YTis/SSSSŠSSSSSSSSSSœ|†‹L__TT]’i~_/Tciy~ƒdƒSSSSSSSSSSSSSSvSSĽL]Y‰
+_=+Mƒ]+=EESml99 @z_‹ŠSSSSSSSSSSSSSS’rdpI/3]ƒ%MZI955]c]r|) &_P§rŠSSS
+SSSS–SS†S]s‰Ew3]d@E]vdE5@L@S™“œ'"56ƒm'œœƒ†SSSSSS~SS†3_•%cyi?’Eib= TFHCCERi†
+´Ś@9@°ƒ”ƒS”SSSSƒSS†d6¤c7d/’II9IS)b—‚rREED[…ilE/=S˘w´zSSS”o|’sms§C
+b+"@I/bş‘xbEHDZ…ZƒiE5°œS´ƒSSSŠ¤Sœ]sidi…Fl5@I) ׿şąŹ—~[CC9||w|f_´|Sœœš
+§ŠSs3ƒ–Si@Sd5"B/uá×ËÁľœˆrCEDT†bƒci&œ6]SSœ`´S§šLviBjivP9Y/LWŢ×áĘşą˜‚[H
+HB|b–bB]BƒL´Sƒ”SS”š7‰)7…Z|]p Ec79ŢŢáŐĹŤĽˆrHEPbŒ–ZvT&œSrSSSŠn|]SjcŽM° LF
+L@@LcŚ×áĺáËÁĽ˜~XE@sbşvI_–SSSSSs SŠdŹ™m%p~r[EHEEiWœ×éáĘŤĄˆ~RE0"rŞ_9˘_¤ŽSSS§§¤is™ŞITEľˆxnHECDBu´××´żĽ•pLZ;@b`ƒv?y|Š´S†i’^ylsT%ŐşąĽ˜‚bECEBS•´×ŔÁĽ˜XSS@B†mRšr@‰'œœ”SS SLcŞWƒ|m@bŐËĹĹĽ˜xYCCClC_şŐÁœuljL"Y†|Y^7_LyŚ†SSSS¤@…†Sjąá×ŐĹľˆrHCHF"97Lyd…9'bw•E]Œ?m§§ƒSSSSœvvœ´œşéŢŐËşľ˜xYCH6;?S†]…††‹"0]¤ƒL^‰TsfSƒSSSScpv†bœ’‘ééĺŐżşĽŠbE6irM_rr|L"bYIT˘/5bƒ_LSSŠSœiiS’S]+9ÁéĺŐËşœ—nEBru[DDE@IC…†v~i f‹S+‰ŠSŠSSSŹSp|p‰IÁĺĺË´şˆbDC‘—ˆrRDEBlpdWƒY7¤T=Y‰ŻSŠ”SSs”WFšc5&áËŔËÁĽuRIąľąĄ—xYEEFdjI]9^r7+p&BÍS”|SSƒSS|‹œ@=•ĹŐÁ—rITŐżżş—rHCDcBIpcy)7?s§S§SSœ§´F’|fL?@@+Y3+şá×ĘĹľœ‚[CE@PSTEjI"§SSšSSSSş]ƒ)ƒf?6YY@L/%şéĺĺĘÁą•‚EHFmCL|iIZP6§Sœ|SSSSs§Ż†)sl/@'Llic3Ááĺĺ×Áľ˜uRH@=r_|SSLT'R†SsSSSS||S^]S36?@6/psBŤáéĺ×Čľœ‚YE@FBi|Y@PBS|٧SSSSSšb‚prWB'6MSEááéËĹąœ‚RES]bvb_PdSĂ||SSSSS|œœccƒIC6/0";9ˆËËĘ´Ť‘xHF@?œ…IY6L§§SSSSSS†”sySSsvI^?"+";/6ŢĘÁľˆ_R;5S†SEL§´œSsSSSSSSS§´SsFvTM]M6 ; +x˜xlIpZrW0'~§ĂSĂSSSSSSSS§”ISpŹb´¤ş‰00/I//ISB"Y]ŽŻ´SSSSSSSSSSƒS|YSrc†ƒ’mZc+6"+=pS‹rSÍSSSSSSSSSSSSSnS|sœœ˘^lcIrSL?"50+//I9SIZ–S¤SSSSSSSSSSSSSilSS˘Ž§–|Pffb|3cjIB+"S+)]Z¤SSTSSSSSSSSSSSSSSSsrSSŠ†œs¤rTr9Mƒ†r@0'"+9?E|‹ ƒƒ ´SSSSSSSSSSSSSSSSSS–SS)ƒSSŠ~)FISrMsY5ƒœşSS|´SSSSSSSSSSSSSSSSSSSSSy•p”SSSSŠp]ciw@ƒşƒ|iSSSSSSSSSSSSSSSSSSSSSSSSƒ|Ż°–~´œ§SS§S|SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS§ƒƒ”§†¤”SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSMSSSSS||SSSSSSSSSSSSSSSSSSSSS€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€
diff --git a/examples/demo/opengl/printpreview.ui b/examples/demo/opengl/printpreview.ui
new file mode 100644
index 0000000..559f0cf
--- /dev/null
+++ b/examples/demo/opengl/printpreview.ui
@@ -0,0 +1,277 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>PrintPreview</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>PrintPreview</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>634</width>
+ <height>195</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Print Preview</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>true</bool>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QGroupBox" row="0" column="0">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Preview</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>pixmapLabel</cstring>
+ </property>
+ <property name="text">
+ <string>TextLabel1</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox" row="0" column="1">
+ <property name="name">
+ <cstring>GroupBox2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title">
+ <string>Modify</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>checkInvert</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Invert Colors</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>checkMirror</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Mirror</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>checkFlip</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Flip</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>checkLeft</cstring>
+ </property>
+ <property name="text">
+ <string>Rotate 90° &amp;left</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>checkRight</cstring>
+ </property>
+ <property name="text">
+ <string>Rotate 90° &amp;right</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonHelp</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Help</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="caption">
+ <string></string>
+ </property>
+ <property name="text">
+ <string>&amp;Print</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Discard</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>PrintPreview</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>PrintPreview</receiver>
+ <slot>reject()</slot>
+ </connection>
+ <connection>
+ <sender>checkLeft</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>checkRight</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>checkRight</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>checkLeft</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>checkInvert</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>PrintPreview</receiver>
+ <slot>invertColors(bool)</slot>
+ </connection>
+ <connection>
+ <sender>checkMirror</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>PrintPreview</receiver>
+ <slot>mirror(bool)</slot>
+ </connection>
+ <connection>
+ <sender>checkFlip</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>PrintPreview</receiver>
+ <slot>flip(bool)</slot>
+ </connection>
+ <connection>
+ <sender>checkLeft</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>PrintPreview</receiver>
+ <slot>rotateLeft(bool)</slot>
+ </connection>
+ <connection>
+ <sender>checkRight</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>PrintPreview</receiver>
+ <slot>rotateRight(bool)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="global" impldecl="in declaration">qimage.h</include>
+ <include location="global" impldecl="in declaration">qpixmap.h</include>
+ <include location="local" impldecl="in implementation">printpreview.ui.h</include>
+</includes>
+<variables>
+ <variable>QPixmap pix</variable>
+</variables>
+<slots>
+ <slot access="protected">init()</slot>
+ <slot access="protected">destroy()</slot>
+ <slot>updatePreview()</slot>
+ <slot>flip( bool )</slot>
+ <slot>invertColors( bool )</slot>
+ <slot>mirror( bool )</slot>
+ <slot>rotateLeft( bool )</slot>
+ <slot>rotateRight( bool )</slot>
+ <slot>setPixmap( const QPixmap &amp; pm )</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/examples/demo/opengl/printpreview.ui.h b/examples/demo/opengl/printpreview.ui.h
new file mode 100644
index 0000000..db5dbfb
--- /dev/null
+++ b/examples/demo/opengl/printpreview.ui.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions respectively slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+
+void PrintPreview::init()
+{
+
+}
+
+void PrintPreview::destroy()
+{
+
+}
+
+void PrintPreview::updatePreview()
+{
+ QImage img = pix.convertToImage();
+ if ( checkInvert->isChecked() ) {
+ img.invertPixels();
+ }
+ if ( checkMirror->isChecked() ) {
+ img = img.mirror( TRUE, FALSE );
+ }
+ if ( checkFlip->isChecked() ) {
+ img = img.mirror( FALSE, TRUE );
+ }
+ if ( checkLeft->isEnabled() && checkLeft->isChecked() ) {
+ }
+ if ( checkRight->isEnabled() && checkRight->isChecked() ) {
+ }
+ QPixmap pm;
+ pm.convertFromImage( img );
+ pixmapLabel->setPixmap( pm );
+}
+
+void PrintPreview::flip( bool )
+{
+ updatePreview();
+}
+
+void PrintPreview::invertColors( bool )
+{
+ updatePreview();
+}
+
+void PrintPreview::mirror( bool )
+{
+ updatePreview();
+}
+
+void PrintPreview::rotateLeft( bool )
+{
+ updatePreview();
+}
+
+void PrintPreview::rotateRight( bool )
+{
+ updatePreview();
+}
+
+void PrintPreview::setPixmap( const QPixmap & pm )
+{
+ pix = pm;
+ updatePreview();
+}
diff --git a/examples/demo/opengl/qtlogo.bmp b/examples/demo/opengl/qtlogo.bmp
new file mode 100644
index 0000000..b7f9215
--- /dev/null
+++ b/examples/demo/opengl/qtlogo.bmp
Binary files differ
diff --git a/examples/demo/opengl/qtlogo.png b/examples/demo/opengl/qtlogo.png
new file mode 100644
index 0000000..e6e3bee
--- /dev/null
+++ b/examples/demo/opengl/qtlogo.png
Binary files differ
diff --git a/examples/demo/opengl/snapshot.xpm b/examples/demo/opengl/snapshot.xpm
new file mode 100644
index 0000000..1c7180c
--- /dev/null
+++ b/examples/demo/opengl/snapshot.xpm
@@ -0,0 +1,238 @@
+/* XPM */
+static char *camera[] = {
+/* width height num_colors chars_per_pixel */
+" 32 32 151 2",
+/* colors */
+".. c None",
+".# c #1f1f1f",
+".a c #202020",
+".b c #2f2720",
+".c c #302020",
+".d c #302820",
+".e c #3f2720",
+".f c #3f2820",
+".g c #3f2f2f",
+".h c #3f3730",
+".i c #402820",
+".j c #402f20",
+".k c #403730",
+".l c #4f2820",
+".m c #4f302f",
+".n c #4f403f",
+".o c #4f484f",
+".p c #50302f",
+".q c #50403f",
+".r c #5f2f20",
+".s c #5f3020",
+".t c #5f3830",
+".u c #5f4f30",
+".v c #5f4f50",
+".w c #5f5760",
+".x c #60372f",
+".y c #60382f",
+".z c #60482f",
+".A c #604f40",
+".B c #60504f",
+".C c #60606f",
+".D c #6f4030",
+".E c #6f4730",
+".F c #6f676f",
+".G c #6f7790",
+".H c #70402f",
+".I c #704030",
+".J c #704830",
+".K c #704f3f",
+".L c #705f50",
+".M c #706860",
+".N c #707780",
+".O c #7f6850",
+".P c #7f706f",
+".Q c #804f2f",
+".R c #80573f",
+".S c #805f40",
+".T c #806740",
+".U c #807060",
+".V c #807f80",
+".W c #80808f",
+".X c #8090b0",
+".Y c #80a0d0",
+".Z c #8f5730",
+".0 c #8f5840",
+".1 c #8f7f7f",
+".2 c #8f8f90",
+".3 c #905f40",
+".4 c #906740",
+".5 c #90684f",
+".6 c #907f6f",
+".7 c #908780",
+".8 c #908f8f",
+".9 c #9097a0",
+"#. c #909fb0",
+"## c #90a7cf",
+"#a c #9f5f30",
+"#b c #9f684f",
+"#c c #9f7750",
+"#d c #9f887f",
+"#e c #9f8f80",
+"#f c #9f9790",
+"#g c #9f98a0",
+"#h c #9fa0af",
+"#i c #9fafd0",
+"#j c #9fafdf",
+"#k c #a06f4f",
+"#l c #a0703f",
+"#m c #a07f5f",
+"#n c #a0906f",
+"#o c #a09780",
+"#p c #a09890",
+"#q c #a09f9f",
+"#r c #a0b0c0",
+"#s c #a0b7e0",
+"#t c #af7850",
+"#u c #af875f",
+"#v c #af978f",
+"#w c #af9fa0",
+"#x c #afa09f",
+"#y c #afa0a0",
+"#z c #afa7af",
+"#A c #afa8a0",
+"#B c #afa8b0",
+"#C c #afafcf",
+"#D c #afb7d0",
+"#E c #b07f50",
+"#F c #b07f5f",
+"#G c #b0a08f",
+"#H c #b0a79f",
+"#I c #b0a8af",
+"#J c #b0afa0",
+"#K c #b0b0b0",
+"#L c #b0c7ef",
+"#M c #bf875f",
+"#N c #bfa89f",
+"#O c #bfaf9f",
+"#P c #bfb0a0",
+"#Q c #bfb0af",
+"#R c #bfb7b0",
+"#S c #bfb8bf",
+"#T c #c0b09f",
+"#U c #c0b7af",
+"#V c #c0b8af",
+"#W c #c0b8bf",
+"#X c #c0bfb0",
+"#Y c #c0c0bf",
+"#Z c #c0d0df",
+"#0 c #cf9f6f",
+"#1 c #cfc0b0",
+"#2 c #cfc0c0",
+"#3 c #cfd7f0",
+"#4 c #d0bfa0",
+"#5 c #d0c8c0",
+"#6 c #d0cfc0",
+"#7 c #d0cfd0",
+"#8 c #d0d7a0",
+"#9 c #dfcfbf",
+"a. c #dfd7cf",
+"a# c #dfd7df",
+"aa c #dfd8df",
+"ab c #dfe0bf",
+"ac c #dfe7ff",
+"ad c #e0d7af",
+"ae c #e0d7d0",
+"af c #e0d8df",
+"ag c #e0e0e0",
+"ah c #efe0e0",
+"ai c #efe7e0",
+"aj c #efe7ef",
+"ak c #efe88f",
+"al c #efe8f0",
+"am c #eff0a0",
+"an c #f0e0c0",
+"ao c #f0e7e0",
+"ap c #f0e8e0",
+"aq c #f0f0ef",
+"ar c #f0f0ff",
+"as c #f0f8ff",
+"at c #fff7ff",
+"au c #fff8f0",
+/* pixels */
+"............................................#o#N#N#v#P..........",
+"........................................#H#U#H#N#U#5ae#Y#H......",
+"......................................#H#v#e#N#U#1aeaeahah#H....",
+"....................................#H#v.1#d#O#Y#5aeahapaqaa#H..",
+"..................................#H#N.1.M.7#Ya#aeagapatapap#5..",
+"..................................#1#y.V.7#q#I#S#Ya#agajalalah#O",
+"...................8#y.V.P.h.h...1a.#1#P#W#q.V.9#.#.#Kaaatauau#1",
+".............8#y#q#y#I#R#Y#q.e.c#Papapaual#B.G###r#i.X#Calauau#1",
+".........p.f.8#K#S#R#K#S#S#S#q.b#1auauauau.X#rakab#L.Y#iasauau#7",
+".......p.l.j.n#d#K#R#R#S#K#K#S#p#Pauauauau#D#8amac#L.Y##auauaual",
+".....p.j.e.p.i.q#d#A#I#W#W#Q#S#S#Pauauauau#D#Zacac#L#j#sauauauag",
+"...m.p.m.f.e.i.l.S#Raaaaagalatal#Xauauatah#K#L#3ac#3#j#3auauau#6",
+"...l.m.m.e.i.y#b.Laiauauauauauau#Pauauahafaf#7#r#r#i#Dauauauauae",
+"...e.f.j.b.e#b.R.haaauauauauauau#Hahaoaf#5#6#7#K#h#Ba#ajauauag#H",
+".D.D.l.b.a.f#M.h.#aaauauauauauau.P#5aeae#1#Y#6#w.2.9#g#z#7#7ae..",
+".p.s.s.b.a.f#F.t.baiaualagahalag.E#dae#1#P#J#Y#y.F.C.N.W.2#f#H..",
+".e.p.p.a.a.f#E.D.calau.F.#.u#n#2.K.f#4#X#x.8#y#A.F.o.w.C.7#H....",
+".t.x.f.a.a.e#E.D.caqau.g.z.A.A#J.R.f.O#Y#U#f#y#P#N.M.v#d#x......",
+"...i.c.b.a.f#E.D.calaq.Bad#G.d#I.E.#.q#o#N#X#P#P#P#v#A#x........",
+"...e.a.a.b.f#t.x.capap.M.L.k.oae.D.#.K.R.f.B#Y#1#1#V............",
+"...e.b.b.b.f#t.t.calau#P.n.n#Qau.y.#.R.R.#.c....................",
+"...i.e.c.b.f#t.x.haqauau#Y#Yaqau.p.#.R.R.c.h....................",
+"...l.c.e.e.j#t.s.tauau#6.q.q#Nau.h.c.T.0.c.j....................",
+"...c.e.i.i.j#F.x.Dauau.U.S.1.q#5.D.c.5.R.c.j....................",
+"...e.i.l.l.y#b.x.taq#5.A#4an.1#9.H.c#c.Z.c.p....................",
+"...e.l.l.l.3.0.r.5auae.U#N#O#e#9.D.c#m.4.r.I....................",
+"...c.r.x.r.0.J#t#0arau#9.6#d#9au.J.c.R.3.s.I....................",
+"...e.x.y.y.3.3.Z#uauauauauauauah.Q.l.D.0.x......................",
+".....l.H.I.Z#k.y#mauauauau#9#v.4.J.r............................",
+".......y.I.J#k.x.3#T#q#m.3.Q.Q.y.s..............................",
+".........y.Z#t#l#a.Z.J.y.H.x....................................",
+"...........y#l.I.x.x.x.........................................."
+};
+SIMPLE = T
+BITPIX = 8
+NAXIS = 2
+NAXIS1 = 32
+NAXIS2 = 32
+HISTORY Written by XV 3.10
+END
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+SSSSSDxNCCCSSSSSSSSSSSSSSSSSSSSSSSSSDd„xmdRDMCSSSSSSSSSSSSSSSSSSSSSDNRzCk˛Ÿ…kZZD
+=SSSSSSSSSSSSSSSSS4MNdzD…ůůůůҞoR=SSSSSSSSSSSSSSS.CDDkkdŽůůůůůůĺZ4MgCSSSSSSSSSSS
+S%=C=gR„¨ňů҂ŽŇůR%ak=NSSSSSSSSSSS.444kg=qůŮsŽ˛’ŇM%…o=NSSSSSSSSSSS./44DwCDďÉRŔŕ„Ň
+M%~d%:SSSSSSSSSSS%.//2ŠCMůůse„EÉM%qa%2SSSSSSSSSSS4%..2„=DůůÍEEŽů8%ig%2SSSSSSSSSS
+S/.%(.„C8ďůůżżďů:aa%8SSSSSSSSSSS.(((.„D%ëů˛EEľůDaa%SSSSSSSSSSS. (.„C%ééib9KŮ
+MWa.UżÂšSSSSSSS/%( .ˆM%ëďUÓ˘)ŤQE–Ž˝˛˛˛žŠĽSSSSDC. .ˆM%ďů4LRR­a.lż¸˜Ľ˛ŽiTŽĽSSS
+.:: .ˆM%ëůkOĹW.Ŕ˝ĽĽŠkK[b‰¨SS:==( .ŠD(čůëŕĺëŕQŽŮ²­żĽkbv‚˜¨SMM4( .”8Űůůůůůů
+uÉŮŮ¿ͤ–›ŤĎĎŮSS..2(.wa8Űůůůůůů¨ĺéŰÉÍĎ°˘ŤŰëůůŕ¨S4::./Dwbčůůůůůů˛ůůĺŰŰĎ­­Ž¸ůůůůŮ
+S:::../4e¸ŰŰŕëűë˝ůůűĺ°ĹŘčŘąŘůůůÍSS:2.:/EŽŠŤťťľťť˛ůůůů¸ĚččĹąľůůůŕSSS:42EŽ°¸¸ť°°ť™
+˛ůůůů¸ĚăčŜĽůůůëSSSS:.°ť¸°ťťťŸ(Âůůůů­ÜÚŜŽöůůĎSSSSSSĽŸĽŤ¸żŸ.%˛ééůëŤxĽ­Ž´ëůůÂ
+SSSSSSSSSĽu88S„Ř²ťŸ–œœ°ŰűůůÂSSSSSSSSSSSSSSSSSÂĽ‰ŸŤťżŰŕëëëĺ˛SSSSSSSSSSSSSSSS
+S¨Ž„i‰żŰŮŕéűééÉSSSSSSSSSSSSSSSSSSS¨ž„Ž˛żÉŮĺéďۨSSSSSSSSSSSSSSSSSSSS¨ž’Ž¸ÂŮŮĺĺ¨SSSSSSSSSSSSSSSSSSSSSS¨¸¨Ž¸ÉŮż¨SSSSSSSSSSSSSSSSSSSSSSSSS–ŽŽž˛SSSSS€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€
diff --git a/examples/demo/opengl/texture.xpm b/examples/demo/opengl/texture.xpm
new file mode 100644
index 0000000..3c423e9
--- /dev/null
+++ b/examples/demo/opengl/texture.xpm
@@ -0,0 +1,130 @@
+/* XPM */
+static char *Monalisa[] = {
+/* width height num_colors chars_per_pixel */
+" 48 48 27 1",
+/* colors */
+". c #000000",
+"# c #281808",
+"a c #38240c",
+"b c #492c10",
+"c c #553414",
+"d c #593818",
+"e c #5a5a5a",
+"f c #65411c",
+"g c #794d24",
+"h c #7d5124",
+"i c #86592c",
+"j c #966534",
+"k c #9a6938",
+"l c #aa7545",
+"m c #ae7949",
+"n c #b68251",
+"o c #be8a59",
+"p c #c79665",
+"q c #cf9e6d",
+"r c #d3a275",
+"s c #d7aa7d",
+"t c #dfb28a",
+"u c #e3ba92",
+"v c #ebc7a6",
+"w c #ebcbae",
+"x c #ffffff",
+"y c None",
+/* pixels */
+"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
+"e..............................................x",
+"e.oppqnnoononoonnoonpppooqpooonopppqppoonnpoopox",
+"e.oloonpnoonpooooopnpolljjllnpnqoopooopnnnnpoopx",
+"e.looooopnoonpoppoplifbbbbccdgloppppoqpoooopoqqx",
+"e.ooopqppqpoopopppibbdcababbddcdloppqoolpnppppqx",
+"e.pporpppppqppqoogbcdgabbbbbaccdckppqqpoopoqrrrx",
+"e.rpqqqooppoprrrgbccgdbcbbaababccbjppqqppopoqrrx",
+"e.pqppqsqpppqrrkbbdilkigcbabbabbdcclpqpqopppqqqx",
+"e.oqqqppqpqqrtpcgnrstrrnmifbbbbccccdnpqrqqqoqqqx",
+"e.qpqpqpqpqstrjdnruwwwusrnigcbabccdchrrsrqrqqprx",
+"e.oqqpqqpqrttoajrvwwwwwwrrlhdbbaacdcborqrrrrqrrx",
+"e.qqqrrtrstwtfdntwvvwvwwuqmjgcbbbacbbirqpqrrrrsx",
+"e.qrrrrrrrtvofdntwvwwvwutpmkidcbaaababpnopppprrx",
+"e.srprrrprspidhouwwvvwvtsrpnkjfbbaaaabjknnmnpprx",
+"e.rrsrrssssoddiruvvvvwvwttrrokgccbbabagjkkkmpnpx",
+"e.stwrwrwrvkddipuuvvvvtssrrpnkfdcbbaaafiijkllmnx",
+"e.lnrsrwrvpjddfppoqutslllmmkjifcddbbbbffhiklknmx",
+"e.kjjrsrwrmfddffkkjpslfilifdbhgcccbbbbcfgghjkkkx",
+"e.ijjrwrrrofdddblafmtiimmahfklhbccbabacfffgjjjhx",
+"e.hjjppklonddakoonlrtilrrnkornicccbbaacgfggfihfx",
+"e.fhfkiidjkdbakttrsrtmosstttrmhddddcbcbdffhkfghx",
+"e.dffafhfffhaairuutusqmwuwurplhdfddcdccggggghffx",
+"e.dddddfdddaddhruututnrswutrlkfcdfdfdcchjjkkmmkx",
+"e.daffdadaddaadrstrutomustsokffddddcdccddfhihjkx",
+"e.fgddddabadddalrsotpiktutpmkidcddfddcdddddghfgx",
+"e.fcddddbabbdbainrsnfairspnkigdcdfccdcccdddddfdx",
+"e.ddddbbddbbbadfmlsrkmmmmomkjgddfdfgdccdfffffffx",
+"e.ddcdadbbabddahlnlnmiiioonlffdbfdccddddfffffffx",
+"e.cdbbdbdcbcdbdakorrmmkmopniifdcddddcddddffgfgfx",
+"e.cddcbdddcabddadkrqmlmmnlkfhdbccccddcccdfdfgfgx",
+"e.dgffffhhcfadbddalsvtonkjffddcdccddcdccdggfgggx",
+"e.dcdddffgdadddbadaoqomkffffdbbbcbdddcbccfffgfgx",
+"e.cdddgilkfbcdbdaaaaiffffdfdbddbccddccbbcffdfgfx",
+"e.fhggghkkhddbdbaaaaadfafddbfbddccccbcbbcfddfgdx",
+"e.hkhmllkkidabdbbaaaafdfadbddffdcbabbbbabdffdfgx",
+"e.imlllhliifddbbb#baakjffddfhhhfcbdbbbbbbfdfiffx",
+"e.hljhllhjhfbdbbaaadafmlkihhhiihdbbbbabbbdfgghgx",
+"e.dhlggiiigdccdbaa#abgmlmkkjkklkhdbdbbdaabbccccx",
+"e.hbadfdcbcbaabaaabdfimnnmllmnmkiddbdddbbbabddcx",
+"e.gbbabbbabbbcbbbbbinrppoonppppojfdffddcbbabcbcx",
+"e.dba#abcbabcbcbdhknrtrtrrrrrrroliffidccccbdcghx",
+"e.fbab#acbbcbbccinsrtttssttwssrpkfigifcbbcbbbcfx",
+"e.daacbbdcbbbbdborpwttwwttwswsrpmigfgdbbdbbbbcdx",
+"e.dcccbcddcbddfirtuwwwswswswrwprlfigfdcddccbacdx",
+"e.fdcdcddbbcddgmrswwwuwtswwtwsrpjiiffccbcfddcbcx",
+"e.fdfhccbbbbfhiowwswwwtwutwttwrpjfiggbcdhgdfcbbx",
+"exxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+};
+SIMPLE = T
+BITPIX = 8
+NAXIS = 2
+NAXIS1 = 48
+NAXIS2 = 48
+HISTORY Written by XV 3.10
+COMMENT the GIMP was here
+END
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Z˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙˙Z€G>GY::1111GYa”ŃѲŃŃŃťŃÁťŃťťŃŤŸ
+nGaUU1:>YU>G:11˙Z€G>:>:>>11:>>UƒŤ˛ŃŃŃÁŃť˛ŃѝѲŤŸnaaGG::1:G>>:1:˙Z€>:::1:>>:1>>Ga
+ŤťÁŃŃѲѲѲѫџŤGaUG>:>>::1':>˙Z€>'':11>:1111>1”ŤŸŃťťŃŃťťŃ˛Ń˛ŤŸƒaUGU>11>1111:>˙
+Z€G1'1':11:11::aŒ˛Ťťťť˛˛ťťŃ˛˛ŤŸrGaUaG:11:111:G˙Z€>1''1:1'1:1:1>YrŒŤťŤťŤŤŤŤŤŤŤ”
+aGGa>::::1>:UY˙Z€U11'111'111:11111aŒŤŸŸ””ŒŸŸŸŸ”nG>GG>>:11'1:1:˙Z€Y1'>G>:1:1''1'
+''1>GaƒŒŒƒƒŒƒra>>1>>>111'1>>:˙Z€>YUUaaaU>::>1'''1UƒƒrrnrrrY>1>11>''11::::˙
+Z€YnYYnYG1>11'''>'GƒraYYYaaY>1111'111>GUUYU˙Z€aƒYaaG>>1111''rnGG>>GYYYG
+:1>111111G>GaGG˙Z€YrYƒrra>'1>11''''G>G'>1>>GG>:1'1111'1>GG>GU˙Z€GYUUUYrrY>>1>1
+'''''>G'G>>1G1>>::::1:11:G>>GU>˙Z€:>>>UarG1:>1>''''aGGGG>G>1>>1::>>::11:GG>GUG˙
+Z€>:>>>GGU>'>>>1'>'”§”ƒrGGGG>111:1>>>:1::GGGUGU˙Z€>UGGGGYY:G'>1>>'˛Îť”ŒrnGG>>:>
+::>>:>::>UUGUUU˙Z€:>>:1>>>:'1>>'>rŤ§ƒƒƒŒrGY>1::::>>:::>G>GUGU˙Z€:>11>1>:1:>1>'
+r”ŤŤƒƒrƒ”ŸŒaaG>:>>>>:>>>>GGUGUG˙Z€>>:>'>11'1>>'YŒŒƒaaa””ŒGG>1G>::>>>>GGGGGGG˙Z€>>>>11>>111'>Gƒ˛Ťrƒƒƒƒ”ƒrnU>>G>GU>::>GGGGGGG˙Z€G:>>>>1'11>1'aŒŤ˛ŒG'aŤ˛ŸŒraU>:>G::>:::>>>>>G>˙Z€GU>>>>'1'>>>'Ť˛”ťŸarťÁťŸƒra>:>>G>>:>>>>>UYGU˙Z€>'GG>'>'>>''>Ť˛ťŤÁť”ƒÁ˛ť˛”rGG>>>>:>::>>GYaYnr˙Z€>>>>>G>>>'>>YŤÁÁťÁťŒŤ˛ŃÁťŤrG:>G>G>::Ynnrrƒƒr˙Z€>GG'GYGGGY''aŤÁÁťÁ˛§ƒŃÁŃÁŤŸY>G>>:>::UUUUUYGG˙Z€GYGraa>nr>1'rťťŤ˛Ťťƒ”˛˛ťťťŤƒY>>>>:1:1>GGYrGUY˙Z€YnnŸŸr”Œ>>'r””ŒŤťaŤŤŒr”ŤŒa:::11'':UGUUGaYG˙Z€annŤŃŤŤŤ”G>>>1'Gƒťaaƒƒ'YGrY1::1'1':GGGUnnnY˙Z€rnnŤ˛ŤŃŤƒG>>GGrrnŸ˛GaaG>1YU:::1111:GUUYnrrr˙Z€ŒŤ˛ŤŃŤÎŸn>>GŸŸ”§Áť˛ƒƒrnaG:>>1111GGYarrŒƒ˙Z€˛ťŃŤŃŤŃŤÎr>>aŸÁÁÎÎÎÎť˛˛ŤŤŸŒrG>:11'''GaanrƒŒ˙Z€ŤŤ˛ŤŤ˛˛˛˛”>>aŤÁÎÎÎÎŃÎŃťťŤŤ”rU::11'1'UnrrrƒŸŒŸ˙Z€˛ŤŸŤŤŤŸŤ˛Ÿa>Y”ÁŃŃÎÎŃÎť˛ŤŸŒrnG11''''1nrŒŒƒŒŸŸŤ˙Z€§ŤŤŤŤŤŤŤťÎ”G>ŒťŃÎŃŃÎŃÁťŸƒra>:1'''1'1ŸŒ”ŸŸŸŸŤŤ˙Z€§§§ŤŤťŤ˛ťŃťG>ŒťŃÎÎŃÎŃŃÁ§ƒnU:111':11aŤ§Ÿ§ŤŤŤŤ˛˙Z€”§§Ÿ§§Ÿ§Ťťť”'nŤÎŃŃŃŃŃŃŤŤY>11'':>:1”Ť§ŤŤŤŤ§ŤŤ˙Z€§Ÿ§Ÿ§Ÿ§Ÿ§˛ťŤn>ŒŤÁŃŃŃÁ˛ŤŒaU:1'1::>:YŤŤ˛Ť§Ť§§ŸŤ˙Z€”§§§ŸŸ§Ÿ§§ŤťŸ:UŒŤ˛ťŤŤŒƒaG1111::::>ŒŸ§Ť§§§”§§§˙Z€Ÿ§ŸŸ§˛§ŸŸŸ§ŤŤr11>araU:1'11'11>::Ÿ§Ÿ§”ŸŸŸ§§§˙Z€ŤŸ§§§””ŸŸ”ŸŤŤŤU1::U>1:11''1'1::1nŸŸ§§ŸŸ”Ÿ”§ŤŤ˙Z€ŸŸ”ŤŸŸŸŸŸ§ŸŸ§””U1:>U'11111'::>:rŸŸ§§Ÿ””Ÿ”§ŤŤŤ˙Z€”””Ÿ§ŸŸ§Ÿ””Ÿ”ŸŸŸa11>:'1'11>>:>”ŸŸ§””ŸŒŸŸŸŸ§˙Z€”””””ŸŒ””ŒŸ”ŸŸ”ŸaG1111::>U”ŸŸŸŸ”§Ÿ””””Ÿ”§§˙Z€”””ŒŸŒ””ŒŸ”””””ŸŒŸ”nnŒŸŒ§””Ÿ”””ŸŒŒŒŒŸ””Ÿ˙Z€”ŸŸ§ŒŒ””Œ”Œ””ŒŒ””ŒŸŸŸ””§Ÿ”””Œ”ŸŸŸ§ŸŸ””ŒŒŸ””Ÿ”˙Z€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€˙ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€
diff --git a/examples/demo/opengl/wirebox.xpm b/examples/demo/opengl/wirebox.xpm
new file mode 100644
index 0000000..77ca534
--- /dev/null
+++ b/examples/demo/opengl/wirebox.xpm
@@ -0,0 +1,155 @@
+/* XPM */
+static char * EscherCube_xpm[] = {
+"48 48 104 2",
+" c None",
+". c #30C230C22081",
+"X c #30C230C230C2",
+"o c #30C2410330C2",
+"O c #410330C24103",
+"+ c #410341034103",
+"@ c #514451445144",
+"# c #514461855144",
+"$ c #618551446185",
+"% c #618561856185",
+"& c #71C671C671C6",
+"* c #71C6820771C6",
+"= c #965882078617",
+"- c #861792488617",
+"; c #965892489658",
+": c #9658A2899658",
+"> c #9E79A2899E79",
+", c #AEBAAEBA9E79",
+"< c #AEBAAEBAAEBA",
+"1 c #AEBABEFBAEBA",
+"2 c #BEFBBEFBBEFB",
+"3 c #CF3CBEFBCF3C",
+"4 c #CF3CCF3CCF3C",
+"5 c #DF7DCF3CCF3C",
+"6 c #DF7DDF7DCF3C",
+"7 c #DF7DDF7DDF7D",
+"8 c #EFBEDF7DDF7D",
+"9 c #DF7DEFBEDF7D",
+"0 c #EFBEDF7DEFBE",
+"q c #EFBEEFBEDF7D",
+"w c #208130C22081",
+"e c #410351445144",
+"r c #514451446185",
+"t c #71C6618571C6",
+"y c #861771C68617",
+"u c #9E7992489E79",
+"i c #9E79AEBA9E79",
+"p c #BEFBAEBABEFB",
+"a c #BEFBCF3CBEFB",
+"s c #BEFBCF3CCF3C",
+"d c #CF3CCF3CDF7D",
+"f c #CF3CDF7DCF3C",
+"g c #DF7DDF7DEFBE",
+"h c #208120812081",
+"j c #30C2208130C2",
+"k c #410330C230C2",
+"l c #4103410330C2",
+"z c #410351444103",
+"x c #618551445144",
+"c c #618561855144",
+"v c #618571C66185",
+"b c #861771C671C6",
+"n c #8617820771C6",
+"m c #965882079658",
+"M c #9E7992489658",
+"N c #AEBAA289AEBA",
+"B c #BEFBAEBAAEBA",
+"V c #DF7DCF3CDF7D",
+"C c #CF3CDF7DDF7D",
+"Z c #208120811040",
+"A c #965892488617",
+"S c #104020812081",
+"D c #861782078617",
+"F c #861792489658",
+"G c #965892489E79",
+"H c #104020811040",
+"J c #208110402081",
+"K c #30C220812081",
+"L c #BEFBBEFBCF3C",
+"P c #104010401040",
+"I c #208110401040",
+"U c #618571C671C6",
+"Y c #71C671C68617",
+"T c #71C682078617",
+"R c #CF3CBEFBBEFB",
+"E c #CF3CCF3CBEFB",
+"W c #000010401040",
+"Q c #104010402081",
+"! c #9E79AEBAAEBA",
+"~ c #104010400000",
+"^ c #AEBAA2899E79",
+"/ c #71C671C66185",
+"( c #000010400000",
+") c #000000000000",
+"_ c #104000001040",
+"` c #2081208130C2",
+"' c #9658A2899E79",
+"] c #104000000000",
+"[ c #000000001040",
+"{ c #30C241034103",
+"} c #9E79A289AEBA",
+"| c #AEBABEFBBEFB",
+" . c #514461856185",
+".. c #9E79A2899658",
+"X. c #71C661856185",
+"o. c #30C230C24103",
+"O. c #514441035144",
+"+. c #514451444103",
+"@. c #410341035144",
+"#. c #AEBAAEBABEFB",
+"$. c #208130C230C2",
+"%. c #6185618571C6",
+"&. c #514441034103",
+"*. c #861782079658",
+" . X o O + @ # $ % & * = - ; : > , < 1 2 2 3 4 5 6 7 7 8 9 0 q ",
+" w X X O + @ e r % t & y - ; : u i < < p a 3 s d f 7 7 g 9 0 9 ; ",
+" h j X k l + z x c t v b n m ; M > N < B 2 2 a 3 4 V 6 7 7 0 9 m ; ",
+" h h w X f d f d f V f V f 7 f 7 C 7 f V f V f d f V f 7 9 g 9 m ; ; ",
+" Z h w j - 4 4 5 4 5 4 5 4 V f V 6 V f V f V 4 5 4 5 4 V 7 7 7 m A ; ; ",
+" S h h j - D s 4 4 4 4 4 4 4 4 d f V f d f d 4 d 4 4 4 V C 7 7 m - ; F G ",
+" H J Z K * D D m ; M 5 4 V 7 = D m - ; ; ",
+" H h S h * y D L F ; : 4 f V C D D m a ; ; G ",
+" P I H J & b n 2 2 m A M 3 4 5 f y D = 2 2 A ; ; ",
+" P P H J U Y & p 1 2 - ; : 4 4 d f y T D 1 p 1 ; F G ",
+" P P H J % t & < < < m ; u R E 4 f b * y B < < A ; ; ",
+" W P P Q % t v < ! < - ; : L a 4 4 & * y < < ! ; ; G ",
+" ~ P ~ I c $ % > ^ > m ; M 2 2 3 4 t / b ^ i ^ ; M ; ",
+" ( P W P # $ % > > > F ; : p a 3 s t U & > > > ; ; G ",
+" ) _ ( _ @ $ # M ; u m ; u p 2 2 a % v t M ; u ; M ; ",
+" ( _ ( P P P H h h ` w X o : ; F F ; : & * D - G ' > i < 1 2 a % v t : ; F ; : u ",
+" ) ] ( _ ~ P P I Z h w j X O m - m ; ; M & y - m ; > i N < 2 2 $ c % m - m ; M : ",
+") [ ( _ W P P Q H h h j X O { D D - F G : y T m ; u > } < p | r .% D D - G : u ",
+"V f 5 4 5 f V f V f V f V f V y * y m ; u f 5 f V f 5 4 V f x @ $ y * y : u ..",
+"4 d f 4 f d f d 4 d f V f V f U & U F G : d f d f d f 4 4 d @ r # U & U G : > ",
+"3 4 3 E 4 E 4 4 3 4 4 4 5 4 5 t v X.; ; u 4 4 4 4 E 4 E 3 4 @ @ x t v X.; u ..",
+"a 4 a o.{ + .% v ; G > 3 a 4 e @ # .% v u ' > ",
+"3 2 3 X O o $ # $ ; ; u 2 3 2 O.+.@ $ # $ : u > ",
+"a 2 a X o + @ @ @ ; u ' 2 2 2 z @ @ @ @ @ u > } ",
+"p < p X k l O.z O.; : u 1 p < O.+.@ O.z O...> i ",
+"1 < 1 o.o + @.z @.; G > #.1 < z O.@ + @.z > > } ",
+"N , N X O o l + o ; ; u 1 1 1 O.+.@ O l + : u > ",
+"i } i o.o + O o o.; u o + z @ # % v } i } e @ @ } < #.| L a 4 f V o o.o G ' > ",
+"> ..u o O + . X . ; o O + O.@ $ % & u u ..@ @ x , < 1 2 2 3 4 5 6 X . X ; u ..",
+"' u : O + + j $.j $.o.{ O.e r % %.U G : u @ r # < < p 2 3 s d f 7 $.j $.u : u ",
+"; A M l + + h j . K h j h K h h h h ; ; A x @ $ h h h h h K h j 6 7 7 0 : u ..",
+"- m - + { @. h h w %.w h h h h h S h S m - m # r # h S h S h h h f 7 9 g F G : ",
+"y D D l + + Z h h t % h Z J Z J Z J Z J D y D x # $ H J Z J Z J f V 7 7 - M ; ",
+"* y * + z O. S h h & U t y * y @ $ . 4 d C 7 - m ; ",
+"& / b l + + P J Z y & t & & / x c $ E 5 4 V n = D ",
+"v %.v + z O. H J H D * & & v %.# % . a 4 f V * D - ",
+"X.% % + &.z P P H D n y c $ % $ c $ a 3 4 V * y D ",
+"# $ # + z @ P P H J m - D $ # $ # $ % 2 3 4 d * y T ",
+"@ @ x + + z W P P Q m D m @ @ @ $ c % 2 R E 4 & b * ",
+"z O.e + z @ P ~ I ; ; *. @ z O. .% % L s 4 U & * ",
+"&.+ &.l &.+.W P M ; m + &.+ $ c X.2 3 v t & ",
+"{ + { @.z O._ u ' ; + { + .$ % 3 v t & ",
+"O o k + O.P P P H h h ` w X o l + z @ c X./ b n m ; u o O o $ % % % t v ",
+"$.X $.@._ ~ P P I Z h w j X O + + @ # % v & * D - ; : X $.X .% v %.v ",
+"j . j _ W P P Q H h h j X O { + &.@ $ c t & y D m ; > . j . % c X.% ",
+"w j w ` w j w ` w ` h ` h h S h h h h ` h ` w ` w j w ` w j .% % ",
+"h h K h h h h h h h J h J H J Z J H J h h h h h h h J h h h $ % ",
+"S h h h H h S h S h S h H Q H J H Q H h H h S h S h S h S h . "};