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