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