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