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

source code of qtbase/src/gui/math3d/qmatrix4x4.h