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