diff options
author | Timothy Pearson <[email protected]> | 2011-07-10 15:24:15 -0500 |
---|---|---|
committer | Timothy Pearson <[email protected]> | 2011-07-10 15:24:15 -0500 |
commit | bd0f3345a938b35ce6a12f6150373b0955b8dd12 (patch) | |
tree | 7a520322212d48ebcb9fbe1087e7fca28b76185c /examples/opengl | |
download | qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.tar.gz qt3-bd0f3345a938b35ce6a12f6150373b0955b8dd12.zip |
Add Qt3 development HEAD version
Diffstat (limited to 'examples/opengl')
61 files changed, 4313 insertions, 0 deletions
diff --git a/examples/opengl/box/README b/examples/opengl/box/README new file mode 100644 index 0000000..113f82d --- /dev/null +++ b/examples/opengl/box/README @@ -0,0 +1,8 @@ + +The box example + +This example program shows how to use OpenGL in Qt: Put your OpenGL +code in a class inherited from QGLWidget. The resulting subclass may +be used like any other Qt widget, with signals and slots, geometry +management, etc.. + diff --git a/examples/opengl/box/box.doc b/examples/opengl/box/box.doc new file mode 100644 index 0000000..51297fa --- /dev/null +++ b/examples/opengl/box/box.doc @@ -0,0 +1,18 @@ +/*! \page opengl-box-example.html + + \ingroup opengl-examples + \title OpenGL Box Example + +This example demonstrates how to use OpenGL in Qt. + +Essentially, all you do is put your OpenGL code in a class inherited +from QGLWidget. This class may then be used like any other Qt widget, +including the use of signals and slots and geometry management. + +See \c{$QTDIR/examples/opengl/box} for the source code. + +*/ + + + + diff --git a/examples/opengl/box/box.pro b/examples/opengl/box/box.pro new file mode 100644 index 0000000..8078453 --- /dev/null +++ b/examples/opengl/box/box.pro @@ -0,0 +1,15 @@ +TEMPLATE = app +TARGET = box + +CONFIG += qt opengl warn_on release +CONFIG -= dlopen_opengl + +DEPENDPATH = ../include + +REQUIRES = opengl + +HEADERS = glbox.h \ + globjwin.h +SOURCES = glbox.cpp \ + globjwin.cpp \ + main.cpp diff --git a/examples/opengl/box/glbox.cpp b/examples/opengl/box/glbox.cpp new file mode 100644 index 0000000..11c8d5d --- /dev/null +++ b/examples/opengl/box/glbox.cpp @@ -0,0 +1,170 @@ +/**************************************************************************** +** +** 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 ) + : QGLWidget( parent, name ) +{ + 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(); + glTranslatef( 0.0, 0.0, -10.0 ); + 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 ); + + glCallList( object ); +} + + +/*! + 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; +} + + +/*! + Set the rotation angle of the object to \e degrees around the X axis. +*/ + +void GLBox::setXRotation( int degrees ) +{ + xRot = (GLfloat)(degrees % 360); + updateGL(); +} + + +/*! + Set the rotation angle of the object to \e degrees around the Y axis. +*/ + +void GLBox::setYRotation( int degrees ) +{ + yRot = (GLfloat)(degrees % 360); + updateGL(); +} + + +/*! + Set the rotation angle of the object to \e degrees around the Z axis. +*/ + +void GLBox::setZRotation( int degrees ) +{ + zRot = (GLfloat)(degrees % 360); + updateGL(); +} diff --git a/examples/opengl/box/glbox.h b/examples/opengl/box/glbox.h new file mode 100644 index 0000000..2c85e1d --- /dev/null +++ b/examples/opengl/box/glbox.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** 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 <qgl.h> + + +class GLBox : public QGLWidget +{ + Q_OBJECT + +public: + + GLBox( QWidget* parent, const char* name ); + ~GLBox(); + +public slots: + + void setXRotation( int degrees ); + void setYRotation( int degrees ); + void setZRotation( int degrees ); + +protected: + + void initializeGL(); + void paintGL(); + void resizeGL( int w, int h ); + + virtual GLuint makeObject(); + +private: + + GLuint object; + GLfloat xRot, yRot, zRot, scale; + +}; + + +#endif // GLBOX_H diff --git a/examples/opengl/box/globjwin.cpp b/examples/opengl/box/globjwin.cpp new file mode 100644 index 0000000..3a20cba --- /dev/null +++ b/examples/opengl/box/globjwin.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ + +#include <qpushbutton.h> +#include <qslider.h> +#include <qlayout.h> +#include <qframe.h> +#include <qmenubar.h> +#include <qpopupmenu.h> +#include <qapplication.h> +#include <qkeycode.h> +#include "globjwin.h" +#include "glbox.h" + + +GLObjectWindow::GLObjectWindow( QWidget* parent, const char* name ) + : QWidget( parent, name ) +{ + + // Create a menu + QPopupMenu *file = new QPopupMenu( this ); + file->insertItem( "Exit", qApp, SLOT(quit()), CTRL+Key_Q ); + + // Create a menu bar + QMenuBar *m = new QMenuBar( this ); + m->setSeparator( QMenuBar::InWindowsStyle ); + m->insertItem("&File", file ); + + // Create a nice frame to put around the OpenGL widget + QFrame* f = new QFrame( this, "frame" ); + f->setFrameStyle( QFrame::Sunken | QFrame::Panel ); + f->setLineWidth( 2 ); + + // Create our OpenGL widget + GLBox* c = new GLBox( f, "glbox"); + + // Create the three sliders; one for each rotation axis + QSlider* x = new QSlider ( 0, 360, 60, 0, QSlider::Vertical, this, "xsl" ); + x->setTickmarks( QSlider::Left ); + QObject::connect( x, SIGNAL(valueChanged(int)),c,SLOT(setXRotation(int)) ); + + QSlider* y = new QSlider ( 0, 360, 60, 0, QSlider::Vertical, this, "ysl" ); + y->setTickmarks( QSlider::Left ); + QObject::connect( y, SIGNAL(valueChanged(int)),c,SLOT(setYRotation(int)) ); + + QSlider* z = new QSlider ( 0, 360, 60, 0, QSlider::Vertical, this, "zsl" ); + z->setTickmarks( QSlider::Left ); + QObject::connect( z, SIGNAL(valueChanged(int)),c,SLOT(setZRotation(int)) ); + + + // Now that we have all the widgets, put them into a nice layout + + // Put the sliders on top of each other + QVBoxLayout* vlayout = new QVBoxLayout( 20, "vlayout"); + vlayout->addWidget( x ); + vlayout->addWidget( y ); + vlayout->addWidget( z ); + + // Put the GL widget inside the frame + QHBoxLayout* flayout = new QHBoxLayout( f, 2, 2, "flayout"); + flayout->addWidget( c, 1 ); + + // Top level layout, puts the sliders to the left of the frame/GL widget + QHBoxLayout* hlayout = new QHBoxLayout( this, 20, 20, "hlayout"); + hlayout->setMenuBar( m ); + hlayout->addLayout( vlayout ); + hlayout->addWidget( f, 1 ); +} diff --git a/examples/opengl/box/globjwin.h b/examples/opengl/box/globjwin.h new file mode 100644 index 0000000..68fa233 --- /dev/null +++ b/examples/opengl/box/globjwin.h @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ + +/**************************************************************************** +** +** The GLObjectWindow contains a GLBox and three sliders connected to +** the GLBox's rotation slots. +** +****************************************************************************/ + +#ifndef GLOBJWIN_H +#define GLOBJWIN_H + +#include <qwidget.h> + + +class GLObjectWindow : public QWidget +{ + Q_OBJECT +public: + GLObjectWindow( QWidget* parent = 0, const char* name = 0 ); + +}; + + +#endif // GLOBJWIN_H diff --git a/examples/opengl/box/main.cpp b/examples/opengl/box/main.cpp new file mode 100644 index 0000000..897cd3f --- /dev/null +++ b/examples/opengl/box/main.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ +// +// Qt OpenGL example: Box +// +// A small example showing how a GLWidget can be used just as any Qt widget +// +// File: main.cpp +// +// The main() function +// + +#include "globjwin.h" +#include <qapplication.h> +#include <qgl.h> + +/* + The main program is here. +*/ + +int main( int argc, char **argv ) +{ + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication a(argc,argv); + + if ( !QGLFormat::hasOpenGL() ) { + qWarning( "This system has no OpenGL support. Exiting." ); + return -1; + } + + GLObjectWindow w; + w.resize( 400, 350 ); + a.setMainWidget( &w ); + w.show(); + return a.exec(); +} diff --git a/examples/opengl/gear/README b/examples/opengl/gear/README new file mode 100644 index 0000000..15f55e7 --- /dev/null +++ b/examples/opengl/gear/README @@ -0,0 +1,4 @@ + +The gear example + +This example program demonstrates how to use OpenGL display lists. diff --git a/examples/opengl/gear/gear.cpp b/examples/opengl/gear/gear.cpp new file mode 100644 index 0000000..8f138e9 --- /dev/null +++ b/examples/opengl/gear/gear.cpp @@ -0,0 +1,296 @@ +/**************************************************************************** +** +** 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 <qgl.h> +#include <qapplication.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(); + +} + + +static GLfloat view_rotx=20.0, view_roty=30.0, view_rotz=0.0; +static GLint gear1, gear2, gear3; +static GLfloat angle = 0.0; + + +static void draw() +{ + angle += 2.0; + view_roty += 1.0; + + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + 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(); +} + + +static int timer_interval = 10; // timer interval (millisec) + + +class GearWidget : public QGLWidget +{ +public: + GearWidget( QWidget *parent=0, const char *name=0 ); +protected: + void initializeGL(); + void resizeGL( int, int ); + void paintGL(); + void timerEvent( QTimerEvent * ); +}; + +GearWidget::GearWidget( QWidget *parent, const char *name ) + : QGLWidget( parent, name ) +{ + startTimer( timer_interval ); +} + +void GearWidget::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 GearWidget::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 GearWidget::paintGL() +{ + draw(); +} + +void GearWidget::timerEvent(QTimerEvent*) +{ + updateGL(); +} + + + +int main( int argc, char **argv ) +{ + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication a( argc, argv ); + + if ( !QGLFormat::hasOpenGL() ) { + qWarning( "This system has no OpenGL support. Exiting." ); + return -1; + } + + if ( argc >= 2 ) { + bool ok = TRUE; + timer_interval = QString::fromLatin1( argv[1] ).toInt( &ok ); + if ( !ok ) + timer_interval = 10; + } + + GearWidget w; + a.setMainWidget( &w ); + w.show(); + return a.exec(); +} diff --git a/examples/opengl/gear/gear.doc b/examples/opengl/gear/gear.doc new file mode 100644 index 0000000..2fe049a --- /dev/null +++ b/examples/opengl/gear/gear.doc @@ -0,0 +1,11 @@ +/*! \page opengl-gear-example.html + + \ingroup opengl-examples + \title OpenGL Gear Example + + +This example demonstrates how to use OpenGL display lists. + +See \c{$QTDIR/examples/opengl/gear} for the source code. + +*/ diff --git a/examples/opengl/gear/gear.pro b/examples/opengl/gear/gear.pro new file mode 100644 index 0000000..b91691c --- /dev/null +++ b/examples/opengl/gear/gear.pro @@ -0,0 +1,12 @@ +TEMPLATE = app +TARGET = gear + +CONFIG += qt opengl warn_on release +CONFIG -= dlopen_opengl +!mac:unix:LIBS += -lm +DEPENDPATH = ../include + +REQUIRES = opengl + +HEADERS = +SOURCES = gear.cpp diff --git a/examples/opengl/glpixmap/README b/examples/opengl/glpixmap/README new file mode 100644 index 0000000..b01cfaf --- /dev/null +++ b/examples/opengl/glpixmap/README @@ -0,0 +1,8 @@ + +The OpenGL pixmap example + +This example program is an extension of the "box" example program. + +It demonstrates how to render OpenGL into a QPixmap. + + diff --git a/examples/opengl/glpixmap/glbox.cpp b/examples/opengl/glpixmap/glbox.cpp new file mode 100644 index 0000000..604267a --- /dev/null +++ b/examples/opengl/glpixmap/glbox.cpp @@ -0,0 +1,256 @@ +/**************************************************************************** +** +** 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 a box +** +** The OpenGL code is mostly borrowed from Brian Pauls "spin" example +** in the Mesa distribution +** +****************************************************************************/ + +#include <math.h> + +#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, const QGLWidget* shareWidget ) + : QGLWidget( parent, name, shareWidget ) +{ + xRot = yRot = zRot = 0.0; // default object rotation + scale = 1.5; // default object scale +} + + +/*! + Create a GLBox widget +*/ + +GLBox::GLBox( const QGLFormat& format, QWidget* parent, const char* name, + const QGLWidget* shareWidget ) + : QGLWidget( format, parent, name, shareWidget ) +{ + xRot = yRot = zRot = 0.0; // default object rotation + scale = 1.5; // default object scale +} + + +/*! + Release allocated resources +*/ + +GLBox::~GLBox() +{ +} + + +/*! + Set up the OpenGL rendering state, and define display list +*/ + +void GLBox::initializeGL() +{ + qglClearColor( green ); // Let OpenGL clear to green + object = makeObject(); // Make display list + glEnable( GL_DEPTH_TEST ); +} + + +/*! + 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, 1.0, 200.0); +} + + +/*! + Paint the box. The actual openGL commands for drawing the box are + performed here. +*/ + +void GLBox::paintGL() +{ + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + glTranslatef( 0.0, 0.0, -3.0 ); + 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 ); + + glCallList( object ); +} + + + + + + +/*! + 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 ); + + GLint i, j, rings, sides; + float theta1, phi1, theta2, phi2; + float v0[03], v1[3], v2[3], v3[3]; + float t0[03], t1[3], t2[3], t3[3]; + float n0[3], n1[3], n2[3], n3[3]; + float innerRadius=0.4; + float outerRadius=0.8; + float scalFac; + double pi = 3.14159265358979323846; + + rings = 8; + sides = 10; + scalFac=1/(outerRadius*2); + + for (i = 0; i < rings; i++) { + theta1 = (float)i * 2.0 * pi / rings; + theta2 = (float)(i + 1) * 2.0 * pi / rings; + for (j = 0; j < sides; j++) { + phi1 = (float)j * 2.0 * pi / sides; + phi2 = (float)(j + 1) * 2.0 * pi / sides; + + v0[0] = cos(theta1) * (outerRadius + innerRadius * cos(phi1)); + v0[1] = -sin(theta1) * (outerRadius + innerRadius * cos(phi1)); + v0[2] = innerRadius * sin(phi1); + + v1[0] = cos(theta2) * (outerRadius + innerRadius * cos(phi1)); + v1[1] = -sin(theta2) * (outerRadius + innerRadius * cos(phi1)); + v1[2] = innerRadius * sin(phi1); + v2[0] = cos(theta2) * (outerRadius + innerRadius * cos(phi2)); + v2[1] = -sin(theta2) * (outerRadius + innerRadius * cos(phi2)); + v2[2] = innerRadius * sin(phi2); + + v3[0] = cos(theta1) * (outerRadius + innerRadius * cos(phi2)); + v3[1] = -sin(theta1) * (outerRadius + innerRadius * cos(phi2)); + v3[2] = innerRadius * sin(phi2); + + n0[0] = cos(theta1) * (cos(phi1)); + n0[1] = -sin(theta1) * (cos(phi1)); + n0[2] = sin(phi1); + + n1[0] = cos(theta2) * (cos(phi1)); + n1[1] = -sin(theta2) * (cos(phi1)); + n1[2] = sin(phi1); + + n2[0] = cos(theta2) * (cos(phi2)); + n2[1] = -sin(theta2) * (cos(phi2)); + n2[2] = sin(phi2); + + n3[0] = cos(theta1) * (cos(phi2)); + n3[1] = -sin(theta1) * (cos(phi2)); + n3[2] = sin(phi2); + + t0[0] = v0[0]*scalFac + 0.5; + t0[1] = v0[1]*scalFac + 0.5; + t0[2] = v0[2]*scalFac + 0.5; + + t1[0] = v1[0]*scalFac + 0.5; + t1[1] = v1[1]*scalFac + 0.5; + t1[2] = v1[2]*scalFac + 0.5; + + t2[0] = v2[0]*scalFac + 0.5; + t2[1] = v2[1]*scalFac + 0.5; + t2[2] = v2[2]*scalFac + 0.5; + + t3[0] = v3[0]*scalFac + 0.5; + t3[1] = v3[1]*scalFac + 0.5; + t3[2] = v3[2]*scalFac + 0.5; + + // Create blue-black checkered coloring + if ( (i+j) % 2 ) + qglColor( black ); + else + qglColor( QColor( "steelblue" ) ); + + glBegin(GL_POLYGON); + glNormal3fv(n3); glTexCoord3fv(t3); glVertex3fv(v3); + glNormal3fv(n2); glTexCoord3fv(t2); glVertex3fv(v2); + glNormal3fv(n1); glTexCoord3fv(t1); glVertex3fv(v1); + glNormal3fv(n0); glTexCoord3fv(t0); glVertex3fv(v0); + glEnd(); + } + } + glEndList(); + + return list; +} + + +/*! + Set the rotation angle of the object to \e degrees around the X axis. +*/ + +void GLBox::setXRotation( int degrees ) +{ + xRot = (GLfloat)(degrees % 360); + updateGL(); +} + + +/*! + Set the rotation angle of the object to \e degrees around the Y axis. +*/ + +void GLBox::setYRotation( int degrees ) +{ + yRot = (GLfloat)(degrees % 360); + updateGL(); +} + + +/*! + Set the rotation angle of the object to \e degrees around the Z axis. +*/ + +void GLBox::setZRotation( int degrees ) +{ + zRot = (GLfloat)(degrees % 360); + updateGL(); +} + + + + +/*! + Sets the rotation angles of this object to that of \a fromBox +*/ + +void GLBox::copyRotation( const GLBox& fromBox ) +{ + xRot = fromBox.xRot; + yRot = fromBox.yRot; + zRot = fromBox.zRot; +} diff --git a/examples/opengl/glpixmap/glbox.h b/examples/opengl/glpixmap/glbox.h new file mode 100644 index 0000000..d6a78ad --- /dev/null +++ b/examples/opengl/glpixmap/glbox.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** 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 a box +** +****************************************************************************/ + +#ifndef GLBOX_H +#define GLBOX_H + +#include <qgl.h> + + +class GLBox : public QGLWidget +{ + Q_OBJECT + +public: + + GLBox( QWidget* parent, const char* name, const QGLWidget* shareWidget=0 ); + GLBox( const QGLFormat& format, QWidget* parent, const char* name, + const QGLWidget* shareWidget=0 ); + ~GLBox(); + + void copyRotation( const GLBox& fromBox ); + +public slots: + + void setXRotation( int degrees ); + void setYRotation( int degrees ); + void setZRotation( int degrees ); + +protected: + + void initializeGL(); + void paintGL(); + void resizeGL( int w, int h ); + + virtual GLuint makeObject(); + +private: + + GLuint object; + + GLfloat xRot, yRot, zRot, scale; + +}; + + +#endif // GLBOX_H diff --git a/examples/opengl/glpixmap/globjwin.cpp b/examples/opengl/glpixmap/globjwin.cpp new file mode 100644 index 0000000..1b3269b --- /dev/null +++ b/examples/opengl/glpixmap/globjwin.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ + +/**************************************************************************** +** +** Implementation of GLObjectWindow widget class +** +****************************************************************************/ + + +#include <qpushbutton.h> +#include <qslider.h> +#include <qlayout.h> +#include <qframe.h> +#include <qlabel.h> +#include <qmenubar.h> +#include <qpopupmenu.h> +#include <qapplication.h> +#include <qkeycode.h> +#include <qpixmap.h> +#include <qimage.h> +#include <qpainter.h> +#include "globjwin.h" +#include "glbox.h" + + +GLObjectWindow::GLObjectWindow( QWidget* parent, const char* name ) + : QWidget( parent, name ) +{ + // Create a menu + file = new QPopupMenu( this ); + file->setCheckable( TRUE ); + file->insertItem( "Grab Frame Buffer", this, SLOT(grabFrameBuffer()) ); + file->insertItem( "Render Pixmap", this, SLOT(makePixmap()) ); + file->insertItem( "Render Pixmap Hidden", this, SLOT(makePixmapHidden()) ); + file->insertSeparator(); + fixMenuItemId = file->insertItem( "Use Fixed Pixmap Size", this, + SLOT(useFixedPixmapSize()) ); + file->insertSeparator(); + insertMenuItemId = file->insertItem( "Insert Pixmap Here", this, + SLOT(makePixmapForMenu()) ); + file->insertSeparator(); + file->insertItem( "Exit", qApp, SLOT(quit()), CTRL+Key_Q ); + + // Create a menu bar + QMenuBar *m = new QMenuBar( this ); + m->setSeparator( QMenuBar::InWindowsStyle ); + m->insertItem("&File", file ); + + // Create nice frames to put around the OpenGL widgets + QFrame* f1 = new QFrame( this, "frame1" ); + f1->setFrameStyle( QFrame::Sunken | QFrame::Panel ); + f1->setLineWidth( 2 ); + + // Create an OpenGL widget + c1 = new GLBox( f1, "glbox1"); + + // Create a label that can display the pixmap + lb = new QLabel( this, "pixlabel" ); + lb->setFrameStyle( QFrame::Sunken | QFrame::Panel ); + lb->setLineWidth( 2 ); + lb->setAlignment( AlignCenter ); + lb->setMargin( 0 ); + lb->setIndent( 0 ); + + // Create the three sliders; one for each rotation axis + QSlider* x = new QSlider ( 0, 360, 60, 0, QSlider::Vertical, this, "xsl" ); + x->setTickmarks( QSlider::Left ); + connect( x, SIGNAL(valueChanged(int)), c1, SLOT(setXRotation(int)) ); + + QSlider* y = new QSlider ( 0, 360, 60, 0, QSlider::Vertical, this, "ysl" ); + y->setTickmarks( QSlider::Left ); + connect( y, SIGNAL(valueChanged(int)), c1, SLOT(setYRotation(int)) ); + + QSlider* z = new QSlider ( 0, 360, 60, 0, QSlider::Vertical, this, "zsl" ); + z->setTickmarks( QSlider::Left ); + connect( z, SIGNAL(valueChanged(int)), c1, SLOT(setZRotation(int)) ); + + + // Now that we have all the widgets, put them into a nice layout + + // Put the sliders on top of each other + QVBoxLayout* vlayout = new QVBoxLayout( 20, "vlayout"); + vlayout->addWidget( x ); + vlayout->addWidget( y ); + vlayout->addWidget( z ); + + // Put the GL widget inside the frame + QHBoxLayout* flayout1 = new QHBoxLayout( f1, 2, 2, "flayout1"); + flayout1->addWidget( c1, 1 ); + + // Top level layout, puts the sliders to the left of the frame/GL widget + QHBoxLayout* hlayout = new QHBoxLayout( this, 20, 20, "hlayout"); + hlayout->setMenuBar( m ); + hlayout->addLayout( vlayout ); + hlayout->addWidget( f1, 1 ); + hlayout->addWidget( lb, 1 ); + +} + + + +void GLObjectWindow::grabFrameBuffer() +{ + QImage img = c1->grabFrameBuffer(); + + // Convert image to pixmap so we can show it + QPixmap pm; + pm.convertFromImage( img, AvoidDither ); + drawOnPixmap( &pm ); + lb->setPixmap( pm ); +} + + + +void GLObjectWindow::makePixmap() +{ + // Make a pixmap to to be rendered by the gl widget + QPixmap pm; + + // Render the pixmap, with either c1's size or the fixed size pmSz + if ( pmSz.isValid() ) + pm = c1->renderPixmap( pmSz.width(), pmSz.height() ); + else + pm = c1->renderPixmap(); + + if ( !pm.isNull() ) { + // Present the pixmap to the user + drawOnPixmap( &pm ); + lb->setPixmap( pm ); + } + else { + lb->setText( "Failed to render Pixmap." ); + } +} + + +void GLObjectWindow::makePixmapHidden() +{ + // Make a QGLWidget to draw the pixmap. This widget will not be shown. + GLBox* w = new GLBox( this, "temporary glwidget", c1 ); + + bool success = FALSE; + QPixmap pm; + + if ( w->isValid() ) { + // Set the current rotation + w->copyRotation( *c1 ); + + // Determine wanted pixmap size + QSize sz = pmSz.isValid() ? pmSz : c1->size(); + + // Make our hidden glwidget render the pixmap + pm = w->renderPixmap( sz.width(), sz.height() ); + + if ( !pm.isNull() ) + success = TRUE; + } + + if ( success ) { + // Present the pixmap to the user + drawOnPixmap( &pm ); + lb->setPixmap( pm ); + } + else { + lb->setText( "Failed to render Pixmap." ); + } + delete w; +} + + +void GLObjectWindow::drawOnPixmap( QPixmap* pm ) +{ + // Draw some text on the pixmap to differentiate it from the GL window + + if ( pm->isNull() ) { + qWarning("Cannot draw on null pixmap"); + return; + } + else { + QPainter p( pm ); + p.setFont( QFont( "Helvetica", 18 ) ); + p.setPen( white ); + p.drawText( pm->rect(), AlignCenter, "This is a Pixmap" ); + } +} + + + +void GLObjectWindow::useFixedPixmapSize() +{ + if ( pmSz.isValid() ) { + pmSz = QSize(); + file->setItemChecked( fixMenuItemId, FALSE ); + } + else { + pmSz = QSize( 200, 200 ); + file->setItemChecked( fixMenuItemId, TRUE ); + } +} + + +void GLObjectWindow::makePixmapForMenu() +{ + QPixmap pm = c1->renderPixmap( 32, 32 ); + if ( !pm.isNull() ) + file->changeItem( pm, "Insert Pixmap Here", insertMenuItemId ); +} diff --git a/examples/opengl/glpixmap/globjwin.h b/examples/opengl/glpixmap/globjwin.h new file mode 100644 index 0000000..b629369 --- /dev/null +++ b/examples/opengl/glpixmap/globjwin.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ + +/**************************************************************************** +** +** The GLObjectWindow contains a GLBox and three sliders connected to +** the GLBox's rotation slots. +** +****************************************************************************/ + +#ifndef GLOBJWIN_H +#define GLOBJWIN_H + +#include <qwidget.h> + +class GLBox; +class QLabel; +class QPopupMenu; + +class GLObjectWindow : public QWidget +{ + Q_OBJECT +public: + GLObjectWindow( QWidget* parent = 0, const char* name = 0 ); + +protected slots: + + void grabFrameBuffer(); + void makePixmap(); + void makePixmapHidden(); + void makePixmapForMenu(); + void useFixedPixmapSize(); + +private: + void drawOnPixmap( QPixmap* pm ); + GLBox* c1; + QLabel* lb; + int fixMenuItemId; + int insertMenuItemId; + QSize pmSz; + QPopupMenu* file; +}; + + +#endif // GLOBJWIN_H diff --git a/examples/opengl/glpixmap/glpixmap.doc b/examples/opengl/glpixmap/glpixmap.doc new file mode 100644 index 0000000..8406076 --- /dev/null +++ b/examples/opengl/glpixmap/glpixmap.doc @@ -0,0 +1,14 @@ +/*! \page opengl-pixmap-example.html + + \ingroup opengl-examples + \title OpenGL Pixmap Example + +This example program is an extension of the \link +opengl-box-example.html OpenGL Box example\endlink. + +It demonstrates how to render OpenGL into a QPixmap. + +See \c{$QTDIR/examples/opengl/glpixmap} for the source code. + +*/ + diff --git a/examples/opengl/glpixmap/glpixmap.pro b/examples/opengl/glpixmap/glpixmap.pro new file mode 100644 index 0000000..597f94c --- /dev/null +++ b/examples/opengl/glpixmap/glpixmap.pro @@ -0,0 +1,15 @@ +TEMPLATE = app +TARGET = glpixmap + +CONFIG += qt opengl warn_on release +CONFIG -= dlopen_opengl +!mac:unix:LIBS += -lm +DEPENDPATH = ../include + +REQUIRES = opengl + +HEADERS = glbox.h \ + globjwin.h +SOURCES = glbox.cpp \ + globjwin.cpp \ + main.cpp diff --git a/examples/opengl/glpixmap/main.cpp b/examples/opengl/glpixmap/main.cpp new file mode 100644 index 0000000..25ee5b4 --- /dev/null +++ b/examples/opengl/glpixmap/main.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ +// +// Qt OpenGL example: Shared Box +// +// A small example showing how to use OpenGL display list sharing +// +// File: main.cpp +// +// The main() function +// + +#include "globjwin.h" +#include <qapplication.h> +#include <qgl.h> + +/* + The main program is here. +*/ + +int main( int argc, char **argv ) +{ + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication a(argc,argv); + + if ( !QGLFormat::hasOpenGL() ) { + qWarning( "This system has no OpenGL support. Exiting." ); + return -1; + } + + GLObjectWindow w; + w.resize( 550, 350 ); + a.setMainWidget( &w ); + w.show(); + return a.exec(); +} diff --git a/examples/opengl/overlay/README b/examples/opengl/overlay/README new file mode 100644 index 0000000..f08e539 --- /dev/null +++ b/examples/opengl/overlay/README @@ -0,0 +1,9 @@ + +The overlay example + +This example program shows how to use OpenGL overlays with the Qt OpenGL +Extension. It contains a QGLWidget with a relatively expensive +redrawing operation, and rubber-band drawing in the overlay plane. +Using the overlay has the advantage that the rubber-band may be drawn +and erased without damaging the image in the main plane, so costly +redraws are avoided. diff --git a/examples/opengl/overlay/globjwin.cpp b/examples/opengl/overlay/globjwin.cpp new file mode 100644 index 0000000..8879b8d --- /dev/null +++ b/examples/opengl/overlay/globjwin.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ + +#include <qlayout.h> +#include <qframe.h> +#include <qmenubar.h> +#include <qpopupmenu.h> +#include <qapplication.h> +#include <qmessagebox.h> +#include "globjwin.h" +#include "glteapots.h" + + +GLObjectWindow::GLObjectWindow( QWidget* parent, const char* name ) + : QWidget( parent, name ) +{ + // Create a menu + QPopupMenu *file = new QPopupMenu( this ); + file->insertItem( "Exit", qApp, SLOT(quit()), CTRL+Key_Q ); + + // Create a menu bar + QMenuBar *m = new QMenuBar( this ); + m->setSeparator( QMenuBar::InWindowsStyle ); + m->insertItem("&File", file ); + + // Create a nice frame to put around the OpenGL widget + QFrame* f = new QFrame( this, "frame" ); + f->setFrameStyle( QFrame::Sunken | QFrame::Panel ); + f->setLineWidth( 2 ); + + // Create our OpenGL widget. + GLTeapots* c = new GLTeapots( f, "glteapots" ); + + // Check if we obtained an overlay + if ( !c->format().hasOverlay() ) { + QMessageBox::warning( 0, qApp->argv()[0], + "Failed to get an OpenGL overlay", + "OK" ); + } + + // Now that we have all the widgets, put them into a nice layout + + // Put the GL widget inside the frame + QHBoxLayout* flayout = new QHBoxLayout( f, 2, 2, "flayout"); + flayout->addWidget( c, 1 ); + + // Top level layout + QVBoxLayout* hlayout = new QVBoxLayout( this, 20, 20, "hlayout"); + hlayout->setMenuBar( m ); + hlayout->addWidget( f, 1 ); +} diff --git a/examples/opengl/overlay/globjwin.h b/examples/opengl/overlay/globjwin.h new file mode 100644 index 0000000..46de98e --- /dev/null +++ b/examples/opengl/overlay/globjwin.h @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ + +/**************************************************************************** +** +** The GLObjectWindow contains a GLBox and three sliders connected to +** the GLBox's rotation slots. +** +****************************************************************************/ + +#ifndef GLOBJWIN_H +#define GLOBJWIN_H + +#include <qwidget.h> + + +class GLObjectWindow : public QWidget +{ + Q_OBJECT +public: + GLObjectWindow( QWidget* parent = 0, const char* name = 0 ); + + +}; + + +#endif // GLOBJWIN_H diff --git a/examples/opengl/overlay/glteapots.cpp b/examples/opengl/overlay/glteapots.cpp new file mode 100644 index 0000000..f3aaec1 --- /dev/null +++ b/examples/opengl/overlay/glteapots.cpp @@ -0,0 +1,457 @@ +/**************************************************************************** +** +** Implementation of GLTeapots +** This is a QGLWidget displaying a group of teapots and a rubber-band +** in an overlay plane +** +** The OpenGL code in this example is mostly borrowed from the "teapots" +** example program in the "OpenGL Programming Guide", by Jackie Neider, +** Tom Davis, and Mason Woo, Addison Wesley 1993. +** It can be obtained from ftp.sgi.com and contains the following copyright +** notice: + + * (c) Copyright 1993, Silicon Graphics, Inc. + * ALL RIGHTS RESERVED + * Permission to use, copy, modify, and distribute this software for + * any purpose and without fee is hereby granted, provided that the above + * copyright notice appear in all copies and that both the copyright notice + * and this permission notice appear in supporting documentation, and that + * the name of Silicon Graphics, Inc. not be used in advertising + * or publicity pertaining to distribution of the software without specific, + * written prior permission. + * + * THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" + * AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR + * FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON + * GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, + * SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY + * KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, + * LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF + * THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN + * ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE + * POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + * + * US Government Users Restricted Rights + * Use, duplication, or disclosure by the Government is subject to + * restrictions set forth in FAR 52.227.19(c)(2) or subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 252.227-7013 and/or in similar or successor + * clauses in the FAR or the DOD or NASA FAR Supplement. + * Unpublished-- rights reserved under the copyright laws of the + * United States. Contractor/manufacturer is Silicon Graphics, + * Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + * + * OpenGL(TM) is a trademark of Silicon Graphics, Inc. + +****************************************************************************/ + +#include "glteapots.h" +#include <qapplication.h> + +#if defined(Q_CC_MSVC) +#pragma warning(disable:4305) // init: truncation from const double to float +#endif + +/*! + Create a GLTeapots widget. + + Specifies the following frame buffer requirements to the QGLWidget + constructor: + <ul> + <li> HasOverlay - we want an overlay context to draw the rubber-band in + <li> SingleBuffer - makes the drawing process of the teapots visible + </ul> +*/ + + +GLTeapots::GLTeapots( QWidget* parent, const char* name ) + : QGLWidget( QGLFormat( QGL::SingleBuffer | QGL::HasOverlay ), + parent, name ) +{ + teapotList = 0; + rubberOn = FALSE; +} + +/*! + Release allocated resources +*/ + +GLTeapots::~GLTeapots() +{ + makeCurrent(); + glDeleteLists( teapotList, 1 ); +} + + +/*! + Do the main plane painting: a set of teapots. +*/ + +void GLTeapots::paintGL() +{ + QApplication::setOverrideCursor( waitCursor ); // Since it takes some time + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + renderTeapot( 2.0, 17.0, 0.0215, 0.1745, 0.0215, + 0.07568, 0.61424, 0.07568, + 0.633, 0.727811, 0.633, 0.6 ); + renderTeapot( 2.0, 14.0, 0.135, 0.2225, 0.1575, + 0.54, 0.89, 0.63, 0.316228, + 0.316228, 0.316228, 0.1 ); + renderTeapot( 2.0, 11.0, 0.05375, 0.05, 0.06625, + 0.18275, 0.17, 0.22525, + 0.332741, 0.328634, 0.346435, 0.3 ); + renderTeapot( 2.0, 8.0, 0.25, 0.20725, 0.20725, + 1, 0.829, 0.829, 0.296648, + 0.296648, 0.296648, 0.088 ); + renderTeapot( 2.0, 5.0, 0.1745, 0.01175, 0.01175, + 0.61424, 0.04136, 0.04136, + 0.727811, 0.626959, 0.626959, 0.6); + renderTeapot( 2.0, 2.0, 0.1, 0.18725, 0.1745, + 0.396, 0.74151, 0.69102, + 0.297254, 0.30829, 0.306678, 0.1 ); + + renderTeapot( 6.0, 17.0, 0.329412, 0.223529, 0.027451, + 0.780392, 0.568627, 0.113725, + 0.992157, 0.941176, 0.807843, 0.21794872 ); + renderTeapot( 6.0, 14.0, 0.2125, 0.1275, 0.054, + 0.714, 0.4284, 0.18144, + 0.393548, 0.271906, 0.166721, 0.2 ); + renderTeapot( 6.0, 11.0, 0.25, 0.25, 0.25, + 0.4, 0.4, 0.4, + 0.774597, 0.774597, 0.774597, 0.6 ); + renderTeapot( 6.0, 8.0, 0.19125, 0.0735, 0.0225, + 0.7038, 0.27048, 0.0828, + 0.256777, 0.137622, 0.086014, 0.1 ); + renderTeapot( 6.0, 5.0, 0.24725, 0.1995, 0.0745, + 0.75164, 0.60648, 0.22648, + 0.628281, 0.555802, 0.366065, 0.4 ); + renderTeapot( 6.0, 2.0, 0.19225, 0.19225, 0.19225, + 0.50754, 0.50754, 0.50754, + 0.508273, 0.508273, 0.508273, 0.4 ); + + renderTeapot( 10.0, 17.0, 0.0, 0.0, 0.0, + 0.01, 0.01, 0.01, + 0.50, 0.50, 0.50, .25 ); + renderTeapot( 10.0, 14.0, 0.0, 0.1, 0.06, + 0.0, 0.50980392, 0.50980392, + 0.50196078, 0.50196078, 0.50196078, .25 ); + renderTeapot( 10.0, 11.0, 0.0, 0.0, 0.0, + 0.1, 0.35, 0.1, + 0.45, 0.55, 0.45, .25 ); + renderTeapot( 10.0, 8.0, 0.0, 0.0, 0.0, + 0.5, 0.0, 0.0, + 0.7, 0.6, 0.6, .25 ); + renderTeapot( 10.0, 5.0, 0.0, 0.0, 0.0, + 0.55, 0.55, 0.55, + 0.70, 0.70, 0.70, .25 ); + renderTeapot( 10.0, 2.0, 0.0, 0.0, 0.0, + 0.5, 0.5, 0.0, + 0.60, 0.60, 0.50, .25 ); + + renderTeapot( 14.0, 17.0, 0.02, 0.02, 0.02, + 0.01, 0.01, 0.01, + 0.4, 0.4, 0.4, .078125 ); + renderTeapot( 14.0, 14.0, 0.0, 0.05, 0.05, + 0.4, 0.5, 0.5, + 0.04, 0.7, 0.7, .078125 ); + renderTeapot( 14.0, 11.0, 0.0, 0.05, 0.0, + 0.4, 0.5, 0.4, + 0.04, 0.7, 0.04, .078125 ); + renderTeapot( 14.0, 8.0, 0.05, 0.0, 0.0, + 0.5, 0.4, 0.4, + 0.7, 0.04, 0.04, .078125 ); + renderTeapot( 14.0, 5.0, 0.05, 0.05, 0.05, + 0.5, 0.5, 0.5, + 0.7, 0.7, 0.7, .078125 ); + renderTeapot( 14.0, 2.0, 0.05, 0.05, 0.0, + 0.5, 0.5, 0.4, + 0.7, 0.7, 0.04, .078125 ); + + // May add a glFinish() here to make sure the GL rendering has finished + // before the mouse cursor is reset from "waiting" to normal. + QApplication::restoreOverrideCursor(); +} + + +/*! + Set up the OpenGL rendering state of the main plane +*/ + +void GLTeapots::initializeGL() +{ + GLfloat ambient[] = { 0.0, 0.0, 0.0, 1.0 }; + GLfloat diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; + GLfloat position[] = { 0.0, 3.0, 3.0, 0.0 }; + + GLfloat lmodel_ambient[] = { 0.2, 0.2, 0.2, 1.0 }; + GLfloat local_view[] = { 0.0 }; + + glLightfv( GL_LIGHT0, GL_AMBIENT, ambient ); + glLightfv( GL_LIGHT0, GL_DIFFUSE, diffuse ); + glLightfv( GL_LIGHT0, GL_POSITION, position ); + glLightModelfv( GL_LIGHT_MODEL_AMBIENT, lmodel_ambient ); + glLightModelfv( GL_LIGHT_MODEL_LOCAL_VIEWER, local_view ); + + glFrontFace( GL_CW ); + glEnable( GL_LIGHTING ); + glEnable( GL_LIGHT0 ); + glEnable( GL_AUTO_NORMAL ); + glEnable( GL_NORMALIZE ); + glEnable( GL_DEPTH_TEST ); + glDepthFunc( GL_LESS ); +} + + + +/*! + Set up the main plane's view port, matrix mode, etc. suitably for + viewing the teapots. +*/ + +void GLTeapots::resizeGL( int w, int h ) +{ + glViewport(0, 0, w, h); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + if ( w <= h ) + glOrtho( 0.0, 20.0, 0.0, 20.0*(GLfloat)h/(GLfloat)w, -10.0, 10.0 ); + else + glOrtho( 0.0, 20.0*(GLfloat)w/(GLfloat)h, 0.0, 20.0, -10.0, 10.0 ); + glMatrixMode(GL_MODELVIEW); +} + + +/*! + Set up the OpenGL rendering state of the overlay plane +*/ + +void GLTeapots::initializeOverlayGL() +{ + glLineWidth( 2 ); + glLineStipple( 3, 0xAAAA ); + glEnable( GL_LINE_STIPPLE ); +} + + +/*! + Do the overlay plane painting: a rubber-band (if the user has + dragged out one). + +*/ + +void GLTeapots::paintOverlayGL() +{ + glClear( GL_COLOR_BUFFER_BIT ); + if ( rubberOn ) { + qglColor( QColor( 255, 255, 0 ) ); + glBegin( GL_LINE_LOOP ); + glVertex2i( rubberP1.x(), rubberP1.y() ); + glVertex2i( rubberP2.x(), rubberP1.y() ); + glVertex2i( rubberP2.x(), rubberP2.y() ); + glVertex2i( rubberP1.x(), rubberP2.y() ); + glEnd(); + } +} + + +/*! + Set up the overlay plane's view port, matrix mode, etc. suitably for + viewing the rubber-band. +*/ + +void GLTeapots::resizeOverlayGL( int w, int h ) +{ + glViewport( 0, 0, w, h ); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluOrtho2D( 0, w, h, 0 ); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); +} + + +/*! + User presses a mouse button: start pulling out a rubber-band rectangle +*/ + +// We do a simple rubber-band drawing here; erasing the whole overlay +// plane for each repaint. For less flickering of the rubber-band +// itself, we could remember the coordinates of the last rectangle +// drawn, and then erase only that by painting it again with +// transparent color. + +void GLTeapots::mousePressEvent( QMouseEvent* e ) +{ + rubberP1 = e->pos(); + rubberP2 = rubberP1; + rubberOn = TRUE; +} + +/*! + User drags the mouse: Update the rubber-band coordinates and repaint + the overlay. +*/ + +void GLTeapots::mouseMoveEvent( QMouseEvent* e ) +{ + if ( rubberOn ) { + rubberP2 = e->pos(); + updateOverlayGL(); + } +} + +/*! + User releases the mouse button: remove the rubber-band. +*/ + +void GLTeapots::mouseReleaseEvent( QMouseEvent* ) +{ + if ( rubberOn ) { + rubberOn = FALSE; + updateOverlayGL(); + } +} + + +/*! + Renders a teapot with the given material properties +*/ + +void GLTeapots::renderTeapot( GLfloat x, GLfloat y, GLfloat ambr, + GLfloat ambg, GLfloat ambb, GLfloat difr, + GLfloat difg, GLfloat difb, + GLfloat specr, GLfloat specg, + GLfloat specb, GLfloat shine ) +{ + float mat[4]; + + glPushMatrix(); + glTranslatef (x, y, 0.0); + mat[0] = ambr; mat[1] = ambg; mat[2] = ambb; mat[3] = 1.0; + glMaterialfv (GL_FRONT, GL_AMBIENT, mat); + mat[0] = difr; mat[1] = difg; mat[2] = difb; + glMaterialfv (GL_FRONT, GL_DIFFUSE, mat); + mat[0] = specr; mat[1] = specg; mat[2] = specb; + glMaterialfv (GL_FRONT, GL_SPECULAR, mat); + glMaterialf (GL_FRONT, GL_SHININESS, shine*128.0); + teapot(); + glPopMatrix(); +} + + +/*! + Draw a classic OpenGL teapot +*/ + +void GLTeapots::teapot() +{ + static long patchdata[][16] = { + {102,103,104,105,4,5,6,7,8,9,10,11,12,13,14,15}, + {12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27}, + {24,25,26,27,29,30,31,32,33,34,35,36,37,38,39,40}, + {96,96,96,96,97,98,99,100,101,101,101,101,0,1,2,3,}, + {0,1,2,3,106,107,108,109,110,111,112,113,114,115,116,117}, + {118,118,118,118,124,122,119,121,123,126,125,120,40,39,38,37}, + {41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56}, + {53,54,55,56,57,58,59,60,61,62,63,64,28,65,66,67}, + {68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83}, + {80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95} + }; + + static float cpdata[][3] = { + {0.2,0,2.7},{0.2,-0.112,2.7},{0.112,-0.2,2.7},{0,-0.2,2.7}, + {1.3375,0,2.53125},{1.3375,-0.749,2.53125},{0.749,-1.3375,2.53125}, + {0,-1.3375,2.53125},{1.4375,0,2.53125},{1.4375,-0.805,2.53125}, + {0.805,-1.4375,2.53125},{0,-1.4375,2.53125},{1.5,0,2.4}, + {1.5,-0.84,2.4},{0.84,-1.5,2.4},{0,-1.5,2.4},{1.75,0,1.875}, + {1.75,-0.98,1.875},{0.98,-1.75,1.875},{0,-1.75,1.875},{2,0,1.35}, + {2,-1.12,1.35},{1.12,-2,1.35},{0,-2,1.35},{2,0,0.9},{2,-1.12,0.9}, + {1.12,-2,0.9},{0,-2,0.9},{-2,0,0.9},{2,0,0.45},{2,-1.12,0.45}, + {1.12,-2,0.45},{0,-2,0.45},{1.5,0,0.225},{1.5,-0.84,0.225}, + {0.84,-1.5,0.225},{0,-1.5,0.225},{1.5,0,0.15},{1.5,-0.84,0.15}, + {0.84,-1.5,0.15},{0,-1.5,0.15},{-1.6,0,2.025},{-1.6,-0.3,2.025}, + {-1.5,-0.3,2.25},{-1.5,0,2.25},{-2.3,0,2.025},{-2.3,-0.3,2.025}, + {-2.5,-0.3,2.25},{-2.5,0,2.25},{-2.7,0,2.025},{-2.7,-0.3,2.025}, + {-3,-0.3,2.25},{-3,0,2.25},{-2.7,0,1.8},{-2.7,-0.3,1.8},{-3,-0.3,1.8}, + {-3,0,1.8},{-2.7,0,1.575},{-2.7,-0.3,1.575},{-3,-0.3,1.35},{-3,0,1.35}, + {-2.5,0,1.125},{-2.5,-0.3,1.125},{-2.65,-0.3,0.9375},{-2.65,0,0.9375}, + {-2,-0.3,0.9},{-1.9,-0.3,0.6},{-1.9,0,0.6},{1.7,0,1.425}, + {1.7,-0.66,1.425},{1.7,-0.66,0.6},{1.7,0,0.6},{2.6,0,1.425}, + {2.6,-0.66,1.425},{3.1,-0.66,0.825},{3.1,0,0.825},{2.3,0,2.1}, + {2.3,-0.25,2.1},{2.4,-0.25,2.025},{2.4,0,2.025},{2.7,0,2.4}, + {2.7,-0.25,2.4},{3.3,-0.25,2.4},{3.3,0,2.4},{2.8,0,2.475}, + {2.8,-0.25,2.475},{3.525,-0.25,2.49375},{3.525,0,2.49375}, + {2.9,0,2.475},{2.9,-0.15,2.475},{3.45,-0.15,2.5125},{3.45,0,2.5125}, + {2.8,0,2.4},{2.8,-0.15,2.4},{3.2,-0.15,2.4},{3.2,0,2.4},{0,0,3.15}, + {0.8,0,3.15},{0.8,-0.45,3.15},{0.45,-0.8,3.15},{0,-0.8,3.15}, + {0,0,2.85},{1.4,0,2.4},{1.4,-0.784,2.4},{0.784,-1.4,2.4},{0,-1.4,2.4}, + {0.4,0,2.55},{0.4,-0.224,2.55},{0.224,-0.4,2.55},{0,-0.4,2.55}, + {1.3,0,2.55},{1.3,-0.728,2.55},{0.728,-1.3,2.55},{0,-1.3,2.55}, + {1.3,0,2.4},{1.3,-0.728,2.4},{0.728,-1.3,2.4},{0,-1.3,2.4},{0,0,0}, + {1.425,-0.798,0},{1.5,0,0.075},{1.425,0,0},{0.798,-1.425,0}, + {0,-1.5,0.075},{0,-1.425,0},{1.5,-0.84,0.075},{0.84,-1.5,0.075} + }; + + static float tex[2][2][2] = {{{0, 0},{1, 0}},{{0, 1},{1, 1}}}; + + if ( !glIsList( teapotList ) ) { + float p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3]; + long grid = 14; + + teapotList = glGenLists( 1 ); + glNewList( teapotList, GL_COMPILE ); + glPushMatrix(); + glRotatef( 270.0, 1.0, 0.0, 0.0 ); + glScalef( 0.5, 0.5, 0.5 ); + glTranslatef( 0.0, 0.0, -1.5 ); + for ( long i = 0; i < 10; i++ ) { + for ( long j = 0; j < 4; j++ ) { + for ( long k = 0; k < 4; k++ ) { + for ( long l = 0; l < 3; l++ ) { + p[j][k][l] = cpdata[patchdata[i][j*4+k]][l]; + q[j][k][l] = cpdata[patchdata[i][j*4+(3-k)]][l]; + if ( l == 1 ) + q[j][k][l] *= -1.0; + if ( i < 6 ) { + r[j][k][l] = cpdata[patchdata[i][j*4+(3-k)]][l]; + if ( l == 0 ) + r[j][k][l] *= -1.0; + s[j][k][l] = cpdata[patchdata[i][j*4+k]][l]; + if ( l == 0 ) + s[j][k][l] *= -1.0; + if ( l == 1 ) + s[j][k][l] *= -1.0; + } + } + } + } + glMap2f( GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2, + &tex[0][0][0] ); + glMap2f( GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &p[0][0][0] ); + glEnable( GL_MAP2_VERTEX_3); + glEnable(GL_MAP2_TEXTURE_COORD_2 ); + glMapGrid2f( grid, 0.0, 1.0, grid, 0.0, 1.0 ); + glEvalMesh2( GL_LINE, 0, grid, 0, grid ); + glMap2f( GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, &q[0][0][0] ); + glEvalMesh2( GL_LINE, 0, grid, 0, grid ); + if ( i < 6 ) { + glMap2f( GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, + &r[0][0][0]); + glEvalMesh2( GL_LINE, 0, grid, 0, grid ); + glMap2f( GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, + &s[0][0][0] ); + glEvalMesh2( GL_LINE, 0, grid, 0, grid ); + } + } + glDisable(GL_MAP2_VERTEX_3); + glDisable(GL_MAP2_TEXTURE_COORD_2); + glPopMatrix(); + glEndList(); + } + + glCallList( teapotList ); +} diff --git a/examples/opengl/overlay/glteapots.h b/examples/opengl/overlay/glteapots.h new file mode 100644 index 0000000..11f4bef --- /dev/null +++ b/examples/opengl/overlay/glteapots.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** 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 QGLWidget displaying a group of teapots and a rubber-band +** in an overlay plane +** +****************************************************************************/ + +#ifndef GLBOX_H +#define GLBOX_H + +#include <qgl.h> + + +class GLTeapots : public QGLWidget +{ + Q_OBJECT + +public: + + GLTeapots( QWidget* parent, const char* name ); + ~GLTeapots(); + +protected: + + void initializeGL(); + void paintGL(); + void resizeGL( int w, int h ); + + void initializeOverlayGL(); + void paintOverlayGL(); + void resizeOverlayGL( int w, int h ); + + void mousePressEvent( QMouseEvent* e ); + void mouseMoveEvent( QMouseEvent* e ); + void mouseReleaseEvent( QMouseEvent* e ); + + void renderTeapot( GLfloat x, GLfloat y, GLfloat ambr, + GLfloat ambg, GLfloat ambb, GLfloat difr, + GLfloat difg, GLfloat difb, + GLfloat specr, GLfloat specg, + GLfloat specb, GLfloat shine ); + + void teapot(); + +private: + GLuint teapotList; + QPoint rubberP1; + QPoint rubberP2; + bool rubberOn; +}; + + +#endif // GLBOX_H diff --git a/examples/opengl/overlay/main.cpp b/examples/opengl/overlay/main.cpp new file mode 100644 index 0000000..2939ecb --- /dev/null +++ b/examples/opengl/overlay/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ +// +// Qt OpenGL example: Box +// +// A small example showing how a GLWidget can be used just as any Qt widget +// +// File: main.cpp +// +// The main() function +// + +#include "globjwin.h" +#include <qapplication.h> +#include <qgl.h> +#include <qmessagebox.h> + +/* + The main program is here. +*/ + +int main( int argc, char **argv ) +{ + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication a(argc,argv); + + if ( !QGLFormat::hasOpenGL() ) { + qWarning( "This system has no OpenGL support. Exiting." ); + return -1; + } + + // Check for existence of overlays + if ( !QGLFormat::hasOpenGLOverlays() ) { + QMessageBox::critical( 0, qApp->argv()[0], + "This system does not support OpenGL overlays", + "Exit" ); + return 1; + } + + GLObjectWindow w; + w.resize( 400, 350 ); + a.setMainWidget( &w ); + + w.show(); + return a.exec(); +} diff --git a/examples/opengl/overlay/overlay.doc b/examples/opengl/overlay/overlay.doc new file mode 100644 index 0000000..7a10b3c --- /dev/null +++ b/examples/opengl/overlay/overlay.doc @@ -0,0 +1,16 @@ +/*! \page opengl-overlay-example.html + + \ingroup opengl-examples + \title OpenGL Overlay Example + +This example demonstrates how to use OpenGL overlays with the Qt OpenGL +Extension. It features a QGLWidget with a relatively expensive redrawing +operation, and rubber-band drawing in the overlay plane. Using the +overlay has the advantage that the rubber-band may be drawn and erased +without damaging the image in the main plane, so costly redraws are +avoided. + +See \c{$QTDIR/examples/opengl/overlay} for the source code. + +*/ + diff --git a/examples/opengl/overlay/overlay.pro b/examples/opengl/overlay/overlay.pro new file mode 100644 index 0000000..bc08165 --- /dev/null +++ b/examples/opengl/overlay/overlay.pro @@ -0,0 +1,14 @@ +TEMPLATE = app +TARGET = overlay + +CONFIG += qt opengl warn_on release +CONFIG -= dlopen_opengl +DEPENDPATH = ../include + +REQUIRES = opengl + +HEADERS = glteapots.h \ + globjwin.h +SOURCES = glteapots.cpp \ + globjwin.cpp \ + main.cpp diff --git a/examples/opengl/overlay_x11/README b/examples/opengl/overlay_x11/README new file mode 100644 index 0000000..eba728e --- /dev/null +++ b/examples/opengl/overlay_x11/README @@ -0,0 +1,74 @@ + +----------------------------------------------------------------------- +UPDATE: From version 5.0 onwards, the Qt OpenGL Extension includes +direct support for use of OpenGL overlays. For many uses of overlays, +this makes the technique described below redundant. See the 'overlay' +example program. The following is a discussion on how to use non-QGL +widgets in overlay planes. +----------------------------------------------------------------------- + +Overlayrubber: An example program showing how to use Qt and Qt OpenGL +Extension with X11 overlay visuals. + +(Background information for this example can be found in the file + README.X11-OVERLAYS) + +The example program has three main parts: + +GearWidget: A simple QGLWidget that renders the usual gears. Modified +so that it will print a debug message every time it redraws (renders) +itself. Thus, you can eaily confirm that drawing in the overlay plane +does not cause redrawings in the main plane where the QGLWidget +resides. + +RubberbandWidget: Very simple standard (non-GL) Qt widget that +implements rubberband drawing. Designed for use in an overlay +plane. It takes the planes' transparent color as a constructor +argument and uses that for its background color. Thus, the widget +itself will be invisible, only the rubberbands it draws will be +visible. + +main.cpp: Creates a GearWidget and a Rubberbandwidget and puts the +latter on top of the former. Contains a routine that checks that the +default visual is in an overlay plane, and returns the transparent +color of that plane. + + +Running it: +----------- + +Start the overlayrubber executable. Click and drag with the left mouse +button to see rubberband drawing. Observe that the QGLWidget does +not redraw itself (no redraw debug messages are output), and yet the +image is not destroyed. Marvel at the coolness of X11 overlays! + + +Using this technique in a real application +------------------------------------------ + +For clarity, this example program has been kept very simple. Here are +some hints for real application use: + +All normal widgets can go in the overlay plane: This means that you +can put all kinds of Qt widgets (your own or those provided with Qt) +on top of the OpenGL image (widget), e.g. pushbuttons etc., and they +can be moved, resized, or removed without destroying the OpenGL image. + +Using with geometry management: The QLayout classes will not allow you +to put one widget (the overlay) on top of another (the OpenGL widget); +that would defy the whole purpose of the automatic layout. The +solution is to add just one of them to the QLayout object. Have it +keep a pointer to the other (i.e. the QGLWidget knows about its +overlay widget or vice versa). Implement the resizeEvent() method of +the widget you put in the layout, and make it call setGeometry() on +the other widget with its own geometry as parameters, thus keeping the +two widgets' geometries synchronized. + +Using with QPalette and QColorGroup: Instead of the somewhat +simplistic setBackgroundColor( transparentColor ), you can use Qt's +QPalette system for having your overlay widgets use transparent color +for what you want. This way, the normal Qt widgets can be used as +overlays for fancy effects: just create a palette for them with the +transparent color for the wanted color roles, e.g. Background and +Base, in the Normal and/or Active modes. This way, you can create +see-through QPushButtons etc. diff --git a/examples/opengl/overlay_x11/README.X11-OVERLAYS b/examples/opengl/overlay_x11/README.X11-OVERLAYS new file mode 100644 index 0000000..f415f4e --- /dev/null +++ b/examples/opengl/overlay_x11/README.X11-OVERLAYS @@ -0,0 +1,92 @@ + + HOW TO USE X11 OVERLAYS WITH THE QT OPENGL EXTENSION + +X11 overlays is a powerful mechanism that allows one to draw +annotations etc. on top of an image without destroying it, thus saving +significant image rendering time. For more information, consult the +highly recommended book "OpenGL Programming for the X Window System" +(Mark Kilgard, Addison Wesley Developers Press 1996). + +----------------------------------------------------------------------- +UPDATE: From version 5.0 onwards, the Qt OpenGL Extension includes +direct support for use of OpenGL overlays. For many uses of overlays, +this makes the technique described below redundant. See the 'overlay' +example program. The following is a discussion on how to use non-QGL +widgets in overlay planes. +----------------------------------------------------------------------- + +In the typical case, X11 overlays can easily be used together with the +current version of Qt and the Qt OpenGL Extension. The following +requirements apply: + +1) Your X server and graphics card/hardware must support overlays (of + course). For many X servers, overlay support can be turned on with + a configuration option; consult your X server installation + documentation. + +2) Your X server must (be configured to) use an overlay visual as the + default visual. Most modern X servers do this, since this has the + added advantage that pop-up menus, overlapping windows etc. will + not destroy underlying images in the main plane, saving expensive + redraws. + +3) The best (deepest) visual for OpenGL rendering is in the main + plane. This is the normal case. Typically, X servers that support + overlays provide a 24 bit deep TrueColor visuals in the main plane, + and an 8 bit PseudoColor (default) visual in the overlay plane. + +The provided example program "overlayrubber" will check for all this +and tell you what is wrong, if anything. See "About X11 Visuals" below +for more information. + + +How it works: +------------- + +Given the above, a QGLWidget will by default use the main plane +visual, while all other widgets will use the overlay visual. Thus, one +can place a normal widget on top of the QGLWidget, and do drawing in +it, without destroying the image in the OpenGL window. In other words, +one can use all the drawing capabilities of QPainter to draw the +annotations, rubberbands, whatever. For the typical use of overlays, +this is much easier than using OpenGL for rendering the annotations. + +An overlay plane has a specific color called the transparent +color. Pixels drawn in this color will not be visible, instead the +underlying OpenGL image will show through. In the example program +"overlayrubber", the file main.cpp contains a routine that returns a +QColor containing the transparent color. For the overlay widget, one +will typically want to set the background color to the transparent +color, so that the OpenGL image shows through except where explicitly +overpainted. + +Note: To use this technique, you must not use the "ManyColor" or +"TrueColor" ColorSpec for the QApplication, because this will force +the normal Qt widgets to use a TrueColor visual, which will typically +be in the main plane, not in the overlay plane as desired. + + + +About X11 visuals: +------------------ + +The utilities directory contains two small programs that can help you +determine the capabilities of your X server. These programs are from +the OpenGL book mentioned above, see utilities/NOTICE for copyright +information. The full set of example programs from this book is +available at ftp://ftp.sgi.com/pub/opengl/opengl_for_x/ + +"glxvisuals" will list all the GL-capable visuals the X server provides, +together with the depth and other GL-specific information for +each. Note especially the column "lvl"; a number in this column means +the visual is in an overlay plane. + +"sovinfo" will list all available visuals, and provides special +transparency information for overlay visuals. + +The overlayrubber example program will output what visual is used for +the normal Qt widgets, and what visual is used by the QGLWidget. + + + +Comments are welcome at [email protected]. diff --git a/examples/opengl/overlay_x11/gearwidget.cpp b/examples/opengl/overlay_x11/gearwidget.cpp new file mode 100644 index 0000000..e98938d --- /dev/null +++ b/examples/opengl/overlay_x11/gearwidget.cpp @@ -0,0 +1,268 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ +// +// A Qt OpenGL widget that draws a gear. +// +// Portions of this code has been borrowed from Brian Paul's Mesa +// distribution. +// + +#include "gearwidget.h" +#include <math.h> +#if defined(Q_WS_X11) +#include <X11/Xlib.h> +#endif + +#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(); + +} + + +static GLfloat view_rotx=20.0, view_roty=30.0, view_rotz=0.0; +static GLint gear1, gear2, gear3; +static GLfloat angle = 0.0; + + +static void draw() +{ + angle += 2.0; + view_roty += 1.0; + + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + 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(); +} + + + +GearWidget::GearWidget( QWidget *parent, const char *name ) + : QGLWidget( parent, name ) +{ +} + +void GearWidget::initializeGL() +{ + static GLfloat pos[4] = {5.0, 5.0, 10.0, 1.0 }; + static GLfloat redgear[4] = {0.8, 0.1, 0.0, 1.0 }; + static GLfloat greengear[4] = {0.0, 0.8, 0.2, 1.0 }; + static GLfloat bluegear[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, redgear ); + 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, greengear ); + 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, bluegear ); + gear( 1.3, 2.0, 0.5, 10, 0.7 ); + glEndList(); + + glEnable( GL_NORMALIZE ); +} + + +void GearWidget::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 GearWidget::paintGL() +{ + qDebug( "GearWidget: Doing GL rendering." ); +#if defined (Q_GLX) + static bool doneIt = FALSE; + if ( !doneIt ) { + doneIt = TRUE; + // Print out the Visual ID. Access to this will be made + // simpler in future versions of Qt! + XWindowAttributes a; + XGetWindowAttributes( x11Display(), winId(), &a ); + qDebug( "QGLWidget: using Visual ID: 0x%x.", + (int)XVisualIDFromVisual( a.visual ) ); + } +#endif + draw(); +} + diff --git a/examples/opengl/overlay_x11/gearwidget.h b/examples/opengl/overlay_x11/gearwidget.h new file mode 100644 index 0000000..fb0a2f8 --- /dev/null +++ b/examples/opengl/overlay_x11/gearwidget.h @@ -0,0 +1,29 @@ +/**************************************************************************** +** +** Definition of a simple Qt OpenGL widget +** +** Copyright (C) 1999-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 GEAR_H +#define GEAR_H + +#include <qgl.h> + +class GearWidget : public QGLWidget +{ +public: + GearWidget( QWidget *parent=0, const char *name=0 ); + +protected: + void initializeGL(); + void resizeGL( int, int ); + void paintGL(); +}; + + +#endif diff --git a/examples/opengl/overlay_x11/main.cpp b/examples/opengl/overlay_x11/main.cpp new file mode 100644 index 0000000..10ff6fc --- /dev/null +++ b/examples/opengl/overlay_x11/main.cpp @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Example application showing how to use Qt and Qt OpenGL Extension on an +** X11 overlay visual +** +** Copyright (C) 1999-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. +** +*****************************************************************************/ + +#include <qapplication.h> +#include "gearwidget.h" +#include "rubberbandwidget.h" + +#if defined(Q_WS_X11) +#include <X11/Xlib.h> +#endif + +QColor findOverlayTransparentColor() +{ + QColor invalidColor; + +#if defined(Q_WS_X11) + + Display* appDisplay; + Visual* appVisual; + + // The static methods are called 'App' in Qt 2.x +#if QT_VERSION < 200 + appDisplay = QPaintDevice::x__Display(); + appVisual = (Visual*)QPaintDevice::x11Visual(); +#else + appDisplay = QPaintDevice::x11AppDisplay(); + appVisual = (Visual*)QPaintDevice::x11AppVisual(); +#endif + + qDebug( "Default Visual ID: 0x%x", (int)XVisualIDFromVisual(appVisual) ); + + typedef struct OverlayProp { + long visual; + long type; + long value; + long layer; + } OverlayProp; + + QWidget* rootWin = QApplication::desktop(); + if ( !rootWin ) + return invalidColor; // Should not happen + + Atom overlayVisualsAtom = XInternAtom( appDisplay, + "SERVER_OVERLAY_VISUALS", True ); + if ( overlayVisualsAtom == None ) { + warning( "Server has no overlay visuals" ); + return invalidColor; + } + + Atom actualType; + int actualFormat; + ulong nItems; + ulong bytesAfter; + OverlayProp* overlayProp; + int res = XGetWindowProperty( appDisplay, QApplication::desktop()->winId(), + overlayVisualsAtom, 0, 10000, False, + overlayVisualsAtom, &actualType, + &actualFormat, &nItems, &bytesAfter, + (uchar**)&overlayProp ); + + if ( res != Success || actualType != overlayVisualsAtom + || actualFormat != 32 || nItems < 4 ) { + warning( "Failed to get overlay visual property from server" ); + return invalidColor; + } + + + for ( uint i = 0; i < nItems/4; i++ ) { + if ( (VisualID)overlayProp[i].visual == XVisualIDFromVisual(appVisual) + && overlayProp[i].type == 1 ) + return QColor( qRgb( 1, 2, 3 ), overlayProp[i].value ); + } + + qWarning( "Default visual is not in overlay plane" ); + return invalidColor; + +#else // defined(Q_WS_X11) + qWarning( "Wrong window system - Only X11 has overlay support." ); + return invalidColor; +#endif +} + + +int main( int argc, char **argv ) +{ + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication a( argc, argv ); + + if ( !QGLFormat::hasOpenGL() ) { + qWarning( "This system has no OpenGL support. Exiting." ); + return -1; + } + + QColor transparentColor = findOverlayTransparentColor(); + if ( !transparentColor.isValid() ) { + qWarning( "Failed to get transparent color for overlay. Exiting." ); + return -1; + } + + QWidget top; + a.setMainWidget( &top ); + top.setGeometry( 50, 50, 600, 400 ); + + // Make an OpenGL widget. It will use the deepest visual available + // (typically a TrueColor visual), which typically is in the normal layer. + GearWidget g( &top ); + g.setGeometry( 20, 20, 560, 360 ); + + // Put the rubberband widget (which uses the default, i.e. overlay visual) + // on top of the OpenGL widget: + RubberbandWidget r( transparentColor, &top ); + r.setGeometry( 20, 20, 560, 360 ); + + top.show(); + return a.exec(); +} diff --git a/examples/opengl/overlay_x11/overlay_x11.doc b/examples/opengl/overlay_x11/overlay_x11.doc new file mode 100644 index 0000000..6dddc9b --- /dev/null +++ b/examples/opengl/overlay_x11/overlay_x11.doc @@ -0,0 +1,82 @@ +/*! \page opengl-overlay-x11-example.html + + \ingroup opengl-examples + \title OpenGL Overlay X11 Example + +\warning From version 5.0 onwards, the Qt OpenGL Extension includes +direct support for use of OpenGL overlays. For many uses of overlays, +this makes the technique described below redundant. See the \link +opengl-overlay-example.html overlay\endlink example program. The +following is a discussion on how to use non-QGL widgets in overlay +planes. + +Overlayrubber: An example program showing how to use Qt and Qt OpenGL +Extension with X11 overlay visuals. + +See \c{$QTDIR/examples/opengl/overlay_x11} for the source code. + +Background information for this example can be found in the +information on \link opengl-x11-overlays.html overlays\endlink. + +The example program has three main parts: + +\list 1 +\i \e GearWidget - a normal, simple QGLWidget. This renders the usual +gears. It has been modified to print a debug message every time it +redraws (renders) itself. Thus, you can easily confirm that drawing in +the overlay plane does not cause redrawings in the main plane where +the QGLWidget resides. + +\i \e RubberbandWidget - Very simple standard (non-GL) Qt widget that +implements rubberband drawing. Designed for use in an overlay plane. +It takes the plane's transparent color as a constructor argument and +uses that for its background color. Thus, the widget itself will be +invisible, only the rubberbands it draws will be visible. + +\i \e{main.cpp} Creates a GearWidget and a Rubberbandwidget and puts the +latter on top of the former. Contains a routine that checks that the +default visual is in an overlay plane, and returns the transparent +color of that plane. +\endlist + +\section1 Running the Example + +Start the \c overlayrubber executable. Click and drag with the left +mouse button to see rubberband drawing. Observe that the QGLWidget +does not redraw itself (no redraw debug messages are output), and yet +the image is not destroyed. Marvel at the coolness of X11 overlays! + + +\section1 Using this technique in a real application + +For clarity, this example program has been kept very simple. Here are +some hints for real application usage: + +\list + +\i \e{All normal widgets are in the overlay plane.} This means that you +can put all kinds of Qt widgets (your own or standard Qt widgets) on +top of the OpenGL image (widget), e.g. pushbuttons etc., and they can +be moved, resized, or removed without destroying the OpenGL image. + +\i \e{Using with geometry management.} The QLayout classes don't permit +putting one widget (the overlay) on top of another (the OpenGL +widget); that would defy the whole purpose of the automatic layout. +The solution is to add just one of them to the QLayout object. Have it +keep a pointer to the other (i.e. the QGLWidget knows about its +overlay widget or vice versa). Implement the resizeEvent() method of +the widget you put in the layout, and make it call setGeometry() on +the other widget with its own geometry as parameters, thus keeping the +two widgets' geometries synchronized. + +\i \e{Using together with QPalette and QColorGroup.} Instead of the +simplistic setBackgroundColor( transparentColor ), you can +use Qt's QPalette system to make your overlay widgets use +transparent color for what you want. This way, the normal Qt widgets +can be used as overlays for fancy effects. Just create a palette for +them with the transparent color for the relevant color roles, e.g. +Background and Base, in the Normal and/or Active modes. This way, you +can create see-through QPushButtons etc. +\endlist + +*/ diff --git a/examples/opengl/overlay_x11/overlayrubber.pro b/examples/opengl/overlay_x11/overlayrubber.pro new file mode 100644 index 0000000..5381ebb --- /dev/null +++ b/examples/opengl/overlay_x11/overlayrubber.pro @@ -0,0 +1,14 @@ +TEMPLATE = app +TARGET = overlayrubber + +CONFIG += qt opengl warn_on release +CONFIG -= dlopen_opengl +DEPENDPATH = ../include + +REQUIRES = opengl full-config + +HEADERS = gearwidget.h \ + rubberbandwidget.h +SOURCES = gearwidget.cpp \ + main.cpp \ + rubberbandwidget.cpp diff --git a/examples/opengl/overlay_x11/rubberbandwidget.cpp b/examples/opengl/overlay_x11/rubberbandwidget.cpp new file mode 100644 index 0000000..7a3b003 --- /dev/null +++ b/examples/opengl/overlay_x11/rubberbandwidget.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Implementation of a widget that draws a rubberband. Designed to be used +** in an X11 overlay visual +** +** Copyright (C) 1999-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. +** +*****************************************************************************/ + +#include "rubberbandwidget.h" +#include <qpainter.h> + + +RubberbandWidget::RubberbandWidget( QColor transparentColor, QWidget *parent, + const char *name, WFlags f ) + : QWidget( parent, name, f ) +{ + setBackgroundColor( transparentColor ); + on = FALSE; +} + + +void RubberbandWidget::mousePressEvent( QMouseEvent* e ) +{ + p1 = e->pos(); + p2 = p1; + p3 = p1; + on = TRUE; + setMouseTracking( TRUE ); +} + + +void RubberbandWidget::mouseMoveEvent( QMouseEvent* e ) +{ + if ( on ) { + p2 = e->pos(); + QPainter p( this ); + // Erase last drawn rubberband: + p.setPen( QPen( backgroundColor(), 3 ) ); + p.drawRect( QRect( p1, p3 ) ); + // Draw the new one: + p.setPen( QPen( white, 3 ) ); + p.drawRect( QRect(p1, p2) ); + p3 = p2; + } +} + +void RubberbandWidget::mouseReleaseEvent( QMouseEvent* ) +{ + if ( on ) { + QPainter p ( this ); + p.eraseRect( rect() ); + } + on = FALSE; + setMouseTracking( FALSE ); +} diff --git a/examples/opengl/overlay_x11/rubberbandwidget.h b/examples/opengl/overlay_x11/rubberbandwidget.h new file mode 100644 index 0000000..d401294 --- /dev/null +++ b/examples/opengl/overlay_x11/rubberbandwidget.h @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Definition of a widget that draws a rubberband. Designed to be used +** in an X11 overlay visual +** +** Copyright (C) 1999-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 RUBBERBANDWIDGET_H +#define RUBBERBANDWIDGET_H + +#include <qwidget.h> + + +class RubberbandWidget : public QWidget +{ +public: + RubberbandWidget( QColor transparentColor, QWidget *parent=0, + const char *name=0, WFlags f=0 ); + +protected: + void mousePressEvent( QMouseEvent* e ); + void mouseMoveEvent( QMouseEvent* e ); + void mouseReleaseEvent( QMouseEvent* e ); + + QColor c; + QPoint p1; + QPoint p2; + QPoint p3; + bool on; +}; + +#endif diff --git a/examples/opengl/overlay_x11/utilities/NOTICE b/examples/opengl/overlay_x11/utilities/NOTICE new file mode 100644 index 0000000..4157392 --- /dev/null +++ b/examples/opengl/overlay_x11/utilities/NOTICE @@ -0,0 +1,11 @@ + +NOTICE: This source code distribution contains source code contained +in the book "Programming OpenGL for the X Window System" (ISBN: +0-201-48359-9) published by Addison-Wesley. The programs and +associated files contained in the distribution were developed by Mark +J. Kilgard and are Copyright 1994, 1995, 1996 by Mark J. Kilgard +(unless otherwise noted). The programs are not in the public domain, +but they are freely distributable without licensing fees. These +programs are provided without guarantee or warranty expressed or +implied. + diff --git a/examples/opengl/overlay_x11/utilities/README b/examples/opengl/overlay_x11/utilities/README new file mode 100644 index 0000000..d96f343 --- /dev/null +++ b/examples/opengl/overlay_x11/utilities/README @@ -0,0 +1,22 @@ + +Welcome to the "Programming OpenGL for the X Window System" Xlib-based +example source code. The following table names each example program +directory and what section of the book discusses the example. + +Section Example directory +---------- ------------------ + 1.5 glxsimple + 2.1 glxdino + 2.2.2 glxvisuals + 2.6.1 pixmap2eps + 6.2.3.1 xdevices + 6.2.7 dials + 6.3.4 sovinfo + 6.3.5 layerdemo + +I've tried to make the Makefiles as simple and as portable as +possible. If you find problems with these examples, please report bugs + +- Mark Kilgard + diff --git a/examples/opengl/overlay_x11/utilities/glxvisuals/glxvisuals.c b/examples/opengl/overlay_x11/utilities/glxvisuals/glxvisuals.c new file mode 100644 index 0000000..3c1a21e --- /dev/null +++ b/examples/opengl/overlay_x11/utilities/glxvisuals/glxvisuals.c @@ -0,0 +1,147 @@ + +/* Copyright (c) Mark J. Kilgard, 1996. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +#include <stdlib.h> +#include <stdio.h> +#include <X11/Xlib.h> +#include <GL/glx.h> + +static char *ClassOf(int c); +static char *Format(int n, int w); + +void +main(int argc, char *argv[]) +{ + Display *dpy; + XVisualInfo match, *visualList, *vi, *visualToTry; + int errorBase, eventBase, major, minor, found; + int glxCapable, bufferSize, level, renderType, doubleBuffer, stereo, + auxBuffers, redSize, greenSize, blueSize, alphaSize, depthSize, + stencilSize, acRedSize, acGreenSize, acBlueSize, acAlphaSize; + + dpy = XOpenDisplay(NULL); + if (!dpy) { + fprintf(stderr, "Could not connect to %s.\n", XDisplayName(NULL)); + exit(1); + } + if (glXQueryExtension(dpy, &errorBase, &eventBase) == False) { + fprintf(stderr, "OpenGL not supported by X server.\n"); + exit(1); + } + + glXQueryVersion(dpy, &major, &minor); + printf("display: %s\n", XDisplayName(NULL)); + printf("using GLX version: %d.%d\n\n", major, minor); + + match.screen = DefaultScreen(dpy); + visualList = XGetVisualInfo(dpy, VisualScreenMask, &match, &found); + + printf(" visual bf lv rg d st r g b a ax dp st accum buffs\n"); + printf(" id dep cl sz l ci b ro sz sz sz sz bf th cl r g b a\n"); + printf("-------------------------------------------------------------\n"); + + visualToTry = NULL; + for(vi = visualList; found > 0; found--, vi++) { + glXGetConfig(dpy, vi, GLX_USE_GL, &glxCapable); + if (glxCapable) { + printf("0x%x %2d %s", vi->visualid, vi->depth, ClassOf(vi->class)); + glXGetConfig(dpy, vi, GLX_BUFFER_SIZE, &bufferSize); + glXGetConfig(dpy, vi, GLX_LEVEL, &level); + glXGetConfig(dpy, vi, GLX_RGBA, &renderType); + glXGetConfig(dpy, vi, GLX_DOUBLEBUFFER, &doubleBuffer); + glXGetConfig(dpy, vi, GLX_STEREO, &stereo); + glXGetConfig(dpy, vi, GLX_AUX_BUFFERS, &auxBuffers); + glXGetConfig(dpy, vi, GLX_RED_SIZE, &redSize); + glXGetConfig(dpy, vi, GLX_GREEN_SIZE, &greenSize); + glXGetConfig(dpy, vi, GLX_BLUE_SIZE, &blueSize); + glXGetConfig(dpy, vi, GLX_ALPHA_SIZE, &alphaSize); + glXGetConfig(dpy, vi, GLX_DEPTH_SIZE, &depthSize); + glXGetConfig(dpy, vi, GLX_STENCIL_SIZE, &stencilSize); + glXGetConfig(dpy, vi, GLX_ACCUM_RED_SIZE, &acRedSize); + glXGetConfig(dpy, vi, GLX_ACCUM_GREEN_SIZE, &acGreenSize); + glXGetConfig(dpy, vi, GLX_ACCUM_BLUE_SIZE, &acBlueSize); + glXGetConfig(dpy, vi, GLX_ACCUM_ALPHA_SIZE, &acAlphaSize); + printf(" %2s %2s %1s %1s %1s ", + Format(bufferSize, 2), Format(level, 2), + renderType ? "r" : "c", + doubleBuffer ? "y" : ".", + stereo ? "y" : "."); + printf("%2s %2s %2s %2s ", + Format(redSize, 2), Format(greenSize, 2), + Format(blueSize, 2), Format(alphaSize, 2)); + printf("%2s %2s %2s %2s %2s %2s %2s", + Format(auxBuffers, 2), Format(depthSize, 2), Format(stencilSize, 2), + Format(acRedSize, 2), Format(acGreenSize, 2), + Format(acBlueSize, 2), Format(acAlphaSize, 2)); + printf("\n"); + visualToTry = vi; + } + } + + if (visualToTry) { + GLXContext context; + Window window; + Colormap colormap; + XSetWindowAttributes swa; + + context = glXCreateContext(dpy, visualToTry, 0, GL_TRUE); + colormap = XCreateColormap(dpy, + RootWindow(dpy, visualToTry->screen), + visualToTry->visual, AllocNone); + swa.colormap = colormap; + swa.border_pixel = 0; + window = XCreateWindow(dpy, RootWindow(dpy, visualToTry->screen), 0, 0, 100, 100, + 0, visualToTry->depth, InputOutput, visualToTry->visual, + CWBorderPixel | CWColormap, &swa); + glXMakeCurrent(dpy, window, context); + printf("\n"); + printf("OpenGL vendor string: %s\n", glGetString(GL_VENDOR)); + printf("OpenGL renderer string: %s\n", glGetString(GL_RENDERER)); + printf("OpenGL version string: %s\n", glGetString(GL_VERSION)); + if (glXIsDirect(dpy, context)) + printf("direct rendering: supported\n"); + printf( "GL extensions: '%s'\n\n", glGetString(GL_EXTENSIONS) ); +#if defined(GLX_VERSION_1_1) + printf( "GLX extensions: '%s'\n\n", glXQueryExtensionsString( dpy, visualToTry->screen ) ); +#endif + + } else + printf("No GLX-capable visuals!\n"); + XFree(visualList); +} + +static char * +ClassOf(int c) +{ + switch (c) { + case StaticGray: return "sg"; + case GrayScale: return "gs"; + case StaticColor: return "sc"; + case PseudoColor: return "pc"; + case TrueColor: return "tc"; + case DirectColor: return "dc"; + default: return "??"; + } +} + +static char * +Format(int n, int w) +{ + static char buffer[256]; + static int bufptr; + char *buf; + + if (bufptr >= sizeof(buffer) - w) + bufptr = 0; + buf = buffer + bufptr; + if (n == 0) + sprintf(buf, "%*s", w, "."); + else + sprintf(buf, "%*d", w, n); + bufptr += w + 1; + return buf; +} diff --git a/examples/opengl/overlay_x11/utilities/sovinfo/sovLayerUtil.h b/examples/opengl/overlay_x11/utilities/sovinfo/sovLayerUtil.h new file mode 100644 index 0000000..f45423a --- /dev/null +++ b/examples/opengl/overlay_x11/utilities/sovinfo/sovLayerUtil.h @@ -0,0 +1,54 @@ +#ifndef __sovLayerUtil_h__ +#define __sovLayerUtil_h__ + +/* Copyright (c) Mark J. Kilgard, 1996. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/Xmd.h> + +/* Transparent type values */ +/* None 0 */ +#define TransparentPixel 1 +#define TransparentMask 2 + +/* layered visual info template flags */ +#define VisualLayerMask 0x200 +#define VisualTransparentType 0x400 +#define VisualTransparentValue 0x800 +#define VisualAllLayerMask 0xFFF + +/* layered visual info structure */ +typedef struct _sovVisualInfo { + XVisualInfo vinfo; + int layer; + int type; + unsigned long value; +} sovVisualInfo; + +/* SERVER_OVERLAY_VISUALS property element */ +typedef struct _sovOverlayInfo { + long overlay_visual; + long transparent_type; + long value; + long layer; +} sovOverlayInfo; + +extern sovVisualInfo *sovGetVisualInfo( + Display *display, + long lvinfo_mask, + sovVisualInfo *lvinfo_template, + int *nitems_return); +extern Status sovMatchVisualInfo( + Display *display, + int screen, + int depth, + int class, + int layer, + sovVisualInfo *lvinfo_return); + +#endif /* __sovLayerUtil_h__ */ diff --git a/examples/opengl/overlay_x11/utilities/sovinfo/sovinfo.c b/examples/opengl/overlay_x11/utilities/sovinfo/sovinfo.c new file mode 100644 index 0000000..059050c --- /dev/null +++ b/examples/opengl/overlay_x11/utilities/sovinfo/sovinfo.c @@ -0,0 +1,95 @@ + +/* Copyright (c) Mark J. Kilgard, 1996. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +/* compile: cc -o sovinfo sovinfo.c sovLayerUtil.c -lX11 */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "sovLayerUtil.h" + +int +main(int argc, char *argv[]) +{ + Display *dpy; + char *display_name, *arg, *class; + sovVisualInfo template, *lvinfo; + int nVisuals, i, overlaysOnly = 0; + + display_name = NULL; + for (i = 1; i < argc; i++) { + arg = argv[i]; + if (!strcmp(arg, "-display")) { + if (++i >= argc) { + fprintf(stderr, "sovinfo: missing argument to -display\n"); + exit(1); + } + display_name = argv[i]; + } else if (!strcmp(arg, "-overlays_only")) { + overlaysOnly = 1; + } else { + fprintf(stderr, + "usage: sovinfo [-display dpy] [-overlays_only]\n"); + exit(1); + } + } + dpy = XOpenDisplay(display_name); + if (dpy == NULL) { + fprintf(stderr, "sovinfo: cannot open display %s\n", + XDisplayName(NULL)); + exit(1); + } + lvinfo = sovGetVisualInfo(dpy, 0L, &template, &nVisuals); + for (i = 0; i < nVisuals; i++) { + if (!overlaysOnly || lvinfo[i].layer > 0) { + printf(" Visual ID: 0x%x\n", lvinfo[i].vinfo.visualid); + printf(" screen: %d\n", lvinfo[i].vinfo.screen); + printf(" depth: %d\n", lvinfo[i].vinfo.depth); + switch (lvinfo[i].vinfo.class) { + case StaticGray: + class = "StaticGray"; + break; + case GrayScale: + class = "GrayScale"; + break; + case StaticColor: + class = "StaticColor"; + break; + case PseudoColor: + class = "PseudoColor"; + break; + case TrueColor: + class = "TrueColor"; + break; + case DirectColor: + class = "DirectColor"; + break; + default: + class = "Unknown"; + break; + } + printf(" class: %s\n", class); + switch (lvinfo[i].type) { + case None: + printf(" transparent type: None\n"); + break; + case TransparentPixel: + printf(" transparent type: TransparentPixel\n"); + printf(" pixel value: %d\n", lvinfo[i].value); + break; + case TransparentMask: + printf(" transparent type: TransparentMask\n"); + printf(" transparency mask: %0x%x\n", lvinfo[i].value); + break; + default: + printf(" transparent type: Unknown or invalid\n"); + break; + } + printf(" layer: %d\n", lvinfo[i].layer); + } + } + return 0; +} diff --git a/examples/opengl/overlay_x11/utilities/sovinfo/sovlayerutil.c b/examples/opengl/overlay_x11/utilities/sovinfo/sovlayerutil.c new file mode 100644 index 0000000..8837d06 --- /dev/null +++ b/examples/opengl/overlay_x11/utilities/sovinfo/sovlayerutil.c @@ -0,0 +1,150 @@ + +/* Copyright (c) Mark J. Kilgard, 1996. */ + +/* This program is freely distributable without licensing fees + and is provided without guarantee or warrantee expressed or + implied. This program is -not- in the public domain. */ + +#include <stdlib.h> +#include "sovLayerUtil.h" + +static Bool layersRead; +static Atom overlayVisualsAtom; +static sovOverlayInfo **overlayInfoPerScreen; +static int *numOverlaysPerScreen; + +sovVisualInfo * +sovGetVisualInfo(Display *display, long lvinfo_mask, + sovVisualInfo *lvinfo_template, int *nitems_return) +{ + XVisualInfo *vinfo; + sovVisualInfo *layerInfo; + Window root; + Status status; + Atom actualType; + unsigned long sizeData, bytesLeft; + int actualFormat, numVisuals, numScreens, count, i, j; + + vinfo = XGetVisualInfo(display, lvinfo_mask & VisualAllMask, + &lvinfo_template->vinfo, nitems_return); + if (vinfo == NULL) + return NULL; + numVisuals = *nitems_return; + if (layersRead == False) { + overlayVisualsAtom = XInternAtom(display, + "SERVER_OVERLAY_VISUALS", True); + if (overlayVisualsAtom != None) { + numScreens = ScreenCount(display); + overlayInfoPerScreen = (sovOverlayInfo **) + malloc(numScreens * sizeof(sovOverlayInfo *)); + numOverlaysPerScreen = (int *) malloc(numScreens * sizeof(int)); + if (overlayInfoPerScreen != NULL && + numOverlaysPerScreen != NULL) { + for (i = 0; i < numScreens; i++) { + root = RootWindow(display, i); + status = XGetWindowProperty(display, root, overlayVisualsAtom, + 0L, (long) 10000, False, overlayVisualsAtom, + &actualType, &actualFormat, + &sizeData, &bytesLeft, + (unsigned char **) &overlayInfoPerScreen[i]); + if (status != Success || + actualType != overlayVisualsAtom || + actualFormat != 32 || sizeData < 4) + numOverlaysPerScreen[i] = 0; + else + numOverlaysPerScreen[i] = sizeData / 4; + } + layersRead = True; + } else { + if (overlayInfoPerScreen != NULL) + free(overlayInfoPerScreen); + if (numOverlaysPerScreen != NULL) + free(numOverlaysPerScreen); + } + } + } + layerInfo = (sovVisualInfo *) + malloc(numVisuals * sizeof(sovVisualInfo)); + if (layerInfo == NULL) { + XFree(vinfo); + return NULL; + } + count = 0; + for (i = 0; i < numVisuals; i++) { + XVisualInfo *pVinfo; + int screen; + sovOverlayInfo *overlayInfo; + + pVinfo = &vinfo[i]; + screen = pVinfo->screen; + overlayInfo = NULL; + if (layersRead) { + for (j = 0; j < numOverlaysPerScreen[screen]; j++) + if (pVinfo->visualid == + overlayInfoPerScreen[screen][j].overlay_visual) { + overlayInfo = &overlayInfoPerScreen[screen][j]; + break; + } + } + if (lvinfo_mask & VisualLayerMask) + if (overlayInfo == NULL) { + if (lvinfo_template->layer != 0) + continue; + } else if (lvinfo_template->layer != overlayInfo->layer) + continue; + if (lvinfo_mask & VisualTransparentType) + if (overlayInfo == NULL) { + if (lvinfo_template->type != None) + continue; + } else if (lvinfo_template->type != + overlayInfo->transparent_type) + continue; + if (lvinfo_mask & VisualTransparentValue) + if (overlayInfo == NULL) + /* non-overlay visuals have no sense of + TransparentValue */ + continue; + else if (lvinfo_template->value != overlayInfo->value) + continue; + layerInfo[count].vinfo = *pVinfo; + if (overlayInfo == NULL) { + layerInfo[count].layer = 0; + layerInfo[count].type = None; + layerInfo[count].value = 0; /* meaningless */ + } else { + layerInfo[count].layer = overlayInfo->layer; + layerInfo[count].type = overlayInfo->transparent_type; + layerInfo[count].value = overlayInfo->value; + } + count++; + } + XFree(vinfo); + *nitems_return = count; + if (count == 0) { + XFree(layerInfo); + return NULL; + } else + return layerInfo; +} + +Status +sovMatchVisualInfo(Display *display, int screen, + int depth, int class, int layer, sovVisualInfo *lvinfo_return) +{ + sovVisualInfo *lvinfo; + sovVisualInfo lvinfoTemplate; + int nitems; + + lvinfoTemplate.vinfo.screen = screen; + lvinfoTemplate.vinfo.depth = depth; + lvinfoTemplate.vinfo.class = class; + lvinfoTemplate.layer = layer; + lvinfo = sovGetVisualInfo(display, + VisualScreenMask|VisualDepthMask|VisualClassMask|VisualLayerMask, + &lvinfoTemplate, &nitems); + if (lvinfo != NULL && nitems > 0) { + *lvinfo_return = *lvinfo; + return 1; + } else + return 0; +} diff --git a/examples/opengl/sharedbox/README b/examples/opengl/sharedbox/README new file mode 100644 index 0000000..4959294 --- /dev/null +++ b/examples/opengl/sharedbox/README @@ -0,0 +1,8 @@ + +The shared box example + +This example program is an extension of the "box" example program. + +It demonstrates how to use OpenGL display list sharing with QGLWidgets. + + diff --git a/examples/opengl/sharedbox/glbox.cpp b/examples/opengl/sharedbox/glbox.cpp new file mode 100644 index 0000000..4d52ca5 --- /dev/null +++ b/examples/opengl/sharedbox/glbox.cpp @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** 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 a box +** +** The OpenGL code is mostly borrowed from Brian Pauls "spin" example +** in the Mesa distribution +** +****************************************************************************/ + +#include "glbox.h" + +// Initialize static class variables: + +// Shared display list id: +GLuint GLBox::sharedDisplayList = 0; + +// Counter keeping track of number of GLBox instances sharing +// the display list, so that the last instance can delete it: +int GLBox::sharedListUsers = 0; + + +/*! + Create a GLBox widget +*/ + +GLBox::GLBox( QWidget* parent, const char* name, const QGLWidget* shareWidget ) + : QGLWidget( parent, name, shareWidget ) +{ + xRot = yRot = zRot = 0.0; // default object rotation + scale = 1.0; // default object scale + object = 0; + localDisplayList = 0; +} + + +/*! + Set up the OpenGL rendering state. Robustly access shared display list. +*/ + +void GLBox::initializeGL() +{ + // Let OpenGL clear to black + qglClearColor( black ); + + glEnable(GL_DEPTH_TEST); + + if ( sharedListUsers == 0 ) { // No shared list has been made yet + sharedDisplayList = makeObject(); // Make one + object = sharedDisplayList; // Use it + sharedListUsers++; // Keep reference count + qDebug( "GLBox %s created shared display list.", name() ); + } + else { // There is a shared diplay list + if ( isSharing() ) { // Can we access it? + object = sharedDisplayList; // Yes, use it + sharedListUsers++; // Keep reference count + qDebug( "GLBox %s uses shared display list.", name() ); + } + else { + localDisplayList = makeObject(); // No, roll our own + object = localDisplayList; // and use that + qDebug( "GLBox %s uses private display list.", name() ); + } + } +} + + + +/*! + Release allocated resources +*/ + +GLBox::~GLBox() +{ + makeCurrent(); // We're going to do gl calls + if ( localDisplayList != 0 ) { // Did we make our own? + glDeleteLists( localDisplayList, 1 ); // Yes, delete it + qDebug( "GLBox %s deleted private display list.", name() ); + } + else { + sharedListUsers--; // No, we used the shared one; keep refcount + if ( sharedListUsers == 0 ) { // Any sharers left? + glDeleteLists( sharedDisplayList, 1 ); // No, delete it + sharedDisplayList = 0; + qDebug( "GLBox %s deleted shared display list.", name() ); + } + } +} + + +/*! + Paint the box. The actual openGL commands for drawing the box are + performed here. +*/ + +void GLBox::paintGL() +{ + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + glTranslatef( 0.0, 0.0, -3.0 ); + 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 ); + + glCallList( object ); +} + + + + +/*! + 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, 1.0, 10.0); +} + + +/*! + 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 ); + + glBegin(GL_QUADS); + /* Front face */ + qglColor( green ); + glVertex3f(-1.0, 1.0, 1.0); + glVertex3f(1.0, 1.0, 1.0); + glVertex3f(1.0, -1.0, 1.0); + glVertex3f(-1.0, -1.0, 1.0); + /* Back face */ + qglColor( yellow ); + glVertex3f(-1.0, 1.0, -1.0); + glVertex3f(1.0, 1.0, -1.0); + glVertex3f(1.0, -1.0, -1.0); + glVertex3f(-1.0, -1.0, -1.0); + /* Top side face */ + qglColor( blue ); + glVertex3f(-1.0, 1.0, 1.0); + glVertex3f(1.0, 1.0, 1.0); + glVertex3f(1.0, 1.0, -1.0); + glVertex3f(-1.0, 1.0, -1.0); + /* Bottom side face */ + qglColor( red ); + glVertex3f(-1.0, -1.0, 1.0); + glVertex3f(1.0, -1.0, 1.0); + glVertex3f(1.0, -1.0, -1.0); + glVertex3f(-1.0, -1.0, -1.0); + glEnd(); + glEndList(); + + return list; +} + + +/*! + Set the rotation angle of the object to \e degrees around the X axis. +*/ + +void GLBox::setXRotation( int degrees ) +{ + xRot = (GLfloat)(degrees % 360); + updateGL(); +} + + +/*! + Set the rotation angle of the object to \e degrees around the Y axis. +*/ + +void GLBox::setYRotation( int degrees ) +{ + yRot = (GLfloat)(degrees % 360); + updateGL(); +} + + +/*! + Set the rotation angle of the object to \e degrees around the Z axis. +*/ + +void GLBox::setZRotation( int degrees ) +{ + zRot = (GLfloat)(degrees % 360); + updateGL(); +} diff --git a/examples/opengl/sharedbox/glbox.h b/examples/opengl/sharedbox/glbox.h new file mode 100644 index 0000000..aa40877 --- /dev/null +++ b/examples/opengl/sharedbox/glbox.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** 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 a box +** +****************************************************************************/ + +#ifndef GLBOX_H +#define GLBOX_H + +#include <qgl.h> + + +class GLBox : public QGLWidget +{ + Q_OBJECT + +public: + + GLBox( QWidget* parent, const char* name, const QGLWidget* shareWidget=0 ); + ~GLBox(); + +public slots: + + void setXRotation( int degrees ); + void setYRotation( int degrees ); + void setZRotation( int degrees ); + +protected: + + void initializeGL(); + void paintGL(); + void resizeGL( int w, int h ); + + virtual GLuint makeObject(); + +private: + + GLuint object; + GLuint localDisplayList; + + static GLuint sharedDisplayList; + static int sharedListUsers; + + GLfloat xRot, yRot, zRot, scale; + +}; + + +#endif // GLBOX_H diff --git a/examples/opengl/sharedbox/globjwin.cpp b/examples/opengl/sharedbox/globjwin.cpp new file mode 100644 index 0000000..e9ebc9e --- /dev/null +++ b/examples/opengl/sharedbox/globjwin.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ + +#include <qpushbutton.h> +#include <qslider.h> +#include <qlayout.h> +#include <qframe.h> +#include <qmenubar.h> +#include <qpopupmenu.h> +#include <qapplication.h> +#include <qkeycode.h> +#include "globjwin.h" +#include "glbox.h" + + +GLObjectWindow::GLObjectWindow( QWidget* parent, const char* name ) + : QWidget( parent, name ) +{ + // Create a menu + QPopupMenu *file = new QPopupMenu( this ); + file->insertItem( "Delete Left QGLWidget", this, + SLOT(deleteFirstWidget()) ); + file->insertItem( "Exit", qApp, SLOT(quit()), CTRL+Key_Q ); + + // Create a menu bar + QMenuBar *m = new QMenuBar( this ); + m->setSeparator( QMenuBar::InWindowsStyle ); + m->insertItem("&File", file ); + + // Create nice frames to put around the OpenGL widgets + QFrame* f1 = new QFrame( this, "frame1" ); + f1->setFrameStyle( QFrame::Sunken | QFrame::Panel ); + f1->setLineWidth( 2 ); + QFrame* f2 = new QFrame( this, "frame2" ); + f2->setFrameStyle( QFrame::Sunken | QFrame::Panel ); + f2->setLineWidth( 2 ); + + // Create an OpenGL widget + c1 = new GLBox( f1, "glbox1" ); + + // Create another OpenGL widget that shares display lists with the first + c2 = new GLBox( f2, "glbox2", c1 ); + + // Create the three sliders; one for each rotation axis + // Make them spin the boxes, but not in synch + QSlider* x = new QSlider ( 0, 360, 60, 0, QSlider::Vertical, this, "xsl" ); + x->setTickmarks( QSlider::Left ); + connect( x, SIGNAL(valueChanged(int)), c1, SLOT(setXRotation(int)) ); + connect( x, SIGNAL(valueChanged(int)), c2, SLOT(setZRotation(int)) ); + + QSlider* y = new QSlider ( 0, 360, 60, 0, QSlider::Vertical, this, "ysl" ); + y->setTickmarks( QSlider::Left ); + connect( y, SIGNAL(valueChanged(int)), c1, SLOT(setYRotation(int)) ); + connect( y, SIGNAL(valueChanged(int)), c2, SLOT(setXRotation(int)) ); + + QSlider* z = new QSlider ( 0, 360, 60, 0, QSlider::Vertical, this, "zsl" ); + z->setTickmarks( QSlider::Left ); + connect( z, SIGNAL(valueChanged(int)), c1, SLOT(setZRotation(int)) ); + connect( z, SIGNAL(valueChanged(int)), c2, SLOT(setYRotation(int)) ); + + + // Now that we have all the widgets, put them into a nice layout + + // Put the sliders on top of each other + QVBoxLayout* vlayout = new QVBoxLayout( 20, "vlayout"); + vlayout->addWidget( x ); + vlayout->addWidget( y ); + vlayout->addWidget( z ); + + // Put the GL widgets inside the frames + QHBoxLayout* flayout1 = new QHBoxLayout( f1, 2, 2, "flayout1"); + flayout1->addWidget( c1, 1 ); + QHBoxLayout* flayout2 = new QHBoxLayout( f2, 2, 2, "flayout2"); + flayout2->addWidget( c2, 1 ); + + // Top level layout, puts the sliders to the left of the frame/GL widget + QHBoxLayout* hlayout = new QHBoxLayout( this, 20, 20, "hlayout"); + hlayout->setMenuBar( m ); + hlayout->addLayout( vlayout ); + hlayout->addWidget( f1, 1 ); + hlayout->addWidget( f2, 1 ); + +} + + +void GLObjectWindow::deleteFirstWidget() +{ + // Delete only c1; c2 will keep working and use the shared display list + if ( c1 ) { + delete c1; + c1 = 0; + } +} diff --git a/examples/opengl/sharedbox/globjwin.h b/examples/opengl/sharedbox/globjwin.h new file mode 100644 index 0000000..91ad7fe --- /dev/null +++ b/examples/opengl/sharedbox/globjwin.h @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ + +/**************************************************************************** +** +** The GLObjectWindow contains a GLBox and three sliders connected to +** the GLBox's rotation slots. +** +****************************************************************************/ + +#ifndef GLOBJWIN_H +#define GLOBJWIN_H + +#include <qwidget.h> +class GLBox; + +class GLObjectWindow : public QWidget +{ + Q_OBJECT +public: + GLObjectWindow( QWidget* parent = 0, const char* name = 0 ); + +protected slots: + + void deleteFirstWidget(); + +private: + GLBox* c1; + GLBox* c2; +}; + + +#endif // GLOBJWIN_H diff --git a/examples/opengl/sharedbox/main.cpp b/examples/opengl/sharedbox/main.cpp new file mode 100644 index 0000000..25ee5b4 --- /dev/null +++ b/examples/opengl/sharedbox/main.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ +// +// Qt OpenGL example: Shared Box +// +// A small example showing how to use OpenGL display list sharing +// +// File: main.cpp +// +// The main() function +// + +#include "globjwin.h" +#include <qapplication.h> +#include <qgl.h> + +/* + The main program is here. +*/ + +int main( int argc, char **argv ) +{ + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication a(argc,argv); + + if ( !QGLFormat::hasOpenGL() ) { + qWarning( "This system has no OpenGL support. Exiting." ); + return -1; + } + + GLObjectWindow w; + w.resize( 550, 350 ); + a.setMainWidget( &w ); + w.show(); + return a.exec(); +} diff --git a/examples/opengl/sharedbox/sharedbox.doc b/examples/opengl/sharedbox/sharedbox.doc new file mode 100644 index 0000000..21e7a66 --- /dev/null +++ b/examples/opengl/sharedbox/sharedbox.doc @@ -0,0 +1,16 @@ +/*! \page opengl-sharedbox-example.html + + \ingroup opengl-examples + \title OpenGL Shared Box Example + + +This example program is an extension of the \link +opengl-box-example.html Box example\endlink. + +It demonstrates how to use OpenGL display list sharing with +QGLWidgets. + +See \c{$QTDIR/examples/opengl/sharedbox} for the source code. + +*/ + diff --git a/examples/opengl/sharedbox/sharedbox.pro b/examples/opengl/sharedbox/sharedbox.pro new file mode 100644 index 0000000..30b92e8 --- /dev/null +++ b/examples/opengl/sharedbox/sharedbox.pro @@ -0,0 +1,14 @@ +TEMPLATE = app +TARGET = sharedbox + +CONFIG += qt opengl warn_on release +CONFIG -= dlopen_opengl +DEPENDPATH = ../include + +REQUIRES = opengl + +HEADERS = glbox.h \ + globjwin.h +SOURCES = glbox.cpp \ + globjwin.cpp \ + main.cpp diff --git a/examples/opengl/texture/README b/examples/opengl/texture/README new file mode 100644 index 0000000..5b85cd7 --- /dev/null +++ b/examples/opengl/texture/README @@ -0,0 +1,4 @@ + +The texture example + +This example program demonstrates how to use OpenGL 2D textures. diff --git a/examples/opengl/texture/gllogo.bmp b/examples/opengl/texture/gllogo.bmp Binary files differnew file mode 100644 index 0000000..ee64a10 --- /dev/null +++ b/examples/opengl/texture/gllogo.bmp diff --git a/examples/opengl/texture/globjwin.cpp b/examples/opengl/texture/globjwin.cpp new file mode 100644 index 0000000..4fe6b62 --- /dev/null +++ b/examples/opengl/texture/globjwin.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ + +#include <qpushbutton.h> +#include <qslider.h> +#include <qlayout.h> +#include <qframe.h> +#include <qmenubar.h> +#include <qpopupmenu.h> +#include <qapplication.h> +#include <qkeycode.h> +#include "globjwin.h" +#include "gltexobj.h" + + +GLObjectWindow::GLObjectWindow( QWidget* parent, const char* name ) + : QWidget( parent, name ) +{ + + // Create nice frames to put around the OpenGL widgets + QFrame* f1 = new QFrame( this, "frame1" ); + f1->setFrameStyle( QFrame::Sunken | QFrame::Panel ); + f1->setLineWidth( 2 ); + + // Create an OpenGL widget + GLTexobj* c = new GLTexobj( f1, "glbox1"); + + // Create a menu + QPopupMenu *file = new QPopupMenu( this ); + file->insertItem( "Toggle Animation", c, SLOT(toggleAnimation()), + CTRL+Key_A ); + file->insertSeparator(); + file->insertItem( "Exit", qApp, SLOT(quit()), CTRL+Key_Q ); + + // Create a menu bar + QMenuBar *m = new QMenuBar( this ); + m->setSeparator( QMenuBar::InWindowsStyle ); + m->insertItem("&File", file ); + + // Create the three sliders; one for each rotation axis + QSlider* x = new QSlider ( 0, 360, 60, 0, QSlider::Vertical, this, "xsl" ); + x->setTickmarks( QSlider::Left ); + connect( x, SIGNAL(valueChanged(int)), c, SLOT(setXRotation(int)) ); + + QSlider* y = new QSlider ( 0, 360, 60, 0, QSlider::Vertical, this, "ysl" ); + y->setTickmarks( QSlider::Left ); + connect( y, SIGNAL(valueChanged(int)), c, SLOT(setYRotation(int)) ); + + QSlider* z = new QSlider ( 0, 360, 60, 0, QSlider::Vertical, this, "zsl" ); + z->setTickmarks( QSlider::Left ); + connect( z, SIGNAL(valueChanged(int)), c, SLOT(setZRotation(int)) ); + + + // Now that we have all the widgets, put them into a nice layout + + // Put the sliders on top of each other + QVBoxLayout* vlayout = new QVBoxLayout( 20, "vlayout"); + vlayout->addWidget( x ); + vlayout->addWidget( y ); + vlayout->addWidget( z ); + + // Put the GL widget inside the frame + QHBoxLayout* flayout1 = new QHBoxLayout( f1, 2, 2, "flayout1"); + flayout1->addWidget( c, 1 ); + + // Top level layout, puts the sliders to the left of the frame/GL widget + QHBoxLayout* hlayout = new QHBoxLayout( this, 20, 20, "hlayout"); + hlayout->setMenuBar( m ); + hlayout->addLayout( vlayout ); + hlayout->addWidget( f1, 1 ); + +} diff --git a/examples/opengl/texture/globjwin.h b/examples/opengl/texture/globjwin.h new file mode 100644 index 0000000..68fa233 --- /dev/null +++ b/examples/opengl/texture/globjwin.h @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ + +/**************************************************************************** +** +** The GLObjectWindow contains a GLBox and three sliders connected to +** the GLBox's rotation slots. +** +****************************************************************************/ + +#ifndef GLOBJWIN_H +#define GLOBJWIN_H + +#include <qwidget.h> + + +class GLObjectWindow : public QWidget +{ + Q_OBJECT +public: + GLObjectWindow( QWidget* parent = 0, const char* name = 0 ); + +}; + + +#endif // GLOBJWIN_H diff --git a/examples/opengl/texture/gltexobj.cpp b/examples/opengl/texture/gltexobj.cpp new file mode 100644 index 0000000..2fc05d6 --- /dev/null +++ b/examples/opengl/texture/gltexobj.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** 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> +#include <qtimer.h> + + +const int redrawWait = 50; + +/*! + Create a GLTexobj widget +*/ + +GLTexobj::GLTexobj( QWidget* parent, const char* name ) + : QGLWidget( parent, name ) +{ + xRot = yRot = zRot = 0.0; // default object rotation + scale = 5.0; // default object scale + object = 0; + animation = TRUE; + timer = new QTimer( this ); + connect( timer, SIGNAL(timeout()), SLOT(update()) ); + timer->start( redrawWait, TRUE ); +} + + +/*! + 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() +{ + if ( animation ) { + xRot += 1.0; + yRot += 2.5; + zRot -= 5.0; + } + glClear( GL_COLOR_BUFFER_BIT ); + glPushMatrix(); + glRotatef( xRot, 1.0, 0.0, 0.0 ); + glRotatef( yRot, 0.0, 1.0, 0.0 ); + glRotatef( zRot, 0.0, 0.0, 1.0 ); + glScalef( scale, scale, scale ); + glCallList( object ); + glPopMatrix(); + + if ( animation ) { + glFlush(); // Make sure everything is drawn before restarting timer + timer->start( redrawWait, TRUE ); // Wait this many msecs before redraw + } +} + + +/*! + 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); + 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( "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( "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; +} + + +/*! + Set the rotation angle of the object to \e degrees around the X axis. +*/ + +void GLTexobj::setXRotation( int degrees ) +{ + xRot = (GLfloat)(degrees % 360); + updateGL(); +} + + +/*! + Set the rotation angle of the object to \e degrees around the Y axis. +*/ + +void GLTexobj::setYRotation( int degrees ) +{ + yRot = (GLfloat)(degrees % 360); + updateGL(); +} + + +/*! + Set the rotation angle of the object to \e degrees around the Z axis. +*/ + +void GLTexobj::setZRotation( int degrees ) +{ + zRot = (GLfloat)(degrees % 360); + updateGL(); +} + + +/*! + Turns animation on or off +*/ + +void GLTexobj::toggleAnimation() +{ + animation = !animation; + if ( animation ) + updateGL(); + else + timer->stop(); +} diff --git a/examples/opengl/texture/gltexobj.h b/examples/opengl/texture/gltexobj.h new file mode 100644 index 0000000..62d8881 --- /dev/null +++ b/examples/opengl/texture/gltexobj.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** 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 <qgl.h> + + +class GLTexobj : public QGLWidget +{ + Q_OBJECT + +public: + + GLTexobj( QWidget* parent, const char* name ); + ~GLTexobj(); + +public slots: + + void setXRotation( int degrees ); + void setYRotation( int degrees ); + void setZRotation( int degrees ); + void toggleAnimation(); + +protected: + + void initializeGL(); + void paintGL(); + void resizeGL( int w, int h ); + + virtual GLuint makeObject( const QImage& tex1, const QImage& tex2 ); + +private: + bool animation; + GLuint object; + GLfloat xRot, yRot, zRot, scale; + QTimer* timer; +}; + + +#endif // GLTEXOBJ_H diff --git a/examples/opengl/texture/main.cpp b/examples/opengl/texture/main.cpp new file mode 100644 index 0000000..0470d00 --- /dev/null +++ b/examples/opengl/texture/main.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** 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. +** +*****************************************************************************/ +// +// Qt OpenGL example: Texture +// +// File: main.cpp +// +// The main() function +// + +#include "globjwin.h" +#include <qapplication.h> +#include <qgl.h> + +/* + The main program is here. +*/ + +int main( int argc, char **argv ) +{ + QApplication::setColorSpec( QApplication::CustomColor ); + QApplication a(argc,argv); + + if ( !QGLFormat::hasOpenGL() ) { + qWarning( "This system has no OpenGL support. Exiting." ); + return -1; + } + + GLObjectWindow* w = new GLObjectWindow; + w->resize( 400, 350 ); + a.setMainWidget( w ); + w->show(); + int result = a.exec(); + delete w; + return result; +} diff --git a/examples/opengl/texture/qtlogo.bmp b/examples/opengl/texture/qtlogo.bmp Binary files differnew file mode 100644 index 0000000..b7f9215 --- /dev/null +++ b/examples/opengl/texture/qtlogo.bmp diff --git a/examples/opengl/texture/texture.doc b/examples/opengl/texture/texture.doc new file mode 100644 index 0000000..28f1d3f --- /dev/null +++ b/examples/opengl/texture/texture.doc @@ -0,0 +1,10 @@ +/*! \page opengl-texture-example.html + + \ingroup opengl-examples + \title OpenGL Texture Example + +This example program demonstrates how to use OpenGL 2D textures. + +See \c{$QTDIR/examples/opengl/texture} for the source code. + +*/ diff --git a/examples/opengl/texture/texture.pro b/examples/opengl/texture/texture.pro new file mode 100644 index 0000000..a9a31b8 --- /dev/null +++ b/examples/opengl/texture/texture.pro @@ -0,0 +1,14 @@ +TEMPLATE = app +TARGET = texture + +CONFIG += qt opengl warn_on release +CONFIG -= dlopen_opengl +DEPENDPATH = ../include + +REQUIRES = opengl + +HEADERS = gltexobj.h \ + globjwin.h +SOURCES = gltexobj.cpp \ + globjwin.cpp \ + main.cpp |