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