1 /****************************************************************************
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the examples of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include <QtGui/QImage>
47 #ifndef GL_MULTISAMPLE
48 #define GL_MULTISAMPLE 0x809D
51 GLWidget::GLWidget(QWidget
*parent
)
52 : QGLWidget(QGLFormat(QGL::SampleBuffers
|QGL::AlphaChannel
), parent
)
54 setWindowTitle(tr("OpenGL framebuffer objects"));
57 if (QGLFramebufferObject::hasOpenGLFramebufferBlit()) {
58 QGLFramebufferObjectFormat format
;
60 format
.setAttachment(QGLFramebufferObject::CombinedDepthStencil
);
62 render_fbo
= new QGLFramebufferObject(512, 512, format
);
63 texture_fbo
= new QGLFramebufferObject(512, 512);
65 render_fbo
= new QGLFramebufferObject(1024, 1024);
66 texture_fbo
= render_fbo
;
69 rot_x
= rot_y
= rot_z
= 0.0f
;
71 anim
= new QTimeLine(750, this);
72 anim
->setUpdateInterval(20);
73 connect(anim
, SIGNAL(valueChanged(qreal
)), SLOT(animate(qreal
)));
74 connect(anim
, SIGNAL(finished()), SLOT(animFinished()));
76 svg_renderer
= new QSvgRenderer(QLatin1String(":/res/bubbles.svg"), this);
77 connect(svg_renderer
, SIGNAL(repaintNeeded()), this, SLOT(draw()));
79 logo
= QImage(":/res/designer.png");
80 logo
= logo
.convertToFormat(QImage::Format_ARGB32
);
82 tile_list
= glGenLists(1);
83 glNewList(tile_list
, GL_COMPILE
);
86 glTexCoord2f(0.0f
, 0.0f
); glVertex3f(-1.0f
, -1.0f
, 1.0f
);
87 glTexCoord2f(1.0f
, 0.0f
); glVertex3f( 1.0f
, -1.0f
, 1.0f
);
88 glTexCoord2f(1.0f
, 1.0f
); glVertex3f( 1.0f
, 1.0f
, 1.0f
);
89 glTexCoord2f(0.0f
, 1.0f
); glVertex3f(-1.0f
, 1.0f
, 1.0f
);
91 glTexCoord2f(1.0f
, 0.0f
); glVertex3f(-1.0f
, -1.0f
, -1.0f
);
92 glTexCoord2f(1.0f
, 1.0f
); glVertex3f(-1.0f
, 1.0f
, -1.0f
);
93 glTexCoord2f(0.0f
, 1.0f
); glVertex3f( 1.0f
, 1.0f
, -1.0f
);
94 glTexCoord2f(0.0f
, 0.0f
); glVertex3f( 1.0f
, -1.0f
, -1.0f
);
96 glTexCoord2f(0.0f
, 1.0f
); glVertex3f(-1.0f
, 1.0f
, -1.0f
);
97 glTexCoord2f(0.0f
, 0.0f
); glVertex3f(-1.0f
, 1.0f
, 1.0f
);
98 glTexCoord2f(1.0f
, 0.0f
); glVertex3f( 1.0f
, 1.0f
, 1.0f
);
99 glTexCoord2f(1.0f
, 1.0f
); glVertex3f( 1.0f
, 1.0f
, -1.0f
);
101 glTexCoord2f(1.0f
, 1.0f
); glVertex3f(-1.0f
, -1.0f
, -1.0f
);
102 glTexCoord2f(0.0f
, 1.0f
); glVertex3f( 1.0f
, -1.0f
, -1.0f
);
103 glTexCoord2f(0.0f
, 0.0f
); glVertex3f( 1.0f
, -1.0f
, 1.0f
);
104 glTexCoord2f(1.0f
, 0.0f
); glVertex3f(-1.0f
, -1.0f
, 1.0f
);
106 glTexCoord2f(1.0f
, 0.0f
); glVertex3f( 1.0f
, -1.0f
, -1.0f
);
107 glTexCoord2f(1.0f
, 1.0f
); glVertex3f( 1.0f
, 1.0f
, -1.0f
);
108 glTexCoord2f(0.0f
, 1.0f
); glVertex3f( 1.0f
, 1.0f
, 1.0f
);
109 glTexCoord2f(0.0f
, 0.0f
); glVertex3f( 1.0f
, -1.0f
, 1.0f
);
111 glTexCoord2f(0.0f
, 0.0f
); glVertex3f(-1.0f
, -1.0f
, -1.0f
);
112 glTexCoord2f(1.0f
, 0.0f
); glVertex3f(-1.0f
, -1.0f
, 1.0f
);
113 glTexCoord2f(1.0f
, 1.0f
); glVertex3f(-1.0f
, 1.0f
, 1.0f
);
114 glTexCoord2f(0.0f
, 1.0f
); glVertex3f(-1.0f
, 1.0f
, -1.0f
);
119 wave
= new GLfloat
[logo
.width()*logo
.height()];
120 memset(wave
, 0, logo
.width()*logo
.height());
121 startTimer(30); // wave timer
124 GLWidget::~GLWidget()
127 glDeleteLists(tile_list
, 1);
129 if (render_fbo
!= texture_fbo
)
133 void GLWidget::paintEvent(QPaintEvent
*)
138 void GLWidget::draw()
140 QPainter
p(this); // used for text overlay
142 // save the GL state set for QPainter
145 // render the 'bubbles.svg' file into our framebuffer object
146 QPainter
fbo_painter(render_fbo
);
147 svg_renderer
->render(&fbo_painter
);
150 if (render_fbo
!= texture_fbo
) {
151 QRect
rect(0, 0, render_fbo
->width(), render_fbo
->height());
152 QGLFramebufferObject::blitFramebuffer(texture_fbo
, rect
,
156 // draw into the GL widget
157 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
158 glMatrixMode(GL_PROJECTION
);
160 glFrustum(-1, 1, -1, 1, 10, 100);
161 glTranslatef(0.0f
, 0.0f
, -15.0f
);
162 glMatrixMode(GL_MODELVIEW
);
164 glViewport(0, 0, width(), height());
166 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
168 glBindTexture(GL_TEXTURE_2D
, texture_fbo
->texture());
169 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
170 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
171 glEnable(GL_TEXTURE_2D
);
172 glEnable(GL_MULTISAMPLE
);
173 glEnable(GL_CULL_FACE
);
177 glScalef(1.7f
, 1.7f
, 1.7f
);
178 glColor4f(1.0f
, 1.0f
, 1.0f
, 1.0f
);
179 glCallList(tile_list
);
182 const int w
= logo
.width();
183 const int h
= logo
.height();
185 glRotatef(rot_x
, 1.0f
, 0.0f
, 0.0f
);
186 glRotatef(rot_y
, 0.0f
, 1.0f
, 0.0f
);
187 glRotatef(rot_z
, 0.0f
, 0.0f
, 1.0f
);
188 glScalef(scale
/w
, scale
/w
, scale
/w
);
190 glDepthFunc(GL_LESS
);
191 glEnable(GL_DEPTH_TEST
);
193 glTranslatef(-w
+1, -h
+1, 0.0f
);
194 for (int y
=h
-1; y
>=0; --y
) {
195 uint
*p
= (uint
*) logo
.scanLine(y
);
199 glColor4ub(qRed(*p
), qGreen(*p
), qBlue(*p
), uchar(qAlpha(*p
)*.9));
200 glTranslatef(0.0f
, 0.0f
, wave
[y
*w
+x
]);
201 if (qAlpha(*p
) > 128)
202 glCallList(tile_list
);
203 glTranslatef(0.0f
, 0.0f
, -wave
[y
*w
+x
]);
204 glTranslatef(2.0f
, 0.0f
, 0.0f
);
208 glTranslatef(-w
*2.0f
, 2.0f
, 0.0f
);
211 // restore the GL state that QPainter expects
214 // draw the overlayed text using QPainter
215 p
.setPen(QColor(197, 197, 197, 157));
216 p
.setBrush(QColor(197, 197, 197, 127));
217 p
.drawRect(QRect(0, 0, width(), 50));
219 p
.setBrush(Qt::NoBrush
);
220 const QString
str1(tr("A simple OpenGL framebuffer object example."));
221 const QString
str2(tr("Use the mouse wheel to zoom, press buttons and move mouse to rotate, double-click to flip."));
222 QFontMetrics
fm(p
.font());
223 p
.drawText(width()/2 - fm
.width(str1
)/2, 20, str1
);
224 p
.drawText(width()/2 - fm
.width(str2
)/2, 20 + fm
.lineSpacing(), str2
);
227 void GLWidget::mousePressEvent(QMouseEvent
*e
)
232 void GLWidget::mouseMoveEvent(QMouseEvent
*e
)
234 QPoint diff
= e
->pos() - anchor
;
235 if (e
->buttons() & Qt::LeftButton
) {
236 rot_x
+= diff
.y()/5.0f
;
237 rot_y
+= diff
.x()/5.0f
;
238 } else if (e
->buttons() & Qt::RightButton
) {
239 rot_z
+= diff
.x()/5.0f
;
246 void GLWidget::wheelEvent(QWheelEvent
*e
)
248 e
->delta() > 0 ? scale
+= scale
*0.1f
: scale
-= scale
*0.1f
;
252 void GLWidget::mouseDoubleClickEvent(QMouseEvent
*)
257 void GLWidget::animate(qreal val
)
263 void GLWidget::animFinished()
265 if (anim
->direction() == QTimeLine::Forward
)
266 anim
->setDirection(QTimeLine::Backward
);
268 anim
->setDirection(QTimeLine::Forward
);
271 void GLWidget::saveGLState()
273 glPushAttrib(GL_ALL_ATTRIB_BITS
);
274 glMatrixMode(GL_PROJECTION
);
276 glMatrixMode(GL_MODELVIEW
);
280 void GLWidget::restoreGLState()
282 glMatrixMode(GL_PROJECTION
);
284 glMatrixMode(GL_MODELVIEW
);
291 void GLWidget::timerEvent(QTimerEvent
*)
293 if (QApplication::mouseButtons() != 0)
296 static bool scale_in
= true;
298 if (scale_in
&& scale
> 35.0f
)
300 else if (!scale_in
&& scale
< .5f
)
303 scale
= scale_in
? scale
+ scale
*0.01f
: scale
-scale
*0.01f
;
307 int dx
, dy
; // disturbance point
310 static float wt
[128][128];
311 const int width
= logo
.width();
314 dx
= dy
= width
>> 1;
317 v
= -4; // wave speed
319 for (i
= 0; i
< width
; ++i
) {
320 for ( j
= 0; j
< width
; ++j
) {
321 s
= sqrt((double) ((j
- dx
) * (j
- dx
) + (i
- dy
) * (i
- dy
)));
325 wave
[i
*width
+ j
] = AMP
* sin(2 * PI
* W
* (wt
[i
][j
] + t
)) / (0.2*(s
+ 2));
327 wave
[i
*width
+ j
] = AMP
* sin(2 * PI
* W
* (wt
[i
][j
] + t
));