1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtGui module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
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>
56 #ifndef QT_NO_MATRIX4X4
62 class Q_GUI_EXPORT QMatrix4x4
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);
72 template <int N, int M>
73 explicit QMatrix4x4(const QGenericMatrix<N, M, float>& matrix);
75 QMatrix4x4(const float *values, int cols, int rows);
76 QMatrix4x4(const QTransform& transform);
77 QMatrix4x4(const QMatrix& matrix);
79 inline const float& operator()(int row, int column) const;
80 inline float& operator()(int row, int column);
82 #ifndef QT_NO_VECTOR4D
83 inline QVector4D column(int index) const;
84 inline void setColumn(int index, const QVector4D& value);
86 inline QVector4D row(int index) const;
87 inline void setRow(int index, const QVector4D& value);
90 inline bool isIdentity() const;
91 inline void setToIdentity();
93 inline void fill(float value);
95 double determinant() const;
96 QMatrix4x4 inverted(bool *invertible = 0) const;
97 QMatrix4x4 transposed() const;
98 QMatrix3x3 normalMatrix() const;
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;
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);
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);
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);
128 friend inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2);
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);
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);
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);
153 void flipCoordinates();
155 void copyDataTo(float *values) const;
157 QMatrix toAffine() const;
158 QTransform toTransform() const;
159 QTransform toTransform(float distanceToPlane) const;
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;
167 #ifndef QT_NO_VECTOR4D
168 QVector4D map(const QVector4D& point) const;
170 QRect mapRect(const QRect& rect) const;
171 QRectF mapRect(const QRectF& rect) const;
173 template <int N, int M>
174 QGenericMatrix<N, M, float> toGenericMatrix() const;
176 inline float *data();
177 inline const float *data() const { return *m; }
178 inline const float *constData() const { return *m; }
182 operator QVariant() const;
184 #ifndef QT_NO_DEBUG_STREAM
185 friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
189 float m[4][4]; // Column-major order to match OpenGL.
190 int flagBits; // Flag bits from the enum below.
192 // When matrices are multiplied, the flag bits are or-ed together.
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
203 // Construct without initializing identity matrix.
204 explicit QMatrix4x4(int) { }
206 QMatrix4x4 orthonormalInverse() const;
208 void projectedRotate(float angle, float x, float y, float z);
210 friend class QGraphicsRotation;
213 Q_DECLARE_TYPEINFO(QMatrix4x4, Q_MOVABLE_TYPE);
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)
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;
228 template <int N, int M>
229 Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
230 (const QGenericMatrix<N, M, float>& matrix)
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;
240 m[matrixCol][matrixRow] = 0.0f;
246 template <int N, int M>
247 QGenericMatrix<N, M, float> QMatrix4x4::toGenericMatrix() const
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;
258 values[matrixCol * M + matrixRow] = 0.0f;
264 inline const float& QMatrix4x4::operator()(int aRow, int aColumn) const
266 Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
267 return m[aColumn][aRow];
270 inline float& QMatrix4x4::operator()(int aRow, int aColumn)
272 Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
274 return m[aColumn][aRow];
277 #ifndef QT_NO_VECTOR4D
278 inline QVector4D QMatrix4x4::column(int index) const
280 Q_ASSERT(index >= 0 && index < 4);
281 return QVector4D(m[index][0], m[index][1], m[index][2], m[index][3]);
284 inline void QMatrix4x4::setColumn(int index, const QVector4D& value)
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();
294 inline QVector4D QMatrix4x4::row(int index) const
296 Q_ASSERT(index >= 0 && index < 4);
297 return QVector4D(m[0][index], m[1][index], m[2][index], m[3][index]);
300 inline void QMatrix4x4::setRow(int index, const QVector4D& value)
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();
311 Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor);
313 inline bool QMatrix4x4::isIdentity() const
315 if (flagBits == Identity)
317 if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
319 if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f)
321 if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f)
323 if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f)
325 if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f)
327 return (m[3][3] == 1.0f);
330 inline void QMatrix4x4::setToIdentity()
351 inline void QMatrix4x4::fill(float value)
372 inline QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
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];
394 inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
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];
416 inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& other)
418 flagBits |= other.flagBits;
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];
425 m[0][0] *= other.m[0][0];
426 m[1][1] *= other.m[1][1];
427 m[2][2] *= other.m[2][2];
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];
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];
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];
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];
514 inline QMatrix4x4& QMatrix4x4::operator*=(float factor)
536 inline bool QMatrix4x4::operator==(const QMatrix4x4& other) const
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];
556 inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
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];
576 inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
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;
599 inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
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;
622 inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
624 int flagBits = m1.flagBits | m2.flagBits;
625 if (flagBits < QMatrix4x4::Rotation2D) {
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];
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;
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];
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];
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];
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;
710 #ifndef QT_NO_VECTOR3D
712 inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
715 x = vector.x() * matrix.m[0][0] +
716 vector.y() * matrix.m[0][1] +
717 vector.z() * matrix.m[0][2] +
719 y = vector.x() * matrix.m[1][0] +
720 vector.y() * matrix.m[1][1] +
721 vector.z() * matrix.m[1][2] +
723 z = vector.x() * matrix.m[2][0] +
724 vector.y() * matrix.m[2][1] +
725 vector.z() * matrix.m[2][2] +
727 w = vector.x() * matrix.m[3][0] +
728 vector.y() * matrix.m[3][1] +
729 vector.z() * matrix.m[3][2] +
732 return QVector3D(x, y, z);
734 return QVector3D(x / w, y / w, z / w);
737 inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
740 if (matrix.flagBits == QMatrix4x4::Identity) {
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]);
753 x = vector.x() * matrix.m[0][0] +
754 vector.y() * matrix.m[1][0] +
755 vector.z() * matrix.m[2][0] +
757 y = vector.x() * matrix.m[0][1] +
758 vector.y() * matrix.m[1][1] +
759 vector.z() * matrix.m[2][1] +
761 z = vector.x() * matrix.m[0][2] +
762 vector.y() * matrix.m[1][2] +
763 vector.z() * matrix.m[2][2] +
765 w = vector.x() * matrix.m[0][3] +
766 vector.y() * matrix.m[1][3] +
767 vector.z() * matrix.m[2][3] +
770 return QVector3D(x, y, z);
772 return QVector3D(x / w, y / w, z / w);
778 #ifndef QT_NO_VECTOR4D
780 inline QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
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);
802 inline QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
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);
826 inline QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
832 x = xin * matrix.m[0][0] +
833 yin * matrix.m[0][1] +
835 y = xin * matrix.m[1][0] +
836 yin * matrix.m[1][1] +
838 w = xin * matrix.m[3][0] +
839 yin * matrix.m[3][1] +
842 return QPoint(qRound(x), qRound(y));
844 return QPoint(qRound(x / w), qRound(y / w));
847 inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
853 x = xin * matrix.m[0][0] +
854 yin * matrix.m[0][1] +
856 y = xin * matrix.m[1][0] +
857 yin * matrix.m[1][1] +
859 w = xin * matrix.m[3][0] +
860 yin * matrix.m[3][1] +
863 return QPointF(float(x), float(y));
865 return QPointF(float(x / w), float(y / w));
869 inline QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
875 if (matrix.flagBits == QMatrix4x4::Identity) {
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]));
885 x = xin * matrix.m[0][0] +
886 yin * matrix.m[1][0] +
888 y = xin * matrix.m[0][1] +
889 yin * matrix.m[1][1] +
891 w = xin * matrix.m[0][3] +
892 yin * matrix.m[1][3] +
895 return QPoint(qRound(x), qRound(y));
897 return QPoint(qRound(x / w), qRound(y / w));
901 inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
907 if (matrix.flagBits == QMatrix4x4::Identity) {
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]);
917 x = xin * matrix.m[0][0] +
918 yin * matrix.m[1][0] +
920 y = xin * matrix.m[0][1] +
921 yin * matrix.m[1][1] +
923 w = xin * matrix.m[0][3] +
924 yin * matrix.m[1][3] +
927 return QPointF(float(x), float(y));
929 return QPointF(float(x / w), float(y / w));
934 inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
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;
957 inline QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix)
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;
980 inline QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor)
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;
1003 inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
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]);
1023 inline QPoint QMatrix4x4::map(const QPoint& point) const
1025 return *this * point;
1028 inline QPointF QMatrix4x4::map(const QPointF& point) const
1030 return *this * point;
1033 #ifndef QT_NO_VECTOR3D
1035 inline QVector3D QMatrix4x4::map(const QVector3D& point) const
1037 return *this * point;
1040 inline QVector3D QMatrix4x4::mapVector(const QVector3D& vector) const
1042 if (flagBits < Scale) {
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]);
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]);
1065 #ifndef QT_NO_VECTOR4D
1067 inline QVector4D QMatrix4x4::map(const QVector4D& point) const
1069 return *this * point;
1074 inline float *QMatrix4x4::data()
1076 // We have to assume that the caller will modify the matrix elements,
1077 // so we flip it over to "General" mode.
1082 #ifndef QT_NO_DEBUG_STREAM
1083 Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
1086 #ifndef QT_NO_DATASTREAM
1087 Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &);
1088 Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &);
1091 #if QT_DEPRECATED_SINCE(5, 0)
1092 template <int N, int M>
1093 QT_DEPRECATED QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, float>& matrix)
1095 return QMatrix4x4(matrix.constData(), N, M);
1098 template <int N, int M>
1099 QT_DEPRECATED QGenericMatrix<N, M, float> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
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;
1111 values[col * M + row] = 0.0f;