<?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <title>Qt 4.2: glwidget.cpp Example File (opengl/pbuffers2/glwidget.cpp)</title> <link href="classic.css" rel="stylesheet" type="text/css" /> </head> <body> <table border="0" cellpadding="0" cellspacing="0" width="100%"> <tr> <td align="left" valign="top" width="32"><a href="http://www.trolltech.com/products/qt"><img src="images/qt-logo.png" align="left" width="32" height="32" border="0" /></a></td> <td width="1"> </td><td class="postheader" valign="center"><a href="index.html"><font color="#004faf">Home</font></a> · <a href="classes.html"><font color="#004faf">All Classes</font></a> · <a href="mainclasses.html"><font color="#004faf">Main Classes</font></a> · <a href="groups.html"><font color="#004faf">Grouped Classes</font></a> · <a href="modules.html"><font color="#004faf">Modules</font></a> · <a href="functions.html"><font color="#004faf">Functions</font></a></td> <td align="right" valign="top" width="230"><a href="http://www.trolltech.com"><img src="images/trolltech-logo.png" align="right" width="203" height="32" border="0" /></a></td></tr></table><h1 align="center">glwidget.cpp Example File<br /><sup><sup>opengl/pbuffers2/glwidget.cpp</sup></sup></h1> <pre> /**************************************************************************** ** ** Copyright (C) 2005-2006 Trolltech ASA. All rights reserved. ** ** This file is part of the example classes of the Qt Toolkit. ** ** This file may be used under the terms of the GNU General Public ** License version 2.0 as published by the Free Software Foundation ** and appearing in the file LICENSE.GPL included in the packaging of ** this file. Please review the following information to ensure GNU ** General Public Licensing requirements will be met: ** http:<span class="comment">//www.trolltech.com/products/qt/opensource.html</span> ** ** If you are unsure which license is appropriate for your use, please ** review the following information: ** http:<span class="comment">//www.trolltech.com/products/qt/licensing.html or contact the</span> ** sales department at sales@trolltech.com. ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ** ****************************************************************************/ #include <QtGui/QImage> #include "glwidget.h" #include <math.h> #ifndef GL_MULTISAMPLE #define GL_MULTISAMPLE 0x809D #endif GLWidget::GLWidget(QWidget *parent) : QGLWidget(QGLFormat(QGL::SampleBuffers), parent) { setWindowTitle(tr("OpenGL pbuffers 2")); pbuffer = new QGLPixelBuffer(512, 512, format(), this); rot_x = rot_y = rot_z = 0.0f; scale = 0.1f; anim = new QTimeLine(750, this); anim->setUpdateInterval(20); connect(anim, SIGNAL(valueChanged(qreal)), SLOT(animate(qreal))); connect(anim, SIGNAL(finished()), SLOT(animFinished())); svg_renderer = new QSvgRenderer(QLatin1String(":/res/bubbles.svg"), this); connect(svg_renderer, SIGNAL(repaintNeeded()), this, SLOT(draw())); logo = QImage(":/res/qt4-logo.png"); logo = logo.convertToFormat(QImage::Format_ARGB32); makeCurrent(); <span class="comment">// need a current context to create the display list</span> tile_list = glGenLists(1); glNewList(tile_list, GL_COMPILE); glBegin(GL_QUADS); { glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); } glEnd(); glEndList(); wave = new GLfloat[logo.width()*logo.height()]; memset(wave, 0, logo.width()*logo.height()); startTimer(30); <span class="comment">// wave timer</span> pbuffer->makeCurrent(); dynamicTexture = pbuffer->generateDynamicTexture(); <span class="comment">// bind the dynamic texture to the pbuffer - this is a no-op under X11</span> pbuffer->bindToDynamicTexture(dynamicTexture); } GLWidget::~GLWidget() { delete[] wave; glDeleteLists(tile_list, 1); pbuffer->releaseFromDynamicTexture(); glDeleteTextures(1, &dynamicTexture); delete pbuffer; } void GLWidget::paintEvent(QPaintEvent *) { draw(); } void GLWidget::draw() { QPainter p(this); <span class="comment">// used for text overlay</span> <span class="comment">// save the GL state set for QPainter</span> saveGLState(); <span class="comment">// render the 'bubbles.svg' file into our pbuffer</span> QPainter pbuffer_painter(pbuffer); svg_renderer->render(&pbuffer_painter); pbuffer_painter.end(); glFlush(); #if defined(Q_WS_X11) <span class="comment">// rendering directly to a texture is not supported on X11, unfortunately</span> pbuffer->updateDynamicTexture(dynamicTexture); #endif makeCurrent(); <span class="comment">// draw into the GL widget</span> glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1, 1, -1, 1, 10, 100); glTranslatef(0.0f, 0.0f, -15.0f); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glViewport(0, 0, width(), height()); glBindTexture(GL_TEXTURE_2D, dynamicTexture); glEnable(GL_TEXTURE_2D); glEnable(GL_MULTISAMPLE); glEnable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); <span class="comment">// draw background</span> glPushMatrix(); glScalef(1.7f, 1.7f, 1.7f); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glCallList(tile_list); glPopMatrix(); const int w = logo.width(); const int h = logo.height(); glRotatef(rot_x, 1.0f, 0.0f, 0.0f); glRotatef(rot_y, 0.0f, 1.0f, 0.0f); glRotatef(rot_z, 0.0f, 0.0f, 1.0f); glScalef(scale/w, scale/w, scale/w); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); <span class="comment">// draw the Qt icon</span> glTranslatef(-w+1, -h+1, 0.0f); for (int y=h-1; y>=0; --y) { uint *p = (uint*) logo.scanLine(y); uint *end = p + w; int x = 0; while (p < end) { glColor4ub(qRed(*p), qGreen(*p), qBlue(*p), uchar(qAlpha(*p)*.9)); glTranslatef(0.0f, 0.0f, wave[y*w+x]); if (qAlpha(*p) > 128) glCallList(tile_list); glTranslatef(0.0f, 0.0f, -wave[y*w+x]); glTranslatef(2.0f, 0.0f, 0.0f); ++x; ++p; } glTranslatef(-w*2.0f, 2.0f, 0.0f); } <span class="comment">// restore the GL state that QPainter expects</span> restoreGLState(); <span class="comment">// draw the overlayed text using QPainter</span> p.setPen(QColor(197, 197, 197, 157)); p.setBrush(QColor(197, 197, 197, 127)); p.drawRect(QRect(0, 0, width(), 50)); p.setPen(Qt::black); p.setBrush(Qt::NoBrush); const QString str1(tr("A simple OpenGL pbuffer example.")); const QString str2(tr("Use the mouse wheel to zoom, press buttons and move mouse to rotate, double-click to flip.")); QFontMetrics fm(p.font()); p.drawText(width()/2 - fm.width(str1)/2, 20, str1); p.drawText(width()/2 - fm.width(str2)/2, 20 + fm.lineSpacing(), str2); } void GLWidget::mousePressEvent(QMouseEvent *e) { anchor = e->pos(); } void GLWidget::mouseMoveEvent(QMouseEvent *e) { QPoint diff = e->pos() - anchor; if (e->buttons() & Qt::LeftButton) { rot_x += diff.y()/5.0f; rot_y += diff.x()/5.0f; } else if (e->buttons() & Qt::RightButton) { rot_z += diff.x()/5.0f; } anchor = e->pos(); draw(); } void GLWidget::wheelEvent(QWheelEvent *e) { e->delta() > 0 ? scale += scale*0.1f : scale -= scale*0.1f; draw(); } void GLWidget::mouseDoubleClickEvent(QMouseEvent *) { anim->start(); } void GLWidget::animate(qreal val) { rot_y = val * 180; draw(); } void GLWidget::animFinished() { if (anim->direction() == QTimeLine::Forward) anim->setDirection(QTimeLine::Backward); else anim->setDirection(QTimeLine::Forward); } void GLWidget::saveGLState() { glPushAttrib(GL_ALL_ATTRIB_BITS); glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); } void GLWidget::restoreGLState() { glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glPopAttrib(); } #define PI 3.14159 void GLWidget::timerEvent(QTimerEvent *) { if (QApplication::mouseButtons() != 0) return; static bool scale_in = true; if (scale_in && scale > 35.0f) scale_in = false; else if (!scale_in && scale < .5f) scale_in = true; scale = scale_in ? scale + scale*0.01f : scale-scale*0.01f; rot_z += 0.3f; rot_x += 0.1f; int dx, dy; <span class="comment">// disturbance point</span> float s, v, W, t; int i, j; static float wt[128][128]; const int width = logo.width(); const int AMP = 5; dx = dy = width >> 1; W = .3f; v = -4; <span class="comment">// wave speed</span> for (i = 0; i < width; ++i) { for ( j = 0; j < width; ++j) { s = sqrt((double) ((j - dx) * (j - dx) + (i - dy) * (i - dy))); wt[i][j] += 0.1f; t = s / v; if (s != 0) wave[i*width + j] = AMP * sin(2 * PI * W * (wt[i][j] + t)) / (0.2*(s + 2)); else wave[i*width + j] = AMP * sin(2 * PI * W * (wt[i][j] + t)); } } }</pre> <p /><address><hr /><div align="center"> <table width="100%" cellspacing="0" border="0"><tr class="address"> <td width="30%">Copyright © 2006 <a href="trolltech.html">Trolltech</a></td> <td width="40%" align="center"><a href="trademarks.html">Trademarks</a></td> <td width="30%" align="right"><div align="right">Qt 4.2.1</div></td> </tr></table></div></address></body> </html>