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