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