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