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 void toGenericMatrix_impl(float *dst, int n, int m) const;
189
190 friend class ::tst_QMatrixNxN; // for access to flagBits
191};
192
193Q_DECLARE_OPERATORS_FOR_FLAGS(QMatrix4x4::Flags)
194
195QT_WARNING_PUSH
196QT_WARNING_DISABLE_FLOAT_COMPARE
197
198Q_DECLARE_TYPEINFO(QMatrix4x4, Q_PRIMITIVE_TYPE);
199
200inline QMatrix4x4::QMatrix4x4
201 (float m11, float m12, float m13, float m14,
202 float m21, float m22, float m23, float m24,
203 float m31, float m32, float m33, float m34,
204 float m41, float m42, float m43, float m44)
205{
206 m[0][0] = m11; m[0][1] = m21; m[0][2] = m31; m[0][3] = m41;
207 m[1][0] = m12; m[1][1] = m22; m[1][2] = m32; m[1][3] = m42;
208 m[2][0] = m13; m[2][1] = m23; m[2][2] = m33; m[2][3] = m43;
209 m[3][0] = m14; m[3][1] = m24; m[3][2] = m34; m[3][3] = m44;
210 flagBits = General;
211}
212
213template <int N, int M>
214Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
215 (const QGenericMatrix<N, M, float>& matrix)
216{
217 const float *values = matrix.constData();
218 for (int matrixCol = 0; matrixCol < 4; ++matrixCol) {
219 for (int matrixRow = 0; matrixRow < 4; ++matrixRow) {
220 if (matrixCol < N && matrixRow < M)
221 m[matrixCol][matrixRow] = values[matrixCol * M + matrixRow];
222 else if (matrixCol == matrixRow)
223 m[matrixCol][matrixRow] = 1.0f;
224 else
225 m[matrixCol][matrixRow] = 0.0f;
226 }
227 }
228 flagBits = General;
229}
230
231template <int N, int M>
232QGenericMatrix<N, M, float> QMatrix4x4::toGenericMatrix() const
233{
234 Q_DECL_UNINITIALIZED
235 QGenericMatrix<N, M, float> result(Qt::Uninitialized);
236 toGenericMatrix_impl(result.data(), N, M);
237 return result;
238}
239
240inline const float& QMatrix4x4::operator()(int aRow, int aColumn) const
241{
242 Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
243 return m[aColumn][aRow];
244}
245
246inline float& QMatrix4x4::operator()(int aRow, int aColumn)
247{
248 Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
249 flagBits = General;
250 return m[aColumn][aRow];
251}
252
253#ifndef QT_NO_VECTOR4D
254inline QVector4D QMatrix4x4::column(int index) const
255{
256 Q_ASSERT(index >= 0 && index < 4);
257 return QVector4D(m[index][0], m[index][1], m[index][2], m[index][3]);
258}
259
260inline void QMatrix4x4::setColumn(int index, const QVector4D& value)
261{
262 Q_ASSERT(index >= 0 && index < 4);
263 m[index][0] = value.x();
264 m[index][1] = value.y();
265 m[index][2] = value.z();
266 m[index][3] = value.w();
267 flagBits = General;
268}
269
270inline QVector4D QMatrix4x4::row(int index) const
271{
272 Q_ASSERT(index >= 0 && index < 4);
273 return QVector4D(m[0][index], m[1][index], m[2][index], m[3][index]);
274}
275
276inline void QMatrix4x4::setRow(int index, const QVector4D& value)
277{
278 Q_ASSERT(index >= 0 && index < 4);
279 m[0][index] = value.x();
280 m[1][index] = value.y();
281 m[2][index] = value.z();
282 m[3][index] = value.w();
283 flagBits = General;
284}
285#endif
286
287Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor);
288
289inline bool QMatrix4x4::isAffine() const
290{
291 return m[0][3] == 0.0f && m[1][3] == 0.0f && m[2][3] == 0.0f && m[3][3] == 1.0f;
292}
293
294inline bool QMatrix4x4::isIdentity() const
295{
296 if (flagBits == Identity)
297 return true;
298 if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
299 return false;
300 if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f)
301 return false;
302 if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f)
303 return false;
304 if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f)
305 return false;
306 if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f)
307 return false;
308 return (m[3][3] == 1.0f);
309}
310
311inline void QMatrix4x4::setToIdentity()
312{
313 m[0][0] = 1.0f;
314 m[0][1] = 0.0f;
315 m[0][2] = 0.0f;
316 m[0][3] = 0.0f;
317 m[1][0] = 0.0f;
318 m[1][1] = 1.0f;
319 m[1][2] = 0.0f;
320 m[1][3] = 0.0f;
321 m[2][0] = 0.0f;
322 m[2][1] = 0.0f;
323 m[2][2] = 1.0f;
324 m[2][3] = 0.0f;
325 m[3][0] = 0.0f;
326 m[3][1] = 0.0f;
327 m[3][2] = 0.0f;
328 m[3][3] = 1.0f;
329 flagBits = Identity;
330}
331
332inline void QMatrix4x4::fill(float value)
333{
334 m[0][0] = value;
335 m[0][1] = value;
336 m[0][2] = value;
337 m[0][3] = value;
338 m[1][0] = value;
339 m[1][1] = value;
340 m[1][2] = value;
341 m[1][3] = value;
342 m[2][0] = value;
343 m[2][1] = value;
344 m[2][2] = value;
345 m[2][3] = value;
346 m[3][0] = value;
347 m[3][1] = value;
348 m[3][2] = value;
349 m[3][3] = value;
350 flagBits = General;
351}
352
353inline QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
354{
355 m[0][0] += other.m[0][0];
356 m[0][1] += other.m[0][1];
357 m[0][2] += other.m[0][2];
358 m[0][3] += other.m[0][3];
359 m[1][0] += other.m[1][0];
360 m[1][1] += other.m[1][1];
361 m[1][2] += other.m[1][2];
362 m[1][3] += other.m[1][3];
363 m[2][0] += other.m[2][0];
364 m[2][1] += other.m[2][1];
365 m[2][2] += other.m[2][2];
366 m[2][3] += other.m[2][3];
367 m[3][0] += other.m[3][0];
368 m[3][1] += other.m[3][1];
369 m[3][2] += other.m[3][2];
370 m[3][3] += other.m[3][3];
371 flagBits = General;
372 return *this;
373}
374
375inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
376{
377 m[0][0] -= other.m[0][0];
378 m[0][1] -= other.m[0][1];
379 m[0][2] -= other.m[0][2];
380 m[0][3] -= other.m[0][3];
381 m[1][0] -= other.m[1][0];
382 m[1][1] -= other.m[1][1];
383 m[1][2] -= other.m[1][2];
384 m[1][3] -= other.m[1][3];
385 m[2][0] -= other.m[2][0];
386 m[2][1] -= other.m[2][1];
387 m[2][2] -= other.m[2][2];
388 m[2][3] -= other.m[2][3];
389 m[3][0] -= other.m[3][0];
390 m[3][1] -= other.m[3][1];
391 m[3][2] -= other.m[3][2];
392 m[3][3] -= other.m[3][3];
393 flagBits = General;
394 return *this;
395}
396
397inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& o)
398{
399 const QMatrix4x4 other = o; // prevent aliasing when &o == this ### Qt 6: take o by value
400 flagBits |= other.flagBits;
401
402 if (flagBits.toInt() < Rotation2D) {
403 m[3][0] += m[0][0] * other.m[3][0];
404 m[3][1] += m[1][1] * other.m[3][1];
405 m[3][2] += m[2][2] * other.m[3][2];
406
407 m[0][0] *= other.m[0][0];
408 m[1][1] *= other.m[1][1];
409 m[2][2] *= other.m[2][2];
410 return *this;
411 }
412
413 float m0, m1, m2;
414 m0 = m[0][0] * other.m[0][0]
415 + m[1][0] * other.m[0][1]
416 + m[2][0] * other.m[0][2]
417 + m[3][0] * other.m[0][3];
418 m1 = m[0][0] * other.m[1][0]
419 + m[1][0] * other.m[1][1]
420 + m[2][0] * other.m[1][2]
421 + m[3][0] * other.m[1][3];
422 m2 = m[0][0] * other.m[2][0]
423 + m[1][0] * other.m[2][1]
424 + m[2][0] * other.m[2][2]
425 + m[3][0] * other.m[2][3];
426 m[3][0] = m[0][0] * other.m[3][0]
427 + m[1][0] * other.m[3][1]
428 + m[2][0] * other.m[3][2]
429 + m[3][0] * other.m[3][3];
430 m[0][0] = m0;
431 m[1][0] = m1;
432 m[2][0] = m2;
433
434 m0 = m[0][1] * other.m[0][0]
435 + m[1][1] * other.m[0][1]
436 + m[2][1] * other.m[0][2]
437 + m[3][1] * other.m[0][3];
438 m1 = m[0][1] * other.m[1][0]
439 + m[1][1] * other.m[1][1]
440 + m[2][1] * other.m[1][2]
441 + m[3][1] * other.m[1][3];
442 m2 = m[0][1] * other.m[2][0]
443 + m[1][1] * other.m[2][1]
444 + m[2][1] * other.m[2][2]
445 + m[3][1] * other.m[2][3];
446 m[3][1] = m[0][1] * other.m[3][0]
447 + m[1][1] * other.m[3][1]
448 + m[2][1] * other.m[3][2]
449 + m[3][1] * other.m[3][3];
450 m[0][1] = m0;
451 m[1][1] = m1;
452 m[2][1] = m2;
453
454 m0 = m[0][2] * other.m[0][0]
455 + m[1][2] * other.m[0][1]
456 + m[2][2] * other.m[0][2]
457 + m[3][2] * other.m[0][3];
458 m1 = m[0][2] * other.m[1][0]
459 + m[1][2] * other.m[1][1]
460 + m[2][2] * other.m[1][2]
461 + m[3][2] * other.m[1][3];
462 m2 = m[0][2] * other.m[2][0]
463 + m[1][2] * other.m[2][1]
464 + m[2][2] * other.m[2][2]
465 + m[3][2] * other.m[2][3];
466 m[3][2] = m[0][2] * other.m[3][0]
467 + m[1][2] * other.m[3][1]
468 + m[2][2] * other.m[3][2]
469 + m[3][2] * other.m[3][3];
470 m[0][2] = m0;
471 m[1][2] = m1;
472 m[2][2] = m2;
473
474 m0 = m[0][3] * other.m[0][0]
475 + m[1][3] * other.m[0][1]
476 + m[2][3] * other.m[0][2]
477 + m[3][3] * other.m[0][3];
478 m1 = m[0][3] * other.m[1][0]
479 + m[1][3] * other.m[1][1]
480 + m[2][3] * other.m[1][2]
481 + m[3][3] * other.m[1][3];
482 m2 = m[0][3] * other.m[2][0]
483 + m[1][3] * other.m[2][1]
484 + m[2][3] * other.m[2][2]
485 + m[3][3] * other.m[2][3];
486 m[3][3] = m[0][3] * other.m[3][0]
487 + m[1][3] * other.m[3][1]
488 + m[2][3] * other.m[3][2]
489 + m[3][3] * other.m[3][3];
490 m[0][3] = m0;
491 m[1][3] = m1;
492 m[2][3] = m2;
493 return *this;
494}
495
496inline QMatrix4x4& QMatrix4x4::operator*=(float factor)
497{
498 m[0][0] *= factor;
499 m[0][1] *= factor;
500 m[0][2] *= factor;
501 m[0][3] *= factor;
502 m[1][0] *= factor;
503 m[1][1] *= factor;
504 m[1][2] *= factor;
505 m[1][3] *= factor;
506 m[2][0] *= factor;
507 m[2][1] *= factor;
508 m[2][2] *= factor;
509 m[2][3] *= factor;
510 m[3][0] *= factor;
511 m[3][1] *= factor;
512 m[3][2] *= factor;
513 m[3][3] *= factor;
514 flagBits = General;
515 return *this;
516}
517
518inline bool QMatrix4x4::operator==(const QMatrix4x4& other) const
519{
520 return m[0][0] == other.m[0][0] &&
521 m[0][1] == other.m[0][1] &&
522 m[0][2] == other.m[0][2] &&
523 m[0][3] == other.m[0][3] &&
524 m[1][0] == other.m[1][0] &&
525 m[1][1] == other.m[1][1] &&
526 m[1][2] == other.m[1][2] &&
527 m[1][3] == other.m[1][3] &&
528 m[2][0] == other.m[2][0] &&
529 m[2][1] == other.m[2][1] &&
530 m[2][2] == other.m[2][2] &&
531 m[2][3] == other.m[2][3] &&
532 m[3][0] == other.m[3][0] &&
533 m[3][1] == other.m[3][1] &&
534 m[3][2] == other.m[3][2] &&
535 m[3][3] == other.m[3][3];
536}
537
538inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
539{
540 return m[0][0] != other.m[0][0] ||
541 m[0][1] != other.m[0][1] ||
542 m[0][2] != other.m[0][2] ||
543 m[0][3] != other.m[0][3] ||
544 m[1][0] != other.m[1][0] ||
545 m[1][1] != other.m[1][1] ||
546 m[1][2] != other.m[1][2] ||
547 m[1][3] != other.m[1][3] ||
548 m[2][0] != other.m[2][0] ||
549 m[2][1] != other.m[2][1] ||
550 m[2][2] != other.m[2][2] ||
551 m[2][3] != other.m[2][3] ||
552 m[3][0] != other.m[3][0] ||
553 m[3][1] != other.m[3][1] ||
554 m[3][2] != other.m[3][2] ||
555 m[3][3] != other.m[3][3];
556}
557
558inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
559{
560 Q_DECL_UNINITIALIZED
561 QMatrix4x4 m(Qt::Uninitialized);
562 m.m[0][0] = m1.m[0][0] + m2.m[0][0];
563 m.m[0][1] = m1.m[0][1] + m2.m[0][1];
564 m.m[0][2] = m1.m[0][2] + m2.m[0][2];
565 m.m[0][3] = m1.m[0][3] + m2.m[0][3];
566 m.m[1][0] = m1.m[1][0] + m2.m[1][0];
567 m.m[1][1] = m1.m[1][1] + m2.m[1][1];
568 m.m[1][2] = m1.m[1][2] + m2.m[1][2];
569 m.m[1][3] = m1.m[1][3] + m2.m[1][3];
570 m.m[2][0] = m1.m[2][0] + m2.m[2][0];
571 m.m[2][1] = m1.m[2][1] + m2.m[2][1];
572 m.m[2][2] = m1.m[2][2] + m2.m[2][2];
573 m.m[2][3] = m1.m[2][3] + m2.m[2][3];
574 m.m[3][0] = m1.m[3][0] + m2.m[3][0];
575 m.m[3][1] = m1.m[3][1] + m2.m[3][1];
576 m.m[3][2] = m1.m[3][2] + m2.m[3][2];
577 m.m[3][3] = m1.m[3][3] + m2.m[3][3];
578 return m;
579}
580
581inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
582{
583 Q_DECL_UNINITIALIZED
584 QMatrix4x4 m(Qt::Uninitialized);
585 m.m[0][0] = m1.m[0][0] - m2.m[0][0];
586 m.m[0][1] = m1.m[0][1] - m2.m[0][1];
587 m.m[0][2] = m1.m[0][2] - m2.m[0][2];
588 m.m[0][3] = m1.m[0][3] - m2.m[0][3];
589 m.m[1][0] = m1.m[1][0] - m2.m[1][0];
590 m.m[1][1] = m1.m[1][1] - m2.m[1][1];
591 m.m[1][2] = m1.m[1][2] - m2.m[1][2];
592 m.m[1][3] = m1.m[1][3] - m2.m[1][3];
593 m.m[2][0] = m1.m[2][0] - m2.m[2][0];
594 m.m[2][1] = m1.m[2][1] - m2.m[2][1];
595 m.m[2][2] = m1.m[2][2] - m2.m[2][2];
596 m.m[2][3] = m1.m[2][3] - m2.m[2][3];
597 m.m[3][0] = m1.m[3][0] - m2.m[3][0];
598 m.m[3][1] = m1.m[3][1] - m2.m[3][1];
599 m.m[3][2] = m1.m[3][2] - m2.m[3][2];
600 m.m[3][3] = m1.m[3][3] - m2.m[3][3];
601 return m;
602}
603
604inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
605{
606 Q_DECL_UNINITIALIZED
607 QMatrix4x4 m(Qt::Uninitialized);
608 QMatrix4x4::Flags flagBits = m1.flagBits | m2.flagBits;
609 if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
610 // Scale | Translation
611 m.m[0][0] = m1.m[0][0] * m2.m[0][0];
612 m.m[0][1] = 0.0f;
613 m.m[0][2] = 0.0f;
614 m.m[0][3] = 0.0f;
615
616 m.m[1][0] = 0.0f;
617 m.m[1][1] = m1.m[1][1] * m2.m[1][1];
618 m.m[1][2] = 0.0f;
619 m.m[1][3] = 0.0f;
620
621 m.m[2][0] = 0.0f;
622 m.m[2][1] = 0.0f;
623 m.m[2][2] = m1.m[2][2] * m2.m[2][2];
624 m.m[2][3] = 0.0f;
625
626 m.m[3][0] = m1.m[3][0] + m1.m[0][0] * m2.m[3][0];
627 m.m[3][1] = m1.m[3][1] + m1.m[1][1] * m2.m[3][1];
628 m.m[3][2] = m1.m[3][2] + m1.m[2][2] * m2.m[3][2];
629 m.m[3][3] = 1.0f;
630 m.flagBits = flagBits;
631 return m;
632 }
633
634 m.m[0][0] = m1.m[0][0] * m2.m[0][0]
635 + m1.m[1][0] * m2.m[0][1]
636 + m1.m[2][0] * m2.m[0][2]
637 + m1.m[3][0] * m2.m[0][3];
638 m.m[0][1] = m1.m[0][1] * m2.m[0][0]
639 + m1.m[1][1] * m2.m[0][1]
640 + m1.m[2][1] * m2.m[0][2]
641 + m1.m[3][1] * m2.m[0][3];
642 m.m[0][2] = m1.m[0][2] * m2.m[0][0]
643 + m1.m[1][2] * m2.m[0][1]
644 + m1.m[2][2] * m2.m[0][2]
645 + m1.m[3][2] * m2.m[0][3];
646 m.m[0][3] = m1.m[0][3] * m2.m[0][0]
647 + m1.m[1][3] * m2.m[0][1]
648 + m1.m[2][3] * m2.m[0][2]
649 + m1.m[3][3] * m2.m[0][3];
650
651 m.m[1][0] = m1.m[0][0] * m2.m[1][0]
652 + m1.m[1][0] * m2.m[1][1]
653 + m1.m[2][0] * m2.m[1][2]
654 + m1.m[3][0] * m2.m[1][3];
655 m.m[1][1] = m1.m[0][1] * m2.m[1][0]
656 + m1.m[1][1] * m2.m[1][1]
657 + m1.m[2][1] * m2.m[1][2]
658 + m1.m[3][1] * m2.m[1][3];
659 m.m[1][2] = m1.m[0][2] * m2.m[1][0]
660 + m1.m[1][2] * m2.m[1][1]
661 + m1.m[2][2] * m2.m[1][2]
662 + m1.m[3][2] * m2.m[1][3];
663 m.m[1][3] = m1.m[0][3] * m2.m[1][0]
664 + m1.m[1][3] * m2.m[1][1]
665 + m1.m[2][3] * m2.m[1][2]
666 + m1.m[3][3] * m2.m[1][3];
667
668 m.m[2][0] = m1.m[0][0] * m2.m[2][0]
669 + m1.m[1][0] * m2.m[2][1]
670 + m1.m[2][0] * m2.m[2][2]
671 + m1.m[3][0] * m2.m[2][3];
672 m.m[2][1] = m1.m[0][1] * m2.m[2][0]
673 + m1.m[1][1] * m2.m[2][1]
674 + m1.m[2][1] * m2.m[2][2]
675 + m1.m[3][1] * m2.m[2][3];
676 m.m[2][2] = m1.m[0][2] * m2.m[2][0]
677 + m1.m[1][2] * m2.m[2][1]
678 + m1.m[2][2] * m2.m[2][2]
679 + m1.m[3][2] * m2.m[2][3];
680 m.m[2][3] = m1.m[0][3] * m2.m[2][0]
681 + m1.m[1][3] * m2.m[2][1]
682 + m1.m[2][3] * m2.m[2][2]
683 + m1.m[3][3] * m2.m[2][3];
684
685 m.m[3][0] = m1.m[0][0] * m2.m[3][0]
686 + m1.m[1][0] * m2.m[3][1]
687 + m1.m[2][0] * m2.m[3][2]
688 + m1.m[3][0] * m2.m[3][3];
689 m.m[3][1] = m1.m[0][1] * m2.m[3][0]
690 + m1.m[1][1] * m2.m[3][1]
691 + m1.m[2][1] * m2.m[3][2]
692 + m1.m[3][1] * m2.m[3][3];
693 m.m[3][2] = m1.m[0][2] * m2.m[3][0]
694 + m1.m[1][2] * m2.m[3][1]
695 + m1.m[2][2] * m2.m[3][2]
696 + m1.m[3][2] * m2.m[3][3];
697 m.m[3][3] = m1.m[0][3] * m2.m[3][0]
698 + m1.m[1][3] * m2.m[3][1]
699 + m1.m[2][3] * m2.m[3][2]
700 + m1.m[3][3] * m2.m[3][3];
701 m.flagBits = flagBits;
702 return m;
703}
704
705#ifndef QT_NO_VECTOR3D
706
707#if QT_DEPRECATED_SINCE(6, 1)
708
709QT_DEPRECATED_VERSION_X_6_1("Extend the QVector3D to a QVector4D with 1.0 as the w coordinate before multiplying")
710inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
711{
712 float x, y, z, w;
713 x = vector.x() * matrix.m[0][0] +
714 vector.y() * matrix.m[0][1] +
715 vector.z() * matrix.m[0][2] +
716 matrix.m[0][3];
717 y = vector.x() * matrix.m[1][0] +
718 vector.y() * matrix.m[1][1] +
719 vector.z() * matrix.m[1][2] +
720 matrix.m[1][3];
721 z = vector.x() * matrix.m[2][0] +
722 vector.y() * matrix.m[2][1] +
723 vector.z() * matrix.m[2][2] +
724 matrix.m[2][3];
725 w = vector.x() * matrix.m[3][0] +
726 vector.y() * matrix.m[3][1] +
727 vector.z() * matrix.m[3][2] +
728 matrix.m[3][3];
729 if (w == 1.0f)
730 return QVector3D(x, y, z);
731 else
732 return QVector3D(x / w, y / w, z / w);
733}
734
735QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(vector) instead")
736inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
737{
738 return matrix.map(vector);
739}
740
741#endif
742
743#endif
744
745#ifndef QT_NO_VECTOR4D
746
747inline QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
748{
749 float x, y, z, w;
750 x = vector.x() * matrix.m[0][0] +
751 vector.y() * matrix.m[0][1] +
752 vector.z() * matrix.m[0][2] +
753 vector.w() * matrix.m[0][3];
754 y = vector.x() * matrix.m[1][0] +
755 vector.y() * matrix.m[1][1] +
756 vector.z() * matrix.m[1][2] +
757 vector.w() * matrix.m[1][3];
758 z = vector.x() * matrix.m[2][0] +
759 vector.y() * matrix.m[2][1] +
760 vector.z() * matrix.m[2][2] +
761 vector.w() * matrix.m[2][3];
762 w = vector.x() * matrix.m[3][0] +
763 vector.y() * matrix.m[3][1] +
764 vector.z() * matrix.m[3][2] +
765 vector.w() * matrix.m[3][3];
766 return QVector4D(x, y, z, w);
767}
768
769inline QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
770{
771 float x, y, z, w;
772 x = vector.x() * matrix.m[0][0] +
773 vector.y() * matrix.m[1][0] +
774 vector.z() * matrix.m[2][0] +
775 vector.w() * matrix.m[3][0];
776 y = vector.x() * matrix.m[0][1] +
777 vector.y() * matrix.m[1][1] +
778 vector.z() * matrix.m[2][1] +
779 vector.w() * matrix.m[3][1];
780 z = vector.x() * matrix.m[0][2] +
781 vector.y() * matrix.m[1][2] +
782 vector.z() * matrix.m[2][2] +
783 vector.w() * matrix.m[3][2];
784 w = vector.x() * matrix.m[0][3] +
785 vector.y() * matrix.m[1][3] +
786 vector.z() * matrix.m[2][3] +
787 vector.w() * matrix.m[3][3];
788 return QVector4D(x, y, z, w);
789}
790
791#endif
792
793inline QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
794{
795 float xin, yin;
796 float x, y, w;
797 xin = point.x();
798 yin = point.y();
799 x = xin * matrix.m[0][0] +
800 yin * matrix.m[0][1] +
801 matrix.m[0][3];
802 y = xin * matrix.m[1][0] +
803 yin * matrix.m[1][1] +
804 matrix.m[1][3];
805 w = xin * matrix.m[3][0] +
806 yin * matrix.m[3][1] +
807 matrix.m[3][3];
808 if (w == 1.0f)
809 return QPoint(qRound(x), qRound(y));
810 else
811 return QPoint(qRound(x / w), qRound(y / w));
812}
813
814inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
815{
816 float xin, yin;
817 float x, y, w;
818 xin = float(point.x());
819 yin = float(point.y());
820 x = xin * matrix.m[0][0] +
821 yin * matrix.m[0][1] +
822 matrix.m[0][3];
823 y = xin * matrix.m[1][0] +
824 yin * matrix.m[1][1] +
825 matrix.m[1][3];
826 w = xin * matrix.m[3][0] +
827 yin * matrix.m[3][1] +
828 matrix.m[3][3];
829 if (w == 1.0f) {
830 return QPointF(qreal(x), qreal(y));
831 } else {
832 return QPointF(qreal(x / w), qreal(y / w));
833 }
834}
835
836#if QT_DEPRECATED_SINCE(6, 1)
837
838QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(point) instead")
839inline QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
840{
841 return matrix.map(point);
842}
843
844QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(point) instead")
845inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
846{
847 return matrix.map(point);
848}
849
850#endif
851
852inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
853{
854 Q_DECL_UNINITIALIZED
855 QMatrix4x4 m(Qt::Uninitialized);
856 m.m[0][0] = -matrix.m[0][0];
857 m.m[0][1] = -matrix.m[0][1];
858 m.m[0][2] = -matrix.m[0][2];
859 m.m[0][3] = -matrix.m[0][3];
860 m.m[1][0] = -matrix.m[1][0];
861 m.m[1][1] = -matrix.m[1][1];
862 m.m[1][2] = -matrix.m[1][2];
863 m.m[1][3] = -matrix.m[1][3];
864 m.m[2][0] = -matrix.m[2][0];
865 m.m[2][1] = -matrix.m[2][1];
866 m.m[2][2] = -matrix.m[2][2];
867 m.m[2][3] = -matrix.m[2][3];
868 m.m[3][0] = -matrix.m[3][0];
869 m.m[3][1] = -matrix.m[3][1];
870 m.m[3][2] = -matrix.m[3][2];
871 m.m[3][3] = -matrix.m[3][3];
872 return m;
873}
874
875inline QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix)
876{
877 Q_DECL_UNINITIALIZED
878 QMatrix4x4 m(Qt::Uninitialized);
879 m.m[0][0] = matrix.m[0][0] * factor;
880 m.m[0][1] = matrix.m[0][1] * factor;
881 m.m[0][2] = matrix.m[0][2] * factor;
882 m.m[0][3] = matrix.m[0][3] * factor;
883 m.m[1][0] = matrix.m[1][0] * factor;
884 m.m[1][1] = matrix.m[1][1] * factor;
885 m.m[1][2] = matrix.m[1][2] * factor;
886 m.m[1][3] = matrix.m[1][3] * factor;
887 m.m[2][0] = matrix.m[2][0] * factor;
888 m.m[2][1] = matrix.m[2][1] * factor;
889 m.m[2][2] = matrix.m[2][2] * factor;
890 m.m[2][3] = matrix.m[2][3] * factor;
891 m.m[3][0] = matrix.m[3][0] * factor;
892 m.m[3][1] = matrix.m[3][1] * factor;
893 m.m[3][2] = matrix.m[3][2] * factor;
894 m.m[3][3] = matrix.m[3][3] * factor;
895 return m;
896}
897
898inline QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor)
899{
900 Q_DECL_UNINITIALIZED
901 QMatrix4x4 m(Qt::Uninitialized);
902 m.m[0][0] = matrix.m[0][0] * factor;
903 m.m[0][1] = matrix.m[0][1] * factor;
904 m.m[0][2] = matrix.m[0][2] * factor;
905 m.m[0][3] = matrix.m[0][3] * factor;
906 m.m[1][0] = matrix.m[1][0] * factor;
907 m.m[1][1] = matrix.m[1][1] * factor;
908 m.m[1][2] = matrix.m[1][2] * factor;
909 m.m[1][3] = matrix.m[1][3] * factor;
910 m.m[2][0] = matrix.m[2][0] * factor;
911 m.m[2][1] = matrix.m[2][1] * factor;
912 m.m[2][2] = matrix.m[2][2] * factor;
913 m.m[2][3] = matrix.m[2][3] * factor;
914 m.m[3][0] = matrix.m[3][0] * factor;
915 m.m[3][1] = matrix.m[3][1] * factor;
916 m.m[3][2] = matrix.m[3][2] * factor;
917 m.m[3][3] = matrix.m[3][3] * factor;
918 return m;
919}
920
921inline QPoint QMatrix4x4::map(const QPoint& point) const
922{
923 float xin, yin;
924 float x, y, w;
925 xin = point.x();
926 yin = point.y();
927 if (flagBits == QMatrix4x4::Identity) {
928 return point;
929 } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
930 // Translation | Scale
931 return QPoint(qRound(xin * m[0][0] + m[3][0]),
932 qRound(yin * m[1][1] + m[3][1]));
933 } else if (flagBits.toInt() < QMatrix4x4::Perspective) {
934 return QPoint(qRound(xin * m[0][0] + yin * m[1][0] + m[3][0]),
935 qRound(xin * m[0][1] + yin * m[1][1] + m[3][1]));
936 } else {
937 x = xin * m[0][0] +
938 yin * m[1][0] +
939 m[3][0];
940 y = xin * m[0][1] +
941 yin * m[1][1] +
942 m[3][1];
943 w = xin * m[0][3] +
944 yin * m[1][3] +
945 m[3][3];
946 if (w == 1.0f)
947 return QPoint(qRound(x), qRound(y));
948 else
949 return QPoint(qRound(x / w), qRound(y / w));
950 }
951}
952
953inline QPointF QMatrix4x4::map(const QPointF& point) const
954{
955 qreal xin, yin;
956 qreal x, y, w;
957 xin = point.x();
958 yin = point.y();
959 if (flagBits == QMatrix4x4::Identity) {
960 return point;
961 } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
962 // Translation | Scale
963 return QPointF(xin * qreal(m[0][0]) + qreal(m[3][0]),
964 yin * qreal(m[1][1]) + qreal(m[3][1]));
965 } else if (flagBits.toInt() < QMatrix4x4::Perspective) {
966 return QPointF(xin * qreal(m[0][0]) + yin * qreal(m[1][0]) +
967 qreal(m[3][0]),
968 xin * qreal(m[0][1]) + yin * qreal(m[1][1]) +
969 qreal(m[3][1]));
970 } else {
971 x = xin * qreal(m[0][0]) +
972 yin * qreal(m[1][0]) +
973 qreal(m[3][0]);
974 y = xin * qreal(m[0][1]) +
975 yin * qreal(m[1][1]) +
976 qreal(m[3][1]);
977 w = xin * qreal(m[0][3]) +
978 yin * qreal(m[1][3]) +
979 qreal(m[3][3]);
980 if (w == 1.0) {
981 return QPointF(qreal(x), qreal(y));
982 } else {
983 return QPointF(qreal(x / w), qreal(y / w));
984 }
985 }
986}
987
988#ifndef QT_NO_VECTOR3D
989
990inline QVector3D QMatrix4x4::map(const QVector3D& point) const
991{
992 float x, y, z, w;
993 if (flagBits == QMatrix4x4::Identity) {
994 return point;
995 } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
996 // Translation | Scale
997 return QVector3D(point.x() * m[0][0] + m[3][0],
998 point.y() * m[1][1] + m[3][1],
999 point.z() * m[2][2] + m[3][2]);
1000 } else if (flagBits.toInt() < QMatrix4x4::Rotation) {
1001 // Translation | Scale | Rotation2D
1002 return QVector3D(point.x() * m[0][0] + point.y() * m[1][0] + m[3][0],
1003 point.x() * m[0][1] + point.y() * m[1][1] + m[3][1],
1004 point.z() * m[2][2] + m[3][2]);
1005 } else {
1006 x = point.x() * m[0][0] +
1007 point.y() * m[1][0] +
1008 point.z() * m[2][0] +
1009 m[3][0];
1010 y = point.x() * m[0][1] +
1011 point.y() * m[1][1] +
1012 point.z() * m[2][1] +
1013 m[3][1];
1014 z = point.x() * m[0][2] +
1015 point.y() * m[1][2] +
1016 point.z() * m[2][2] +
1017 m[3][2];
1018 w = point.x() * m[0][3] +
1019 point.y() * m[1][3] +
1020 point.z() * m[2][3] +
1021 m[3][3];
1022 if (w == 1.0f)
1023 return QVector3D(x, y, z);
1024 else
1025 return QVector3D(x / w, y / w, z / w);
1026 }
1027}
1028
1029inline QVector3D QMatrix4x4::mapVector(const QVector3D& vector) const
1030{
1031 if (flagBits.toInt() < Scale) {
1032 // Translation
1033 return vector;
1034 } else if (flagBits.toInt() < Rotation2D) {
1035 // Translation | Scale
1036 return QVector3D(vector.x() * m[0][0],
1037 vector.y() * m[1][1],
1038 vector.z() * m[2][2]);
1039 } else {
1040 return QVector3D(vector.x() * m[0][0] +
1041 vector.y() * m[1][0] +
1042 vector.z() * m[2][0],
1043 vector.x() * m[0][1] +
1044 vector.y() * m[1][1] +
1045 vector.z() * m[2][1],
1046 vector.x() * m[0][2] +
1047 vector.y() * m[1][2] +
1048 vector.z() * m[2][2]);
1049 }
1050}
1051
1052#endif
1053
1054#ifndef QT_NO_VECTOR4D
1055
1056inline QVector4D QMatrix4x4::map(const QVector4D& point) const
1057{
1058 return *this * point;
1059}
1060
1061#endif
1062
1063inline float *QMatrix4x4::data()
1064{
1065 // We have to assume that the caller will modify the matrix elements,
1066 // so we flip it over to "General" mode.
1067 flagBits = General;
1068 return *m;
1069}
1070
1071inline void QMatrix4x4::viewport(const QRectF &rect)
1072{
1073 viewport(float(rect.x()), float(rect.y()), float(rect.width()), float(rect.height()));
1074}
1075
1077
1078#ifndef QT_NO_DEBUG_STREAM
1079Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
1080#endif
1081
1082#ifndef QT_NO_DATASTREAM
1083Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &);
1084Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &);
1085#endif
1086
1087#endif
1088
1089QT_END_NAMESPACE
1090
1091#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:604
QMatrix4x4 operator-(const QMatrix4x4 &matrix)
Definition qmatrix4x4.h:852
QMatrix4x4 operator*(const QMatrix4x4 &matrix, float factor)
Definition qmatrix4x4.h:898
QMatrix4x4 operator*(float factor, const QMatrix4x4 &matrix)
Definition qmatrix4x4.h:875
QMatrix4x4 operator-(const QMatrix4x4 &m1, const QMatrix4x4 &m2)
Definition qmatrix4x4.h:581
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)