Merge "Merge branch 'newdocs'" into refs/staging/master
[profile/ivi/qtbase.git] / src / gui / math3d / qmatrix4x4.h
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 #ifndef QMATRIX4X4_H
43 #define QMATRIX4X4_H
44
45 #include <QtGui/qvector3d.h>
46 #include <QtGui/qvector4d.h>
47 #include <QtGui/qquaternion.h>
48 #include <QtGui/qgenericmatrix.h>
49 #include <QtCore/qrect.h>
50
51 QT_BEGIN_HEADER
52
53 QT_BEGIN_NAMESPACE
54
55
56 #ifndef QT_NO_MATRIX4X4
57
58 class QMatrix;
59 class QTransform;
60 class QVariant;
61
62 class Q_GUI_EXPORT QMatrix4x4
63 {
64 public:
65     inline QMatrix4x4() { setToIdentity(); }
66     explicit QMatrix4x4(const float *values);
67     inline QMatrix4x4(float m11, float m12, float m13, float m14,
68                       float m21, float m22, float m23, float m24,
69                       float m31, float m32, float m33, float m34,
70                       float m41, float m42, float m43, float m44);
71
72     template <int N, int M>
73     explicit QMatrix4x4(const QGenericMatrix<N, M, float>& matrix);
74
75     QMatrix4x4(const float *values, int cols, int rows);
76     QMatrix4x4(const QTransform& transform);
77     QMatrix4x4(const QMatrix& matrix);
78
79     inline const float& operator()(int row, int column) const;
80     inline float& operator()(int row, int column);
81
82 #ifndef QT_NO_VECTOR4D
83     inline QVector4D column(int index) const;
84     inline void setColumn(int index, const QVector4D& value);
85
86     inline QVector4D row(int index) const;
87     inline void setRow(int index, const QVector4D& value);
88 #endif
89
90     inline bool isIdentity() const;
91     inline void setToIdentity();
92
93     inline void fill(float value);
94
95     double determinant() const;
96     QMatrix4x4 inverted(bool *invertible = 0) const;
97     QMatrix4x4 transposed() const;
98     QMatrix3x3 normalMatrix() const;
99
100     inline QMatrix4x4& operator+=(const QMatrix4x4& other);
101     inline QMatrix4x4& operator-=(const QMatrix4x4& other);
102     inline QMatrix4x4& operator*=(const QMatrix4x4& other);
103     inline QMatrix4x4& operator*=(float factor);
104     QMatrix4x4& operator/=(float divisor);
105     inline bool operator==(const QMatrix4x4& other) const;
106     inline bool operator!=(const QMatrix4x4& other) const;
107
108     friend QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2);
109     friend QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2);
110     friend QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2);
111 #ifndef QT_NO_VECTOR3D
112     friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector);
113     friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix);
114 #endif
115 #ifndef QT_NO_VECTOR4D
116     friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix);
117     friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector);
118 #endif
119     friend QPoint operator*(const QPoint& point, const QMatrix4x4& matrix);
120     friend QPointF operator*(const QPointF& point, const QMatrix4x4& matrix);
121     friend QMatrix4x4 operator-(const QMatrix4x4& matrix);
122     friend QPoint operator*(const QMatrix4x4& matrix, const QPoint& point);
123     friend QPointF operator*(const QMatrix4x4& matrix, const QPointF& point);
124     friend QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix);
125     friend QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor);
126     friend Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor);
127
128     friend inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2);
129
130 #ifndef QT_NO_VECTOR3D
131     void scale(const QVector3D& vector);
132     void translate(const QVector3D& vector);
133     void rotate(float angle, const QVector3D& vector);
134 #endif
135     void scale(float x, float y);
136     void scale(float x, float y, float z);
137     void scale(float factor);
138     void translate(float x, float y);
139     void translate(float x, float y, float z);
140     void rotate(float angle, float x, float y, float z = 0.0f);
141 #ifndef QT_NO_QUATERNION
142     void rotate(const QQuaternion& quaternion);
143 #endif
144
145     void ortho(const QRect& rect);
146     void ortho(const QRectF& rect);
147     void ortho(float left, float right, float bottom, float top, float nearPlane, float farPlane);
148     void frustum(float left, float right, float bottom, float top, float nearPlane, float farPlane);
149     void perspective(float angle, float aspect, float nearPlane, float farPlane);
150 #ifndef QT_NO_VECTOR3D
151     void lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up);
152 #endif
153     void flipCoordinates();
154
155     void copyDataTo(float *values) const;
156
157     QMatrix toAffine() const;
158     QTransform toTransform() const;
159     QTransform toTransform(float distanceToPlane) const;
160
161     QPoint map(const QPoint& point) const;
162     QPointF map(const QPointF& point) const;
163 #ifndef QT_NO_VECTOR3D
164     QVector3D map(const QVector3D& point) const;
165     QVector3D mapVector(const QVector3D& vector) const;
166 #endif
167 #ifndef QT_NO_VECTOR4D
168     QVector4D map(const QVector4D& point) const;
169 #endif
170     QRect mapRect(const QRect& rect) const;
171     QRectF mapRect(const QRectF& rect) const;
172
173     template <int N, int M>
174     QGenericMatrix<N, M, float> toGenericMatrix() const;
175
176     inline float *data();
177     inline const float *data() const { return *m; }
178     inline const float *constData() const { return *m; }
179
180     void optimize();
181
182     operator QVariant() const;
183
184 #ifndef QT_NO_DEBUG_STREAM
185     friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
186 #endif
187
188 private:
189     float m[4][4];          // Column-major order to match OpenGL.
190     int flagBits;           // Flag bits from the enum below.
191
192     // When matrices are multiplied, the flag bits are or-ed together.
193     enum {
194         Identity        = 0x0000, // Identity matrix
195         Translation     = 0x0001, // Contains a translation
196         Scale           = 0x0002, // Contains a scale
197         Rotation2D      = 0x0004, // Contains a rotation about the Z axis
198         Rotation        = 0x0008, // Contains an arbitrary rotation
199         Perspective     = 0x0010, // Last row is different from (0, 0, 0, 1)
200         General         = 0x001f  // General matrix, unknown contents
201     };
202
203     // Construct without initializing identity matrix.
204     explicit QMatrix4x4(int) { }
205
206     QMatrix4x4 orthonormalInverse() const;
207
208     void projectedRotate(float angle, float x, float y, float z);
209
210     friend class QGraphicsRotation;
211 };
212
213 Q_DECLARE_TYPEINFO(QMatrix4x4, Q_MOVABLE_TYPE);
214
215 inline QMatrix4x4::QMatrix4x4
216         (float m11, float m12, float m13, float m14,
217          float m21, float m22, float m23, float m24,
218          float m31, float m32, float m33, float m34,
219          float m41, float m42, float m43, float m44)
220 {
221     m[0][0] = m11; m[0][1] = m21; m[0][2] = m31; m[0][3] = m41;
222     m[1][0] = m12; m[1][1] = m22; m[1][2] = m32; m[1][3] = m42;
223     m[2][0] = m13; m[2][1] = m23; m[2][2] = m33; m[2][3] = m43;
224     m[3][0] = m14; m[3][1] = m24; m[3][2] = m34; m[3][3] = m44;
225     flagBits = General;
226 }
227
228 template <int N, int M>
229 Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
230     (const QGenericMatrix<N, M, float>& matrix)
231 {
232     const float *values = matrix.constData();
233     for (int matrixCol = 0; matrixCol < 4; ++matrixCol) {
234         for (int matrixRow = 0; matrixRow < 4; ++matrixRow) {
235             if (matrixCol < N && matrixRow < M)
236                 m[matrixCol][matrixRow] = values[matrixCol * M + matrixRow];
237             else if (matrixCol == matrixRow)
238                 m[matrixCol][matrixRow] = 1.0f;
239             else
240                 m[matrixCol][matrixRow] = 0.0f;
241         }
242     }
243     flagBits = General;
244 }
245
246 template <int N, int M>
247 QGenericMatrix<N, M, float> QMatrix4x4::toGenericMatrix() const
248 {
249     QGenericMatrix<N, M, float> result;
250     float *values = result.data();
251     for (int matrixCol = 0; matrixCol < N; ++matrixCol) {
252         for (int matrixRow = 0; matrixRow < M; ++matrixRow) {
253             if (matrixCol < 4 && matrixRow < 4)
254                 values[matrixCol * M + matrixRow] = m[matrixCol][matrixRow];
255             else if (matrixCol == matrixRow)
256                 values[matrixCol * M + matrixRow] = 1.0f;
257             else
258                 values[matrixCol * M + matrixRow] = 0.0f;
259         }
260     }
261     return result;
262 }
263
264 inline const float& QMatrix4x4::operator()(int aRow, int aColumn) const
265 {
266     Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
267     return m[aColumn][aRow];
268 }
269
270 inline float& QMatrix4x4::operator()(int aRow, int aColumn)
271 {
272     Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
273     flagBits = General;
274     return m[aColumn][aRow];
275 }
276
277 #ifndef QT_NO_VECTOR4D
278 inline QVector4D QMatrix4x4::column(int index) const
279 {
280     Q_ASSERT(index >= 0 && index < 4);
281     return QVector4D(m[index][0], m[index][1], m[index][2], m[index][3]);
282 }
283
284 inline void QMatrix4x4::setColumn(int index, const QVector4D& value)
285 {
286     Q_ASSERT(index >= 0 && index < 4);
287     m[index][0] = value.x();
288     m[index][1] = value.y();
289     m[index][2] = value.z();
290     m[index][3] = value.w();
291     flagBits = General;
292 }
293
294 inline QVector4D QMatrix4x4::row(int index) const
295 {
296     Q_ASSERT(index >= 0 && index < 4);
297     return QVector4D(m[0][index], m[1][index], m[2][index], m[3][index]);
298 }
299
300 inline void QMatrix4x4::setRow(int index, const QVector4D& value)
301 {
302     Q_ASSERT(index >= 0 && index < 4);
303     m[0][index] = value.x();
304     m[1][index] = value.y();
305     m[2][index] = value.z();
306     m[3][index] = value.w();
307     flagBits = General;
308 }
309 #endif
310
311 Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor);
312
313 inline bool QMatrix4x4::isIdentity() const
314 {
315     if (flagBits == Identity)
316         return true;
317     if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
318         return false;
319     if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f)
320         return false;
321     if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f)
322         return false;
323     if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f)
324         return false;
325     if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f)
326         return false;
327     return (m[3][3] == 1.0f);
328 }
329
330 inline void QMatrix4x4::setToIdentity()
331 {
332     m[0][0] = 1.0f;
333     m[0][1] = 0.0f;
334     m[0][2] = 0.0f;
335     m[0][3] = 0.0f;
336     m[1][0] = 0.0f;
337     m[1][1] = 1.0f;
338     m[1][2] = 0.0f;
339     m[1][3] = 0.0f;
340     m[2][0] = 0.0f;
341     m[2][1] = 0.0f;
342     m[2][2] = 1.0f;
343     m[2][3] = 0.0f;
344     m[3][0] = 0.0f;
345     m[3][1] = 0.0f;
346     m[3][2] = 0.0f;
347     m[3][3] = 1.0f;
348     flagBits = Identity;
349 }
350
351 inline void QMatrix4x4::fill(float value)
352 {
353     m[0][0] = value;
354     m[0][1] = value;
355     m[0][2] = value;
356     m[0][3] = value;
357     m[1][0] = value;
358     m[1][1] = value;
359     m[1][2] = value;
360     m[1][3] = value;
361     m[2][0] = value;
362     m[2][1] = value;
363     m[2][2] = value;
364     m[2][3] = value;
365     m[3][0] = value;
366     m[3][1] = value;
367     m[3][2] = value;
368     m[3][3] = value;
369     flagBits = General;
370 }
371
372 inline QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
373 {
374     m[0][0] += other.m[0][0];
375     m[0][1] += other.m[0][1];
376     m[0][2] += other.m[0][2];
377     m[0][3] += other.m[0][3];
378     m[1][0] += other.m[1][0];
379     m[1][1] += other.m[1][1];
380     m[1][2] += other.m[1][2];
381     m[1][3] += other.m[1][3];
382     m[2][0] += other.m[2][0];
383     m[2][1] += other.m[2][1];
384     m[2][2] += other.m[2][2];
385     m[2][3] += other.m[2][3];
386     m[3][0] += other.m[3][0];
387     m[3][1] += other.m[3][1];
388     m[3][2] += other.m[3][2];
389     m[3][3] += other.m[3][3];
390     flagBits = General;
391     return *this;
392 }
393
394 inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
395 {
396     m[0][0] -= other.m[0][0];
397     m[0][1] -= other.m[0][1];
398     m[0][2] -= other.m[0][2];
399     m[0][3] -= other.m[0][3];
400     m[1][0] -= other.m[1][0];
401     m[1][1] -= other.m[1][1];
402     m[1][2] -= other.m[1][2];
403     m[1][3] -= other.m[1][3];
404     m[2][0] -= other.m[2][0];
405     m[2][1] -= other.m[2][1];
406     m[2][2] -= other.m[2][2];
407     m[2][3] -= other.m[2][3];
408     m[3][0] -= other.m[3][0];
409     m[3][1] -= other.m[3][1];
410     m[3][2] -= other.m[3][2];
411     m[3][3] -= other.m[3][3];
412     flagBits = General;
413     return *this;
414 }
415
416 inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& other)
417 {
418     flagBits |= other.flagBits;
419
420     if (flagBits < Rotation2D) {
421         m[3][0] += m[0][0] * other.m[3][0];
422         m[3][1] += m[1][1] * other.m[3][1];
423         m[3][2] += m[2][2] * other.m[3][2];
424
425         m[0][0] *= other.m[0][0];
426         m[1][1] *= other.m[1][1];
427         m[2][2] *= other.m[2][2];
428         return *this;
429     }
430
431     float m0, m1, m2;
432     m0 = m[0][0] * other.m[0][0]
433             + m[1][0] * other.m[0][1]
434             + m[2][0] * other.m[0][2]
435             + m[3][0] * other.m[0][3];
436     m1 = m[0][0] * other.m[1][0]
437             + m[1][0] * other.m[1][1]
438             + m[2][0] * other.m[1][2]
439             + m[3][0] * other.m[1][3];
440     m2 = m[0][0] * other.m[2][0]
441             + m[1][0] * other.m[2][1]
442             + m[2][0] * other.m[2][2]
443             + m[3][0] * other.m[2][3];
444     m[3][0] = m[0][0] * other.m[3][0]
445             + m[1][0] * other.m[3][1]
446             + m[2][0] * other.m[3][2]
447             + m[3][0] * other.m[3][3];
448     m[0][0] = m0;
449     m[1][0] = m1;
450     m[2][0] = m2;
451
452     m0 = m[0][1] * other.m[0][0]
453             + m[1][1] * other.m[0][1]
454             + m[2][1] * other.m[0][2]
455             + m[3][1] * other.m[0][3];
456     m1 = m[0][1] * other.m[1][0]
457             + m[1][1] * other.m[1][1]
458             + m[2][1] * other.m[1][2]
459             + m[3][1] * other.m[1][3];
460     m2 = m[0][1] * other.m[2][0]
461             + m[1][1] * other.m[2][1]
462             + m[2][1] * other.m[2][2]
463             + m[3][1] * other.m[2][3];
464     m[3][1] = m[0][1] * other.m[3][0]
465             + m[1][1] * other.m[3][1]
466             + m[2][1] * other.m[3][2]
467             + m[3][1] * other.m[3][3];
468     m[0][1] = m0;
469     m[1][1] = m1;
470     m[2][1] = m2;
471
472     m0 = m[0][2] * other.m[0][0]
473             + m[1][2] * other.m[0][1]
474             + m[2][2] * other.m[0][2]
475             + m[3][2] * other.m[0][3];
476     m1 = m[0][2] * other.m[1][0]
477             + m[1][2] * other.m[1][1]
478             + m[2][2] * other.m[1][2]
479             + m[3][2] * other.m[1][3];
480     m2 = m[0][2] * other.m[2][0]
481             + m[1][2] * other.m[2][1]
482             + m[2][2] * other.m[2][2]
483             + m[3][2] * other.m[2][3];
484     m[3][2] = m[0][2] * other.m[3][0]
485             + m[1][2] * other.m[3][1]
486             + m[2][2] * other.m[3][2]
487             + m[3][2] * other.m[3][3];
488     m[0][2] = m0;
489     m[1][2] = m1;
490     m[2][2] = m2;
491
492     m0 = m[0][3] * other.m[0][0]
493             + m[1][3] * other.m[0][1]
494             + m[2][3] * other.m[0][2]
495             + m[3][3] * other.m[0][3];
496     m1 = m[0][3] * other.m[1][0]
497             + m[1][3] * other.m[1][1]
498             + m[2][3] * other.m[1][2]
499             + m[3][3] * other.m[1][3];
500     m2 = m[0][3] * other.m[2][0]
501             + m[1][3] * other.m[2][1]
502             + m[2][3] * other.m[2][2]
503             + m[3][3] * other.m[2][3];
504     m[3][3] = m[0][3] * other.m[3][0]
505             + m[1][3] * other.m[3][1]
506             + m[2][3] * other.m[3][2]
507             + m[3][3] * other.m[3][3];
508     m[0][3] = m0;
509     m[1][3] = m1;
510     m[2][3] = m2;
511     return *this;
512 }
513
514 inline QMatrix4x4& QMatrix4x4::operator*=(float factor)
515 {
516     m[0][0] *= factor;
517     m[0][1] *= factor;
518     m[0][2] *= factor;
519     m[0][3] *= factor;
520     m[1][0] *= factor;
521     m[1][1] *= factor;
522     m[1][2] *= factor;
523     m[1][3] *= factor;
524     m[2][0] *= factor;
525     m[2][1] *= factor;
526     m[2][2] *= factor;
527     m[2][3] *= factor;
528     m[3][0] *= factor;
529     m[3][1] *= factor;
530     m[3][2] *= factor;
531     m[3][3] *= factor;
532     flagBits = General;
533     return *this;
534 }
535
536 inline bool QMatrix4x4::operator==(const QMatrix4x4& other) const
537 {
538     return m[0][0] == other.m[0][0] &&
539            m[0][1] == other.m[0][1] &&
540            m[0][2] == other.m[0][2] &&
541            m[0][3] == other.m[0][3] &&
542            m[1][0] == other.m[1][0] &&
543            m[1][1] == other.m[1][1] &&
544            m[1][2] == other.m[1][2] &&
545            m[1][3] == other.m[1][3] &&
546            m[2][0] == other.m[2][0] &&
547            m[2][1] == other.m[2][1] &&
548            m[2][2] == other.m[2][2] &&
549            m[2][3] == other.m[2][3] &&
550            m[3][0] == other.m[3][0] &&
551            m[3][1] == other.m[3][1] &&
552            m[3][2] == other.m[3][2] &&
553            m[3][3] == other.m[3][3];
554 }
555
556 inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
557 {
558     return m[0][0] != other.m[0][0] ||
559            m[0][1] != other.m[0][1] ||
560            m[0][2] != other.m[0][2] ||
561            m[0][3] != other.m[0][3] ||
562            m[1][0] != other.m[1][0] ||
563            m[1][1] != other.m[1][1] ||
564            m[1][2] != other.m[1][2] ||
565            m[1][3] != other.m[1][3] ||
566            m[2][0] != other.m[2][0] ||
567            m[2][1] != other.m[2][1] ||
568            m[2][2] != other.m[2][2] ||
569            m[2][3] != other.m[2][3] ||
570            m[3][0] != other.m[3][0] ||
571            m[3][1] != other.m[3][1] ||
572            m[3][2] != other.m[3][2] ||
573            m[3][3] != other.m[3][3];
574 }
575
576 inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
577 {
578     QMatrix4x4 m(1);
579     m.m[0][0] = m1.m[0][0] + m2.m[0][0];
580     m.m[0][1] = m1.m[0][1] + m2.m[0][1];
581     m.m[0][2] = m1.m[0][2] + m2.m[0][2];
582     m.m[0][3] = m1.m[0][3] + m2.m[0][3];
583     m.m[1][0] = m1.m[1][0] + m2.m[1][0];
584     m.m[1][1] = m1.m[1][1] + m2.m[1][1];
585     m.m[1][2] = m1.m[1][2] + m2.m[1][2];
586     m.m[1][3] = m1.m[1][3] + m2.m[1][3];
587     m.m[2][0] = m1.m[2][0] + m2.m[2][0];
588     m.m[2][1] = m1.m[2][1] + m2.m[2][1];
589     m.m[2][2] = m1.m[2][2] + m2.m[2][2];
590     m.m[2][3] = m1.m[2][3] + m2.m[2][3];
591     m.m[3][0] = m1.m[3][0] + m2.m[3][0];
592     m.m[3][1] = m1.m[3][1] + m2.m[3][1];
593     m.m[3][2] = m1.m[3][2] + m2.m[3][2];
594     m.m[3][3] = m1.m[3][3] + m2.m[3][3];
595     m.flagBits = QMatrix4x4::General;
596     return m;
597 }
598
599 inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
600 {
601     QMatrix4x4 m(1);
602     m.m[0][0] = m1.m[0][0] - m2.m[0][0];
603     m.m[0][1] = m1.m[0][1] - m2.m[0][1];
604     m.m[0][2] = m1.m[0][2] - m2.m[0][2];
605     m.m[0][3] = m1.m[0][3] - m2.m[0][3];
606     m.m[1][0] = m1.m[1][0] - m2.m[1][0];
607     m.m[1][1] = m1.m[1][1] - m2.m[1][1];
608     m.m[1][2] = m1.m[1][2] - m2.m[1][2];
609     m.m[1][3] = m1.m[1][3] - m2.m[1][3];
610     m.m[2][0] = m1.m[2][0] - m2.m[2][0];
611     m.m[2][1] = m1.m[2][1] - m2.m[2][1];
612     m.m[2][2] = m1.m[2][2] - m2.m[2][2];
613     m.m[2][3] = m1.m[2][3] - m2.m[2][3];
614     m.m[3][0] = m1.m[3][0] - m2.m[3][0];
615     m.m[3][1] = m1.m[3][1] - m2.m[3][1];
616     m.m[3][2] = m1.m[3][2] - m2.m[3][2];
617     m.m[3][3] = m1.m[3][3] - m2.m[3][3];
618     m.flagBits = QMatrix4x4::General;
619     return m;
620 }
621
622 inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
623 {
624     int flagBits = m1.flagBits | m2.flagBits;
625     if (flagBits < QMatrix4x4::Rotation2D) {
626         QMatrix4x4 m = m1;
627         m.m[3][0] += m.m[0][0] * m2.m[3][0];
628         m.m[3][1] += m.m[1][1] * m2.m[3][1];
629         m.m[3][2] += m.m[2][2] * m2.m[3][2];
630
631         m.m[0][0] *= m2.m[0][0];
632         m.m[1][1] *= m2.m[1][1];
633         m.m[2][2] *= m2.m[2][2];
634         m.flagBits = flagBits;
635         return m;
636     }
637
638     QMatrix4x4 m(1);
639     m.m[0][0] = m1.m[0][0] * m2.m[0][0]
640               + m1.m[1][0] * m2.m[0][1]
641               + m1.m[2][0] * m2.m[0][2]
642               + m1.m[3][0] * m2.m[0][3];
643     m.m[0][1] = m1.m[0][1] * m2.m[0][0]
644               + m1.m[1][1] * m2.m[0][1]
645               + m1.m[2][1] * m2.m[0][2]
646               + m1.m[3][1] * m2.m[0][3];
647     m.m[0][2] = m1.m[0][2] * m2.m[0][0]
648               + m1.m[1][2] * m2.m[0][1]
649               + m1.m[2][2] * m2.m[0][2]
650               + m1.m[3][2] * m2.m[0][3];
651     m.m[0][3] = m1.m[0][3] * m2.m[0][0]
652               + m1.m[1][3] * m2.m[0][1]
653               + m1.m[2][3] * m2.m[0][2]
654               + m1.m[3][3] * m2.m[0][3];
655
656     m.m[1][0] = m1.m[0][0] * m2.m[1][0]
657               + m1.m[1][0] * m2.m[1][1]
658               + m1.m[2][0] * m2.m[1][2]
659               + m1.m[3][0] * m2.m[1][3];
660     m.m[1][1] = m1.m[0][1] * m2.m[1][0]
661               + m1.m[1][1] * m2.m[1][1]
662               + m1.m[2][1] * m2.m[1][2]
663               + m1.m[3][1] * m2.m[1][3];
664     m.m[1][2] = m1.m[0][2] * m2.m[1][0]
665               + m1.m[1][2] * m2.m[1][1]
666               + m1.m[2][2] * m2.m[1][2]
667               + m1.m[3][2] * m2.m[1][3];
668     m.m[1][3] = m1.m[0][3] * m2.m[1][0]
669               + m1.m[1][3] * m2.m[1][1]
670               + m1.m[2][3] * m2.m[1][2]
671               + m1.m[3][3] * m2.m[1][3];
672
673     m.m[2][0] = m1.m[0][0] * m2.m[2][0]
674               + m1.m[1][0] * m2.m[2][1]
675               + m1.m[2][0] * m2.m[2][2]
676               + m1.m[3][0] * m2.m[2][3];
677     m.m[2][1] = m1.m[0][1] * m2.m[2][0]
678               + m1.m[1][1] * m2.m[2][1]
679               + m1.m[2][1] * m2.m[2][2]
680               + m1.m[3][1] * m2.m[2][3];
681     m.m[2][2] = m1.m[0][2] * m2.m[2][0]
682               + m1.m[1][2] * m2.m[2][1]
683               + m1.m[2][2] * m2.m[2][2]
684               + m1.m[3][2] * m2.m[2][3];
685     m.m[2][3] = m1.m[0][3] * m2.m[2][0]
686               + m1.m[1][3] * m2.m[2][1]
687               + m1.m[2][3] * m2.m[2][2]
688               + m1.m[3][3] * m2.m[2][3];
689
690     m.m[3][0] = m1.m[0][0] * m2.m[3][0]
691               + m1.m[1][0] * m2.m[3][1]
692               + m1.m[2][0] * m2.m[3][2]
693               + m1.m[3][0] * m2.m[3][3];
694     m.m[3][1] = m1.m[0][1] * m2.m[3][0]
695               + m1.m[1][1] * m2.m[3][1]
696               + m1.m[2][1] * m2.m[3][2]
697               + m1.m[3][1] * m2.m[3][3];
698     m.m[3][2] = m1.m[0][2] * m2.m[3][0]
699               + m1.m[1][2] * m2.m[3][1]
700               + m1.m[2][2] * m2.m[3][2]
701               + m1.m[3][2] * m2.m[3][3];
702     m.m[3][3] = m1.m[0][3] * m2.m[3][0]
703               + m1.m[1][3] * m2.m[3][1]
704               + m1.m[2][3] * m2.m[3][2]
705               + m1.m[3][3] * m2.m[3][3];
706     m.flagBits = flagBits;
707     return m;
708 }
709
710 #ifndef QT_NO_VECTOR3D
711
712 inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
713 {
714     float x, y, z, w;
715     x = vector.x() * matrix.m[0][0] +
716         vector.y() * matrix.m[0][1] +
717         vector.z() * matrix.m[0][2] +
718         matrix.m[0][3];
719     y = vector.x() * matrix.m[1][0] +
720         vector.y() * matrix.m[1][1] +
721         vector.z() * matrix.m[1][2] +
722         matrix.m[1][3];
723     z = vector.x() * matrix.m[2][0] +
724         vector.y() * matrix.m[2][1] +
725         vector.z() * matrix.m[2][2] +
726         matrix.m[2][3];
727     w = vector.x() * matrix.m[3][0] +
728         vector.y() * matrix.m[3][1] +
729         vector.z() * matrix.m[3][2] +
730         matrix.m[3][3];
731     if (w == 1.0f)
732         return QVector3D(x, y, z);
733     else
734         return QVector3D(x / w, y / w, z / w);
735 }
736
737 inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
738 {
739     float x, y, z, w;
740     if (matrix.flagBits == QMatrix4x4::Identity) {
741         return vector;
742     } else if (matrix.flagBits < QMatrix4x4::Rotation2D) {
743         // Translation | Scale
744         return QVector3D(vector.x() * matrix.m[0][0] + matrix.m[3][0],
745                          vector.y() * matrix.m[1][1] + matrix.m[3][1],
746                          vector.z() * matrix.m[2][2] + matrix.m[3][2]);
747     } else if (matrix.flagBits < QMatrix4x4::Rotation) {
748         // Translation | Scale | Rotation2D
749         return QVector3D(vector.x() * matrix.m[0][0] + vector.y() * matrix.m[1][0] + matrix.m[3][0],
750                          vector.x() * matrix.m[0][1] + vector.y() * matrix.m[1][1] + matrix.m[3][1],
751                          vector.z() * matrix.m[2][2] + matrix.m[3][2]);
752     } else {
753         x = vector.x() * matrix.m[0][0] +
754             vector.y() * matrix.m[1][0] +
755             vector.z() * matrix.m[2][0] +
756             matrix.m[3][0];
757         y = vector.x() * matrix.m[0][1] +
758             vector.y() * matrix.m[1][1] +
759             vector.z() * matrix.m[2][1] +
760             matrix.m[3][1];
761         z = vector.x() * matrix.m[0][2] +
762             vector.y() * matrix.m[1][2] +
763             vector.z() * matrix.m[2][2] +
764             matrix.m[3][2];
765         w = vector.x() * matrix.m[0][3] +
766             vector.y() * matrix.m[1][3] +
767             vector.z() * matrix.m[2][3] +
768             matrix.m[3][3];
769         if (w == 1.0f)
770             return QVector3D(x, y, z);
771         else
772             return QVector3D(x / w, y / w, z / w);
773     }
774 }
775
776 #endif
777
778 #ifndef QT_NO_VECTOR4D
779
780 inline QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
781 {
782     float x, y, z, w;
783     x = vector.x() * matrix.m[0][0] +
784         vector.y() * matrix.m[0][1] +
785         vector.z() * matrix.m[0][2] +
786         vector.w() * matrix.m[0][3];
787     y = vector.x() * matrix.m[1][0] +
788         vector.y() * matrix.m[1][1] +
789         vector.z() * matrix.m[1][2] +
790         vector.w() * matrix.m[1][3];
791     z = vector.x() * matrix.m[2][0] +
792         vector.y() * matrix.m[2][1] +
793         vector.z() * matrix.m[2][2] +
794         vector.w() * matrix.m[2][3];
795     w = vector.x() * matrix.m[3][0] +
796         vector.y() * matrix.m[3][1] +
797         vector.z() * matrix.m[3][2] +
798         vector.w() * matrix.m[3][3];
799     return QVector4D(x, y, z, w);
800 }
801
802 inline QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
803 {
804     float x, y, z, w;
805     x = vector.x() * matrix.m[0][0] +
806         vector.y() * matrix.m[1][0] +
807         vector.z() * matrix.m[2][0] +
808         vector.w() * matrix.m[3][0];
809     y = vector.x() * matrix.m[0][1] +
810         vector.y() * matrix.m[1][1] +
811         vector.z() * matrix.m[2][1] +
812         vector.w() * matrix.m[3][1];
813     z = vector.x() * matrix.m[0][2] +
814         vector.y() * matrix.m[1][2] +
815         vector.z() * matrix.m[2][2] +
816         vector.w() * matrix.m[3][2];
817     w = vector.x() * matrix.m[0][3] +
818         vector.y() * matrix.m[1][3] +
819         vector.z() * matrix.m[2][3] +
820         vector.w() * matrix.m[3][3];
821     return QVector4D(x, y, z, w);
822 }
823
824 #endif
825
826 inline QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
827 {
828     float xin, yin;
829     float x, y, w;
830     xin = point.x();
831     yin = point.y();
832     x = xin * matrix.m[0][0] +
833         yin * matrix.m[0][1] +
834         matrix.m[0][3];
835     y = xin * matrix.m[1][0] +
836         yin * matrix.m[1][1] +
837         matrix.m[1][3];
838     w = xin * matrix.m[3][0] +
839         yin * matrix.m[3][1] +
840         matrix.m[3][3];
841     if (w == 1.0f)
842         return QPoint(qRound(x), qRound(y));
843     else
844         return QPoint(qRound(x / w), qRound(y / w));
845 }
846
847 inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
848 {
849     float xin, yin;
850     float x, y, w;
851     xin = point.x();
852     yin = point.y();
853     x = xin * matrix.m[0][0] +
854         yin * matrix.m[0][1] +
855         matrix.m[0][3];
856     y = xin * matrix.m[1][0] +
857         yin * matrix.m[1][1] +
858         matrix.m[1][3];
859     w = xin * matrix.m[3][0] +
860         yin * matrix.m[3][1] +
861         matrix.m[3][3];
862     if (w == 1.0f) {
863         return QPointF(float(x), float(y));
864     } else {
865         return QPointF(float(x / w), float(y / w));
866     }
867 }
868
869 inline QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
870 {
871     float xin, yin;
872     float x, y, w;
873     xin = point.x();
874     yin = point.y();
875     if (matrix.flagBits == QMatrix4x4::Identity) {
876         return point;
877     } else if (matrix.flagBits < QMatrix4x4::Rotation2D) {
878         // Translation | Scale
879         return QPoint(qRound(xin * matrix.m[0][0] + matrix.m[3][0]),
880                       qRound(yin * matrix.m[1][1] + matrix.m[3][1]));
881     } else if (matrix.flagBits < QMatrix4x4::Perspective) {
882         return QPoint(qRound(xin * matrix.m[0][0] + yin * matrix.m[1][0] + matrix.m[3][0]),
883                       qRound(xin * matrix.m[0][1] + yin * matrix.m[1][1] + matrix.m[3][1]));
884     } else {
885         x = xin * matrix.m[0][0] +
886             yin * matrix.m[1][0] +
887             matrix.m[3][0];
888         y = xin * matrix.m[0][1] +
889             yin * matrix.m[1][1] +
890             matrix.m[3][1];
891         w = xin * matrix.m[0][3] +
892             yin * matrix.m[1][3] +
893             matrix.m[3][3];
894         if (w == 1.0f)
895             return QPoint(qRound(x), qRound(y));
896         else
897             return QPoint(qRound(x / w), qRound(y / w));
898     }
899 }
900
901 inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
902 {
903     float xin, yin;
904     float x, y, w;
905     xin = point.x();
906     yin = point.y();
907     if (matrix.flagBits == QMatrix4x4::Identity) {
908         return point;
909     } else if (matrix.flagBits < QMatrix4x4::Rotation2D) {
910         // Translation | Scale
911         return QPointF(xin * matrix.m[0][0] + matrix.m[3][0],
912                        yin * matrix.m[1][1] + matrix.m[3][1]);
913     } else if (matrix.flagBits < QMatrix4x4::Perspective) {
914         return QPointF(xin * matrix.m[0][0] + yin * matrix.m[1][0] + matrix.m[3][0],
915                        xin * matrix.m[0][1] + yin * matrix.m[1][1] + matrix.m[3][1]);
916     } else {
917         x = xin * matrix.m[0][0] +
918             yin * matrix.m[1][0] +
919             matrix.m[3][0];
920         y = xin * matrix.m[0][1] +
921             yin * matrix.m[1][1] +
922             matrix.m[3][1];
923         w = xin * matrix.m[0][3] +
924             yin * matrix.m[1][3] +
925             matrix.m[3][3];
926         if (w == 1.0f) {
927             return QPointF(float(x), float(y));
928         } else {
929             return QPointF(float(x / w), float(y / w));
930         }
931     }
932 }
933
934 inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
935 {
936     QMatrix4x4 m(1);
937     m.m[0][0] = -matrix.m[0][0];
938     m.m[0][1] = -matrix.m[0][1];
939     m.m[0][2] = -matrix.m[0][2];
940     m.m[0][3] = -matrix.m[0][3];
941     m.m[1][0] = -matrix.m[1][0];
942     m.m[1][1] = -matrix.m[1][1];
943     m.m[1][2] = -matrix.m[1][2];
944     m.m[1][3] = -matrix.m[1][3];
945     m.m[2][0] = -matrix.m[2][0];
946     m.m[2][1] = -matrix.m[2][1];
947     m.m[2][2] = -matrix.m[2][2];
948     m.m[2][3] = -matrix.m[2][3];
949     m.m[3][0] = -matrix.m[3][0];
950     m.m[3][1] = -matrix.m[3][1];
951     m.m[3][2] = -matrix.m[3][2];
952     m.m[3][3] = -matrix.m[3][3];
953     m.flagBits = QMatrix4x4::General;
954     return m;
955 }
956
957 inline QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix)
958 {
959     QMatrix4x4 m(1);
960     m.m[0][0] = matrix.m[0][0] * factor;
961     m.m[0][1] = matrix.m[0][1] * factor;
962     m.m[0][2] = matrix.m[0][2] * factor;
963     m.m[0][3] = matrix.m[0][3] * factor;
964     m.m[1][0] = matrix.m[1][0] * factor;
965     m.m[1][1] = matrix.m[1][1] * factor;
966     m.m[1][2] = matrix.m[1][2] * factor;
967     m.m[1][3] = matrix.m[1][3] * factor;
968     m.m[2][0] = matrix.m[2][0] * factor;
969     m.m[2][1] = matrix.m[2][1] * factor;
970     m.m[2][2] = matrix.m[2][2] * factor;
971     m.m[2][3] = matrix.m[2][3] * factor;
972     m.m[3][0] = matrix.m[3][0] * factor;
973     m.m[3][1] = matrix.m[3][1] * factor;
974     m.m[3][2] = matrix.m[3][2] * factor;
975     m.m[3][3] = matrix.m[3][3] * factor;
976     m.flagBits = QMatrix4x4::General;
977     return m;
978 }
979
980 inline QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor)
981 {
982     QMatrix4x4 m(1);
983     m.m[0][0] = matrix.m[0][0] * factor;
984     m.m[0][1] = matrix.m[0][1] * factor;
985     m.m[0][2] = matrix.m[0][2] * factor;
986     m.m[0][3] = matrix.m[0][3] * factor;
987     m.m[1][0] = matrix.m[1][0] * factor;
988     m.m[1][1] = matrix.m[1][1] * factor;
989     m.m[1][2] = matrix.m[1][2] * factor;
990     m.m[1][3] = matrix.m[1][3] * factor;
991     m.m[2][0] = matrix.m[2][0] * factor;
992     m.m[2][1] = matrix.m[2][1] * factor;
993     m.m[2][2] = matrix.m[2][2] * factor;
994     m.m[2][3] = matrix.m[2][3] * factor;
995     m.m[3][0] = matrix.m[3][0] * factor;
996     m.m[3][1] = matrix.m[3][1] * factor;
997     m.m[3][2] = matrix.m[3][2] * factor;
998     m.m[3][3] = matrix.m[3][3] * factor;
999     m.flagBits = QMatrix4x4::General;
1000     return m;
1001 }
1002
1003 inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
1004 {
1005     return qFuzzyCompare(m1.m[0][0], m2.m[0][0]) &&
1006            qFuzzyCompare(m1.m[0][1], m2.m[0][1]) &&
1007            qFuzzyCompare(m1.m[0][2], m2.m[0][2]) &&
1008            qFuzzyCompare(m1.m[0][3], m2.m[0][3]) &&
1009            qFuzzyCompare(m1.m[1][0], m2.m[1][0]) &&
1010            qFuzzyCompare(m1.m[1][1], m2.m[1][1]) &&
1011            qFuzzyCompare(m1.m[1][2], m2.m[1][2]) &&
1012            qFuzzyCompare(m1.m[1][3], m2.m[1][3]) &&
1013            qFuzzyCompare(m1.m[2][0], m2.m[2][0]) &&
1014            qFuzzyCompare(m1.m[2][1], m2.m[2][1]) &&
1015            qFuzzyCompare(m1.m[2][2], m2.m[2][2]) &&
1016            qFuzzyCompare(m1.m[2][3], m2.m[2][3]) &&
1017            qFuzzyCompare(m1.m[3][0], m2.m[3][0]) &&
1018            qFuzzyCompare(m1.m[3][1], m2.m[3][1]) &&
1019            qFuzzyCompare(m1.m[3][2], m2.m[3][2]) &&
1020            qFuzzyCompare(m1.m[3][3], m2.m[3][3]);
1021 }
1022
1023 inline QPoint QMatrix4x4::map(const QPoint& point) const
1024 {
1025     return *this * point;
1026 }
1027
1028 inline QPointF QMatrix4x4::map(const QPointF& point) const
1029 {
1030     return *this * point;
1031 }
1032
1033 #ifndef QT_NO_VECTOR3D
1034
1035 inline QVector3D QMatrix4x4::map(const QVector3D& point) const
1036 {
1037     return *this * point;
1038 }
1039
1040 inline QVector3D QMatrix4x4::mapVector(const QVector3D& vector) const
1041 {
1042     if (flagBits < Scale) {
1043         // Translation
1044         return vector;
1045     } else if (flagBits < Rotation2D) {
1046         // Translation | Scale
1047         return QVector3D(vector.x() * m[0][0],
1048                          vector.y() * m[1][1],
1049                          vector.z() * m[2][2]);
1050     } else {
1051         return QVector3D(vector.x() * m[0][0] +
1052                          vector.y() * m[1][0] +
1053                          vector.z() * m[2][0],
1054                          vector.x() * m[0][1] +
1055                          vector.y() * m[1][1] +
1056                          vector.z() * m[2][1],
1057                          vector.x() * m[0][2] +
1058                          vector.y() * m[1][2] +
1059                          vector.z() * m[2][2]);
1060     }
1061 }
1062
1063 #endif
1064
1065 #ifndef QT_NO_VECTOR4D
1066
1067 inline QVector4D QMatrix4x4::map(const QVector4D& point) const
1068 {
1069     return *this * point;
1070 }
1071
1072 #endif
1073
1074 inline float *QMatrix4x4::data()
1075 {
1076     // We have to assume that the caller will modify the matrix elements,
1077     // so we flip it over to "General" mode.
1078     flagBits = General;
1079     return *m;
1080 }
1081
1082 #ifndef QT_NO_DEBUG_STREAM
1083 Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
1084 #endif
1085
1086 #ifndef QT_NO_DATASTREAM
1087 Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &);
1088 Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &);
1089 #endif
1090
1091 #if QT_DEPRECATED_SINCE(5, 0)
1092 template <int N, int M>
1093 QT_DEPRECATED QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, float>& matrix)
1094 {
1095     return QMatrix4x4(matrix.constData(), N, M);
1096 }
1097
1098 template <int N, int M>
1099 QT_DEPRECATED QGenericMatrix<N, M, float> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
1100 {
1101     QGenericMatrix<N, M, float> result;
1102     const float *m = matrix.constData();
1103     float *values = result.data();
1104     for (int col = 0; col < N; ++col) {
1105         for (int row = 0; row < M; ++row) {
1106             if (col < 4 && row < 4)
1107                 values[col * M + row] = m[col * 4 + row];
1108             else if (col == row)
1109                 values[col * M + row] = 1.0f;
1110             else
1111                 values[col * M + row] = 0.0f;
1112         }
1113     }
1114     return result;
1115 }
1116 #endif
1117
1118 #endif
1119
1120 QT_END_NAMESPACE
1121
1122 QT_END_HEADER
1123
1124 #endif