Commit eb8dc0938cc7928869bdba20121664861469b18a

Add project() and unproject() functions to QGLPainter.
  
571571 Returns the viewport for the active GL context. The origin for
572572 the returned rectangle is the top-left of the drawing surface.
573573
574 \sa setViewport()
574 \sa setViewport(), resetViewport()
575575*/
576576QRect QGLPainter::viewport() const
577577{
578578 Q_D(QGLPainter);
579579 QGLPAINTER_CHECK_PRIVATE_RETURN(QRect());
580 QPaintDevice *device = d->context->device();
581 if (device) {
580 if (d->viewport.isNull()) {
582581 GLint view[4];
583582 glGetIntegerv(GL_VIEWPORT, view);
584 return QRect(view[0], device->height() - (view[1] + view[3]),
585 view[1], view[3]);
586 } else {
587 return QRect();
583 d->viewport = QRect(view[0], view[1], view[2], view[3]);
588584 }
585 // Convert the GL viewport into standard Qt co-ordinates.
586 return QRect(d->viewport.x(),
587 d->context->device()->height() -
588 (d->viewport.y() + d->viewport.height()),
589 d->viewport.width(), d->viewport.height());
589590}
590591
591592/*!
592593 Sets the viewport for the active GL context to \a rect.
593594 The origin for \a rect is the top-left of the drawing surface.
594595
595 \sa viewport()
596 \sa viewport(), resetViewport()
596597*/
597598void QGLPainter::setViewport(const QRect& rect)
598599{
599600 Q_D(QGLPainter);
600601 QGLPAINTER_CHECK_PRIVATE();
601 QPaintDevice *device = d->context->device();
602 if (device) {
603 int y = device->height() - (rect.y() + rect.height());
604 glViewport(rect.x(), y, rect.width(), rect.height());
605 }
602 int y = d->context->device()->height() - (rect.y() + rect.height());
603 glViewport(rect.x(), y, rect.width(), rect.height());
604 d->viewport = QRect(rect.x(), y, rect.width(), rect.height());
606605}
607606
608607/*!
609608 Sets the viewport for the active GL context to start at the
610609 origin and extend for \a size.
611610
612 \sa viewport()
611 \sa viewport(), resetViewport()
613612*/
614613void QGLPainter::setViewport(const QSize& size)
615614{
615 Q_D(QGLPainter);
616 QGLPAINTER_CHECK_PRIVATE();
616617 glViewport(0, 0, size.width(), size.height());
618 d->viewport = QRect(0, 0, size.width(), size.height());
617619}
618620
619621/*!
620622 Sets the viewport for the active GL context to start at the
621623 origin and extend for \a width and \a height.
622624
623 \sa viewport()
625 \sa viewport(), resetViewport()
624626*/
625627void QGLPainter::setViewport(int width, int height)
626628{
629 Q_D(QGLPainter);
630 QGLPAINTER_CHECK_PRIVATE();
627631 glViewport(0, 0, width, height);
632 d->viewport = QRect(0, 0, width, height);
628633}
629634
630635/*!
636 Resets this painter's notion of what the current viewport()
637 is set to. The next time viewport() is called, the actual
638 viewport rectangle will be fetched from the GL server.
639
640 This function is used to synchronize the state of the application
641 with the GL server after the execution of raw GL commands that may
642 have altered the viewport settings.
643
644 \sa viewport(), setViewport()
645*/
646void QGLPainter::resetViewport()
647{
648 Q_D(QGLPainter);
649 QGLPAINTER_CHECK_PRIVATE();
650 d->viewport = QRect();
651}
652
653/*!
631654 Returns the currently active scissor rectangle; or a null rectangle
632655 if scissoring is disabled.
633656
884884 QBox3D projected = box.transformed
885885 (d->projectionMatrix * d->modelViewMatrix);
886886 return d->viewingCube.intersects(projected);
887}
888
889/*!
890 Projects a \a point in object model space to window co-ordinates
891 using the current modelViewMatrix(), projectionMatrix(), and viewport().
892 Returns the window co-ordinates.
893
894 If \a ok is not null, then it will be set if true if the projection
895 was possible, or false if \a point cannot be projected.
896
897 \sa unproject()
898*/
899QVector3D QGLPainter::project(const QVector3D& point, bool *ok) const
900{
901 Q_D(const QGLPainter);
902 QGLPAINTER_CHECK_PRIVATE_RETURN(QVector3D());
903
904 // Map the point using the modelview and projection matrices.
905 QVector4D v = d->modelViewMatrix.top() * QVector4D(point, 1.0f);
906 v = d->projectionMatrix.top() * v;
907 if (qFuzzyCompare(v.w(), qreal(0.0f))) {
908 if (ok)
909 *ok = false;
910 return QVector3D();
911 }
912
913 // Map the co-ordinates to the range 0-1.
914 qreal x = (v.x() / v.w()) * 0.5f + 0.5f;
915 qreal y = (v.y() / v.w()) * 0.5f + 0.5f;
916 qreal z = (v.z() / v.w()) * 0.5f + 0.5f;
917
918 // Map x and y to the viewport dimensions.
919 if (d->viewport.isNull()) {
920 GLint view[4];
921 glGetIntegerv(GL_VIEWPORT, view);
922 const_cast<QGLPainterPrivate *>(d)->viewport
923 = QRect(view[0], view[1], view[2], view[3]);
924 }
925 x = x * d->viewport.width() + d->viewport.x();
926 y = y * d->viewport.height() + d->viewport.y();
927 if (ok)
928 *ok = true;
929 return QVector3D(x, y, z);
930}
931
932/*!
933 Projects a \a point in window co-ordinates back to object model space
934 using the current modelViewMatrix(), projectionMatrix(), and viewport().
935 Returns the object model co-ordinates.
936
937 If \a ok is not null, then it will be set if true if the projection
938 was possible, or false if \a point cannot be projected.
939
940 \sa project()
941*/
942QVector3D QGLPainter::unproject(const QVector3D& point, bool *ok) const
943{
944 Q_D(const QGLPainter);
945 QGLPAINTER_CHECK_PRIVATE_RETURN(QVector3D());
946
947 // Invert the combined modelview/projection matrix.
948 bool invertible;
949 QMatrix4x4 m = combinedMatrix().inverted(&invertible);
950 if (!invertible) {
951 if (ok)
952 *ok = false;
953 return QVector3D();
954 }
955
956 // Map from window co-ordinates to the (-1, -1) - (1, 1) viewport.
957 if (d->viewport.isNull()) {
958 GLint view[4];
959 glGetIntegerv(GL_VIEWPORT, view);
960 const_cast<QGLPainterPrivate *>(d)->viewport
961 = QRect(view[0], view[1], view[2], view[3]);
962 }
963 qreal x = ((point.x() - d->viewport.x()) / d->viewport.width()) * 2 - 1;
964 qreal y = ((point.y() - d->viewport.y()) / d->viewport.height()) * 2 - 1;
965 qreal z = point.z() * 2 - 1;
966
967 // Map the point back through the inverse of the projection.
968 QVector4D v = m * QVector4D(x, y, z, 1.0f);
969 if (qFuzzyCompare(v.w(), qreal(0.0f))) {
970 if (ok)
971 *ok = false;
972 return QVector3D();
973 }
974 if (ok)
975 *ok = true;
976 return QVector3D(v.x() / v.w(), v.y() / v.w(), v.z() / v.w());
977}
978
979/*!
980 \overload
981
982 Projects a 4D \a point in window co-ordinates back to object model space
983 using the current modelViewMatrix(), projectionMatrix(), and viewport().
984 Returns the object model co-ordinates, including the w co-ordinate.
985
986 The \a nearPlane and \a farPlane parameters are used to specify the
987 near and far clipping planes in the z direction.
988
989 If \a ok is not null, then it will be set if true if the projection
990 was possible, or false if \a point cannot be projected.
991
992 \sa project()
993*/
994QVector4D QGLPainter::unproject
995 (const QVector4D& point, qreal nearPlane, qreal farPlane, bool *ok) const
996{
997 Q_D(const QGLPainter);
998 QGLPAINTER_CHECK_PRIVATE_RETURN(QVector4D());
999
1000 // Invert the combined modelview/projection matrix.
1001 bool invertible;
1002 QMatrix4x4 m = combinedMatrix().inverted(&invertible);
1003 if (!invertible) {
1004 if (ok)
1005 *ok = false;
1006 return QVector4D();
1007 }
1008
1009 // Map from window co-ordinates to the (-1, -1) - (1, 1) viewport.
1010 if (d->viewport.isNull()) {
1011 GLint view[4];
1012 glGetIntegerv(GL_VIEWPORT, view);
1013 const_cast<QGLPainterPrivate *>(d)->viewport
1014 = QRect(view[0], view[1], view[2], view[3]);
1015 }
1016 qreal x = ((point.x() - d->viewport.x()) / d->viewport.width()) * 2 - 1;
1017 qreal y = ((point.y() - d->viewport.y()) / d->viewport.height()) * 2 - 1;
1018 qreal z = ((point.z() - nearPlane) / (farPlane - nearPlane)) * 2 - 1;
1019
1020 // Map the point back through the inverse of the projection.
1021 QVector4D v = m * QVector4D(x, y, z, point.w());
1022 if (qFuzzyCompare(v.w(), qreal(0.0f))) {
1023 if (ok)
1024 *ok = false;
1025 return QVector4D();
1026 }
1027 if (ok)
1028 *ok = true;
1029 return v;
8871030}
8881031
8891032/*!
  
115115 void setViewport(const QRect& rect);
116116 void setViewport(const QSize& size);
117117 void setViewport(int width, int height);
118 void resetViewport();
118119
119120 QRect scissor() const;
120121 void setScissor(const QRect& rect);
129129
130130 bool isVisible(const QVector3D& point) const;
131131 bool isVisible(const QBox3D& box) const;
132
133 QVector3D project(const QVector3D& point, bool *ok = 0) const;
134 QVector3D unproject(const QVector3D& point, bool *ok = 0) const;
135 QVector4D unproject(const QVector4D& point, qreal nearPlane,
136 qreal farPlane, bool *ok = 0) const;
132137
133138 qreal aspectRatio() const;
134139 qreal aspectRatio(const QSize& viewportSize) const;
  
233233 QGLMaterial *backColorMaterial;
234234 const QGLFogParameters *fogParameters;
235235 QBox3D viewingCube;
236 QRect scissor;
236 QRect viewport; // GL co-ordinates - origin bottom-left.
237 QRect scissor; // Qt co-ordinates - origin top-left.
237238 QColor color;
238239 QGLPainter::Updates updates;
239240 GLuint currentBufferId;