util/src/gui/math3d/qmatrix4x4.cpp
changeset 7 f7bc934e204c
equal deleted inserted replaced
3:41300fa6a67c 7:f7bc934e204c
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     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
       
    14 ** this package.
       
    15 **
       
    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.
       
    23 **
       
    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.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qmatrix4x4.h"
       
    43 #include <QtCore/qmath.h>
       
    44 #include <QtCore/qvariant.h>
       
    45 #include <QtGui/qmatrix.h>
       
    46 #include <QtGui/qtransform.h>
       
    47 
       
    48 QT_BEGIN_NAMESPACE
       
    49 
       
    50 #ifndef QT_NO_MATRIX4X4
       
    51 
       
    52 /*!
       
    53     \class QMatrix4x4
       
    54     \brief The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
       
    55     \since 4.6
       
    56     \ingroup painting-3D
       
    57 
       
    58     \sa QVector3D, QGenericMatrix
       
    59 */
       
    60 
       
    61 static const qreal inv_dist_to_plane = 1. / 1024.;
       
    62 
       
    63 /*!
       
    64     \fn QMatrix4x4::QMatrix4x4()
       
    65 
       
    66     Constructs an identity matrix.
       
    67 */
       
    68 
       
    69 /*!
       
    70     Constructs a matrix from the given 16 floating-point \a values.
       
    71     The contents of the array \a values is assumed to be in
       
    72     row-major order.
       
    73 
       
    74     If the matrix has a special type (identity, translate, scale, etc),
       
    75     the programmer should follow this constructor with a call to
       
    76     optimize() if they wish QMatrix4x4 to optimize further
       
    77     calls to translate(), scale(), etc.
       
    78 
       
    79     \sa copyDataTo(), optimize()
       
    80 */
       
    81 QMatrix4x4::QMatrix4x4(const qreal *values)
       
    82 {
       
    83     for (int row = 0; row < 4; ++row)
       
    84         for (int col = 0; col < 4; ++col)
       
    85             m[col][row] = values[row * 4 + col];
       
    86     flagBits = General;
       
    87 }
       
    88 
       
    89 /*!
       
    90     \fn QMatrix4x4::QMatrix4x4(qreal m11, qreal m12, qreal m13, qreal m14, qreal m21, qreal m22, qreal m23, qreal m24, qreal m31, qreal m32, qreal m33, qreal m34, qreal m41, qreal m42, qreal m43, qreal m44)
       
    91 
       
    92     Constructs a matrix from the 16 elements \a m11, \a m12, \a m13, \a m14,
       
    93     \a m21, \a m22, \a m23, \a m24, \a m31, \a m32, \a m33, \a m34,
       
    94     \a m41, \a m42, \a m43, and \a m44.  The elements are specified in
       
    95     row-major order.
       
    96 
       
    97     If the matrix has a special type (identity, translate, scale, etc),
       
    98     the programmer should follow this constructor with a call to
       
    99     optimize() if they wish QMatrix4x4 to optimize further
       
   100     calls to translate(), scale(), etc.
       
   101 
       
   102     \sa optimize()
       
   103 */
       
   104 
       
   105 #if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
       
   106 
       
   107 /*!
       
   108     \fn QMatrix4x4::QMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix)
       
   109 
       
   110     Constructs a 4x4 matrix from the left-most 4 columns and top-most
       
   111     4 rows of \a matrix.  If \a matrix has less than 4 columns or rows,
       
   112     the remaining elements are filled with elements from the identity
       
   113     matrix.
       
   114 
       
   115     \sa toGenericMatrix(), qGenericMatrixToMatrix4x4()
       
   116 */
       
   117 
       
   118 /*!
       
   119     \fn QGenericMatrix<N, M, qreal> QMatrix4x4::toGenericMatrix() const
       
   120 
       
   121     Constructs a NxM generic matrix from the left-most N columns and
       
   122     top-most M rows of this 4x4 matrix.  If N or M is greater than 4,
       
   123     then the remaining elements are filled with elements from the
       
   124     identity matrix.
       
   125 
       
   126     \sa qGenericMatrixFromMatrix4x4()
       
   127 */
       
   128 
       
   129 #endif
       
   130 
       
   131 /*!
       
   132     \fn QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix)
       
   133     \relates QMatrix4x4
       
   134 
       
   135     Returns a 4x4 matrix constructed from the left-most 4 columns and
       
   136     top-most 4 rows of \a matrix.  If \a matrix has less than 4 columns
       
   137     or rows, the remaining elements are filled with elements from the
       
   138     identity matrix.
       
   139 
       
   140     \sa qGenericMatrixFromMatrix4x4()
       
   141 */
       
   142 
       
   143 /*!
       
   144     \fn QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
       
   145     \relates QMatrix4x4
       
   146 
       
   147     Returns a NxM generic matrix constructed from the left-most N columns
       
   148     and top-most M rows of \a matrix.  If N or M is greater than 4,
       
   149     then the remaining elements are filled with elements from the
       
   150     identity matrix.
       
   151 
       
   152     \sa qGenericMatrixToMatrix4x4(), QMatrix4x4::toGenericMatrix()
       
   153 */
       
   154 
       
   155 /*!
       
   156     \internal
       
   157 */
       
   158 QMatrix4x4::QMatrix4x4(const qreal *values, int cols, int rows)
       
   159 {
       
   160     for (int col = 0; col < 4; ++col) {
       
   161         for (int row = 0; row < 4; ++row) {
       
   162             if (col < cols && row < rows)
       
   163                 m[col][row] = values[col * rows + row];
       
   164             else if (col == row)
       
   165                 m[col][row] = 1.0f;
       
   166             else
       
   167                 m[col][row] = 0.0f;
       
   168         }
       
   169     }
       
   170     flagBits = General;
       
   171 }
       
   172 
       
   173 /*!
       
   174     Constructs a 4x4 matrix from a conventional Qt 2D affine
       
   175     transformation \a matrix.
       
   176 
       
   177     If \a matrix has a special type (identity, translate, scale, etc),
       
   178     the programmer should follow this constructor with a call to
       
   179     optimize() if they wish QMatrix4x4 to optimize further
       
   180     calls to translate(), scale(), etc.
       
   181 
       
   182     \sa toAffine(), optimize()
       
   183 */
       
   184 QMatrix4x4::QMatrix4x4(const QMatrix& matrix)
       
   185 {
       
   186     m[0][0] = matrix.m11();
       
   187     m[0][1] = matrix.m12();
       
   188     m[0][2] = 0.0f;
       
   189     m[0][3] = 0.0f;
       
   190     m[1][0] = matrix.m21();
       
   191     m[1][1] = matrix.m22();
       
   192     m[1][2] = 0.0f;
       
   193     m[1][3] = 0.0f;
       
   194     m[2][0] = 0.0f;
       
   195     m[2][1] = 0.0f;
       
   196     m[2][2] = 1.0f;
       
   197     m[2][3] = 0.0f;
       
   198     m[3][0] = matrix.dx();
       
   199     m[3][1] = matrix.dy();
       
   200     m[3][2] = 0.0f;
       
   201     m[3][3] = 1.0f;
       
   202     flagBits = General;
       
   203 }
       
   204 
       
   205 /*!
       
   206     Constructs a 4x4 matrix from the conventional Qt 2D
       
   207     transformation matrix \a transform.
       
   208 
       
   209     If \a transform has a special type (identity, translate, scale, etc),
       
   210     the programmer should follow this constructor with a call to
       
   211     optimize() if they wish QMatrix4x4 to optimize further
       
   212     calls to translate(), scale(), etc.
       
   213 
       
   214     \sa toTransform(), optimize()
       
   215 */
       
   216 QMatrix4x4::QMatrix4x4(const QTransform& transform)
       
   217 {
       
   218     m[0][0] = transform.m11();
       
   219     m[0][1] = transform.m12();
       
   220     m[0][2] = 0.0f;
       
   221     m[0][3] = transform.m13();
       
   222     m[1][0] = transform.m21();
       
   223     m[1][1] = transform.m22();
       
   224     m[1][2] = 0.0f;
       
   225     m[1][3] = transform.m23();
       
   226     m[2][0] = 0.0f;
       
   227     m[2][1] = 0.0f;
       
   228     m[2][2] = 1.0f;
       
   229     m[2][3] = 0.0f;
       
   230     m[3][0] = transform.dx();
       
   231     m[3][1] = transform.dy();
       
   232     m[3][2] = 0.0f;
       
   233     m[3][3] = transform.m33();
       
   234     flagBits = General;
       
   235 }
       
   236 
       
   237 /*!
       
   238     \fn const qreal& QMatrix4x4::operator()(int row, int column) const
       
   239 
       
   240     Returns a constant reference to the element at position
       
   241     (\a row, \a column) in this matrix.
       
   242 
       
   243     \sa column(), row()
       
   244 */
       
   245 
       
   246 /*!
       
   247     \fn qreal& QMatrix4x4::operator()(int row, int column)
       
   248 
       
   249     Returns a reference to the element at position (\a row, \a column)
       
   250     in this matrix so that the element can be assigned to.
       
   251 
       
   252     \sa optimize(), setColumn(), setRow()
       
   253 */
       
   254 
       
   255 /*!
       
   256     \fn QVector4D QMatrix4x4::column(int index) const
       
   257 
       
   258     Returns the elements of column \a index as a 4D vector.
       
   259 
       
   260     \sa setColumn(), row()
       
   261 */
       
   262 
       
   263 /*!
       
   264     \fn void QMatrix4x4::setColumn(int index, const QVector4D& value)
       
   265 
       
   266     Sets the elements of column \a index to the components of \a value.
       
   267 
       
   268     \sa column(), setRow()
       
   269 */
       
   270 
       
   271 /*!
       
   272     \fn QVector4D QMatrix4x4::row(int index) const
       
   273 
       
   274     Returns the elements of row \a index as a 4D vector.
       
   275 
       
   276     \sa setRow(), column()
       
   277 */
       
   278 
       
   279 /*!
       
   280     \fn void QMatrix4x4::setRow(int index, const QVector4D& value)
       
   281 
       
   282     Sets the elements of row \a index to the components of \a value.
       
   283 
       
   284     \sa row(), setColumn()
       
   285 */
       
   286 
       
   287 /*!
       
   288     \fn bool QMatrix4x4::isIdentity() const
       
   289 
       
   290     Returns true if this matrix is the identity; false otherwise.
       
   291 
       
   292     \sa setToIdentity()
       
   293 */
       
   294 
       
   295 /*!
       
   296     \fn void QMatrix4x4::setToIdentity()
       
   297 
       
   298     Sets this matrix to the identity.
       
   299 
       
   300     \sa isIdentity()
       
   301 */
       
   302 
       
   303 /*!
       
   304     \fn void QMatrix4x4::fill(qreal value)
       
   305 
       
   306     Fills all elements of this matrx with \a value.
       
   307 */
       
   308 
       
   309 // The 4x4 matrix inverse algorithm is based on that described at:
       
   310 // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q24
       
   311 // Some optimization has been done to avoid making copies of 3x3
       
   312 // sub-matrices and to unroll the loops.
       
   313 
       
   314 // Calculate the determinant of a 3x3 sub-matrix.
       
   315 //     | A B C |
       
   316 // M = | D E F |   det(M) = A * (EI - HF) - B * (DI - GF) + C * (DH - GE)
       
   317 //     | G H I |
       
   318 static inline qreal matrixDet3
       
   319     (const qreal m[4][4], int col0, int col1, int col2,
       
   320      int row0, int row1, int row2)
       
   321 {
       
   322     return m[col0][row0] *
       
   323                 (m[col1][row1] * m[col2][row2] -
       
   324                  m[col1][row2] * m[col2][row1]) -
       
   325            m[col1][row0] *
       
   326                 (m[col0][row1] * m[col2][row2] -
       
   327                  m[col0][row2] * m[col2][row1]) +
       
   328            m[col2][row0] *
       
   329                 (m[col0][row1] * m[col1][row2] -
       
   330                  m[col0][row2] * m[col1][row1]);
       
   331 }
       
   332 
       
   333 // Calculate the determinant of a 4x4 matrix.
       
   334 static inline qreal matrixDet4(const qreal m[4][4])
       
   335 {
       
   336     qreal det;
       
   337     det  = m[0][0] * matrixDet3(m, 1, 2, 3, 1, 2, 3);
       
   338     det -= m[1][0] * matrixDet3(m, 0, 2, 3, 1, 2, 3);
       
   339     det += m[2][0] * matrixDet3(m, 0, 1, 3, 1, 2, 3);
       
   340     det -= m[3][0] * matrixDet3(m, 0, 1, 2, 1, 2, 3);
       
   341     return det;
       
   342 }
       
   343 
       
   344 /*!
       
   345     Returns the determinant of this matrix.
       
   346 */
       
   347 qreal QMatrix4x4::determinant() const
       
   348 {
       
   349     return qreal(matrixDet4(m));
       
   350 }
       
   351 
       
   352 /*!
       
   353     Returns the inverse of this matrix.  Returns the identity if
       
   354     this matrix cannot be inverted; i.e. determinant() is zero.
       
   355     If \a invertible is not null, then true will be written to
       
   356     that location if the matrix can be inverted; false otherwise.
       
   357 
       
   358     If the matrix is recognized as the identity or an orthonormal
       
   359     matrix, then this function will quickly invert the matrix
       
   360     using optimized routines.
       
   361 
       
   362     \sa determinant(), normalMatrix()
       
   363 */
       
   364 QMatrix4x4 QMatrix4x4::inverted(bool *invertible) const
       
   365 {
       
   366     // Handle some of the easy cases first.
       
   367     if (flagBits == Identity) {
       
   368         if (invertible)
       
   369             *invertible = true;
       
   370         return QMatrix4x4();
       
   371     } else if (flagBits == Translation) {
       
   372         QMatrix4x4 inv;
       
   373         inv.m[3][0] = -m[3][0];
       
   374         inv.m[3][1] = -m[3][1];
       
   375         inv.m[3][2] = -m[3][2];
       
   376         inv.flagBits = Translation;
       
   377         if (invertible)
       
   378             *invertible = true;
       
   379         return inv;
       
   380     } else if (flagBits == Rotation || flagBits == (Rotation | Translation)) {
       
   381         if (invertible)
       
   382             *invertible = true;
       
   383         return orthonormalInverse();
       
   384     }
       
   385 
       
   386     QMatrix4x4 inv(1); // The "1" says to not load the identity.
       
   387 
       
   388     qreal det = matrixDet4(m);
       
   389     if (det == 0.0f) {
       
   390         if (invertible)
       
   391             *invertible = false;
       
   392         return QMatrix4x4();
       
   393     }
       
   394     det = 1.0f / det;
       
   395 
       
   396     inv.m[0][0] =  matrixDet3(m, 1, 2, 3, 1, 2, 3) * det;
       
   397     inv.m[0][1] = -matrixDet3(m, 0, 2, 3, 1, 2, 3) * det;
       
   398     inv.m[0][2] =  matrixDet3(m, 0, 1, 3, 1, 2, 3) * det;
       
   399     inv.m[0][3] = -matrixDet3(m, 0, 1, 2, 1, 2, 3) * det;
       
   400     inv.m[1][0] = -matrixDet3(m, 1, 2, 3, 0, 2, 3) * det;
       
   401     inv.m[1][1] =  matrixDet3(m, 0, 2, 3, 0, 2, 3) * det;
       
   402     inv.m[1][2] = -matrixDet3(m, 0, 1, 3, 0, 2, 3) * det;
       
   403     inv.m[1][3] =  matrixDet3(m, 0, 1, 2, 0, 2, 3) * det;
       
   404     inv.m[2][0] =  matrixDet3(m, 1, 2, 3, 0, 1, 3) * det;
       
   405     inv.m[2][1] = -matrixDet3(m, 0, 2, 3, 0, 1, 3) * det;
       
   406     inv.m[2][2] =  matrixDet3(m, 0, 1, 3, 0, 1, 3) * det;
       
   407     inv.m[2][3] = -matrixDet3(m, 0, 1, 2, 0, 1, 3) * det;
       
   408     inv.m[3][0] = -matrixDet3(m, 1, 2, 3, 0, 1, 2) * det;
       
   409     inv.m[3][1] =  matrixDet3(m, 0, 2, 3, 0, 1, 2) * det;
       
   410     inv.m[3][2] = -matrixDet3(m, 0, 1, 3, 0, 1, 2) * det;
       
   411     inv.m[3][3] =  matrixDet3(m, 0, 1, 2, 0, 1, 2) * det;
       
   412 
       
   413     if (invertible)
       
   414         *invertible = true;
       
   415     return inv;
       
   416 }
       
   417 
       
   418 /*!
       
   419     Returns the normal matrix corresponding to this 4x4 transformation.
       
   420     The normal matrix is the transpose of the inverse of the top-left
       
   421     3x3 part of this 4x4 matrix.  If the 3x3 sub-matrix is not invertible,
       
   422     this function returns the identity.
       
   423 
       
   424     \sa inverted()
       
   425 */
       
   426 QMatrix3x3 QMatrix4x4::normalMatrix() const
       
   427 {
       
   428     QMatrix3x3 inv;
       
   429 
       
   430     // Handle the simple cases first.
       
   431     if (flagBits == Identity || flagBits == Translation) {
       
   432         return inv;
       
   433     } else if (flagBits == Scale || flagBits == (Translation | Scale)) {
       
   434         if (m[0][0] == 0.0f || m[1][1] == 0.0f || m[2][2] == 0.0f)
       
   435             return inv;
       
   436         inv.data()[0] = 1.0f / m[0][0];
       
   437         inv.data()[4] = 1.0f / m[1][1];
       
   438         inv.data()[8] = 1.0f / m[2][2];
       
   439         return inv;
       
   440     }
       
   441 
       
   442     qreal det = matrixDet3(m, 0, 1, 2, 0, 1, 2);
       
   443     if (det == 0.0f)
       
   444         return inv;
       
   445     det = 1.0f / det;
       
   446 
       
   447     qreal *invm = inv.data();
       
   448 
       
   449     // Invert and transpose in a single step.
       
   450     invm[0 + 0 * 3] =  (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * det;
       
   451     invm[1 + 0 * 3] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) * det;
       
   452     invm[2 + 0 * 3] =  (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * det;
       
   453     invm[0 + 1 * 3] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * det;
       
   454     invm[1 + 1 * 3] =  (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * det;
       
   455     invm[2 + 1 * 3] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) * det;
       
   456     invm[0 + 2 * 3] =  (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * det;
       
   457     invm[1 + 2 * 3] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) * det;
       
   458     invm[2 + 2 * 3] =  (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * det;
       
   459 
       
   460     return inv;
       
   461 }
       
   462 
       
   463 /*!
       
   464     Returns this matrix, transposed about its diagonal.
       
   465 */
       
   466 QMatrix4x4 QMatrix4x4::transposed() const
       
   467 {
       
   468     QMatrix4x4 result(1); // The "1" says to not load the identity.
       
   469     for (int row = 0; row < 4; ++row) {
       
   470         for (int col = 0; col < 4; ++col) {
       
   471             result.m[col][row] = m[row][col];
       
   472         }
       
   473     }
       
   474     return result;
       
   475 }
       
   476 
       
   477 /*!
       
   478     \fn QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
       
   479 
       
   480     Adds the contents of \a other to this matrix.
       
   481 */
       
   482 
       
   483 /*!
       
   484     \fn QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
       
   485 
       
   486     Subtracts the contents of \a other from this matrix.
       
   487 */
       
   488 
       
   489 /*!
       
   490     \fn QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& other)
       
   491 
       
   492     Multiplies the contents of \a other by this matrix.
       
   493 */
       
   494 
       
   495 /*!
       
   496     \fn QMatrix4x4& QMatrix4x4::operator*=(qreal factor)
       
   497     \overload
       
   498 
       
   499     Multiplies all elements of this matrix by \a factor.
       
   500 */
       
   501 
       
   502 /*!
       
   503     \overload
       
   504 
       
   505     Divides all elements of this matrix by \a divisor.
       
   506 */
       
   507 QMatrix4x4& QMatrix4x4::operator/=(qreal divisor)
       
   508 {
       
   509     m[0][0] /= divisor;
       
   510     m[0][1] /= divisor;
       
   511     m[0][2] /= divisor;
       
   512     m[0][3] /= divisor;
       
   513     m[1][0] /= divisor;
       
   514     m[1][1] /= divisor;
       
   515     m[1][2] /= divisor;
       
   516     m[1][3] /= divisor;
       
   517     m[2][0] /= divisor;
       
   518     m[2][1] /= divisor;
       
   519     m[2][2] /= divisor;
       
   520     m[2][3] /= divisor;
       
   521     m[3][0] /= divisor;
       
   522     m[3][1] /= divisor;
       
   523     m[3][2] /= divisor;
       
   524     m[3][3] /= divisor;
       
   525     flagBits = General;
       
   526     return *this;
       
   527 }
       
   528 
       
   529 /*!
       
   530     \fn bool QMatrix4x4::operator==(const QMatrix4x4& other) const
       
   531 
       
   532     Returns true if this matrix is identical to \a other; false otherwise.
       
   533     This operator uses an exact floating-point comparison.
       
   534 */
       
   535 
       
   536 /*!
       
   537     \fn bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
       
   538 
       
   539     Returns true if this matrix is not identical to \a other; false otherwise.
       
   540     This operator uses an exact floating-point comparison.
       
   541 */
       
   542 
       
   543 /*!
       
   544     \fn QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
       
   545     \relates QMatrix4x4
       
   546 
       
   547     Returns the sum of \a m1 and \a m2.
       
   548 */
       
   549 
       
   550 /*!
       
   551     \fn QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
       
   552     \relates QMatrix4x4
       
   553 
       
   554     Returns the difference of \a m1 and \a m2.
       
   555 */
       
   556 
       
   557 /*!
       
   558     \fn QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
       
   559     \relates QMatrix4x4
       
   560 
       
   561     Returns the product of \a m1 and \a m2.
       
   562 */
       
   563 
       
   564 #ifndef QT_NO_VECTOR3D
       
   565 
       
   566 /*!
       
   567     \fn QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
       
   568     \relates QMatrix4x4
       
   569 
       
   570     Returns the result of transforming \a vector according to \a matrix,
       
   571     with the matrix applied post-vector.
       
   572 */
       
   573 
       
   574 /*!
       
   575     \fn QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
       
   576     \relates QMatrix4x4
       
   577 
       
   578     Returns the result of transforming \a vector according to \a matrix,
       
   579     with the matrix applied pre-vector.
       
   580 */
       
   581 
       
   582 #endif
       
   583 
       
   584 #ifndef QT_NO_VECTOR4D
       
   585 
       
   586 /*!
       
   587     \fn QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
       
   588     \relates QMatrix4x4
       
   589 
       
   590     Returns the result of transforming \a vector according to \a matrix,
       
   591     with the matrix applied post-vector.
       
   592 */
       
   593 
       
   594 /*!
       
   595     \fn QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
       
   596     \relates QMatrix4x4
       
   597 
       
   598     Returns the result of transforming \a vector according to \a matrix,
       
   599     with the matrix applied pre-vector.
       
   600 */
       
   601 
       
   602 #endif
       
   603 
       
   604 /*!
       
   605     \fn QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
       
   606     \relates QMatrix4x4
       
   607 
       
   608     Returns the result of transforming \a point according to \a matrix,
       
   609     with the matrix applied post-point.
       
   610 */
       
   611 
       
   612 /*!
       
   613     \fn QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
       
   614     \relates QMatrix4x4
       
   615 
       
   616     Returns the result of transforming \a point according to \a matrix,
       
   617     with the matrix applied post-point.
       
   618 */
       
   619 
       
   620 /*!
       
   621     \fn QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
       
   622     \relates QMatrix4x4
       
   623 
       
   624     Returns the result of transforming \a point according to \a matrix,
       
   625     with the matrix applied pre-point.
       
   626 */
       
   627 
       
   628 /*!
       
   629     \fn QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
       
   630     \relates QMatrix4x4
       
   631 
       
   632     Returns the result of transforming \a point according to \a matrix,
       
   633     with the matrix applied pre-point.
       
   634 */
       
   635 
       
   636 /*!
       
   637     \fn QMatrix4x4 operator-(const QMatrix4x4& matrix)
       
   638     \overload
       
   639     \relates QMatrix4x4
       
   640 
       
   641     Returns the negation of \a matrix.
       
   642 */
       
   643 
       
   644 /*!
       
   645     \fn QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix)
       
   646     \relates QMatrix4x4
       
   647 
       
   648     Returns the result of multiplying all elements of \a matrix by \a factor.
       
   649 */
       
   650 
       
   651 /*!
       
   652     \fn QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor)
       
   653     \relates QMatrix4x4
       
   654 
       
   655     Returns the result of multiplying all elements of \a matrix by \a factor.
       
   656 */
       
   657 
       
   658 /*!
       
   659     \relates QMatrix4x4
       
   660 
       
   661     Returns the result of dividing all elements of \a matrix by \a divisor.
       
   662 */
       
   663 QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor)
       
   664 {
       
   665     QMatrix4x4 m(1); // The "1" says to not load the identity.
       
   666     m.m[0][0] = matrix.m[0][0] / divisor;
       
   667     m.m[0][1] = matrix.m[0][1] / divisor;
       
   668     m.m[0][2] = matrix.m[0][2] / divisor;
       
   669     m.m[0][3] = matrix.m[0][3] / divisor;
       
   670     m.m[1][0] = matrix.m[1][0] / divisor;
       
   671     m.m[1][1] = matrix.m[1][1] / divisor;
       
   672     m.m[1][2] = matrix.m[1][2] / divisor;
       
   673     m.m[1][3] = matrix.m[1][3] / divisor;
       
   674     m.m[2][0] = matrix.m[2][0] / divisor;
       
   675     m.m[2][1] = matrix.m[2][1] / divisor;
       
   676     m.m[2][2] = matrix.m[2][2] / divisor;
       
   677     m.m[2][3] = matrix.m[2][3] / divisor;
       
   678     m.m[3][0] = matrix.m[3][0] / divisor;
       
   679     m.m[3][1] = matrix.m[3][1] / divisor;
       
   680     m.m[3][2] = matrix.m[3][2] / divisor;
       
   681     m.m[3][3] = matrix.m[3][3] / divisor;
       
   682     return m;
       
   683 }
       
   684 
       
   685 /*!
       
   686     \fn bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
       
   687     \relates QMatrix4x4
       
   688 
       
   689     Returns true if \a m1 and \a m2 are equal, allowing for a small
       
   690     fuzziness factor for floating-point comparisons; false otherwise.
       
   691 */
       
   692 
       
   693 #ifndef QT_NO_VECTOR3D
       
   694 
       
   695 /*!
       
   696     Multiplies this matrix by another that scales coordinates by
       
   697     the components of \a vector.
       
   698 
       
   699     \sa translate(), rotate()
       
   700 */
       
   701 void QMatrix4x4::scale(const QVector3D& vector)
       
   702 {
       
   703     qreal vx = vector.x();
       
   704     qreal vy = vector.y();
       
   705     qreal vz = vector.z();
       
   706     if (flagBits == Identity) {
       
   707         m[0][0] = vx;
       
   708         m[1][1] = vy;
       
   709         m[2][2] = vz;
       
   710         flagBits = Scale;
       
   711     } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
       
   712         m[0][0] *= vx;
       
   713         m[1][1] *= vy;
       
   714         m[2][2] *= vz;
       
   715     } else if (flagBits == Translation) {
       
   716         m[0][0] = vx;
       
   717         m[1][1] = vy;
       
   718         m[2][2] = vz;
       
   719         flagBits |= Scale;
       
   720     } else {
       
   721         m[0][0] *= vx;
       
   722         m[0][1] *= vx;
       
   723         m[0][2] *= vx;
       
   724         m[0][3] *= vx;
       
   725         m[1][0] *= vy;
       
   726         m[1][1] *= vy;
       
   727         m[1][2] *= vy;
       
   728         m[1][3] *= vy;
       
   729         m[2][0] *= vz;
       
   730         m[2][1] *= vz;
       
   731         m[2][2] *= vz;
       
   732         m[2][3] *= vz;
       
   733         flagBits = General;
       
   734     }
       
   735 }
       
   736 #endif
       
   737 
       
   738 /*!
       
   739     \overload
       
   740 
       
   741     Multiplies this matrix by another that scales coordinates by the
       
   742     components \a x, and \a y.
       
   743 
       
   744     \sa translate(), rotate()
       
   745 */
       
   746 void QMatrix4x4::scale(qreal x, qreal y)
       
   747 {
       
   748     if (flagBits == Identity) {
       
   749         m[0][0] = x;
       
   750         m[1][1] = y;
       
   751         flagBits = Scale;
       
   752     } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
       
   753         m[0][0] *= x;
       
   754         m[1][1] *= y;
       
   755     } else if (flagBits == Translation) {
       
   756         m[0][0] = x;
       
   757         m[1][1] = y;
       
   758         flagBits |= Scale;
       
   759     } else {
       
   760         m[0][0] *= x;
       
   761         m[0][1] *= x;
       
   762         m[0][2] *= x;
       
   763         m[0][3] *= x;
       
   764         m[1][0] *= y;
       
   765         m[1][1] *= y;
       
   766         m[1][2] *= y;
       
   767         m[1][3] *= y;
       
   768         flagBits = General;
       
   769     }
       
   770 }
       
   771 
       
   772 /*!
       
   773     \overload
       
   774 
       
   775     Multiplies this matrix by another that scales coordinates by the
       
   776     components \a x, \a y, and \a z.
       
   777 
       
   778     \sa translate(), rotate()
       
   779 */
       
   780 void QMatrix4x4::scale(qreal x, qreal y, qreal z)
       
   781 {
       
   782     if (flagBits == Identity) {
       
   783         m[0][0] = x;
       
   784         m[1][1] = y;
       
   785         m[2][2] = z;
       
   786         flagBits = Scale;
       
   787     } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
       
   788         m[0][0] *= x;
       
   789         m[1][1] *= y;
       
   790         m[2][2] *= z;
       
   791     } else if (flagBits == Translation) {
       
   792         m[0][0] = x;
       
   793         m[1][1] = y;
       
   794         m[2][2] = z;
       
   795         flagBits |= Scale;
       
   796     } else {
       
   797         m[0][0] *= x;
       
   798         m[0][1] *= x;
       
   799         m[0][2] *= x;
       
   800         m[0][3] *= x;
       
   801         m[1][0] *= y;
       
   802         m[1][1] *= y;
       
   803         m[1][2] *= y;
       
   804         m[1][3] *= y;
       
   805         m[2][0] *= z;
       
   806         m[2][1] *= z;
       
   807         m[2][2] *= z;
       
   808         m[2][3] *= z;
       
   809         flagBits = General;
       
   810     }
       
   811 }
       
   812 
       
   813 /*!
       
   814     \overload
       
   815 
       
   816     Multiplies this matrix by another that scales coordinates by the
       
   817     given \a factor.
       
   818 
       
   819     \sa translate(), rotate()
       
   820 */
       
   821 void QMatrix4x4::scale(qreal factor)
       
   822 {
       
   823     if (flagBits == Identity) {
       
   824         m[0][0] = factor;
       
   825         m[1][1] = factor;
       
   826         m[2][2] = factor;
       
   827         flagBits = Scale;
       
   828     } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
       
   829         m[0][0] *= factor;
       
   830         m[1][1] *= factor;
       
   831         m[2][2] *= factor;
       
   832     } else if (flagBits == Translation) {
       
   833         m[0][0] = factor;
       
   834         m[1][1] = factor;
       
   835         m[2][2] = factor;
       
   836         flagBits |= Scale;
       
   837     } else {
       
   838         m[0][0] *= factor;
       
   839         m[0][1] *= factor;
       
   840         m[0][2] *= factor;
       
   841         m[0][3] *= factor;
       
   842         m[1][0] *= factor;
       
   843         m[1][1] *= factor;
       
   844         m[1][2] *= factor;
       
   845         m[1][3] *= factor;
       
   846         m[2][0] *= factor;
       
   847         m[2][1] *= factor;
       
   848         m[2][2] *= factor;
       
   849         m[2][3] *= factor;
       
   850         flagBits = General;
       
   851     }
       
   852 }
       
   853 
       
   854 #ifndef QT_NO_VECTOR3D
       
   855 /*!
       
   856     Multiplies this matrix by another that translates coordinates by
       
   857     the components of \a vector.
       
   858 
       
   859     \sa scale(), rotate()
       
   860 */
       
   861 void QMatrix4x4::translate(const QVector3D& vector)
       
   862 {
       
   863     qreal vx = vector.x();
       
   864     qreal vy = vector.y();
       
   865     qreal vz = vector.z();
       
   866     if (flagBits == Identity) {
       
   867         m[3][0] = vx;
       
   868         m[3][1] = vy;
       
   869         m[3][2] = vz;
       
   870         flagBits = Translation;
       
   871     } else if (flagBits == Translation) {
       
   872         m[3][0] += vx;
       
   873         m[3][1] += vy;
       
   874         m[3][2] += vz;
       
   875     } else if (flagBits == Scale) {
       
   876         m[3][0] = m[0][0] * vx;
       
   877         m[3][1] = m[1][1] * vy;
       
   878         m[3][2] = m[2][2] * vz;
       
   879         flagBits |= Translation;
       
   880     } else if (flagBits == (Scale | Translation)) {
       
   881         m[3][0] += m[0][0] * vx;
       
   882         m[3][1] += m[1][1] * vy;
       
   883         m[3][2] += m[2][2] * vz;
       
   884     } else {
       
   885         m[3][0] += m[0][0] * vx + m[1][0] * vy + m[2][0] * vz;
       
   886         m[3][1] += m[0][1] * vx + m[1][1] * vy + m[2][1] * vz;
       
   887         m[3][2] += m[0][2] * vx + m[1][2] * vy + m[2][2] * vz;
       
   888         m[3][3] += m[0][3] * vx + m[1][3] * vy + m[2][3] * vz;
       
   889         if (flagBits == Rotation)
       
   890             flagBits |= Translation;
       
   891         else if (flagBits != (Rotation | Translation))
       
   892             flagBits = General;
       
   893     }
       
   894 }
       
   895 
       
   896 #endif
       
   897 
       
   898 /*!
       
   899     \overload
       
   900 
       
   901     Multiplies this matrix by another that translates coordinates
       
   902     by the components \a x, and \a y.
       
   903 
       
   904     \sa scale(), rotate()
       
   905 */
       
   906 void QMatrix4x4::translate(qreal x, qreal y)
       
   907 {
       
   908     if (flagBits == Identity) {
       
   909         m[3][0] = x;
       
   910         m[3][1] = y;
       
   911         flagBits = Translation;
       
   912     } else if (flagBits == Translation) {
       
   913         m[3][0] += x;
       
   914         m[3][1] += y;
       
   915     } else if (flagBits == Scale) {
       
   916         m[3][0] = m[0][0] * x;
       
   917         m[3][1] = m[1][1] * y;
       
   918         m[3][2] = 0.;
       
   919         flagBits |= Translation;
       
   920     } else if (flagBits == (Scale | Translation)) {
       
   921         m[3][0] += m[0][0] * x;
       
   922         m[3][1] += m[1][1] * y;
       
   923     } else {
       
   924         m[3][0] += m[0][0] * x + m[1][0] * y;
       
   925         m[3][1] += m[0][1] * x + m[1][1] * y;
       
   926         m[3][2] += m[0][2] * x + m[1][2] * y;
       
   927         m[3][3] += m[0][3] * x + m[1][3] * y;
       
   928         if (flagBits == Rotation)
       
   929             flagBits |= Translation;
       
   930         else if (flagBits != (Rotation | Translation))
       
   931             flagBits = General;
       
   932     }
       
   933 }
       
   934 
       
   935 /*!
       
   936     \overload
       
   937 
       
   938     Multiplies this matrix by another that translates coordinates
       
   939     by the components \a x, \a y, and \a z.
       
   940 
       
   941     \sa scale(), rotate()
       
   942 */
       
   943 void QMatrix4x4::translate(qreal x, qreal y, qreal z)
       
   944 {
       
   945     if (flagBits == Identity) {
       
   946         m[3][0] = x;
       
   947         m[3][1] = y;
       
   948         m[3][2] = z;
       
   949         flagBits = Translation;
       
   950     } else if (flagBits == Translation) {
       
   951         m[3][0] += x;
       
   952         m[3][1] += y;
       
   953         m[3][2] += z;
       
   954     } else if (flagBits == Scale) {
       
   955         m[3][0] = m[0][0] * x;
       
   956         m[3][1] = m[1][1] * y;
       
   957         m[3][2] = m[2][2] * z;
       
   958         flagBits |= Translation;
       
   959     } else if (flagBits == (Scale | Translation)) {
       
   960         m[3][0] += m[0][0] * x;
       
   961         m[3][1] += m[1][1] * y;
       
   962         m[3][2] += m[2][2] * z;
       
   963     } else {
       
   964         m[3][0] += m[0][0] * x + m[1][0] * y + m[2][0] * z;
       
   965         m[3][1] += m[0][1] * x + m[1][1] * y + m[2][1] * z;
       
   966         m[3][2] += m[0][2] * x + m[1][2] * y + m[2][2] * z;
       
   967         m[3][3] += m[0][3] * x + m[1][3] * y + m[2][3] * z;
       
   968         if (flagBits == Rotation)
       
   969             flagBits |= Translation;
       
   970         else if (flagBits != (Rotation | Translation))
       
   971             flagBits = General;
       
   972     }
       
   973 }
       
   974 
       
   975 #ifndef QT_NO_VECTOR3D
       
   976 
       
   977 /*!
       
   978     Multiples this matrix by another that rotates coordinates through
       
   979     \a angle degrees about \a vector.
       
   980 
       
   981     \sa scale(), translate()
       
   982 */
       
   983 void QMatrix4x4::rotate(qreal angle, const QVector3D& vector)
       
   984 {
       
   985     rotate(angle, vector.x(), vector.y(), vector.z());
       
   986 }
       
   987 
       
   988 #endif
       
   989 
       
   990 /*!
       
   991     \overload
       
   992 
       
   993     Multiplies this matrix by another that rotates coordinates through
       
   994     \a angle degrees about the vector (\a x, \a y, \a z).
       
   995 
       
   996     \sa scale(), translate()
       
   997 */
       
   998 void QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z)
       
   999 {
       
  1000     if (angle == 0.0f)
       
  1001         return;
       
  1002     QMatrix4x4 m(1); // The "1" says to not load the identity.
       
  1003     qreal c, s, ic;
       
  1004     if (angle == 90.0f || angle == -270.0f) {
       
  1005         s = 1.0f;
       
  1006         c = 0.0f;
       
  1007     } else if (angle == -90.0f || angle == 270.0f) {
       
  1008         s = -1.0f;
       
  1009         c = 0.0f;
       
  1010     } else if (angle == 180.0f || angle == -180.0f) {
       
  1011         s = 0.0f;
       
  1012         c = -1.0f;
       
  1013     } else {
       
  1014         qreal a = angle * M_PI / 180.0f;
       
  1015         c = qCos(a);
       
  1016         s = qSin(a);
       
  1017     }
       
  1018     bool quick = false;
       
  1019     if (x == 0.0f) {
       
  1020         if (y == 0.0f) {
       
  1021             if (z != 0.0f) {
       
  1022                 // Rotate around the Z axis.
       
  1023                 m.setToIdentity();
       
  1024                 m.m[0][0] = c;
       
  1025                 m.m[1][1] = c;
       
  1026                 if (z < 0.0f) {
       
  1027                     m.m[1][0] = s;
       
  1028                     m.m[0][1] = -s;
       
  1029                 } else {
       
  1030                     m.m[1][0] = -s;
       
  1031                     m.m[0][1] = s;
       
  1032                 }
       
  1033                 m.flagBits = General;
       
  1034                 quick = true;
       
  1035             }
       
  1036         } else if (z == 0.0f) {
       
  1037             // Rotate around the Y axis.
       
  1038             m.setToIdentity();
       
  1039             m.m[0][0] = c;
       
  1040             m.m[2][2] = c;
       
  1041             if (y < 0.0f) {
       
  1042                 m.m[2][0] = -s;
       
  1043                 m.m[0][2] = s;
       
  1044             } else {
       
  1045                 m.m[2][0] = s;
       
  1046                 m.m[0][2] = -s;
       
  1047             }
       
  1048             m.flagBits = General;
       
  1049             quick = true;
       
  1050         }
       
  1051     } else if (y == 0.0f && z == 0.0f) {
       
  1052         // Rotate around the X axis.
       
  1053         m.setToIdentity();
       
  1054         m.m[1][1] = c;
       
  1055         m.m[2][2] = c;
       
  1056         if (x < 0.0f) {
       
  1057             m.m[2][1] = s;
       
  1058             m.m[1][2] = -s;
       
  1059         } else {
       
  1060             m.m[2][1] = -s;
       
  1061             m.m[1][2] = s;
       
  1062         }
       
  1063         m.flagBits = General;
       
  1064         quick = true;
       
  1065     }
       
  1066     if (!quick) {
       
  1067         qreal len = x * x + y * y + z * z;
       
  1068         if (!qFuzzyIsNull(len - 1.0f) && !qFuzzyIsNull(len)) {
       
  1069             len = qSqrt(len);
       
  1070             x /= len;
       
  1071             y /= len;
       
  1072             z /= len;
       
  1073         }
       
  1074         ic = 1.0f - c;
       
  1075         m.m[0][0] = x * x * ic + c;
       
  1076         m.m[1][0] = x * y * ic - z * s;
       
  1077         m.m[2][0] = x * z * ic + y * s;
       
  1078         m.m[3][0] = 0.0f;
       
  1079         m.m[0][1] = y * x * ic + z * s;
       
  1080         m.m[1][1] = y * y * ic + c;
       
  1081         m.m[2][1] = y * z * ic - x * s;
       
  1082         m.m[3][1] = 0.0f;
       
  1083         m.m[0][2] = x * z * ic - y * s;
       
  1084         m.m[1][2] = y * z * ic + x * s;
       
  1085         m.m[2][2] = z * z * ic + c;
       
  1086         m.m[3][2] = 0.0f;
       
  1087         m.m[0][3] = 0.0f;
       
  1088         m.m[1][3] = 0.0f;
       
  1089         m.m[2][3] = 0.0f;
       
  1090         m.m[3][3] = 1.0f;
       
  1091     }
       
  1092     int flags = flagBits;
       
  1093     *this *= m;
       
  1094     if (flags != Identity)
       
  1095         flagBits = flags | Rotation;
       
  1096     else
       
  1097         flagBits = Rotation;
       
  1098 }
       
  1099 
       
  1100 /*!
       
  1101     \internal
       
  1102 */
       
  1103 void QMatrix4x4::projectedRotate(qreal angle, qreal x, qreal y, qreal z)
       
  1104 {
       
  1105     // Used by QGraphicsRotation::applyTo() to perform a rotation
       
  1106     // and projection back to 2D in a single step.
       
  1107     if (angle == 0.0f)
       
  1108         return;
       
  1109     QMatrix4x4 m(1); // The "1" says to not load the identity.
       
  1110     qreal c, s, ic;
       
  1111     if (angle == 90.0f || angle == -270.0f) {
       
  1112         s = 1.0f;
       
  1113         c = 0.0f;
       
  1114     } else if (angle == -90.0f || angle == 270.0f) {
       
  1115         s = -1.0f;
       
  1116         c = 0.0f;
       
  1117     } else if (angle == 180.0f || angle == -180.0f) {
       
  1118         s = 0.0f;
       
  1119         c = -1.0f;
       
  1120     } else {
       
  1121         qreal a = angle * M_PI / 180.0f;
       
  1122         c = qCos(a);
       
  1123         s = qSin(a);
       
  1124     }
       
  1125     bool quick = false;
       
  1126     if (x == 0.0f) {
       
  1127         if (y == 0.0f) {
       
  1128             if (z != 0.0f) {
       
  1129                 // Rotate around the Z axis.
       
  1130                 m.setToIdentity();
       
  1131                 m.m[0][0] = c;
       
  1132                 m.m[1][1] = c;
       
  1133                 if (z < 0.0f) {
       
  1134                     m.m[1][0] = s;
       
  1135                     m.m[0][1] = -s;
       
  1136                 } else {
       
  1137                     m.m[1][0] = -s;
       
  1138                     m.m[0][1] = s;
       
  1139                 }
       
  1140                 m.flagBits = General;
       
  1141                 quick = true;
       
  1142             }
       
  1143         } else if (z == 0.0f) {
       
  1144             // Rotate around the Y axis.
       
  1145             m.setToIdentity();
       
  1146             m.m[0][0] = c;
       
  1147             m.m[2][2] = 1.0f;
       
  1148             if (y < 0.0f) {
       
  1149                 m.m[0][3] = -s * inv_dist_to_plane;
       
  1150             } else {
       
  1151                 m.m[0][3] = s * inv_dist_to_plane;
       
  1152             }
       
  1153             m.flagBits = General;
       
  1154             quick = true;
       
  1155         }
       
  1156     } else if (y == 0.0f && z == 0.0f) {
       
  1157         // Rotate around the X axis.
       
  1158         m.setToIdentity();
       
  1159         m.m[1][1] = c;
       
  1160         m.m[2][2] = 1.0f;
       
  1161         if (x < 0.0f) {
       
  1162             m.m[1][3] = s * inv_dist_to_plane;
       
  1163         } else {
       
  1164             m.m[1][3] = -s * inv_dist_to_plane;
       
  1165         }
       
  1166         m.flagBits = General;
       
  1167         quick = true;
       
  1168     }
       
  1169     if (!quick) {
       
  1170         qreal len = x * x + y * y + z * z;
       
  1171         if (!qFuzzyIsNull(len - 1.0f) && !qFuzzyIsNull(len)) {
       
  1172             len = qSqrt(len);
       
  1173             x /= len;
       
  1174             y /= len;
       
  1175             z /= len;
       
  1176         }
       
  1177         ic = 1.0f - c;
       
  1178         m.m[0][0] = x * x * ic + c;
       
  1179         m.m[1][0] = x * y * ic - z * s;
       
  1180         m.m[2][0] = 0.0f;
       
  1181         m.m[3][0] = 0.0f;
       
  1182         m.m[0][1] = y * x * ic + z * s;
       
  1183         m.m[1][1] = y * y * ic + c;
       
  1184         m.m[2][1] = 0.0f;
       
  1185         m.m[3][1] = 0.0f;
       
  1186         m.m[0][2] = 0.0f;
       
  1187         m.m[1][2] = 0.0f;
       
  1188         m.m[2][2] = 1.0f;
       
  1189         m.m[3][2] = 0.0f;
       
  1190         m.m[0][3] = (x * z * ic - y * s) * -inv_dist_to_plane;
       
  1191         m.m[1][3] = (y * z * ic + x * s) * -inv_dist_to_plane;
       
  1192         m.m[2][3] = 0.0f;
       
  1193         m.m[3][3] = 1.0f;
       
  1194     }
       
  1195     int flags = flagBits;
       
  1196     *this *= m;
       
  1197     if (flags != Identity)
       
  1198         flagBits = flags | Rotation;
       
  1199     else
       
  1200         flagBits = Rotation;
       
  1201 }
       
  1202 
       
  1203 #ifndef QT_NO_QUATERNION
       
  1204 
       
  1205 /*!
       
  1206     Multiples this matrix by another that rotates coordinates according
       
  1207     to a specified \a quaternion.  The \a quaternion is assumed to have
       
  1208     been normalized.
       
  1209 
       
  1210     \sa scale(), translate(), QQuaternion
       
  1211 */
       
  1212 void QMatrix4x4::rotate(const QQuaternion& quaternion)
       
  1213 {
       
  1214     // Algorithm from:
       
  1215     // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54
       
  1216     QMatrix4x4 m(1);
       
  1217     qreal xx = quaternion.x() * quaternion.x();
       
  1218     qreal xy = quaternion.x() * quaternion.y();
       
  1219     qreal xz = quaternion.x() * quaternion.z();
       
  1220     qreal xw = quaternion.x() * quaternion.scalar();
       
  1221     qreal yy = quaternion.y() * quaternion.y();
       
  1222     qreal yz = quaternion.y() * quaternion.z();
       
  1223     qreal yw = quaternion.y() * quaternion.scalar();
       
  1224     qreal zz = quaternion.z() * quaternion.z();
       
  1225     qreal zw = quaternion.z() * quaternion.scalar();
       
  1226     m.m[0][0] = 1.0f - 2 * (yy + zz);
       
  1227     m.m[1][0] =        2 * (xy - zw);
       
  1228     m.m[2][0] =        2 * (xz + yw);
       
  1229     m.m[3][0] = 0.0f;
       
  1230     m.m[0][1] =        2 * (xy + zw);
       
  1231     m.m[1][1] = 1.0f - 2 * (xx + zz);
       
  1232     m.m[2][1] =        2 * (yz - xw);
       
  1233     m.m[3][1] = 0.0f;
       
  1234     m.m[0][2] =        2 * (xz - yw);
       
  1235     m.m[1][2] =        2 * (yz + xw);
       
  1236     m.m[2][2] = 1.0f - 2 * (xx + yy);
       
  1237     m.m[3][2] = 0.0f;
       
  1238     m.m[0][3] = 0.0f;
       
  1239     m.m[1][3] = 0.0f;
       
  1240     m.m[2][3] = 0.0f;
       
  1241     m.m[3][3] = 1.0f;
       
  1242     int flags = flagBits;
       
  1243     *this *= m;
       
  1244     if (flags != Identity)
       
  1245         flagBits = flags | Rotation;
       
  1246     else
       
  1247         flagBits = Rotation;
       
  1248 }
       
  1249 
       
  1250 #endif
       
  1251 
       
  1252 /*!
       
  1253     \overload
       
  1254 
       
  1255     Multiplies this matrix by another that applies an orthographic
       
  1256     projection for a window with boundaries specified by \a rect.
       
  1257     The near and far clipping planes will be -1 and 1 respectively.
       
  1258 
       
  1259     \sa frustum(), perspective()
       
  1260 */
       
  1261 void QMatrix4x4::ortho(const QRect& rect)
       
  1262 {
       
  1263     // Note: rect.right() and rect.bottom() subtract 1 in QRect,
       
  1264     // which gives the location of a pixel within the rectangle,
       
  1265     // instead of the extent of the rectangle.  We want the extent.
       
  1266     // QRectF expresses the extent properly.
       
  1267     ortho(rect.x(), rect.x() + rect.width(), rect.y() + rect.height(), rect.y(), -1.0f, 1.0f);
       
  1268 }
       
  1269 
       
  1270 /*!
       
  1271     \overload
       
  1272 
       
  1273     Multiplies this matrix by another that applies an orthographic
       
  1274     projection for a window with boundaries specified by \a rect.
       
  1275     The near and far clipping planes will be -1 and 1 respectively.
       
  1276 
       
  1277     \sa frustum(), perspective()
       
  1278 */
       
  1279 void QMatrix4x4::ortho(const QRectF& rect)
       
  1280 {
       
  1281     ortho(rect.left(), rect.right(), rect.bottom(), rect.top(), -1.0f, 1.0f);
       
  1282 }
       
  1283 
       
  1284 /*!
       
  1285     Multiplies this matrix by another that applies an orthographic
       
  1286     projection for a window with lower-left corner (\a left, \a bottom),
       
  1287     upper-right corner (\a right, \a top), and the specified \a nearPlane
       
  1288     and \a farPlane clipping planes.
       
  1289 
       
  1290     \sa frustum(), perspective()
       
  1291 */
       
  1292 void QMatrix4x4::ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
       
  1293 {
       
  1294     // Bail out if the projection volume is zero-sized.
       
  1295     if (left == right || bottom == top || nearPlane == farPlane)
       
  1296         return;
       
  1297 
       
  1298     // Construct the projection.
       
  1299     qreal width = right - left;
       
  1300     qreal invheight = top - bottom;
       
  1301     qreal clip = farPlane - nearPlane;
       
  1302 #ifndef QT_NO_VECTOR3D
       
  1303     if (clip == 2.0f && (nearPlane + farPlane) == 0.0f) {
       
  1304         // We can express this projection as a translate and scale
       
  1305         // which will be more efficient to modify with further
       
  1306         // transformations than producing a "General" matrix.
       
  1307         translate(QVector3D
       
  1308             (-(left + right) / width,
       
  1309              -(top + bottom) / invheight,
       
  1310              0.0f));
       
  1311         scale(QVector3D
       
  1312             (2.0f / width,
       
  1313              2.0f / invheight,
       
  1314              -1.0f));
       
  1315         return;
       
  1316     }
       
  1317 #endif
       
  1318     QMatrix4x4 m(1);
       
  1319     m.m[0][0] = 2.0f / width;
       
  1320     m.m[1][0] = 0.0f;
       
  1321     m.m[2][0] = 0.0f;
       
  1322     m.m[3][0] = -(left + right) / width;
       
  1323     m.m[0][1] = 0.0f;
       
  1324     m.m[1][1] = 2.0f / invheight;
       
  1325     m.m[2][1] = 0.0f;
       
  1326     m.m[3][1] = -(top + bottom) / invheight;
       
  1327     m.m[0][2] = 0.0f;
       
  1328     m.m[1][2] = 0.0f;
       
  1329     m.m[2][2] = -2.0f / clip;
       
  1330     m.m[3][2] = -(nearPlane + farPlane) / clip;
       
  1331     m.m[0][3] = 0.0f;
       
  1332     m.m[1][3] = 0.0f;
       
  1333     m.m[2][3] = 0.0f;
       
  1334     m.m[3][3] = 1.0f;
       
  1335 
       
  1336     // Apply the projection.
       
  1337     *this *= m;
       
  1338     return;
       
  1339 }
       
  1340 
       
  1341 /*!
       
  1342     Multiplies this matrix by another that applies a perspective
       
  1343     frustum projection for a window with lower-left corner (\a left, \a bottom),
       
  1344     upper-right corner (\a right, \a top), and the specified \a nearPlane
       
  1345     and \a farPlane clipping planes.
       
  1346 
       
  1347     \sa ortho(), perspective()
       
  1348 */
       
  1349 void QMatrix4x4::frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
       
  1350 {
       
  1351     // Bail out if the projection volume is zero-sized.
       
  1352     if (left == right || bottom == top || nearPlane == farPlane)
       
  1353         return;
       
  1354 
       
  1355     // Construct the projection.
       
  1356     QMatrix4x4 m(1);
       
  1357     qreal width = right - left;
       
  1358     qreal invheight = top - bottom;
       
  1359     qreal clip = farPlane - nearPlane;
       
  1360     m.m[0][0] = 2.0f * nearPlane / width;
       
  1361     m.m[1][0] = 0.0f;
       
  1362     m.m[2][0] = (left + right) / width;
       
  1363     m.m[3][0] = 0.0f;
       
  1364     m.m[0][1] = 0.0f;
       
  1365     m.m[1][1] = 2.0f * nearPlane / invheight;
       
  1366     m.m[2][1] = (top + bottom) / invheight;
       
  1367     m.m[3][1] = 0.0f;
       
  1368     m.m[0][2] = 0.0f;
       
  1369     m.m[1][2] = 0.0f;
       
  1370     m.m[2][2] = -(nearPlane + farPlane) / clip;
       
  1371     m.m[3][2] = -2.0f * nearPlane * farPlane / clip;
       
  1372     m.m[0][3] = 0.0f;
       
  1373     m.m[1][3] = 0.0f;
       
  1374     m.m[2][3] = -1.0f;
       
  1375     m.m[3][3] = 0.0f;
       
  1376 
       
  1377     // Apply the projection.
       
  1378     *this *= m;
       
  1379 }
       
  1380 
       
  1381 /*!
       
  1382     Multiplies this matrix by another that applies a perspective
       
  1383     projection.  The field of view will be \a angle degrees within
       
  1384     a window with a given \a aspect ratio.  The projection will
       
  1385     have the specified \a nearPlane and \a farPlane clipping planes.
       
  1386 
       
  1387     \sa ortho(), frustum()
       
  1388 */
       
  1389 void QMatrix4x4::perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane)
       
  1390 {
       
  1391     // Bail out if the projection volume is zero-sized.
       
  1392     if (nearPlane == farPlane || aspect == 0.0f)
       
  1393         return;
       
  1394 
       
  1395     // Construct the projection.
       
  1396     QMatrix4x4 m(1);
       
  1397     qreal radians = (angle / 2.0f) * M_PI / 180.0f;
       
  1398     qreal sine = qSin(radians);
       
  1399     if (sine == 0.0f)
       
  1400         return;
       
  1401     qreal cotan = qCos(radians) / sine;
       
  1402     qreal clip = farPlane - nearPlane;
       
  1403     m.m[0][0] = cotan / aspect;
       
  1404     m.m[1][0] = 0.0f;
       
  1405     m.m[2][0] = 0.0f;
       
  1406     m.m[3][0] = 0.0f;
       
  1407     m.m[0][1] = 0.0f;
       
  1408     m.m[1][1] = cotan;
       
  1409     m.m[2][1] = 0.0f;
       
  1410     m.m[3][1] = 0.0f;
       
  1411     m.m[0][2] = 0.0f;
       
  1412     m.m[1][2] = 0.0f;
       
  1413     m.m[2][2] = -(nearPlane + farPlane) / clip;
       
  1414     m.m[3][2] = -(2.0f * nearPlane * farPlane) / clip;
       
  1415     m.m[0][3] = 0.0f;
       
  1416     m.m[1][3] = 0.0f;
       
  1417     m.m[2][3] = -1.0f;
       
  1418     m.m[3][3] = 0.0f;
       
  1419 
       
  1420     // Apply the projection.
       
  1421     *this *= m;
       
  1422 }
       
  1423 
       
  1424 #ifndef QT_NO_VECTOR3D
       
  1425 
       
  1426 /*!
       
  1427     Multiplies this matrix by another that applies an \a eye position
       
  1428     transformation.  The \a center value indicates the center of the
       
  1429     view that the \a eye is looking at.  The \a up value indicates
       
  1430     which direction should be considered up with respect to the \a eye.
       
  1431 */
       
  1432 void QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up)
       
  1433 {
       
  1434     QVector3D forward = (center - eye).normalized();
       
  1435     QVector3D side = QVector3D::crossProduct(forward, up).normalized();
       
  1436     QVector3D upVector = QVector3D::crossProduct(side, forward);
       
  1437 
       
  1438     QMatrix4x4 m(1);
       
  1439 
       
  1440     m.m[0][0] = side.x();
       
  1441     m.m[1][0] = side.y();
       
  1442     m.m[2][0] = side.z();
       
  1443     m.m[3][0] = 0.0f;
       
  1444     m.m[0][1] = upVector.x();
       
  1445     m.m[1][1] = upVector.y();
       
  1446     m.m[2][1] = upVector.z();
       
  1447     m.m[3][1] = 0.0f;
       
  1448     m.m[0][2] = -forward.x();
       
  1449     m.m[1][2] = -forward.y();
       
  1450     m.m[2][2] = -forward.z();
       
  1451     m.m[3][2] = 0.0f;
       
  1452     m.m[0][3] = 0.0f;
       
  1453     m.m[1][3] = 0.0f;
       
  1454     m.m[2][3] = 0.0f;
       
  1455     m.m[3][3] = 1.0f;
       
  1456 
       
  1457     *this *= m;
       
  1458     translate(-eye);
       
  1459 }
       
  1460 
       
  1461 #endif
       
  1462 
       
  1463 /*!
       
  1464     Flips between right-handed and left-handed coordinate systems
       
  1465     by multiplying the y and z co-ordinates by -1.  This is normally
       
  1466     used to create a left-handed orthographic view without scaling
       
  1467     the viewport as ortho() does.
       
  1468 
       
  1469     \sa ortho()
       
  1470 */
       
  1471 void QMatrix4x4::flipCoordinates()
       
  1472 {
       
  1473     if (flagBits == Scale || flagBits == (Scale | Translation)) {
       
  1474         m[1][1] = -m[1][1];
       
  1475         m[2][2] = -m[2][2];
       
  1476     } else if (flagBits == Translation) {
       
  1477         m[1][1] = -m[1][1];
       
  1478         m[2][2] = -m[2][2];
       
  1479         flagBits |= Scale;
       
  1480     } else if (flagBits == Identity) {
       
  1481         m[1][1] = -1.0f;
       
  1482         m[2][2] = -1.0f;
       
  1483         flagBits = Scale;
       
  1484     } else {
       
  1485         m[1][0] = -m[1][0];
       
  1486         m[1][1] = -m[1][1];
       
  1487         m[1][2] = -m[1][2];
       
  1488         m[1][3] = -m[1][3];
       
  1489         m[2][0] = -m[2][0];
       
  1490         m[2][1] = -m[2][1];
       
  1491         m[2][2] = -m[2][2];
       
  1492         m[2][3] = -m[2][3];
       
  1493         flagBits = General;
       
  1494     }
       
  1495 }
       
  1496 
       
  1497 /*!
       
  1498     Retrieves the 16 items in this matrix and copies them to \a values
       
  1499     in row-major order.
       
  1500 */
       
  1501 void QMatrix4x4::copyDataTo(qreal *values) const
       
  1502 {
       
  1503     for (int row = 0; row < 4; ++row)
       
  1504         for (int col = 0; col < 4; ++col)
       
  1505             values[row * 4 + col] = qreal(m[col][row]);
       
  1506 }
       
  1507 
       
  1508 /*!
       
  1509     Returns the conventional Qt 2D affine transformation matrix that
       
  1510     corresponds to this matrix.  It is assumed that this matrix
       
  1511     only contains 2D affine transformation elements.
       
  1512 
       
  1513     \sa toTransform()
       
  1514 */
       
  1515 QMatrix QMatrix4x4::toAffine() const
       
  1516 {
       
  1517     return QMatrix(m[0][0], m[0][1],
       
  1518                    m[1][0], m[1][1],
       
  1519                    m[3][0], m[3][1]);
       
  1520 }
       
  1521 
       
  1522 /*!
       
  1523     Returns the conventional Qt 2D transformation matrix that
       
  1524     corresponds to this matrix.
       
  1525 
       
  1526     The returned QTransform is formed by simply dropping the
       
  1527     third row and third column of the QMatrix4x4.  This is suitable
       
  1528     for implementing orthographic projections where the z co-ordinate
       
  1529     should be dropped rather than projected.
       
  1530 
       
  1531     \sa toAffine()
       
  1532 */
       
  1533 QTransform QMatrix4x4::toTransform() const
       
  1534 {
       
  1535     return QTransform(m[0][0], m[0][1], m[0][3],
       
  1536                       m[1][0], m[1][1], m[1][3],
       
  1537                       m[3][0], m[3][1], m[3][3]);
       
  1538 }
       
  1539 
       
  1540 /*!
       
  1541     Returns the conventional Qt 2D transformation matrix that
       
  1542     corresponds to this matrix.
       
  1543 
       
  1544     If \a distanceToPlane is non-zero, it indicates a projection
       
  1545     factor to use to adjust for the z co-ordinate.  The value of
       
  1546     1024 corresponds to the projection factor used
       
  1547     by QTransform::rotate() for the x and y axes.
       
  1548 
       
  1549     If \a distanceToPlane is zero, then the returned QTransform
       
  1550     is formed by simply dropping the third row and third column
       
  1551     of the QMatrix4x4.  This is suitable for implementing
       
  1552     orthographic projections where the z co-ordinate should
       
  1553     be dropped rather than projected.
       
  1554 
       
  1555     \sa toAffine()
       
  1556 */
       
  1557 QTransform QMatrix4x4::toTransform(qreal distanceToPlane) const
       
  1558 {
       
  1559     if (distanceToPlane == 1024.0f) {
       
  1560         // Optimize the common case with constants.
       
  1561         return QTransform(m[0][0], m[0][1],
       
  1562                                 m[0][3] - m[0][2] * inv_dist_to_plane,
       
  1563                           m[1][0], m[1][1],
       
  1564                                 m[1][3] - m[1][2] * inv_dist_to_plane,
       
  1565                           m[3][0], m[3][1],
       
  1566                                 m[3][3] - m[3][2] * inv_dist_to_plane);
       
  1567     } else if (distanceToPlane != 0.0f) {
       
  1568         // The following projection matrix is pre-multiplied with "matrix":
       
  1569         //      | 1 0 0 0 |
       
  1570         //      | 0 1 0 0 |
       
  1571         //      | 0 0 1 0 |
       
  1572         //      | 0 0 d 1 |
       
  1573         // where d = -1 / distanceToPlane.  After projection, row 3 and
       
  1574         // column 3 are dropped to form the final QTransform.
       
  1575         qreal d = 1.0f / distanceToPlane;
       
  1576         return QTransform(m[0][0], m[0][1], m[0][3] - m[0][2] * d,
       
  1577                           m[1][0], m[1][1], m[1][3] - m[1][2] * d,
       
  1578                           m[3][0], m[3][1], m[3][3] - m[3][2] * d);
       
  1579     } else {
       
  1580         // Orthographic projection: drop row 3 and column 3.
       
  1581         return QTransform(m[0][0], m[0][1], m[0][3],
       
  1582                           m[1][0], m[1][1], m[1][3],
       
  1583                           m[3][0], m[3][1], m[3][3]);
       
  1584     }
       
  1585 }
       
  1586 
       
  1587 /*!
       
  1588     \fn QPoint QMatrix4x4::map(const QPoint& point) const
       
  1589 
       
  1590     Maps \a point by multiplying this matrix by \a point.
       
  1591 
       
  1592     \sa mapRect()
       
  1593 */
       
  1594 
       
  1595 /*!
       
  1596     \fn QPointF QMatrix4x4::map(const QPointF& point) const
       
  1597 
       
  1598     Maps \a point by multiplying this matrix by \a point.
       
  1599 
       
  1600     \sa mapRect()
       
  1601 */
       
  1602 
       
  1603 #ifndef QT_NO_VECTOR3D
       
  1604 
       
  1605 /*!
       
  1606     \fn QVector3D QMatrix4x4::map(const QVector3D& point) const
       
  1607 
       
  1608     Maps \a point by multiplying this matrix by \a point.
       
  1609 
       
  1610     \sa mapRect(), mapVector()
       
  1611 */
       
  1612 
       
  1613 /*!
       
  1614     \fn QVector3D QMatrix4x4::mapVector(const QVector3D& vector) const
       
  1615 
       
  1616     Maps \a vector by multiplying the top 3x3 portion of this matrix
       
  1617     by \a vector.  The translation and projection components of
       
  1618     this matrix are ignored.
       
  1619 
       
  1620     \sa map()
       
  1621 */
       
  1622 
       
  1623 #endif
       
  1624 
       
  1625 #ifndef QT_NO_VECTOR4D
       
  1626 
       
  1627 /*!
       
  1628     \fn QVector4D QMatrix4x4::map(const QVector4D& point) const;
       
  1629 
       
  1630     Maps \a point by multiplying this matrix by \a point.
       
  1631 
       
  1632     \sa mapRect()
       
  1633 */
       
  1634 
       
  1635 #endif
       
  1636 
       
  1637 /*!
       
  1638     Maps \a rect by multiplying this matrix by the corners
       
  1639     of \a rect and then forming a new rectangle from the results.
       
  1640     The returned rectangle will be an ordinary 2D rectangle
       
  1641     with sides parallel to the horizontal and vertical axes.
       
  1642 
       
  1643     \sa map()
       
  1644 */
       
  1645 QRect QMatrix4x4::mapRect(const QRect& rect) const
       
  1646 {
       
  1647     if (flagBits == (Translation | Scale) || flagBits == Scale) {
       
  1648         qreal x = rect.x() * m[0][0] + m[3][0];
       
  1649         qreal y = rect.y() * m[1][1] + m[3][1];
       
  1650         qreal w = rect.width() * m[0][0];
       
  1651         qreal h = rect.height() * m[1][1];
       
  1652         if (w < 0) {
       
  1653             w = -w;
       
  1654             x -= w;
       
  1655         }
       
  1656         if (h < 0) {
       
  1657             h = -h;
       
  1658             y -= h;
       
  1659         }
       
  1660         return QRect(qRound(x), qRound(y), qRound(w), qRound(h));
       
  1661     } else if (flagBits == Translation) {
       
  1662         return QRect(qRound(rect.x() + m[3][0]),
       
  1663                      qRound(rect.y() + m[3][1]),
       
  1664                      rect.width(), rect.height());
       
  1665     }
       
  1666 
       
  1667     QPoint tl = map(rect.topLeft());
       
  1668     QPoint tr = map(QPoint(rect.x() + rect.width(), rect.y()));
       
  1669     QPoint bl = map(QPoint(rect.x(), rect.y() + rect.height()));
       
  1670     QPoint br = map(QPoint(rect.x() + rect.width(),
       
  1671                            rect.y() + rect.height()));
       
  1672 
       
  1673     int xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
       
  1674     int xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
       
  1675     int ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
       
  1676     int ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
       
  1677 
       
  1678     return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
       
  1679 }
       
  1680 
       
  1681 /*!
       
  1682     Maps \a rect by multiplying this matrix by the corners
       
  1683     of \a rect and then forming a new rectangle from the results.
       
  1684     The returned rectangle will be an ordinary 2D rectangle
       
  1685     with sides parallel to the horizontal and vertical axes.
       
  1686 
       
  1687     \sa map()
       
  1688 */
       
  1689 QRectF QMatrix4x4::mapRect(const QRectF& rect) const
       
  1690 {
       
  1691     if (flagBits == (Translation | Scale) || flagBits == Scale) {
       
  1692         qreal x = rect.x() * m[0][0] + m[3][0];
       
  1693         qreal y = rect.y() * m[1][1] + m[3][1];
       
  1694         qreal w = rect.width() * m[0][0];
       
  1695         qreal h = rect.height() * m[1][1];
       
  1696         if (w < 0) {
       
  1697             w = -w;
       
  1698             x -= w;
       
  1699         }
       
  1700         if (h < 0) {
       
  1701             h = -h;
       
  1702             y -= h;
       
  1703         }
       
  1704         return QRectF(x, y, w, h);
       
  1705     } else if (flagBits == Translation) {
       
  1706         return rect.translated(m[3][0], m[3][1]);
       
  1707     }
       
  1708 
       
  1709     QPointF tl = map(rect.topLeft()); QPointF tr = map(rect.topRight());
       
  1710     QPointF bl = map(rect.bottomLeft()); QPointF br = map(rect.bottomRight());
       
  1711 
       
  1712     qreal xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
       
  1713     qreal xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
       
  1714     qreal ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
       
  1715     qreal ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
       
  1716 
       
  1717     return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
       
  1718 }
       
  1719 
       
  1720 /*!
       
  1721     \fn qreal *QMatrix4x4::data()
       
  1722 
       
  1723     Returns a pointer to the raw data of this matrix.
       
  1724 
       
  1725     \sa constData(), optimize()
       
  1726 */
       
  1727 
       
  1728 /*!
       
  1729     \fn const qreal *QMatrix4x4::data() const
       
  1730 
       
  1731     Returns a constant pointer to the raw data of this matrix.
       
  1732 
       
  1733     \sa constData()
       
  1734 */
       
  1735 
       
  1736 /*!
       
  1737     \fn const qreal *QMatrix4x4::constData() const
       
  1738 
       
  1739     Returns a constant pointer to the raw data of this matrix.
       
  1740 
       
  1741     \sa data()
       
  1742 */
       
  1743 
       
  1744 // Helper routine for inverting orthonormal matrices that consist
       
  1745 // of just rotations and translations.
       
  1746 QMatrix4x4 QMatrix4x4::orthonormalInverse() const
       
  1747 {
       
  1748     QMatrix4x4 result(1);  // The '1' says not to load identity
       
  1749 
       
  1750     result.m[0][0] = m[0][0];
       
  1751     result.m[1][0] = m[0][1];
       
  1752     result.m[2][0] = m[0][2];
       
  1753 
       
  1754     result.m[0][1] = m[1][0];
       
  1755     result.m[1][1] = m[1][1];
       
  1756     result.m[2][1] = m[1][2];
       
  1757 
       
  1758     result.m[0][2] = m[2][0];
       
  1759     result.m[1][2] = m[2][1];
       
  1760     result.m[2][2] = m[2][2];
       
  1761 
       
  1762     result.m[0][3] = 0.0f;
       
  1763     result.m[1][3] = 0.0f;
       
  1764     result.m[2][3] = 0.0f;
       
  1765 
       
  1766     result.m[3][0] = -(result.m[0][0] * m[3][0] + result.m[1][0] * m[3][1] + result.m[2][0] * m[3][2]);
       
  1767     result.m[3][1] = -(result.m[0][1] * m[3][0] + result.m[1][1] * m[3][1] + result.m[2][1] * m[3][2]);
       
  1768     result.m[3][2] = -(result.m[0][2] * m[3][0] + result.m[1][2] * m[3][1] + result.m[2][2] * m[3][2]);
       
  1769     result.m[3][3] = 1.0f;
       
  1770 
       
  1771     return result;
       
  1772 }
       
  1773 
       
  1774 /*!
       
  1775     Optimize the usage of this matrix from its current elements.
       
  1776 
       
  1777     Some operations such as translate(), scale(), and rotate() can be
       
  1778     performed more efficiently if the matrix being modified is already
       
  1779     known to be the identity, a previous translate(), a previous
       
  1780     scale(), etc.
       
  1781 
       
  1782     Normally the QMatrix4x4 class keeps track of this special type internally
       
  1783     as operations are performed.  However, if the matrix is modified
       
  1784     directly with operator()() or data(), then QMatrix4x4 will lose track of
       
  1785     the special type and will revert to the safest but least efficient
       
  1786     operations thereafter.
       
  1787 
       
  1788     By calling optimize() after directly modifying the matrix,
       
  1789     the programmer can force QMatrix4x4 to recover the special type if
       
  1790     the elements appear to conform to one of the known optimized types.
       
  1791 
       
  1792     \sa operator()(), data(), translate()
       
  1793 */
       
  1794 void QMatrix4x4::optimize()
       
  1795 {
       
  1796     // If the last element is not 1, then it can never be special.
       
  1797     if (m[3][3] != 1.0f) {
       
  1798         flagBits = General;
       
  1799         return;
       
  1800     }
       
  1801 
       
  1802     // If the upper three elements m12, m13, and m21 are not all zero,
       
  1803     // or the lower elements below the diagonal are not all zero, then
       
  1804     // the matrix can never be special.
       
  1805     if (m[1][0] != 0.0f || m[2][0] != 0.0f || m[2][1] != 0.0f) {
       
  1806         flagBits = General;
       
  1807         return;
       
  1808     }
       
  1809     if (m[0][1] != 0.0f || m[0][2] != 0.0f || m[0][3] != 0.0f ||
       
  1810         m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][3] != 0.0f) {
       
  1811         flagBits = General;
       
  1812         return;
       
  1813     }
       
  1814 
       
  1815     // Determine what we have in the remaining regions of the matrix.
       
  1816     bool identityAlongDiagonal
       
  1817         = (m[0][0] == 1.0f && m[1][1] == 1.0f && m[2][2] == 1.0f);
       
  1818     bool translationPresent
       
  1819         = (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f);
       
  1820 
       
  1821     // Now determine the special matrix type.
       
  1822     if (translationPresent && identityAlongDiagonal)
       
  1823         flagBits = Translation;
       
  1824     else if (translationPresent)
       
  1825         flagBits = (Translation | Scale);
       
  1826     else if (identityAlongDiagonal)
       
  1827         flagBits = Identity;
       
  1828     else
       
  1829         flagBits = Scale;
       
  1830 }
       
  1831 
       
  1832 /*!
       
  1833     Returns the matrix as a QVariant.
       
  1834 */
       
  1835 QMatrix4x4::operator QVariant() const
       
  1836 {
       
  1837     return QVariant(QVariant::Matrix4x4, this);
       
  1838 }
       
  1839 
       
  1840 #ifndef QT_NO_DEBUG_STREAM
       
  1841 
       
  1842 QDebug operator<<(QDebug dbg, const QMatrix4x4 &m)
       
  1843 {
       
  1844     // Create a string that represents the matrix type.
       
  1845     QByteArray bits;
       
  1846     if ((m.flagBits & QMatrix4x4::Identity) != 0)
       
  1847         bits += "Identity,";
       
  1848     if ((m.flagBits & QMatrix4x4::General) != 0)
       
  1849         bits += "General,";
       
  1850     if ((m.flagBits & QMatrix4x4::Translation) != 0)
       
  1851         bits += "Translation,";
       
  1852     if ((m.flagBits & QMatrix4x4::Scale) != 0)
       
  1853         bits += "Scale,";
       
  1854     if ((m.flagBits & QMatrix4x4::Rotation) != 0)
       
  1855         bits += "Rotation,";
       
  1856     if (bits.size() > 0)
       
  1857         bits = bits.left(bits.size() - 1);
       
  1858 
       
  1859     // Output in row-major order because it is more human-readable.
       
  1860     dbg.nospace() << "QMatrix4x4(type:" << bits.constData() << endl
       
  1861         << qSetFieldWidth(10)
       
  1862         << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << endl
       
  1863         << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << endl
       
  1864         << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << endl
       
  1865         << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << endl
       
  1866         << qSetFieldWidth(0) << ')';
       
  1867     return dbg.space();
       
  1868 }
       
  1869 
       
  1870 #endif
       
  1871 
       
  1872 #ifndef QT_NO_DATASTREAM
       
  1873 
       
  1874 /*!
       
  1875     \fn QDataStream &operator<<(QDataStream &stream, const QMatrix4x4 &matrix)
       
  1876     \relates QMatrix4x4
       
  1877 
       
  1878     Writes the given \a matrix to the given \a stream and returns a
       
  1879     reference to the stream.
       
  1880 
       
  1881     \sa {Format of the QDataStream Operators}
       
  1882 */
       
  1883 
       
  1884 QDataStream &operator<<(QDataStream &stream, const QMatrix4x4 &matrix)
       
  1885 {
       
  1886     for (int row = 0; row < 4; ++row)
       
  1887         for (int col = 0; col < 4; ++col)
       
  1888             stream << double(matrix(row, col));
       
  1889     return stream;
       
  1890 }
       
  1891 
       
  1892 /*!
       
  1893     \fn QDataStream &operator>>(QDataStream &stream, QMatrix4x4 &matrix)
       
  1894     \relates QMatrix4x4
       
  1895 
       
  1896     Reads a 4x4 matrix from the given \a stream into the given \a matrix
       
  1897     and returns a reference to the stream.
       
  1898 
       
  1899     \sa {Format of the QDataStream Operators}
       
  1900 */
       
  1901 
       
  1902 QDataStream &operator>>(QDataStream &stream, QMatrix4x4 &matrix)
       
  1903 {
       
  1904     double x;
       
  1905     for (int row = 0; row < 4; ++row) {
       
  1906         for (int col = 0; col < 4; ++col) {
       
  1907             stream >> x;
       
  1908             matrix(row, col) = qreal(x);
       
  1909         }
       
  1910     }
       
  1911     matrix.optimize();
       
  1912     return stream;
       
  1913 }
       
  1914 
       
  1915 #endif // QT_NO_DATASTREAM
       
  1916 
       
  1917 #endif // QT_NO_MATRIX4X4
       
  1918 
       
  1919 QT_END_NAMESPACE