/src/threed/painting/qglpainter.cpp
C++ | 2366 lines | 1308 code | 148 blank | 910 comment | 222 complexity | ec43ac14b87db2d542b2b8f4bf4379f7 MD5 | raw file
Possible License(s): CC-BY-SA-4.0, LGPL-2.1, GPL-3.0, AGPL-3.0, LGPL-3.0
1/****************************************************************************
2**
3** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/
5**
6** This file is part of the Qt3D module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** GNU Lesser General Public License Usage
10** This file may be used under the terms of the GNU Lesser General Public
11** License version 2.1 as published by the Free Software Foundation and
12** appearing in the file LICENSE.LGPL included in the packaging of this
13** file. Please review the following information to ensure the GNU Lesser
14** General Public License version 2.1 requirements will be met:
15** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16**
17** In addition, as a special exception, Nokia gives you certain additional
18** rights. These rights are described in the Nokia Qt LGPL Exception
19** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20**
21** GNU General Public License Usage
22** Alternatively, this file may be used under the terms of the GNU General
23** Public License version 3.0 as published by the Free Software Foundation
24** and appearing in the file LICENSE.GPL included in the packaging of this
25** file. Please review the following information to ensure the GNU General
26** Public License version 3.0 requirements will be met:
27** http://www.gnu.org/copyleft/gpl.html.
28**
29** Other Usage
30** Alternatively, this file may be used in accordance with the terms and
31** conditions contained in a signed written agreement between you and Nokia.
32**
33**
34**
35**
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qglpainter.h"
43#include "qglpainter_p.h"
44#include "qglabstracteffect.h"
45#include "qglext_p.h"
46
47#include <QOpenGLContext>
48#include <QOpenGLShaderProgram>
49#include <QOpenGLFramebufferObject>
50#include <QPainter>
51#include <QPaintEngine>
52#include <QVarLengthArray>
53#include <QMap>
54#include <QDebug>
55
56#if !defined(QT_NO_THREAD)
57#include <QThreadStorage>
58#include <QThread>
59#endif
60
61#include "qglflatcoloreffect_p.h"
62#include "qglflattextureeffect_p.h"
63#include "qgllitmaterialeffect_p.h"
64#include "qgllittextureeffect_p.h"
65#include "qglpickcolors_p.h"
66#include "qgltexture2d.h"
67#include "qgltexturecube.h"
68#include "qgeometrydata.h"
69#include "qglvertexbundle_p.h"
70#include "qmatrix4x4stack_p.h"
71#include "qglwindowsurface.h"
72#include "qglpaintersurface_p.h"
73
74#undef glActiveTexture
75
76QT_BEGIN_NAMESPACE
77
78/*!
79 \class QGLPainter
80 \brief The QGLPainter class provides portable API's for rendering into a GL context.
81 \since 4.8
82 \ingroup qt3d
83 \ingroup qt3d::painting
84
85 TBD - lots of TBD
86
87 All QGLPainter instances on a context share the same context state:
88 matrices, effects, vertex attributes, etc. For example, calling
89 ortho() on one QGLPainter instance for a context will alter the
90 projectionMatrix() as seen by the other QGLPainter instances.
91*/
92
93/*!
94 \enum QGLPainter::Update
95 This enum defines the values that were changed since the last QGLPainter::update().
96
97 \value UpdateColor The color has been updated.
98 \value UpdateModelViewMatrix The modelview matrix has been updated.
99 \value UpdateProjectionMatrix The projection matrix has been updated.
100 \value UpdateMatrices The combination of UpdateModelViewMatrix and
101 UpdateProjectionMatrix.
102 \value UpdateLights The lights have been updated.
103 \value UpdateMaterials The material parameters have been updated.
104 \value UpdateViewport The viewport needs to be updated because the
105 drawing surface has changed.
106 \value UpdateAll All values have been updated. This is specified
107 when an effect is activated.
108*/
109
110#define QGLPAINTER_CHECK_PRIVATE() \
111 Q_ASSERT_X(d, "QGLPainter", "begin() has not been called or it failed")
112
113QGLPainterPrivate::QGLPainterPrivate()
114 : ref(1),
115 badShaderCount(0),
116 eye(QGL::NoEye),
117 lightModel(0),
118 defaultLightModel(0),
119 defaultLight(0),
120 frontMaterial(0),
121 backMaterial(0),
122 defaultMaterial(0),
123 frontColorMaterial(0),
124 backColorMaterial(0),
125 viewingCube(QVector3D(-1, -1, -1), QVector3D(1, 1, 1)),
126 color(255, 255, 255, 255),
127 updates(QGLPainter::UpdateAll),
128 pick(0),
129 boundVertexBuffer(0),
130 boundIndexBuffer(0),
131 renderSequencer(0),
132 isFixedFunction(true) // Updated by QGLPainter::begin()
133{
134 context = 0;
135 effect = 0;
136 userEffect = 0;
137 standardEffect = QGL::FlatColor;
138 memset(stdeffects, 0, sizeof(stdeffects));
139}
140
141QGLPainterPrivate::~QGLPainterPrivate()
142{
143 delete defaultLightModel;
144 delete defaultLight;
145 delete defaultMaterial;
146 delete frontColorMaterial;
147 delete backColorMaterial;
148 for (int effect = 0; effect < QGL_MAX_STD_EFFECTS; ++effect)
149 delete stdeffects[effect];
150 delete pick;
151 qDeleteAll(cachedPrograms);
152 delete renderSequencer;
153}
154
155QGLPainterPickPrivate::QGLPainterPickPrivate()
156{
157 isPicking = false;
158 objectPickId = -1;
159 pickColorIndex = -1;
160 pickColor = 0;
161 defaultPickEffect = new QGLFlatColorEffect();
162}
163
164QGLPainterPickPrivate::~QGLPainterPickPrivate()
165{
166 delete defaultPickEffect;
167}
168
169#if !defined(QT_NO_THREAD)
170
171// QOpenGLContext's are thread-specific, so QGLPainterPrivateCache should be too.
172
173typedef QThreadStorage<QGLPainterPrivateCache *> QGLPainterPrivateStorage;
174Q_GLOBAL_STATIC(QGLPainterPrivateStorage, painterPrivateStorage)
175static QGLPainterPrivateCache *painterPrivateCache()
176{
177 QGLPainterPrivateCache *cache = painterPrivateStorage()->localData();
178 if (!cache) {
179 cache = new QGLPainterPrivateCache();
180 painterPrivateStorage()->setLocalData(cache);
181 }
182 return cache;
183}
184
185#else
186
187Q_GLOBAL_STATIC(QGLPainterPrivateCache, painterPrivateCache)
188
189#endif
190
191QGLPainterPrivateCache::QGLPainterPrivateCache()
192{
193}
194
195QGLPainterPrivateCache::~QGLPainterPrivateCache()
196{
197}
198
199QGLPainterPrivate *QGLPainterPrivateCache::fromContext(QOpenGLContext *context)
200{
201 QGLPainterPrivate *priv = cache.value(context, 0);
202 if (priv)
203 return priv;
204#ifndef QT_NO_THREAD
205 Q_ASSERT_X(context->thread() == QThread::currentThread(),
206 Q_FUNC_INFO,
207 "Attempt to fetch painter state for context outside contexts thread");
208#endif
209 // since we assert this is the same thread then this is bound to be a direct
210 // connection, not a queued (asynchronous) connection
211 connect(context, SIGNAL(destroyed()), this, SLOT(contextDestroyed()));
212 priv = new QGLPainterPrivate();
213 priv->context = context;
214 cache.insert(context, priv);
215 return priv;
216}
217
218QGLPainterPrivateCache *QGLPainterPrivateCache::instance()
219{
220 return painterPrivateCache();
221}
222
223void QGLPainterPrivateCache::contextDestroyed()
224{
225 QOpenGLContext *context = qobject_cast<QOpenGLContext *>(sender());
226 QGLPainterPrivate *priv = cache.value(context, 0);
227 if (priv) {
228 priv->context = 0;
229 cache.remove(context);
230 if (!priv->ref.deref())
231 delete priv;
232 }
233 emit destroyedContext(context);
234}
235
236/*!
237 Constructs a new GL painter. Call begin() to attach the
238 painter to a GL context.
239
240 \sa begin()
241*/
242QGLPainter::QGLPainter()
243 : d_ptr(0)
244{
245}
246
247/*!
248 Constructs a new GL painter and attaches it to \a context.
249 It is not necessary to call begin() after construction.
250
251 \sa begin()
252*/
253QGLPainter::QGLPainter(QOpenGLContext *context)
254 : d_ptr(0)
255{
256 begin(context);
257}
258
259/*!
260 Constructs a new GL painter and attaches it to the GL
261 context associated with \a window. It is not necessary to
262 call begin() after construction.
263
264 \sa begin(), isActive()
265*/
266QGLPainter::QGLPainter(QWindow *window)
267 : d_ptr(0)
268{
269 begin(window);
270}
271
272/*!
273 Constructs a new GL painter and attaches it to the GL context associated
274 with \a painter. It is assumed that \a painter is the currently
275 active painter and that it is associated with the current GL context.
276
277 If \a painter is not using an OpenGL paint engine, then isActive()
278 will return false; true otherwise.
279
280 This constructor is typically used when mixing regular Qt painting
281 operations and GL painting operations on a widget that is being
282 drawn using the OpenGL graphics system.
283
284 \sa begin(), isActive()
285*/
286QGLPainter::QGLPainter(QPainter *painter)
287 : d_ptr(0)
288{
289 begin(painter);
290}
291
292/*!
293 Constructs a new GL painter and attaches it to the GL context associated
294 with \a surface.
295
296 \sa begin(), isActive()
297*/
298QGLPainter::QGLPainter(QGLAbstractSurface *surface)
299 : d_ptr(0)
300{
301 begin(surface);
302}
303
304/*!
305 Destroys this GL painter.
306*/
307QGLPainter::~QGLPainter()
308{
309 end();
310}
311
312/*!
313 Begins painting on the current GL context. Returns false
314 if there is no GL context current.
315
316 \sa end()
317*/
318bool QGLPainter::begin()
319{
320 return begin(QOpenGLContext::currentContext());
321}
322
323/*!
324 Begins painting on \a context. If painting was already in progress,
325 then this function will call end() first. The \a context will be
326 made current if it is not already current.
327
328 Returns true if painting can begin; false otherwise.
329
330 All QGLPainter instances on a context share the same context state:
331 matrices, the effect(), vertex attributes, etc. For example,
332 calling ortho() on one QGLPainter instance for a context will
333 alter the projectionMatrix() as seen by the other QGLPainter instances.
334
335 \sa end(), isActive()
336*/
337bool QGLPainter::begin(QOpenGLContext *context)
338{
339 if (!context)
340 return false;
341 end();
342 return begin(context, QGLAbstractSurface::createSurfaceForContext(context));
343}
344
345/*!
346 \internal
347*/
348bool QGLPainter::begin
349 (QOpenGLContext *context, QGLAbstractSurface *surface,
350 bool destroySurface)
351{
352 // If we don't have a context specified, then use the one
353 // that the surface just made current.
354 if (!context)
355 context = QOpenGLContext::currentContext();
356
357 if (!context)
358 {
359 qWarning() << "##### Attempt to begin painter with no GL context!";
360 return false;
361 }
362
363 // Initialize the QOpenGLFunctions parent class.
364 initializeGLFunctions();
365
366 // Determine if the OpenGL implementation is fixed-function or not.
367 bool isFixedFunction = !hasOpenGLFeature(QOpenGLFunctions::Shaders);
368 if (!isFixedFunction)
369 isFixedFunction = !QOpenGLShaderProgram::hasOpenGLShaderPrograms();
370 if (!isFixedFunction)
371 {
372 QOpenGLContext *ctx = QOpenGLContext::currentContext();
373 QFunctionPointer res = ctx->getProcAddress("glCreateShader");
374 if (!res)
375 {
376 res = ctx->getProcAddress("glCreateShaderObject");
377 if (!res)
378 {
379 res = ctx->getProcAddress("glCreateShaderObjectARB");
380 }
381 }
382 if (!res)
383 isFixedFunction = !res;
384 }
385
386 // Find the QGLPainterPrivate for the context, or create a new one.
387 d_ptr = painterPrivateCache()->fromContext(context);
388 d_ptr->ref.ref();
389 d_ptr->isFixedFunction = isFixedFunction;
390 if (d_ptr->renderSequencer)
391 {
392 d_ptr->renderSequencer->reset();
393 d_ptr->renderSequencer->setPainter(this);
394 }
395
396 // Activate the main surface for the context.
397 QGLAbstractSurface *prevSurface;
398 if (d_ptr->surfaceStack.isEmpty()) {
399 prevSurface = 0;
400 } else {
401 // We are starting a nested begin()/end() scope, so switch
402 // to the new main surface rather than activate from scratch.
403 prevSurface = d_ptr->surfaceStack.last().surface;
404 prevSurface->deactivate(surface);
405 }
406 if (!surface->activate(prevSurface)) {
407 if (prevSurface)
408 prevSurface->activate(surface);
409 if (destroySurface)
410 delete surface;
411 if (!d_ptr->ref.deref())
412 delete d_ptr;
413 d_ptr = 0;
414 return false;
415 }
416
417 // Push a main surface descriptor onto the surface stack.
418 QGLPainterSurfaceInfo psurf;
419 psurf.surface = surface;
420 psurf.destroySurface = destroySurface;
421 psurf.mainSurface = true;
422 d_ptr->surfaceStack.append(psurf);
423
424 // Force the matrices to be updated the first time we use them.
425 d_ptr->modelViewMatrix.setDirty(true);
426 d_ptr->projectionMatrix.setDirty(true);
427
428 return true;
429}
430
431/*!
432 Begins GL painting on \a widget. Returns false if \a widget is null.
433
434 \sa end()
435*/
436bool QGLPainter::begin(QWindow *window)
437{
438 bool result = false;
439 if (window)
440 {
441 end();
442 result = begin(0, new QGLWindowSurface(window));
443 }
444 return result;
445}
446
447/*!
448 Begins painting on the GL context associated with \a painter.
449 Returns false if \a painter is not using an OpenGL paint engine.
450 It is assumed that \a painter is the currently active painter
451 and that it is associated with the current GL context.
452
453 This function is typically used when mixing regular Qt painting
454 operations and GL painting operations on a widget that is being
455 drawn using the OpenGL graphics system.
456
457 \sa end()
458*/
459bool QGLPainter::begin(QPainter *painter)
460{
461 // Validate that the painting is OpenGL-based.
462 if (!painter)
463 return false;
464 QPaintEngine *engine = painter->paintEngine();
465 if (!engine)
466 return false;
467 if (engine->type() != QPaintEngine::OpenGL &&
468 engine->type() != QPaintEngine::OpenGL2)
469 return false;
470
471 // Begin GL painting operations.
472 return begin(0, new QGLPainterSurface(painter));
473}
474
475/*!
476 Begins painting to \a surface. Returns false if \a surface is
477 null or could not be activated.
478
479 \sa end(), QGLAbstractSurface::activate()
480*/
481bool QGLPainter::begin(QGLAbstractSurface *surface)
482{
483 if (!surface)
484 return false;
485 end();
486 return begin(0, surface, false);
487}
488
489/*!
490 Ends GL painting. Returns true if painting was ended successfully;
491 false if this painter was not bound to a GL context.
492
493 The GL context that was bound to this painter will not have
494 QOpenGLContext::doneCurrent() called on it. It is the responsibility
495 of the caller to terminate context operations.
496
497 The effect() will be left active in the GL context and will be
498 assumed to still be active the next time begin() is called.
499 If this assumption doesn't apply, then call disableEffect()
500 to disable the effect before calling end().
501
502 This function will pop all surfaces from the surface stack,
503 and return currentSurface() to null (the default drawing surface).
504
505 \sa begin(), isActive(), disableEffect()
506*/
507bool QGLPainter::end()
508{
509 Q_D(QGLPainter);
510 if (!d)
511 return false;
512
513 // Unbind the current vertex and index buffers.
514 if (d->boundVertexBuffer) {
515 QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
516 d->boundVertexBuffer = 0;
517 }
518 if (d->boundIndexBuffer) {
519 QOpenGLBuffer::release(QOpenGLBuffer::IndexBuffer);
520 d->boundIndexBuffer = 0;
521 }
522
523 // Pop surfaces from the surface stack until we reach a
524 // main surface. Then deactivate the main surface.
525 int size = d->surfaceStack.size();
526 while (size > 0) {
527 --size;
528 QGLPainterSurfaceInfo &surf = d->surfaceStack[size];
529 if (surf.mainSurface) {
530 if (size > 0) {
531 // There are still other surfaces on the stack, probably
532 // because we are within a nested begin()/end() scope.
533 // Re-activate the next surface down in the outer scope.
534 QGLPainterSurfaceInfo &nextSurf = d->surfaceStack[size - 1];
535 surf.surface->switchTo(nextSurf.surface);
536 } else {
537 // Last surface on the stack, so deactivate it permanently.
538 surf.surface->deactivate();
539 }
540 if (surf.destroySurface)
541 delete surf.surface;
542 break;
543 } else if (size > 0) {
544 surf.surface->deactivate(d->surfaceStack[size - 1].surface);
545 }
546 }
547 d->surfaceStack.resize(size);
548
549 // Force a viewport update if we are within a nested begin()/end().
550 d->updates |= UpdateViewport;
551
552 // Destroy the QGLPainterPrivate if this is the last reference.
553 if (!d->ref.deref())
554 delete d;
555 d_ptr = 0;
556 return true;
557}
558
559/*!
560 Returns true if this painter is currently bound to a GL context;
561 false otherwise.
562
563 \sa begin(), end()
564*/
565bool QGLPainter::isActive() const
566{
567 return (d_ptr != 0 && d_ptr->context != 0);
568}
569
570/*!
571 Returns the GL context that is bound to this painter, or null
572 if it is not currently bound.
573*/
574QOpenGLContext *QGLPainter::context() const
575{
576 if (d_ptr)
577 return d_ptr->context;
578 else
579 return 0;
580}
581
582/*!
583 Returns true if the underlying OpenGL implementation is OpenGL 1.x
584 or OpenGL/ES 1.x and only supports fixed-function OpenGL operations.
585 Returns false if the underlying OpenGL implementation is using
586 GLSL or GLSL/ES shaders.
587
588 If this function returns false, then the built-in effects will
589 use shaders and QGLPainter will not update the fixed-function
590 matrices in the OpenGL context when update() is called.
591 User-supplied effects will need to use shaders also or update
592 the fixed-function matrices themselves or call updateFixedFunction().
593
594 \sa update(), updateFixedFunction()
595*/
596bool QGLPainter::isFixedFunction() const
597{
598#if defined(QT_OPENGL_ES_2)
599 return false;
600#else
601 Q_D(const QGLPainter);
602 if (d)
603 return d->isFixedFunction;
604 else
605 return true;
606#endif
607}
608
609/*!
610 Sets the \a color to use to clear the color buffer when \c{glClear()}
611 is called.
612*/
613void QGLPainter::setClearColor(const QColor& color)
614{
615 glClearColor(color.redF(), color.greenF(), color.blueF(), color.alphaF());
616}
617
618/*!
619 Sets the scissor \a rect for the current drawing surface
620 to use when \c{GL_SCISSOR_TEST} is enabled. If \a rect is empty,
621 then the scissor will be set to clip away all drawing.
622
623 Note that \a rect is in Qt co-ordinates with the origin
624 at the top-left of the drawing surface's viewport rectangle.
625 If the currentSurface() is an instance of QGLSubsurface,
626 then \a rect will be adjusted relative to the subsurface's position.
627
628 \sa currentSurface(), QGLAbstractSurface::viewportGL()
629*/
630void QGLPainter::setScissor(const QRect& rect)
631{
632 if (!rect.isEmpty()) {
633 // Adjust the rectangle by the position of the surface viewport.
634 QGLAbstractSurface *surface = currentSurface();
635 QRect viewport = surface->viewportGL();
636 QRect r(viewport.x() + rect.x(),
637 viewport.y() + viewport.height() - (rect.y() + rect.height()),
638 rect.width(), rect.height());
639 if (!r.isEmpty())
640 glScissor(r.x(), r.y(), r.width(), r.height());
641 else
642 glScissor(0, 0, 0, 0);
643 } else {
644 glScissor(0, 0, 0, 0);
645 }
646}
647
648/*!
649 Returns a reference to the projection matrix stack.
650
651 It is recommended that setCamera() be used to set the projection
652 matrix at the beginning of a scene rendering pass so that the
653 eye position can be adjusted for stereo.
654
655 \sa modelViewMatrix(), combinedMatrix(), setCamera()
656*/
657QMatrix4x4Stack& QGLPainter::projectionMatrix()
658{
659 Q_D(QGLPainter);
660 QGLPAINTER_CHECK_PRIVATE();
661 return d->projectionMatrix;
662}
663
664/*!
665 Returns a reference to the modelview matrix stack.
666
667 \sa projectionMatrix(), combinedMatrix(), normalMatrix(), setCamera()
668 \sa worldMatrix()
669*/
670QMatrix4x4Stack& QGLPainter::modelViewMatrix()
671{
672 Q_D(QGLPainter);
673 QGLPAINTER_CHECK_PRIVATE();
674 return d->modelViewMatrix;
675}
676
677/*!
678 \fn QMatrix4x4 QGLPainter::combinedMatrix() const
679
680 Returns the result of multiplying the projectionMatrix()
681 and the modelViewMatrix(). This combined matrix value is
682 useful for setting uniform matrix values on shader programs.
683
684 Calling this function is more efficient than calling
685 projectionMatrix() and modelViewMatrix() separately and
686 multiplying the return values.
687
688 \sa projectionMatrix(), modelViewMatrix(), normalMatrix()
689*/
690QMatrix4x4 QGLPainter::combinedMatrix() const
691{
692 const QGLPainterPrivate *d = d_func();
693 if (!d)
694 return QMatrix4x4();
695 const QMatrix4x4StackPrivate *proj = d->projectionMatrix.d_func();
696 const QMatrix4x4StackPrivate *mv = d->modelViewMatrix.d_func();
697 return proj->matrix * mv->matrix;
698}
699
700// Inverting the eye transformation will often result in values like
701// 1.5e-15 in the world matrix. Clamp these to zero to make worldMatrix()
702// more stable when removing the eye component of the modelViewMatrix().
703static inline qreal qt_gl_stablize_value(qreal value)
704{
705 return (qAbs(value) >= 0.00001f) ? value : 0.0f;
706}
707static inline QMatrix4x4 qt_gl_stablize_matrix(const QMatrix4x4 &m)
708{
709 return QMatrix4x4(qt_gl_stablize_value(m(0, 0)),
710 qt_gl_stablize_value(m(0, 1)),
711 qt_gl_stablize_value(m(0, 2)),
712 qt_gl_stablize_value(m(0, 3)),
713 qt_gl_stablize_value(m(1, 0)),
714 qt_gl_stablize_value(m(1, 1)),
715 qt_gl_stablize_value(m(1, 2)),
716 qt_gl_stablize_value(m(1, 3)),
717 qt_gl_stablize_value(m(2, 0)),
718 qt_gl_stablize_value(m(2, 1)),
719 qt_gl_stablize_value(m(2, 2)),
720 qt_gl_stablize_value(m(2, 3)),
721 qt_gl_stablize_value(m(3, 0)),
722 qt_gl_stablize_value(m(3, 1)),
723 qt_gl_stablize_value(m(3, 2)),
724 qt_gl_stablize_value(m(3, 3)));
725}
726
727/*!
728 Returns the world matrix, which is the modelViewMatrix() without
729 the eye transformation that was set in the previous call to
730 setCamera().
731
732 In the following example, the \c{world} variable will be set to the
733 translation and scale component of the modelview transformation,
734 without the "look at" component from the camera:
735
736 \code
737 painter.setCamera(camera);
738 painter.modelViewMatrix().translate(0.0f, 5.0f, 0.0f);
739 painter.modelViewMatrix().scale(1.5f);
740 QMatrix4x4 world = painter.worldMatrix();
741 \endcode
742
743 Note: the world matrix is determined by multiplying the inverse of
744 the camera's look at component with the current modelview matrix.
745 Thus, the result may not be precisely the same as constructing a
746 matrix from translate and scale operations starting with the identity.
747
748 \sa modelViewMatrix(), setCamera()
749*/
750QMatrix4x4 QGLPainter::worldMatrix() const
751{
752 Q_D(const QGLPainter);
753 QGLPAINTER_CHECK_PRIVATE();
754 return qt_gl_stablize_matrix
755 (d->inverseEyeMatrix * d->modelViewMatrix.top());
756}
757
758/*!
759 \fn QMatrix3x3 QGLPainter::normalMatrix() const
760
761 Returns the normal matrix corresponding to modelViewMatrix().
762
763 The normal matrix is the transpose of the inverse of the top-left
764 3x3 part of the 4x4 modelview matrix. If the 3x3 sub-matrix is not
765 invertible, this function returns the identity.
766
767 \sa modelViewMatrix(), combinedMatrix()
768*/
769QMatrix3x3 QGLPainter::normalMatrix() const
770{
771 const QGLPainterPrivate *d = d_func();
772 if (!d)
773 return QMatrix3x3();
774 const QMatrix4x4StackPrivate *mv = d->modelViewMatrix.d_func();
775 return mv->matrix.normalMatrix();
776}
777
778/*!
779 Returns the camera eye that is currently being used for stereo
780 rendering. The default is QGL::NoEye.
781
782 The eye is used to adjust the camera position by a small amount
783 when setCamera() is called.
784
785 \sa setEye(), setCamera()
786*/
787QGL::Eye QGLPainter::eye() const
788{
789 Q_D(const QGLPainter);
790 QGLPAINTER_CHECK_PRIVATE();
791 return d->eye;
792}
793
794/*!
795 Sets the camera \a eye that is currently being used for stereo
796 rendering.
797
798 The \a eye is used to adjust the camera position by a small amount
799 when setCamera() is called.
800
801 \sa eye(), setCamera()
802*/
803void QGLPainter::setEye(QGL::Eye eye)
804{
805 Q_D(QGLPainter);
806 QGLPAINTER_CHECK_PRIVATE();
807 d->eye = eye;
808}
809
810/*!
811 Sets the modelViewMatrix() and projectionMatrix() to the view
812 defined by \a camera. If eye() is not QGL::NoEye, then the view
813 will be adjusted for the camera's eye separation.
814
815 This function is typically called at the beginning of a scene rendering
816 pass to initialize the modelview and projection matrices.
817
818 Note that this does not cause the painter to take ownership of the camera
819 and it does not save the pointer value. The \a camera may be safely
820 deleted after calling this function.
821
822 \sa eye(), modelViewMatrix(), projectionMatrix(), worldMatrix()
823*/
824void QGLPainter::setCamera(const QGLCamera *camera)
825{
826 Q_ASSERT(camera);
827 Q_D(QGLPainter);
828 QGLPAINTER_CHECK_PRIVATE();
829 QMatrix4x4 lookAt = camera->modelViewMatrix(d->eye);
830 d->modelViewMatrix = lookAt;
831 d->projectionMatrix = camera->projectionMatrix(aspectRatio());
832 d->inverseEyeMatrix = lookAt.inverted();
833}
834
835/*!
836 Returns true if \a point is outside the current viewing volume.
837 This is used to perform object culling checks.
838*/
839bool QGLPainter::isCullable(const QVector3D& point) const
840{
841 Q_D(const QGLPainter);
842 QGLPAINTER_CHECK_PRIVATE();
843 QVector3D projected = d->modelViewMatrix * point;
844 projected = d->projectionMatrix * projected;
845 return !d->viewingCube.contains(projected);
846}
847
848static inline uint outcode(const QVector4D &v)
849{
850 // For a discussion of outcodes see pg 388 Dunn & Parberry.
851 // For why you can't just test if the point is in a bounding box
852 // consider the case where a view frustum with view-size 1.5 x 1.5
853 // is tested against a 2x2 box which encloses the near-plane, while
854 // all the points in the box are outside the frustum.
855 // TODO: optimise this with assembler - according to D&P this can
856 // be done in one line of assembler on some platforms
857 uint code = 0;
858 if (v.x() < -v.w()) code |= 0x01;
859 if (v.x() > v.w()) code |= 0x02;
860 if (v.y() < -v.w()) code |= 0x04;
861 if (v.y() > v.w()) code |= 0x08;
862 if (v.z() < -v.w()) code |= 0x10;
863 if (v.z() > v.w()) code |= 0x20;
864 return code;
865}
866
867/*!
868 Returns true if \a box is completely outside the current viewing volume.
869 This is used to perform object culling checks.
870*/
871bool QGLPainter::isCullable(const QBox3D& box) const
872{
873 Q_D(const QGLPainter);
874 QGLPAINTER_CHECK_PRIVATE();
875 // This function uses the technique of view frustum culling known as
876 // clip space testing. Since the normal QVector3D representation
877 // of the points throws away the w value needed, we convert the box
878 // into a set of 8 points represented as QVector4D's and then apply
879 // the test. The test is to transform the points into clip space
880 // by applying the MV and Proj matrices, then test to see if the 4D
881 // points are outside the clip space by testing x, y & z against w.
882 QArray<QVector4D> box4d;
883 QVector3D n = box.minimum();
884 QVector3D x = box.maximum();
885 box4d.append(QVector4D(n.x(), n.y(), x.z(), 1), QVector4D(x.x(), n.y(), x.z(), 1),
886 QVector4D(x.x(), x.y(), x.z(), 1), QVector4D(n.x(), x.y(), x.z(), 1));
887 box4d.append(QVector4D(n.x(), n.y(), n.z(), 1), QVector4D(x.x(), n.y(), n.z(), 1),
888 QVector4D(x.x(), x.y(), n.z(), 1), QVector4D(n.x(), x.y(), n.z(), 1));
889 QMatrix4x4 mvp = d->projectionMatrix.top() * d->modelViewMatrix.top();
890 for (int i = 0; i < box4d.size(); ++i)
891 {
892 box4d[i] = mvp * box4d.at(i);
893 }
894 // if the logical AND of all the outcodes is non-zero then the BB is
895 // definitely outside the view frustum.
896 uint out = 0xff;
897 for (int i = 0; i < box4d.size(); ++i)
898 {
899 out = out & outcode(box4d.at(i));
900 }
901 return out;
902}
903
904/*!
905 Returns the current render order sequencer.
906
907 \sa QGLRenderSequencer
908*/
909QGLRenderSequencer *QGLPainter::renderSequencer()
910{
911 Q_D(QGLPainter);
912 if (!d->renderSequencer)
913 d->renderSequencer = new QGLRenderSequencer(this);
914 return d->renderSequencer;
915}
916
917/*!
918 Returns the aspect ratio of the viewport for adjusting projection
919 transformations.
920*/
921qreal QGLPainter::aspectRatio() const
922{
923 return currentSurface()->aspectRatio();
924}
925
926/*!
927 Returns the current effect that is in use, which is userEffect()
928 if it is not null, or the effect object associated with
929 standardEffect() otherwise.
930
931 If isPicking() is true, then this will return the effect object
932 that is being used to generate pick colors.
933
934 \sa userEffect(), standardEffect(), isPicking()
935*/
936QGLAbstractEffect *QGLPainter::effect() const
937{
938 Q_D(QGLPainter);
939 QGLPAINTER_CHECK_PRIVATE();
940 d->ensureEffect(const_cast<QGLPainter *>(this));
941 return d->effect;
942}
943
944/*!
945 Returns the user-defined effect that is being used for drawing
946 operations, or null if standardEffect() is in use.
947
948 \sa setUserEffect(), standardEffect(), effect()
949*/
950QGLAbstractEffect *QGLPainter::userEffect() const
951{
952 Q_D(QGLPainter);
953 QGLPAINTER_CHECK_PRIVATE();
954 return d->userEffect;
955}
956
957/*!
958 Sets a user-defined \a effect to use for drawing operations
959 in the current GL context. If \a effect is null, this will
960 disable user-defined effects and return to using standardEffect().
961
962 \sa effect(), draw(), setStandardEffect()
963*/
964void QGLPainter::setUserEffect(QGLAbstractEffect *effect)
965{
966 Q_D(QGLPainter);
967 QGLPAINTER_CHECK_PRIVATE();
968 if (d->userEffect == effect)
969 return;
970 if (d->effect)
971 d->effect->setActive(this, false);
972 d->userEffect = effect;
973 if (effect && (!d->pick || !d->pick->isPicking)) {
974 d->effect = effect;
975 d->effect->setActive(this, true);
976 d->updates = UpdateAll;
977 } else {
978 // Revert to the effect associated with standardEffect().
979 d->effect = 0;
980 d->ensureEffect(this);
981 }
982}
983
984/*!
985 Returns the standard effect to use for rendering fragments in
986 the current GL context when userEffect() is null.
987
988 \sa setStandardEffect(), userEffect()
989*/
990QGL::StandardEffect QGLPainter::standardEffect() const
991{
992 Q_D(QGLPainter);
993 QGLPAINTER_CHECK_PRIVATE();
994 return d->standardEffect;
995}
996
997/*!
998 Sets a standard \a effect to use for rendering fragments
999 in the current GL context. This will also set userEffect()
1000 to null. If \a effect is an invalid value, then the behavior
1001 of QGL::FlatColor will be used instead.
1002
1003 \sa standardEffect(), setUserEffect()
1004*/
1005void QGLPainter::setStandardEffect(QGL::StandardEffect effect)
1006{
1007 Q_D(QGLPainter);
1008 QGLPAINTER_CHECK_PRIVATE();
1009 if (d->standardEffect == effect && d->effect && d->userEffect == 0)
1010 return;
1011 if (d->effect)
1012 d->effect->setActive(this, false);
1013 d->standardEffect = effect;
1014 d->userEffect = 0;
1015 d->effect = 0;
1016 d->ensureEffect(this);
1017}
1018
1019/*!
1020 Disables the current effect and sets userEffect() to null.
1021 Unlike setUserEffect() this not activate the standardEffect()
1022 until the next time effect() is called.
1023
1024 This function can be used to disable all effect-based drawing
1025 operations prior to performing raw GL calls. The next time
1026 effect() is called on this QGLPainter, the standardEffect()
1027 will be reactivated. An effect can also be reactivated by
1028 calling setUserEffect() or setStandardEffect().
1029
1030 \sa userEffect(), standardEffect()
1031*/
1032void QGLPainter::disableEffect()
1033{
1034 Q_D(QGLPainter);
1035 QGLPAINTER_CHECK_PRIVATE();
1036 if (d->effect)
1037 d->effect->setActive(this, false);
1038 d->userEffect = 0;
1039 d->effect = 0;
1040}
1041
1042/*!
1043 Returns the cached shader program associated with \a name; or null
1044 if \a name is not currently associated with a shader program.
1045
1046 \sa setCachedProgram()
1047*/
1048QOpenGLShaderProgram *QGLPainter::cachedProgram(const QString& name) const
1049{
1050 Q_D(const QGLPainter);
1051 QGLPAINTER_CHECK_PRIVATE();
1052 return d->cachedPrograms.value(name, 0);
1053}
1054
1055/*!
1056 Sets the cached shader \a program associated with \a name.
1057
1058 Effect objects can use this function to store pre-compiled
1059 and pre-linked shader programs in the painter for future
1060 use by the same effect. The \a program will be destroyed
1061 when context() is destroyed.
1062
1063 If \a program is null, then the program associated with \a name
1064 will be destroyed. If \a name is already present as a cached
1065 program, then it will be replaced with \a program.
1066
1067 Names that start with "\c{qt.}" are reserved for use by Qt's
1068 internal effects.
1069
1070 \sa cachedProgram()
1071*/
1072void QGLPainter::setCachedProgram
1073 (const QString& name, QOpenGLShaderProgram *program)
1074{
1075 Q_D(QGLPainter);
1076 QGLPAINTER_CHECK_PRIVATE();
1077 QOpenGLShaderProgram *current = d->cachedPrograms.value(name, 0);
1078 if (current != program) {
1079 if (program)
1080 d->cachedPrograms[name] = program;
1081 else
1082 d->cachedPrograms.remove(name);
1083 delete current;
1084 }
1085}
1086
1087void QGLPainterPrivate::createEffect(QGLPainter *painter)
1088{
1089 if (userEffect) {
1090 if (!pick || !pick->isPicking) {
1091 effect = userEffect;
1092 effect->setActive(painter, true);
1093 updates = QGLPainter::UpdateAll;
1094 return;
1095 }
1096 if (userEffect->supportsPicking()) {
1097 effect = userEffect;
1098 effect->setActive(painter, true);
1099 updates = QGLPainter::UpdateAll;
1100 return;
1101 }
1102 effect = pick->defaultPickEffect;
1103 effect->setActive(painter, true);
1104 updates = QGLPainter::UpdateAll;
1105 return;
1106 }
1107 if (uint(standardEffect) >= QGL_MAX_STD_EFFECTS)
1108 effect = stdeffects[int(QGL::FlatColor)];
1109 else
1110 effect = stdeffects[int(standardEffect)];
1111 if (!effect) {
1112 switch (standardEffect) {
1113 case QGL::FlatColor: default:
1114 effect = new QGLFlatColorEffect();
1115 break;
1116 case QGL::FlatPerVertexColor:
1117 effect = new QGLPerVertexColorEffect();
1118 break;
1119 case QGL::FlatReplaceTexture2D:
1120 effect = new QGLFlatTextureEffect();
1121 break;
1122 case QGL::FlatDecalTexture2D:
1123 effect = new QGLFlatDecalTextureEffect();
1124 break;
1125 case QGL::LitMaterial:
1126 effect = new QGLLitMaterialEffect();
1127 break;
1128 case QGL::LitDecalTexture2D:
1129 effect = new QGLLitDecalTextureEffect();
1130 break;
1131 case QGL::LitModulateTexture2D:
1132 effect = new QGLLitModulateTextureEffect();
1133 break;
1134 }
1135 if (uint(standardEffect) >= QGL_MAX_STD_EFFECTS)
1136 stdeffects[int(QGL::FlatColor)] = effect;
1137 else
1138 stdeffects[int(standardEffect)] = effect;
1139 }
1140 if (!pick || !pick->isPicking || effect->supportsPicking()) {
1141 effect->setActive(painter, true);
1142 } else {
1143 effect = pick->defaultPickEffect;
1144 effect->setActive(painter, true);
1145 }
1146 updates = QGLPainter::UpdateAll;
1147}
1148
1149/*!
1150 Returns the last color that was set with setColor(). The default
1151 value is (1, 1, 1, 1).
1152
1153 \sa setColor()
1154*/
1155QColor QGLPainter::color() const
1156{
1157 Q_D(QGLPainter);
1158 QGLPAINTER_CHECK_PRIVATE();
1159 return d->color;
1160}
1161
1162/*!
1163 Sets the default fragment \a color for effects associated
1164 with this painter. This function does not apply the color
1165 to the effect until update() is called.
1166
1167 \sa color(), update()
1168*/
1169void QGLPainter::setColor(const QColor& color)
1170{
1171 Q_D(QGLPainter);
1172 QGLPAINTER_CHECK_PRIVATE();
1173 d->color = color;
1174 d->updates |= UpdateColor;
1175}
1176
1177static void qt_gl_setVertexAttribute(QGL::VertexAttribute attribute, const QGLAttributeValue& value)
1178{
1179#if !defined(QT_OPENGL_ES_2)
1180 switch (attribute) {
1181 case QGL::Position:
1182 glVertexPointer(value.tupleSize(), value.type(),
1183 value.stride(), value.data());
1184 break;
1185
1186 case QGL::Normal:
1187 if (value.tupleSize() == 3)
1188 glNormalPointer(value.type(), value.stride(), value.data());
1189 break;
1190
1191 case QGL::Color:
1192 glColorPointer(value.tupleSize(), value.type(),
1193 value.stride(), value.data());
1194 break;
1195
1196#ifdef GL_TEXTURE_COORD_ARRAY
1197 case QGL::TextureCoord0:
1198 case QGL::TextureCoord1:
1199 case QGL::TextureCoord2:
1200 {
1201 int unit = (int)(attribute - QGL::TextureCoord0);
1202 qt_gl_ClientActiveTexture(GL_TEXTURE0 + unit);
1203 glTexCoordPointer(value.tupleSize(), value.type(),
1204 value.stride(), value.data());
1205 if (unit != 0) // Stay on unit 0 between requests.
1206 qt_gl_ClientActiveTexture(GL_TEXTURE0);
1207 }
1208 break;
1209#endif
1210
1211 default: break;
1212 }
1213#else
1214 Q_UNUSED(attribute);
1215 Q_UNUSED(value);
1216#endif
1217}
1218
1219/*!
1220 Returns the set of vertex attributes that have been set on the
1221 painter state by setVertexAttribute() and setVertexBundle()
1222 since the last call to clearAttributes().
1223
1224 The most common use for this function is to determine if specific
1225 attributes have been supplied on the painter so as to adjust the
1226 current drawing effect accordingly. The following example will
1227 use a lit texture effect if texture co-ordinates were provided
1228 in the vertex bundle, or a simple lit material effect if
1229 texture co-ordinates were not provided:
1230
1231 \code
1232 painter.clearAttributes();
1233 painter.setVertexBundle(bundle);
1234 if (painter.attributes().contains(QGL::TextureCoord0))
1235 painter.setStandardEffect(QGL::LitModulateTexture2D);
1236 else
1237 painter.setStandardEffect(QGL::LitMaterial);
1238 \endcode
1239
1240 It is important to clear the attributes before setting the vertex
1241 bundle, so that attributes from a previous bundle will not leak
1242 through. Multiple vertex bundles may be supplied if they contain
1243 different parts of the same logical piece of geometry.
1244
1245 \sa clearAttributes(), setVertexBundle()
1246*/
1247QGLAttributeSet QGLPainter::attributes() const
1248{
1249 Q_D(const QGLPainter);
1250 QGLPAINTER_CHECK_PRIVATE();
1251 return d->attributeSet;
1252}
1253
1254/*!
1255 Clears the set of vertex attributes that have been set on the
1256 painter state by setVertexAttribute() and setVertexBundle().
1257 See the documentation for attributes() for more information.
1258
1259 \sa attributes()
1260*/
1261void QGLPainter::clearAttributes()
1262{
1263 Q_D(QGLPainter);
1264 QGLPAINTER_CHECK_PRIVATE();
1265 d->attributeSet.clear();
1266}
1267
1268/*!
1269 Sets a vertex \a attribute on the current GL context to \a value.
1270
1271 The vertex attribute is bound to the GL state on the index
1272 corresponding to \a attribute. For example, QGL::Position
1273 will be bound to index 0, QGL::TextureCoord0 will be bound
1274 to index 3, etc.
1275
1276 Vertex attributes are independent of the effect() and can be
1277 bound once and then used with multiple effects.
1278
1279 If this is the first attribute in a new piece of geometry,
1280 it is recommended that clearAttributes() be called before this
1281 function. This will inform QGLPainter that a new piece of geometry
1282 is being provided and that the previous geometry is now invalid.
1283 See the documentation for attributes() for more information.
1284
1285 \sa setVertexBundle(), draw(), clearAttributes(), attributes()
1286*/
1287void QGLPainter::setVertexAttribute
1288 (QGL::VertexAttribute attribute, const QGLAttributeValue& value)
1289{
1290 Q_D(QGLPainter);
1291 QGLPAINTER_CHECK_PRIVATE();
1292 d->ensureEffect(this);
1293 if (d->boundVertexBuffer) {
1294 QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
1295 d->boundVertexBuffer = 0;
1296 }
1297 if (d->isFixedFunction) {
1298 qt_gl_setVertexAttribute(attribute, value);
1299 } else {
1300 glVertexAttribPointer(GLuint(attribute), value.tupleSize(),
1301 value.type(), GL_TRUE,
1302 value.stride(), value.data());
1303 }
1304 d->attributeSet.insert(attribute);
1305}
1306
1307/*!
1308 Sets the vertex attributes on the current GL context that are
1309 stored in \a buffer.
1310
1311 The vertex attributes are bound to the GL state on the indexes
1312 that are specified within \a buffer; QGL::Position will be
1313 bound to index 0, QGL::TextureCoord0 will be bound to index 3, etc.
1314
1315 Vertex attributes are independent of the effect() and can be
1316 bound once and then used with multiple effects.
1317
1318 It is recommended that clearAttributes() be called before this
1319 function to inform QGLPainter that a new piece of geometry is
1320 being provided and that the previous geometry is now invalid.
1321 See the documentation for attributes() for more information.
1322
1323 \sa setVertexAttribute(), draw(), clearAttributes(), attributes()
1324*/
1325void QGLPainter::setVertexBundle(const QGLVertexBundle& buffer)
1326{
1327 Q_D(QGLPainter);
1328 QGLPAINTER_CHECK_PRIVATE();
1329 d->ensureEffect(this);
1330 QGLVertexBundlePrivate *bd = const_cast<QGLVertexBundlePrivate *>(buffer.d_func());
1331 if (bd->buffer.isCreated()) {
1332 GLuint id = bd->buffer.bufferId();
1333 if (id != d->boundVertexBuffer) {
1334 bd->buffer.bind();
1335 d->boundVertexBuffer = id;
1336 }
1337 } else if (d->boundVertexBuffer) {
1338 QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
1339 d->boundVertexBuffer = 0;
1340 }
1341 for (int index = 0; index < bd->attributes.size(); ++index) {
1342 QGLVertexBundleAttribute *attr = bd->attributes[index];
1343 if (d->isFixedFunction) {
1344 qt_gl_setVertexAttribute(attr->attribute, attr->value);
1345 } else {
1346 glVertexAttribPointer(GLuint(attr->attribute),
1347 attr->value.tupleSize(),
1348 attr->value.type(), GL_TRUE,
1349 attr->value.stride(), attr->value.data());
1350 }
1351 }
1352 d->attributeSet.unite(buffer.attributes());
1353}
1354
1355/*!
1356 Updates the projection matrix, modelview matrix, and lighting
1357 conditions in the currently active effect() object by calling
1358 QGLAbstractEffect::update(). Also updates \c{glViewport()}
1359 to cover the currentSurface() if necessary.
1360
1361 Normally this function is called automatically by draw().
1362 However, if the user wishes to use raw GL functions to draw fragments,
1363 it will be necessary to explicitly call this function to ensure that
1364 the matrix state and lighting conditions have been set on the
1365 active effect().
1366
1367 Note that this function informs the effect that an update is needed.
1368 It does not change the GL state itself, except for \c{glViewport()}.
1369 In particular, the modelview and projection matrices in the
1370 fixed-function pipeline are not changed unless the effect or
1371 application calls updateFixedFunction().
1372
1373 \sa setUserEffect(), projectionMatrix(), modelViewMatrix()
1374 \sa draw(), updateFixedFunction()
1375*/
1376void QGLPainter::update()
1377{
1378 Q_D(QGLPainter);
1379 QGLPAINTER_CHECK_PRIVATE();
1380 d->ensureEffect(this);
1381 QGLPainter::Updates updates = d->updates;
1382 d->updates = 0;
1383 if (d->modelViewMatrix.isDirty()) {
1384 updates |= UpdateModelViewMatrix;
1385 d->modelViewMatrix.setDirty(false);
1386 }
1387 if (d->projectionMatrix.isDirty()) {
1388 updates |= UpdateProjectionMatrix;
1389 d->projectionMatrix.setDirty(false);
1390 }
1391 if ((updates & UpdateViewport) != 0) {
1392 QRect viewport = currentSurface()->viewportGL();
1393 glViewport(0, 0, viewport.width(), viewport.height());
1394 }
1395 if (updates != 0)
1396 d->effect->update(this, updates);
1397}
1398
1399#if !defined(QT_OPENGL_ES_2)
1400
1401static void setLight(int light, const QGLLightParameters *parameters,
1402 const QMatrix4x4& transform)
1403{
1404 GLfloat params[4];
1405
1406 QColor color = parameters->ambientColor();
1407 params[0] = color.redF();
1408 params[1] = color.greenF();
1409 params[2] = color.blueF();
1410 params[3] = color.alphaF();
1411 glLightfv(light, GL_AMBIENT, params);
1412
1413 color = parameters->diffuseColor();
1414 params[0] = color.redF();
1415 params[1] = color.greenF();
1416 params[2] = color.blueF();
1417 params[3] = color.alphaF();
1418 glLightfv(light, GL_DIFFUSE, params);
1419
1420 color = parameters->specularColor();
1421 params[0] = color.redF();
1422 params[1] = color.greenF();
1423 params[2] = color.blueF();
1424 params[3] = color.alphaF();
1425 glLightfv(light, GL_SPECULAR, params);
1426
1427 QVector4D vector = parameters->eyePosition(transform);
1428 params[0] = vector.x();
1429 params[1] = vector.y();
1430 params[2] = vector.z();
1431 params[3] = vector.w();
1432 glLightfv(light, GL_POSITION, params);
1433
1434 QVector3D spotDirection = parameters->eyeSpotDirection(transform);
1435 params[0] = spotDirection.x();
1436 params[1] = spotDirection.y();
1437 params[2] = spotDirection.z();
1438 glLightfv(light, GL_SPOT_DIRECTION, params);
1439
1440 params[0] = parameters->spotExponent();
1441 glLightfv(light, GL_SPOT_EXPONENT, params);
1442
1443 params[0] = parameters->spotAngle();
1444 glLightfv(light, GL_SPOT_CUTOFF, params);
1445
1446 params[0] = parameters->constantAttenuation();
1447 glLightfv(light, GL_CONSTANT_ATTENUATION, params);
1448
1449 params[0] = parameters->linearAttenuation();
1450 glLightfv(light, GL_LINEAR_ATTENUATION, params);
1451
1452 params[0] = parameters->quadraticAttenuation();
1453 glLightfv(light, GL_QUADRATIC_ATTENUATION, params);
1454}
1455
1456static void setMaterial(int face, const QGLMaterial *parameters)
1457{
1458 GLfloat params[17];
1459
1460 QColor mcolor = parameters->ambientColor();
1461 params[0] = mcolor.redF();
1462 params[1] = mcolor.greenF();
1463 params[2] = mcolor.blueF();
1464 params[3] = mcolor.alphaF();
1465
1466 mcolor = parameters->diffuseColor();
1467 params[4] = mcolor.redF();
1468 params[5] = mcolor.greenF();
1469 params[6] = mcolor.blueF();
1470 params[7] = mcolor.alphaF();
1471
1472 mcolor = parameters->specularColor();
1473 params[8] = mcolor.redF();
1474 params[9] = mcolor.greenF();
1475 params[10] = mcolor.blueF();
1476 params[11] = mcolor.alphaF();
1477
1478 mcolor = parameters->emittedLight();
1479 params[12] = mcolor.redF();
1480 params[13] = mcolor.greenF();
1481 params[14] = mcolor.blueF();
1482 params[15] = mcolor.alphaF();
1483
1484 params[16] = parameters->shininess();
1485
1486 glMaterialfv(face, GL_AMBIENT, params);
1487 glMaterialfv(face, GL_DIFFUSE, params + 4);
1488 glMaterialfv(face, GL_SPECULAR, params + 8);
1489 glMaterialfv(face, GL_EMISSION, params + 12);
1490 glMaterialfv(face, GL_SHININESS, params + 16);
1491}
1492
1493#endif // !QT_OPENGL_ES_2
1494
1495/*!
1496 Updates the fixed-function pipeline with the current painting
1497 state according to the flags in \a updates.
1498
1499 This function is intended for use by effects in their
1500 QGLAbstractEffect::update() override if they are using the
1501 fixed-function pipeline. It can also be used by user
1502 applications if they need the QGLPainter state to be
1503 set in the fixed-function pipeline.
1504
1505 If the OpenGL implementation does not have a fixed-function
1506 pipeline, e.g. OpenGL/ES 2.0, this function does nothing.
1507
1508 \sa update()
1509*/
1510void QGLPainter::updateFixedFunction(QGLPainter::Updates updates)
1511{
1512#if defined(QT_OPENGL_ES_2)
1513 Q_UNUSED(updates);
1514#else
1515 Q_D(QGLPainter);
1516 QGLPAINTER_CHECK_PRIVATE();
1517 if ((updates & QGLPainter::UpdateColor) != 0) {
1518 QColor color;
1519 if (isPicking())
1520 color = pickColor();
1521 else
1522 color = this->color();
1523 glColor4f(color.redF(), color.greenF(), color.blueF(), color.alphaF());
1524 }
1525 if ((updates & QGLPainter::UpdateModelViewMatrix) != 0) {
1526 const QMatrix4x4 &matrix = d->modelViewMatrix.top();
1527 glMatrixMode(GL_MODELVIEW);
1528 if (sizeof(qreal) == sizeof(GLfloat)) {
1529 glLoadMatrixf(reinterpret_cast<const GLfloat *>
1530 (matrix.constData()));
1531 } else {
1532 GLfloat mat[16];
1533 const qreal *m = matrix.constData();
1534 for (int index = 0; index < 16; ++index)
1535 mat[index] = m[index];
1536 glLoadMatrixf(mat);
1537 }
1538 }
1539 if ((updates & QGLPainter::UpdateProjectionMatrix) != 0) {
1540 const QMatrix4x4 &matrix = d->projectionMatrix.top();
1541 glMatrixMode(GL_PROJECTION);
1542 if (sizeof(qreal) == sizeof(GLfloat)) {
1543 glLoadMatrixf(reinterpret_cast<const GLfloat *>
1544 (matrix.constData()));
1545 } else {
1546 GLfloat mat[16];
1547 const qreal *m = matrix.constData();
1548 for (int index = 0; index < 16; ++index)
1549 mat[index] = m[index];
1550 glLoadMatrixf(mat);
1551 }
1552 }
1553 if ((updates & QGLPainter::UpdateLights) != 0) {
1554 // Save the current modelview matrix and load the identity.
1555 // We need to apply the light in the modelview transformation
1556 // that was active when the light was specified.
1557 glMatrixMode(GL_MODELVIEW);
1558 glPushMatrix();
1559 glLoadIdentity();
1560
1561 // Enable the main light.
1562 const QGLLightParameters *params = mainLight();
1563 setLight(GL_LIGHT0, params, mainLightTransform());
1564
1565 // Restore the previous modelview transformation.
1566 glPopMatrix();
1567
1568 // Set up the light model parameters if at least one light is enabled.
1569 const QGLLightModel *lightModel = this->lightModel();
1570 GLfloat values[4];
1571#ifdef GL_LIGHT_MODEL_TWO_SIDE
1572 if (lightModel->model() == QGLLightModel::TwoSided)
1573 values[0] = 1.0f;
1574 else
1575 values[0] = 0.0f;
1576 glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, values);
1577#endif
1578#ifdef GL_LIGHT_MODEL_COLOR_CONTROL
1579 if (lightModel->colorControl() == QGLLightModel::SeparateSpecularColor)
1580 values[0] = GL_SEPARATE_SPECULAR_COLOR;
1581 else
1582 values[0] = GL_SINGLE_COLOR;
1583 glLightModelfv(GL_LIGHT_MODEL_COLOR_CONTROL, values);
1584#endif
1585#ifdef GL_LIGHT_MODEL_LOCAL_VIEWER
1586 if (lightModel->viewerPosition() == QGLLightModel::LocalViewer)
1587 values[0] = 1.0f;
1588 else
1589 values[0] = 0.0f;
1590 glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, values);
1591#endif
1592#ifdef GL_LIGHT_MODEL_AMBIENT
1593 QColor color = lightModel->ambientSceneColor();
1594 values[0] = color.redF();
1595 values[1] = color.blueF();
1596 values[2] = color.greenF();
1597 values[3] = color.alphaF();
1598 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, values);
1599#endif
1600 }
1601 if ((updates & QGLPainter::UpdateMaterials) != 0) {
1602 const QGLMaterial *frontMaterial = faceMaterial(QGL::FrontFaces);
1603 const QGLMaterial *backMaterial = faceMaterial(QGL::BackFaces);
1604 if (frontMaterial == backMaterial) {
1605 setMaterial(GL_FRONT_AND_BACK, frontMaterial);
1606 } else {
1607 setMaterial(GL_FRONT, frontMaterial);
1608 setMaterial(GL_BACK, backMaterial);
1609 }
1610 }
1611#endif
1612}
1613
1614/*!
1615 Draws primitives using \a count vertices from the arrays specified
1616 by setVertexAttribute(). The type of primitive to draw is specified
1617 by \a mode.
1618
1619 This operation will consume \a count values from the
1620 enabled arrays, starting at \a index.
1621
1622 \sa update()
1623*/
1624void QGLPainter::draw(QGL::DrawingMode mode, int count, int index)
1625{
1626 update();
1627 glDrawArrays((GLenum)mode, index, count);
1628}
1629
1630/*!
1631 \overload
1632
1633 Draws primitives using vertices from the arrays specified by
1634 setVertexAttribute(). The type of primitive to draw is
1635 specified by \a mode.
1636
1637 This operation will consume \a count elements of \a indices,
1638 which are used to index into the enabled arrays.
1639
1640 \sa update()
1641*/
1642void QGLPainter::draw(QGL::DrawingMode mode, const ushort *indices, int count)
1643{
1644 Q_D(QGLPainter);
1645 QGLPAINTER_CHECK_PRIVATE();
1646 update();
1647 if (d->boundIndexBuffer) {
1648 QOpenGLBuffer::release(QOpenGLBuffer::IndexBuffer);
1649 d->boundIndexBuffer = 0;
1650 }
1651 glDrawElements(GLenum(mode), count, GL_UNSIGNED_SHORT, indices);
1652}
1653
1654/*!
1655 Pushes \a surface onto the surface stack and makes it the current
1656 drawing surface for context(). If \a surface is null, then the
1657 current drawing surface will be set to the main surface (e.g. the window).
1658
1659 Note: the \a surface object must remain valid until popped from
1660 the stack or end() is called. All surfaces are popped from
1661 the stack by end().
1662
1663 The UpdateViewport flag will be set to indicate that the
1664 \c{glViewport()} should be adjusted to the extents of \a surface
1665 when update() is next called.
1666
1667 \sa popSurface(), currentSurface(), setSurface()
1668 \sa QGLAbstractSurface::activate()
1669*/
1670void QGLPainter::pushSurface(QGLAbstractSurface *surface)
1671{
1672 Q_D(QGLPainter);
1673 QGLPAINTER_CHECK_PRIVATE();
1674 Q_ASSERT(surface);
1675 if (!surface) {
1676 // Find the most recent main surface for this painter.
1677 int size = d->surfaceStack.size();
1678 while (size > 0 && !d->surfaceStack[size - 1].mainSurface)
1679 --size;
1680 if (!size)
1681 return; // Shouldn't happen, but be safe anyway.
1682 surface = d->surfaceStack[size - 1].surface;
1683 }
1684 Q_ASSERT(!d->surfaceStack.isEmpty()); // Should have a main surface.
1685 QGLAbstractSurface *current = d->surfaceStack.top().surface;
1686 QGLPainterSurfaceInfo psurf;
1687 psurf.surface = surface;
1688 psurf.destroySurface = false;
1689 psurf.mainSurface = false;
1690 d->surfaceStack.append(psurf);
1691 current->switchTo(surface);
1692 d->updates |= UpdateViewport;
1693}
1694
1695/*!
1696 Pops the top-most drawing surface from the surface stack
1697 and returns it. The next object on the stack will be made
1698 the current drawing surface for context(). Returns null if the
1699 surface stack is already at the main surface (e.g. the window).
1700
1701 The UpdateViewport flag will be set to indicate that the
1702 \c{glViewport()} should be adjusted to the new surface extents
1703 when update() is next called.
1704
1705 \sa pushSurface(), currentSurface(), setSurface()
1706*/
1707QGLAbstractSurface *QGLPainter::popSurface()
1708{
1709 Q_D(QGLPainter);
1710 QGLPAINTER_CHECK_PRIVATE();
1711 Q_ASSERT(!d->surfaceStack.isEmpty()); // Should have a main surface.
1712 QGLPainterSurfaceInfo &surf = d->surfaceStack.top();
1713 if (surf.mainSurface)
1714 return 0;
1715 QGLAbstractSurface *surface = surf.surface;
1716 d->surfaceStack.pop();
1717 Q_ASSERT(!d->surfaceStack.isEmpty()); // Should have a main surface.
1718 QGLAbstractSurface *nextSurface = d->surfaceStack.top().surface;
1719 surface->switchTo(nextSurface);
1720 d->updates |= UpdateViewport;
1721 return surface;
1722}
1723
1724/*!
1725 Sets the top-most drawing surface on the surface stack to \a surface
1726 and activate it.
1727
1728 Note: if the top-most drawing surface is the main surface specified
1729 during begin(), then this function will perform a pushSurface()
1730 instead. Typically this function is used to replace the last
1731 surface that was pushed onto the stack and avoid doing popSurface()
1732 followed by pushSurface(). The main surface cannot be replaced
1733 in this manner.
1734
1735 The UpdateViewport flag will be set to indicate that the
1736 \c{glViewport()} should be adjusted to the extents of \a surface
1737 when update() is next called.
1738
1739 \sa pushSurface(), popSurface(), currentSurface()
1740*/
1741void QGLPainter::setSurface(QGLAbstractSurface *surface)
1742{
1743 Q_D(QGLPainter);
1744 QGLPAINTER_CHECK_PRIVATE();
1745 Q_ASSERT(surface);
1746 Q_ASSERT(!d->surfaceStack.isEmpty()); // Should have a main surface.
1747 QGLPainterSurfaceInfo &surf = d->surfaceStack.top();
1748 if (surf.mainSurface) {
1749 pushSurface(surface);
1750 return;
1751 }
1752 QGLAbstractSurface *oldSurface = surf.surface;
1753 surf.surface = surface;
1754 oldSurface->switchTo(surface);
1755 d->updates |= UpdateViewport;
1756}
1757
1758/*!
1759 Returns the current drawing surface.
1760
1761 \sa pushSurface(), popSurface(), setSurface()
1762*/
1763QGLAbstractSurface *QGLPainter::currentSurface() const
1764{
1765 Q_D(const QGLPainter);
1766 QGLPAINTER_CHECK_PRIVATE();
1767 Q_ASSERT(!d->surfaceStack.isEmpty()); // Should have a main surface.
1768 return d->surfaceStack.top().surface;
1769}
1770
1771/*!
1772 Returns the current lighting model.
1773
1774 \sa setLightModel()
1775*/
1776const QGLLightModel *QGLPainter::lightModel() const
1777{
1778 Q_D(QGLPainter);
1779 QGLPAINTER_CHECK_PRIVATE();
1780 if (!d->lightModel) {
1781 if (!d->defaultLightModel)
1782 d->defaultLightModel = new QGLLightModel();
1783 d->lightModel = d->defaultLightModel;
1784 }
1785 return d->lightModel;
1786}
1787
1788/*!
1789 Sets the current lighting model to \a value. If \a value is
1790 null, then the default lighting model parameters will be used.
1791
1792 The light settings in the GL server will not be changed until
1793 update() is called.
1794
1795 \sa lightModel()
1796*/
1797void QGLPainter::setLightModel(const QGLLightModel *value)
1798{
1799 Q_D(QGLPainter);
1800 QGLPAINTER_CHECK_PRIVATE();
1801 d->lightModel = value;
1802 d->updates |= QGLPainter::UpdateLights;
1803}
1804
1805/*!
1806 Returns the parameters for the main light in the scene.
1807
1808 The light parameters are specified in world co-ordinates at
1809 the point when setMainLight() was called. The mainLightTransform()
1810 must be applied to obtain eye co-ordinates.
1811
1812 This function is a convenience that returns the light with
1813 identifier 0. If light 0 is not currently enabled, then a
1814 default light is added to the painter with an identity
1815 transform and then returned as the main light.
1816
1817 \sa setMainLight(), mainLightTransform(), addLight()
1818*/
1819const QGLLightParameters *QGLPainter::mainLight() const
1820{
1821 Q_D(QGLPainter);
1822 QGLPAINTER_CHECK_PRIVATE();
1823 if (d->lights.isEmpty()) {
1824 if (!d->defaultLight)
1825 d->defaultLight = new QGLLightParameters();
1826 d->lights.append(d->defaultLight);
1827 d->lightTransforms.append(QMatrix4x4());
1828 } else if (!d->lights[0]) {
1829 if (!d->defaultLight)
1830 d->defaultLight = new QGLLightParameters();
1831 d->lights[0] = d->defaultLight;
1832 d->lightTransforms[0] = QMatrix4x4();
1833 }
1834 return d->lights[0];
1835}
1836
1837/*!
1838 Sets the \a parameters for the main light in the scene.
1839 The mainLightTransform() is set to the current modelViewMatrix().
1840
1841 Light parameters are stored in world co-ordinates, not eye co-ordinates.
1842 The mainLightTransform() specifies the transformation to apply to
1843 convert the world co-ordinates into eye co-ordinates when the light
1844 is used.
1845
1846 Note: the \a parameters may be ignored by effect() if it
1847 has some other way to determine the lighting conditions.
1848
1849 The light settings in the GL server will not be changed until
1850 update() is called.
1851
1852 This function is a convenience that sets the light with
1853 identifier 0. If \a parameters is null, then light 0
1854 will be removed.
1855
1856 \sa mainLight(), mainLightTransform(), addLight()
1857*/
1858void QGLPainter::setMainLight(const QGLLightParameters *parameters)
1859{
1860 Q_D(QGLPainter);
1861 QGLPAINTER_CHECK_PRIVATE();
1862 if (d->lights.isEmpty()) {
1863 if (parameters) {
1864 d->lights.append(parameters);
1865 d->lightTransforms.append(modelViewMatrix());
1866 d->updates |= QGLPainter::UpdateLights;
1867 }
1868 } else if (parameters) {
1869 d->lights[0] = parameters;
1870 d->lightTransforms[0] = modelViewMatrix();
1871 d->updates |= QGLPainter::UpdateLights;
1872 } else {
1873 removeLight(0);
1874 }
1875}
1876
1877/*!
1878 Sets the \a parameters for the main light in the scene, and set
1879 mainLightTransform() to \a transform.
1880
1881 Light parameters are stored in world co-ordinates, not eye co-ordinates.
1882 The \a transform specifies the transformation to apply to convert the
1883 world co-ordinates into eye co-ordinates when the light is used.
1884
1885 Note: the \a parameters may be ignored by effect() if it
1886 has some other way to determine the lighting conditions.
1887
1888 The light settings in the GL server will not be changed until
1889 update() is called.
1890
1891 This function is a convenience that sets the light with
1892 identifier 0. If \a parameters is null, then light 0
1893 will be removed.
1894
1895 \sa mainLight(), mainLightTransform()
1896*/
1897void QGLPainter::setMainLight
1898 (const QGLLightParameters *parameters, const QMatrix4x4& transform)
1899{
1900 Q_D(QGLPainter);
1901 QGLPAINTER_CHECK_PRIVATE();
1902 if (d->lights.isEmpty()) {
1903 if (parameters) {
1904 d->lights.append(parameters);
1905 d->lightTransforms.append(transform);
1906 d->updates |= QGLPainter::UpdateLights;
1907 }
1908 } else if (parameters) {
1909 d->lights[0] = parameters;
1910 d->lightTransforms[0] = transform;
1911 d->updates |= QGLPainter::UpdateLights;
1912 } else {
1913 removeLight(0);
1914 }
1915}
1916
1917/*!
1918 Returns the modelview transformation matrix for the main light that
1919 was set at the time setMainLight() was called.
1920
1921 The light transform may be used by later painting operations to
1922 convert the light from world co-ordinates into eye co-ordinates.
1923 The eye transformation is set when the light is specified.
1924
1925 This function is a convenience that returns the tranform for the
1926 light with identifier 0. If light 0 is not enabled, then the
1927 function returns the identity matrix.
1928
1929 \sa mainLight(), setMainLight(), addLight()
1930*/
1931QMatrix4x4 QGLPainter::mainLightTransform() const
1932{
1933 Q_D(const QGLPainter);
1934 QGLPAINTER_CHECK_PRIVATE();
1935 if (!d->lights.isEmpty() && d->lights[0])
1936 return d->lightTransforms[0];
1937 else
1938 return QMatrix4x4();
1939}
1940
1941/*!
1942 Adds a light to this painter, with the specified \a parameters.
1943 The lightTransform() for the light is set to the current
1944 modelViewMatrix(). Returns an identifier for the light.
1945
1946 Light parameters are stored in world co-ordinates, not eye co-ordinates.
1947 The lightTransform() specifies the transformation to apply to
1948 convert the world co-ordinates into eye co-ordinates when the light
1949 is used.
1950
1951 Note: the \a parameters may be ignored by effect() if it
1952 has some other way to determine the lighting conditions.
1953
1954 The light settings in the GL server will not be changed until
1955 update() is called.
1956
1957 \sa removeLight(), light(), mainLight()
1958*/
1959int QGLPainter::addLight(const QGLLightParameters *parameters)
1960{
1961 return addLight(parameters, modelViewMatrix());
1962}
1963
1964/*!
1965 Adds a light to this painter, with the specified \a parameters.
1966 The lightTransform() for the light is set to \a transform.
1967 Returns an identifier for the light.
1968
1969 Light parameters are stored in world co-ordinates, not eye co-ordinates.
1970 The \a transform specifies the transformation to apply to
1971 convert the world co-ordinates into eye co-ordinates when the light
1972 is used.
1973
1974 Note: the \a parameters may be ignored by effect() if it
1975 has some other way to determine the lighting conditions.
1976
1977 The light settings in the GL server will not be changed until
1978 update() is called.
1979
1980 \sa removeLight(), light(), mainLight()
1981*/
1982int QGLPainter::addLight(const QGLLightParameters *parameters, const QMatrix4x4 &transform)
1983{
1984 Q_ASSERT(parameters);
1985 Q_D(QGLPainter);
1986 QGLPAINTER_CHECK_PRIVATE();
1987 int lightId = 0;
1988 while (lightId < d->lights.size() && d->lights[lightId] != 0)
1989 ++lightId;
1990 if (lightId < d->lights.size()) {
1991 d->lights[lightId] = parameters;
1992 d->lightTransforms[lightId] = transform;
1993 } else {
1994 d->lights.append(parameters);
1995 d->lightTransforms.append(transform);
1996 }
1997 d->updates |= QGLPainter::UpdateLights;
1998 return lightId;
1999}
2000
2001/*!
2002 Removes the light with the specified \a lightId.
2003
2004 \sa addLight(), light()
2005*/
2006void QGLPainter::removeLight(int lightId)
2007{
2008 Q_D(QGLPainter);
2009 QGLPAINTER_CHECK_PRIVATE();
2010 if (lightId >= 0 && lightId < d->lights.size()) {
2011 d->lights[lightId] = 0;
2012 if (lightId >= (d->lights.size() - 1)) {
2013 do {
2014 d->lights.resize(lightId);
2015 d->lightTransforms.resize(lightId);
2016 --lightId;
2017 } while (lightId >= 0 && d->lights[lightId] == 0);
2018 }
2019 d->updates |= QGLPainter::UpdateLights;
2020 }
2021}
2022
2023/*!
2024 Returns the maximum light identifier currently in use on this painter;
2025 or -1 if there are no lights.
2026
2027 It is possible that some light identifiers less than maximumLightId()
2028 may be invalid because the lights have been removed. Use the following
2029 code to locate all enabled lights:
2030
2031 \code
2032 int maxLightId = painter.maximumLightId();
2033 for (int lightId = 0; index <= maxLightId; ++index) {
2034 const QGLLightParameters *params = painter.light(lightId);
2035 if (params) {
2036 ...
2037 }
2038 }
2039 \endcode
2040
2041 \sa addLight(), light()
2042*/
2043int QGLPainter::maximumLightId() const
2044{
2045 Q_D(const QGLPainter);
2046 QGLPAINTER_CHECK_PRIVATE();
2047 return d->lights.size() - 1;
2048}
2049
2050/*!
2051 Returns the parameters for the light with the identifier \a lightId;
2052 or null if \a lightId is not valid or has been removed.
2053
2054 \sa addLight(), removeLight(), lightTransform()
2055*/
2056const QGLLightParameters *QGLPainter::light(int lightId) const
2057{
2058 Q_D(const QGLPainter);
2059 QGLPAINTER_CHECK_PRIVATE();
2060 if (lightId >= 0 && lightId < d->lights.size())
2061 return d->lights[lightId];
2062 else
2063 return 0;
2064}
2065
2066/*!
2067 Returns the modelview transformation for the light with the identifier
2068 \a lightId; or the identity matrix if \a lightId is not valid or has
2069 been removed.
2070
2071 \sa addLight(), removeLight(), light()
2072*/
2073QMatrix4x4 QGLPainter::lightTransform(int lightId) const
2074{
2075 Q_D(const QGLPainter);
2076 QGLPAINTER_CHECK_PRIVATE();
2077 if (lightId >= 0 && lightId < d->lights.size() && d->lights[lightId])
2078 return d->lightTransforms[lightId];
2079 else
2080 return QMatrix4x4();
2081}
2082
2083/*!
2084 Returns the material that is used for drawing \a face on polygons.
2085 If \a face is QGL::FrontFaces or QGL::AllFaces, then the front
2086 material is returned. If \a face is QGL::BackFaces, then the
2087 back material is returned.
2088
2089 \sa setFaceMaterial(), setFaceColor()
2090*/
2091const QGLMaterial *QGLPainter::faceMaterial(QGL::Face face) const
2092{
2093 Q_D(QGLPainter);
2094 QGLPAINTER_CHECK_PRIVATE();
2095 if (face == QGL::BackFaces) {
2096 if (!d->backMaterial) {
2097 if (!d->defaultMaterial)
2098 d->defaultMaterial = new QGLMaterial();
2099 d->backMaterial = d->defaultMaterial;
2100 }
2101 return d->backMaterial;
2102 } else {
2103 if (!d->frontMaterial) {
2104 if (!d->defaultMaterial)
2105 d->defaultMaterial = new QGLMaterial();
2106 d->frontMaterial = d->defaultMaterial;
2107 }
2108 return d->frontMaterial;
2109 }
2110}
2111
2112/*!
2113 Sets the material that is used for drawing \a face on polygons
2114 to \a value. If \a face is QGL::FrontFaces, then the front
2115 material is set. If \a face is QGL::BackFaces, then the
2116 back material is set. If \a face is QGL::AllFaces, then both
2117 the front and back materials are set.
2118
2119 If \a value is null, then the \a face material will be set to
2120 the default material properties.
2121
2122 The material settings in the GL server will not be changed until
2123 update() is called.
2124
2125 \sa faceMaterial(), setFaceColor()
2126*/
2127void QGLPainter::setFaceMaterial
2128 (QGL::Face face, const QGLMaterial *value)
2129{
2130 Q_D(QGLPainter);
2131 QGLPAINTER_CHECK_PRIVATE();
2132 if (face == QGL::FrontFaces) {
2133 if (d->frontMaterial == value)
2134 return;
2135 d->frontMaterial = value;
2136 } else if (face == QGL::BackFaces) {
2137 if (d->backMaterial == value)
2138 return;
2139 d->backMaterial = value;
2140 } else {
2141 if (d->frontMaterial == value && d->backMaterial == value)
2142 return;
2143 d->frontMaterial = value;
2144 d->backMaterial = value;
2145 }
2146 d->updates |= QGLPainter::UpdateMaterials;
2147}
2148
2149static QGLMaterial *createColorMaterial
2150 (QGLMaterial *prev, const QColor& color)
2151{
2152 QGLMaterial *material;
2153 if (prev)
2154 material = prev;
2155 else
2156 material = new QGLMaterial();
2157 material->setColor(color);
2158 return material;
2159}
2160
2161/*!
2162 Sets the material that is used for drawing \a face on polygons
2163 to \a color. This is a convenience function for setting materials
2164 to simple colors.
2165
2166 The RGB components of the ambient color of the material will be set
2167 to 20% of \a color, and the RGB components of the diffuse color of the
2168 material will be set to 80% of \a color. The alpha components of
2169 the ambient and diffuse material colors will both be set to the
2170 alpha component of \a color.
2171
2172 If \a face is QGL::FrontFaces, then the front material is set.
2173 If \a face is QGL::BackFaces, then the back material is set.
2174 If \a face is QGL::AllFaces, then both the front and back
2175 materials are set.
2176
2177 The material settings in the GL server will not be changed until
2178 update() is called.
2179
2180 \sa faceMaterial(), setFaceMaterial()
2181*/
2182void QGLPainter::setFaceColor(QGL::Face face, const QColor& color)
2183{
2184 Q_D(QGLPainter);
2185 QGLPAINTER_CHECK_PRIVATE();
2186 if (face == QGL::FrontFaces) {
2187 d->frontColorMaterial =
2188 createColorMaterial(d->frontColorMaterial, color);
2189 d->frontMaterial = d->frontColorMaterial;
2190 } else if (face == QGL::BackFaces) {
2191 d->backColorMaterial =
2192 createColorMaterial(d->backColorMaterial, color);
2193 d->backMaterial = d->backColorMaterial;
2194 } else {
2195 d->frontColorMaterial =
2196 createColorMaterial(d->frontColorMaterial, color);
2197 d->backColorMaterial =
2198 createColorMaterial(d->backColorMaterial, color);
2199 d->frontMaterial = d->frontColorMaterial;
2200 d->backMaterial = d->backColorMaterial;
2201 }
2202 d->updates |= QGLPainter::UpdateMaterials;
2203}
2204
2205/*!
2206 Returns true if this painter is in object picking mode;
2207 false if this painter is in normal rendering mode.
2208
2209 \sa setPicking(), objectPickId()
2210*/
2211bool QGLPainter::isPicking() const
2212{
2213 Q_D(QGLPainter);
2214 QGLPAINTER_CHECK_PRIVATE();
2215 return (d->pick ? d->pick->isPicking : false);
2216}
2217
2218/*!
2219 Enables or disables object picking mode according to \a value.
2220
2221 If \a value is true, then the effect() will be overridden with a
2222 simple flat color effect that renders objects with pickColor().
2223 These colors can be read back later with pickObject().
2224
2225 \sa isPicking(), objectPickId(), pickObject()
2226*/
2227void QGLPainter::setPicking(bool value)
2228{
2229 Q_D(QGLPainter);
2230 QGLPAINTER_CHECK_PRIVATE();
2231 if (!d->pick)
2232 d->pick = new QGLPainterPickPrivate();
2233 if (d->pick->isPicking != value) {
2234 // Switch to/from the pick effect.
2235 d->pick->isPicking = value;
2236 if (d->effect)
2237 d->effect->setActive(this, false);
2238 d->effect = 0;
2239 d->ensureEffect(this);
2240 }
2241}
2242
2243/*!
2244 Returns the current object pick identifier. The default value
2245 is -1 which indicates that rendered objects should not have a
2246 pickColor() associated with them.
2247
2248 \sa setObjectPickId(), clearPickObjects(), pickObject()
2249*/
2250int QGLPainter::objectPickId() const
2251{
2252 Q_D(QGLPainter);
2253 QGLPAINTER_CHECK_PRIVATE();
2254 return (d->pick ? d->pick->objectPickId : -1);
2255}
2256
2257/*!
2258 Sets the current object pick identifier to \a value. If \a value
2259 is -1, then subsequent objects will be rendered without a pickColor().
2260
2261 If value is not -1, then the pickColor() is changed to a color
2262 that represents that object pick identifier. If \a value has been
2263 seen previously, then the same pickColor() as last time will
2264 be returned.
2265
2266 The function call will be ignored if isPicking() is false.
2267
2268 \sa objectPickId(), clearPickObjects(), pickObject()
2269*/
2270void QGLPainter::setObjectPickId(int value)
2271{
2272 Q_D(QGLPainter);
2273 QGLPAINTER_CHECK_PRIVATE();
2274 if (!d->pick || !d->pick->isPicking)
2275 return;
2276 d->pick->objectPickId = value;
2277 if (value != -1) {
2278 QRgb color = d->pick->pickObjectToColor.value(value, 0);
2279 if (!color) {
2280 color = qt_qgl_pick_color(d->pick->pickColorIndex++);
2281 d->pick->pickObjectToColor[value] = color;
2282 d->pick->pickColorToObject[color] = value;
2283 }
2284 d->pick->pickColor = color;
2285 d->updates |= UpdateColor;
2286 } else {
2287 d->pick->pickColor = 0;
2288 d->updates |= UpdateColor;
2289 }
2290}
2291
2292/*!
2293 Clears the objectPickId() to pickColor() mappings that
2294 were used previously. This will also set objectPickId()
2295 to -1 and pickColor() to (0, 0, 0, 1).
2296
2297 The function call will be ignored if isPicking() is false.
2298
2299 \sa objectPickId(), pickColor()
2300*/
2301void QGLPainter::clearPickObjects()
2302{
2303 Q_D(QGLPainter);
2304 QGLPAINTER_CHECK_PRIVATE();
2305 if (d->pick && d->pick->isPicking) {
2306 d->pick->pickObjectToColor.clear();
2307 d->pick->pickColorToObject.clear();
2308 d->pick->pickColorIndex = 0;
2309 d->pick->objectPickId = -1;
2310 d->pick->pickColor = 0;
2311 d->updates |= UpdateColor;
2312 }
2313}
2314
2315/*!
2316 Returns the current pick color to use to render the object
2317 associated with objectPickId(). The returned color will
2318 be (0, 0, 0, 1) if objectPickId() is -1.
2319
2320 \sa objectPickId(), clearPickObjects()
2321*/
2322QColor QGLPainter::pickColor() const
2323{
2324 Q_D(QGLPainter);
2325 QGLPAINTER_CHECK_PRIVATE();
2326 if (d->pick) {
2327 QColor color;
2328 color.setRgb(d->pick->pickColor);
2329 return color;
2330 } else {
2331 return Qt::black;
2332 }
2333}
2334
2335/*!
2336 Picks the color at (\a x, \a y) in the color buffer and
2337 returns the objectPickId() that corresponds to that color.
2338 Returns -1 if (\a x, \a y) is not positioned over a
2339 recognized object. The origin (0, 0) is assumed to be
2340 the bottom-left corner of the drawing surface.
2341
2342 \sa objectPickId()
2343*/
2344int QGLPainter::pickObject(int x, int y) const
2345{
2346 Q_D(QGLPainter);
2347 QGLPAINTER_CHECK_PRIVATE();
2348
2349 if (!d->pick)
2350 {
2351 return -1;
2352 }
2353
2354 // Fetch the color at the specified pixel.
2355 unsigned char data[4] = {0, 0, 0, 0};
2356 glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
2357 QRgb color = qRgb(data[0], data[1], data[2]);
2358
2359 // Normalize the color to account for floating-point rounding.
2360 color = qt_qgl_normalize_pick_color(color); // XXX: detect RGB444 screens.
2361
2362 // Map the color back to an object identifier.
2363 return d->pick->pickColorToObject.value(color, -1);
2364}
2365
2366QT_END_NAMESPACE