source: trunk/src/gui/math3d/qmatrix4x4.h@ 651

Last change on this file since 651 was 651, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.2 sources.

  • Property svn:eol-style set to native
File size: 32.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the QtGui module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
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
51QT_BEGIN_HEADER
52
53QT_BEGIN_NAMESPACE
54
55QT_MODULE(Gui)
56
57#ifndef QT_NO_MATRIX4X4
58
59class QMatrix;
60class QTransform;
61class QVariant;
62
63class Q_GUI_EXPORT QMatrix4x4
64{
65public:
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#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
73 template <int N, int M>
74 explicit QMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix);
75#endif
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#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
173 template <int N, int M>
174 QGenericMatrix<N, M, qreal> toGenericMatrix() const;
175#endif
176
177 inline qreal *data();
178 inline const qreal *data() const { return m[0]; }
179 inline const qreal *constData() const { return m[0]; }
180
181 void optimize();
182
183 operator QVariant() const;
184
185#ifndef QT_NO_DEBUG_STREAM
186 friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
187#endif
188
189private:
190 qreal m[4][4]; // Column-major order to match OpenGL.
191 int flagBits; // Flag bits from the enum below.
192
193 enum {
194 Identity = 0x0001, // Identity matrix
195 General = 0x0002, // General matrix, unknown contents
196 Translation = 0x0004, // Contains a simple translation
197 Scale = 0x0008, // Contains a simple scale
198 Rotation = 0x0010 // Contains a simple rotation
199 };
200
201 // Construct without initializing identity matrix.
202 QMatrix4x4(int) { flagBits = General; }
203
204 QMatrix4x4 orthonormalInverse() const;
205
206 void projectedRotate(qreal angle, qreal x, qreal y, qreal z);
207
208 friend class QGraphicsRotation;
209};
210
211inline 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#if !defined(QT_NO_MEMBER_TEMPLATES)
225
226template <int N, int M>
227Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
228 (const QGenericMatrix<N, M, qreal>& matrix)
229{
230 const qreal *values = matrix.constData();
231 for (int matrixCol = 0; matrixCol < 4; ++matrixCol) {
232 for (int matrixRow = 0; matrixRow < 4; ++matrixRow) {
233 if (matrixCol < N && matrixRow < M)
234 m[matrixCol][matrixRow] = values[matrixCol * M + matrixRow];
235 else if (matrixCol == matrixRow)
236 m[matrixCol][matrixRow] = 1.0f;
237 else
238 m[matrixCol][matrixRow] = 0.0f;
239 }
240 }
241 flagBits = General;
242}
243
244template <int N, int M>
245QGenericMatrix<N, M, qreal> QMatrix4x4::toGenericMatrix() const
246{
247 QGenericMatrix<N, M, qreal> result;
248 qreal *values = result.data();
249 for (int matrixCol = 0; matrixCol < N; ++matrixCol) {
250 for (int matrixRow = 0; matrixRow < M; ++matrixRow) {
251 if (matrixCol < 4 && matrixRow < 4)
252 values[matrixCol * M + matrixRow] = m[matrixCol][matrixRow];
253 else if (matrixCol == matrixRow)
254 values[matrixCol * M + matrixRow] = 1.0f;
255 else
256 values[matrixCol * M + matrixRow] = 0.0f;
257 }
258 }
259 return result;
260}
261
262#endif
263
264inline const qreal& QMatrix4x4::operator()(int aRow, int aColumn) const
265{
266 Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
267 return m[aColumn][aRow];
268}
269
270inline qreal& QMatrix4x4::operator()(int aRow, int aColumn)
271{
272 Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
273 flagBits = General;
274 return m[aColumn][aRow];
275}
276
277inline QVector4D QMatrix4x4::column(int index) const
278{
279 Q_ASSERT(index >= 0 && index < 4);
280 return QVector4D(m[index][0], m[index][1], m[index][2], m[index][3]);
281}
282
283inline void QMatrix4x4::setColumn(int index, const QVector4D& value)
284{
285 Q_ASSERT(index >= 0 && index < 4);
286 m[index][0] = value.x();
287 m[index][1] = value.y();
288 m[index][2] = value.z();
289 m[index][3] = value.w();
290 flagBits = General;
291}
292
293inline QVector4D QMatrix4x4::row(int index) const
294{
295 Q_ASSERT(index >= 0 && index < 4);
296 return QVector4D(m[0][index], m[1][index], m[2][index], m[3][index]);
297}
298
299inline void QMatrix4x4::setRow(int index, const QVector4D& value)
300{
301 Q_ASSERT(index >= 0 && index < 4);
302 m[0][index] = value.x();
303 m[1][index] = value.y();
304 m[2][index] = value.z();
305 m[3][index] = value.w();
306 flagBits = General;
307}
308
309Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor);
310
311inline bool QMatrix4x4::isIdentity() const
312{
313 if (flagBits == Identity)
314 return true;
315 if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
316 return false;
317 if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f)
318 return false;
319 if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f)
320 return false;
321 if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f)
322 return false;
323 if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f)
324 return false;
325 return (m[3][3] == 1.0f);
326}
327
328inline void QMatrix4x4::setToIdentity()
329{
330 m[0][0] = 1.0f;
331 m[0][1] = 0.0f;
332 m[0][2] = 0.0f;
333 m[0][3] = 0.0f;
334 m[1][0] = 0.0f;
335 m[1][1] = 1.0f;
336 m[1][2] = 0.0f;
337 m[1][3] = 0.0f;
338 m[2][0] = 0.0f;
339 m[2][1] = 0.0f;
340 m[2][2] = 1.0f;
341 m[2][3] = 0.0f;
342 m[3][0] = 0.0f;
343 m[3][1] = 0.0f;
344 m[3][2] = 0.0f;
345 m[3][3] = 1.0f;
346 flagBits = Identity;
347}
348
349inline void QMatrix4x4::fill(qreal value)
350{
351 m[0][0] = value;
352 m[0][1] = value;
353 m[0][2] = value;
354 m[0][3] = value;
355 m[1][0] = value;
356 m[1][1] = value;
357 m[1][2] = value;
358 m[1][3] = value;
359 m[2][0] = value;
360 m[2][1] = value;
361 m[2][2] = value;
362 m[2][3] = value;
363 m[3][0] = value;
364 m[3][1] = value;
365 m[3][2] = value;
366 m[3][3] = value;
367 flagBits = General;
368}
369
370inline QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
371{
372 m[0][0] += other.m[0][0];
373 m[0][1] += other.m[0][1];
374 m[0][2] += other.m[0][2];
375 m[0][3] += other.m[0][3];
376 m[1][0] += other.m[1][0];
377 m[1][1] += other.m[1][1];
378 m[1][2] += other.m[1][2];
379 m[1][3] += other.m[1][3];
380 m[2][0] += other.m[2][0];
381 m[2][1] += other.m[2][1];
382 m[2][2] += other.m[2][2];
383 m[2][3] += other.m[2][3];
384 m[3][0] += other.m[3][0];
385 m[3][1] += other.m[3][1];
386 m[3][2] += other.m[3][2];
387 m[3][3] += other.m[3][3];
388 flagBits = General;
389 return *this;
390}
391
392inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
393{
394 m[0][0] -= other.m[0][0];
395 m[0][1] -= other.m[0][1];
396 m[0][2] -= other.m[0][2];
397 m[0][3] -= other.m[0][3];
398 m[1][0] -= other.m[1][0];
399 m[1][1] -= other.m[1][1];
400 m[1][2] -= other.m[1][2];
401 m[1][3] -= other.m[1][3];
402 m[2][0] -= other.m[2][0];
403 m[2][1] -= other.m[2][1];
404 m[2][2] -= other.m[2][2];
405 m[2][3] -= other.m[2][3];
406 m[3][0] -= other.m[3][0];
407 m[3][1] -= other.m[3][1];
408 m[3][2] -= other.m[3][2];
409 m[3][3] -= other.m[3][3];
410 flagBits = General;
411 return *this;
412}
413
414inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& other)
415{
416 if (flagBits == Identity) {
417 *this = other;
418 return *this;
419 } else if (other.flagBits == Identity) {
420 return *this;
421 } else {
422 *this = *this * other;
423 return *this;
424 }
425}
426
427inline QMatrix4x4& QMatrix4x4::operator*=(qreal factor)
428{
429 m[0][0] *= factor;
430 m[0][1] *= factor;
431 m[0][2] *= factor;
432 m[0][3] *= factor;
433 m[1][0] *= factor;
434 m[1][1] *= factor;
435 m[1][2] *= factor;
436 m[1][3] *= factor;
437 m[2][0] *= factor;
438 m[2][1] *= factor;
439 m[2][2] *= factor;
440 m[2][3] *= factor;
441 m[3][0] *= factor;
442 m[3][1] *= factor;
443 m[3][2] *= factor;
444 m[3][3] *= factor;
445 flagBits = General;
446 return *this;
447}
448
449inline bool QMatrix4x4::operator==(const QMatrix4x4& other) const
450{
451 return m[0][0] == other.m[0][0] &&
452 m[0][1] == other.m[0][1] &&
453 m[0][2] == other.m[0][2] &&
454 m[0][3] == other.m[0][3] &&
455 m[1][0] == other.m[1][0] &&
456 m[1][1] == other.m[1][1] &&
457 m[1][2] == other.m[1][2] &&
458 m[1][3] == other.m[1][3] &&
459 m[2][0] == other.m[2][0] &&
460 m[2][1] == other.m[2][1] &&
461 m[2][2] == other.m[2][2] &&
462 m[2][3] == other.m[2][3] &&
463 m[3][0] == other.m[3][0] &&
464 m[3][1] == other.m[3][1] &&
465 m[3][2] == other.m[3][2] &&
466 m[3][3] == other.m[3][3];
467}
468
469inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
470{
471 return m[0][0] != other.m[0][0] ||
472 m[0][1] != other.m[0][1] ||
473 m[0][2] != other.m[0][2] ||
474 m[0][3] != other.m[0][3] ||
475 m[1][0] != other.m[1][0] ||
476 m[1][1] != other.m[1][1] ||
477 m[1][2] != other.m[1][2] ||
478 m[1][3] != other.m[1][3] ||
479 m[2][0] != other.m[2][0] ||
480 m[2][1] != other.m[2][1] ||
481 m[2][2] != other.m[2][2] ||
482 m[2][3] != other.m[2][3] ||
483 m[3][0] != other.m[3][0] ||
484 m[3][1] != other.m[3][1] ||
485 m[3][2] != other.m[3][2] ||
486 m[3][3] != other.m[3][3];
487}
488
489inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
490{
491 QMatrix4x4 m(1);
492 m.m[0][0] = m1.m[0][0] + m2.m[0][0];
493 m.m[0][1] = m1.m[0][1] + m2.m[0][1];
494 m.m[0][2] = m1.m[0][2] + m2.m[0][2];
495 m.m[0][3] = m1.m[0][3] + m2.m[0][3];
496 m.m[1][0] = m1.m[1][0] + m2.m[1][0];
497 m.m[1][1] = m1.m[1][1] + m2.m[1][1];
498 m.m[1][2] = m1.m[1][2] + m2.m[1][2];
499 m.m[1][3] = m1.m[1][3] + m2.m[1][3];
500 m.m[2][0] = m1.m[2][0] + m2.m[2][0];
501 m.m[2][1] = m1.m[2][1] + m2.m[2][1];
502 m.m[2][2] = m1.m[2][2] + m2.m[2][2];
503 m.m[2][3] = m1.m[2][3] + m2.m[2][3];
504 m.m[3][0] = m1.m[3][0] + m2.m[3][0];
505 m.m[3][1] = m1.m[3][1] + m2.m[3][1];
506 m.m[3][2] = m1.m[3][2] + m2.m[3][2];
507 m.m[3][3] = m1.m[3][3] + m2.m[3][3];
508 return m;
509}
510
511inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
512{
513 QMatrix4x4 m(1);
514 m.m[0][0] = m1.m[0][0] - m2.m[0][0];
515 m.m[0][1] = m1.m[0][1] - m2.m[0][1];
516 m.m[0][2] = m1.m[0][2] - m2.m[0][2];
517 m.m[0][3] = m1.m[0][3] - m2.m[0][3];
518 m.m[1][0] = m1.m[1][0] - m2.m[1][0];
519 m.m[1][1] = m1.m[1][1] - m2.m[1][1];
520 m.m[1][2] = m1.m[1][2] - m2.m[1][2];
521 m.m[1][3] = m1.m[1][3] - m2.m[1][3];
522 m.m[2][0] = m1.m[2][0] - m2.m[2][0];
523 m.m[2][1] = m1.m[2][1] - m2.m[2][1];
524 m.m[2][2] = m1.m[2][2] - m2.m[2][2];
525 m.m[2][3] = m1.m[2][3] - m2.m[2][3];
526 m.m[3][0] = m1.m[3][0] - m2.m[3][0];
527 m.m[3][1] = m1.m[3][1] - m2.m[3][1];
528 m.m[3][2] = m1.m[3][2] - m2.m[3][2];
529 m.m[3][3] = m1.m[3][3] - m2.m[3][3];
530 return m;
531}
532
533inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
534{
535 if (m1.flagBits == QMatrix4x4::Identity)
536 return m2;
537 else if (m2.flagBits == QMatrix4x4::Identity)
538 return m1;
539
540 QMatrix4x4 m(1);
541 m.m[0][0] = m1.m[0][0] * m2.m[0][0] +
542 m1.m[1][0] * m2.m[0][1] +
543 m1.m[2][0] * m2.m[0][2] +
544 m1.m[3][0] * m2.m[0][3];
545 m.m[0][1] = m1.m[0][1] * m2.m[0][0] +
546 m1.m[1][1] * m2.m[0][1] +
547 m1.m[2][1] * m2.m[0][2] +
548 m1.m[3][1] * m2.m[0][3];
549 m.m[0][2] = m1.m[0][2] * m2.m[0][0] +
550 m1.m[1][2] * m2.m[0][1] +
551 m1.m[2][2] * m2.m[0][2] +
552 m1.m[3][2] * m2.m[0][3];
553 m.m[0][3] = m1.m[0][3] * m2.m[0][0] +
554 m1.m[1][3] * m2.m[0][1] +
555 m1.m[2][3] * m2.m[0][2] +
556 m1.m[3][3] * m2.m[0][3];
557 m.m[1][0] = m1.m[0][0] * m2.m[1][0] +
558 m1.m[1][0] * m2.m[1][1] +
559 m1.m[2][0] * m2.m[1][2] +
560 m1.m[3][0] * m2.m[1][3];
561 m.m[1][1] = m1.m[0][1] * m2.m[1][0] +
562 m1.m[1][1] * m2.m[1][1] +
563 m1.m[2][1] * m2.m[1][2] +
564 m1.m[3][1] * m2.m[1][3];
565 m.m[1][2] = m1.m[0][2] * m2.m[1][0] +
566 m1.m[1][2] * m2.m[1][1] +
567 m1.m[2][2] * m2.m[1][2] +
568 m1.m[3][2] * m2.m[1][3];
569 m.m[1][3] = m1.m[0][3] * m2.m[1][0] +
570 m1.m[1][3] * m2.m[1][1] +
571 m1.m[2][3] * m2.m[1][2] +
572 m1.m[3][3] * m2.m[1][3];
573 m.m[2][0] = m1.m[0][0] * m2.m[2][0] +
574 m1.m[1][0] * m2.m[2][1] +
575 m1.m[2][0] * m2.m[2][2] +
576 m1.m[3][0] * m2.m[2][3];
577 m.m[2][1] = m1.m[0][1] * m2.m[2][0] +
578 m1.m[1][1] * m2.m[2][1] +
579 m1.m[2][1] * m2.m[2][2] +
580 m1.m[3][1] * m2.m[2][3];
581 m.m[2][2] = m1.m[0][2] * m2.m[2][0] +
582 m1.m[1][2] * m2.m[2][1] +
583 m1.m[2][2] * m2.m[2][2] +
584 m1.m[3][2] * m2.m[2][3];
585 m.m[2][3] = m1.m[0][3] * m2.m[2][0] +
586 m1.m[1][3] * m2.m[2][1] +
587 m1.m[2][3] * m2.m[2][2] +
588 m1.m[3][3] * m2.m[2][3];
589 m.m[3][0] = m1.m[0][0] * m2.m[3][0] +
590 m1.m[1][0] * m2.m[3][1] +
591 m1.m[2][0] * m2.m[3][2] +
592 m1.m[3][0] * m2.m[3][3];
593 m.m[3][1] = m1.m[0][1] * m2.m[3][0] +
594 m1.m[1][1] * m2.m[3][1] +
595 m1.m[2][1] * m2.m[3][2] +
596 m1.m[3][1] * m2.m[3][3];
597 m.m[3][2] = m1.m[0][2] * m2.m[3][0] +
598 m1.m[1][2] * m2.m[3][1] +
599 m1.m[2][2] * m2.m[3][2] +
600 m1.m[3][2] * m2.m[3][3];
601 m.m[3][3] = m1.m[0][3] * m2.m[3][0] +
602 m1.m[1][3] * m2.m[3][1] +
603 m1.m[2][3] * m2.m[3][2] +
604 m1.m[3][3] * m2.m[3][3];
605 return m;
606}
607
608#ifndef QT_NO_VECTOR3D
609
610inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
611{
612 qreal x, y, z, w;
613 x = vector.x() * matrix.m[0][0] +
614 vector.y() * matrix.m[0][1] +
615 vector.z() * matrix.m[0][2] +
616 matrix.m[0][3];
617 y = vector.x() * matrix.m[1][0] +
618 vector.y() * matrix.m[1][1] +
619 vector.z() * matrix.m[1][2] +
620 matrix.m[1][3];
621 z = vector.x() * matrix.m[2][0] +
622 vector.y() * matrix.m[2][1] +
623 vector.z() * matrix.m[2][2] +
624 matrix.m[2][3];
625 w = vector.x() * matrix.m[3][0] +
626 vector.y() * matrix.m[3][1] +
627 vector.z() * matrix.m[3][2] +
628 matrix.m[3][3];
629 if (w == 1.0f)
630 return QVector3D(x, y, z);
631 else
632 return QVector3D(x / w, y / w, z / w);
633}
634
635inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
636{
637 qreal x, y, z, w;
638 if (matrix.flagBits == QMatrix4x4::Identity) {
639 return vector;
640 } else if (matrix.flagBits == QMatrix4x4::Translation) {
641 return QVector3D(vector.x() + matrix.m[3][0],
642 vector.y() + matrix.m[3][1],
643 vector.z() + matrix.m[3][2]);
644 } else if (matrix.flagBits ==
645 (QMatrix4x4::Translation | QMatrix4x4::Scale)) {
646 return QVector3D(vector.x() * matrix.m[0][0] + matrix.m[3][0],
647 vector.y() * matrix.m[1][1] + matrix.m[3][1],
648 vector.z() * matrix.m[2][2] + matrix.m[3][2]);
649 } else if (matrix.flagBits == QMatrix4x4::Scale) {
650 return QVector3D(vector.x() * matrix.m[0][0],
651 vector.y() * matrix.m[1][1],
652 vector.z() * matrix.m[2][2]);
653 } else {
654 x = vector.x() * matrix.m[0][0] +
655 vector.y() * matrix.m[1][0] +
656 vector.z() * matrix.m[2][0] +
657 matrix.m[3][0];
658 y = vector.x() * matrix.m[0][1] +
659 vector.y() * matrix.m[1][1] +
660 vector.z() * matrix.m[2][1] +
661 matrix.m[3][1];
662 z = vector.x() * matrix.m[0][2] +
663 vector.y() * matrix.m[1][2] +
664 vector.z() * matrix.m[2][2] +
665 matrix.m[3][2];
666 w = vector.x() * matrix.m[0][3] +
667 vector.y() * matrix.m[1][3] +
668 vector.z() * matrix.m[2][3] +
669 matrix.m[3][3];
670 if (w == 1.0f)
671 return QVector3D(x, y, z);
672 else
673 return QVector3D(x / w, y / w, z / w);
674 }
675}
676
677#endif
678
679#ifndef QT_NO_VECTOR4D
680
681inline QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
682{
683 qreal x, y, z, w;
684 x = vector.x() * matrix.m[0][0] +
685 vector.y() * matrix.m[0][1] +
686 vector.z() * matrix.m[0][2] +
687 vector.w() * matrix.m[0][3];
688 y = vector.x() * matrix.m[1][0] +
689 vector.y() * matrix.m[1][1] +
690 vector.z() * matrix.m[1][2] +
691 vector.w() * matrix.m[1][3];
692 z = vector.x() * matrix.m[2][0] +
693 vector.y() * matrix.m[2][1] +
694 vector.z() * matrix.m[2][2] +
695 vector.w() * matrix.m[2][3];
696 w = vector.x() * matrix.m[3][0] +
697 vector.y() * matrix.m[3][1] +
698 vector.z() * matrix.m[3][2] +
699 vector.w() * matrix.m[3][3];
700 return QVector4D(x, y, z, w);
701}
702
703inline QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
704{
705 qreal x, y, z, w;
706 x = vector.x() * matrix.m[0][0] +
707 vector.y() * matrix.m[1][0] +
708 vector.z() * matrix.m[2][0] +
709 vector.w() * matrix.m[3][0];
710 y = vector.x() * matrix.m[0][1] +
711 vector.y() * matrix.m[1][1] +
712 vector.z() * matrix.m[2][1] +
713 vector.w() * matrix.m[3][1];
714 z = vector.x() * matrix.m[0][2] +
715 vector.y() * matrix.m[1][2] +
716 vector.z() * matrix.m[2][2] +
717 vector.w() * matrix.m[3][2];
718 w = vector.x() * matrix.m[0][3] +
719 vector.y() * matrix.m[1][3] +
720 vector.z() * matrix.m[2][3] +
721 vector.w() * matrix.m[3][3];
722 return QVector4D(x, y, z, w);
723}
724
725#endif
726
727inline QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
728{
729 qreal xin, yin;
730 qreal x, y, w;
731 xin = point.x();
732 yin = point.y();
733 x = xin * matrix.m[0][0] +
734 yin * matrix.m[0][1] +
735 matrix.m[0][3];
736 y = xin * matrix.m[1][0] +
737 yin * matrix.m[1][1] +
738 matrix.m[1][3];
739 w = xin * matrix.m[3][0] +
740 yin * matrix.m[3][1] +
741 matrix.m[3][3];
742 if (w == 1.0f)
743 return QPoint(qRound(x), qRound(y));
744 else
745 return QPoint(qRound(x / w), qRound(y / w));
746}
747
748inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
749{
750 qreal xin, yin;
751 qreal x, y, w;
752 xin = point.x();
753 yin = point.y();
754 x = xin * matrix.m[0][0] +
755 yin * matrix.m[0][1] +
756 matrix.m[0][3];
757 y = xin * matrix.m[1][0] +
758 yin * matrix.m[1][1] +
759 matrix.m[1][3];
760 w = xin * matrix.m[3][0] +
761 yin * matrix.m[3][1] +
762 matrix.m[3][3];
763 if (w == 1.0f) {
764 return QPointF(qreal(x), qreal(y));
765 } else {
766 return QPointF(qreal(x / w), qreal(y / w));
767 }
768}
769
770inline QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
771{
772 qreal xin, yin;
773 qreal x, y, w;
774 xin = point.x();
775 yin = point.y();
776 if (matrix.flagBits == QMatrix4x4::Identity) {
777 return point;
778 } else if (matrix.flagBits == QMatrix4x4::Translation) {
779 return QPoint(qRound(xin + matrix.m[3][0]),
780 qRound(yin + matrix.m[3][1]));
781 } else if (matrix.flagBits ==
782 (QMatrix4x4::Translation | QMatrix4x4::Scale)) {
783 return QPoint(qRound(xin * matrix.m[0][0] + matrix.m[3][0]),
784 qRound(yin * matrix.m[1][1] + matrix.m[3][1]));
785 } else if (matrix.flagBits == QMatrix4x4::Scale) {
786 return QPoint(qRound(xin * matrix.m[0][0]),
787 qRound(yin * matrix.m[1][1]));
788 } else {
789 x = xin * matrix.m[0][0] +
790 yin * matrix.m[1][0] +
791 matrix.m[3][0];
792 y = xin * matrix.m[0][1] +
793 yin * matrix.m[1][1] +
794 matrix.m[3][1];
795 w = xin * matrix.m[0][3] +
796 yin * matrix.m[1][3] +
797 matrix.m[3][3];
798 if (w == 1.0f)
799 return QPoint(qRound(x), qRound(y));
800 else
801 return QPoint(qRound(x / w), qRound(y / w));
802 }
803}
804
805inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
806{
807 qreal xin, yin;
808 qreal x, y, w;
809 xin = point.x();
810 yin = point.y();
811 if (matrix.flagBits == QMatrix4x4::Identity) {
812 return point;
813 } else if (matrix.flagBits == QMatrix4x4::Translation) {
814 return QPointF(xin + matrix.m[3][0],
815 yin + matrix.m[3][1]);
816 } else if (matrix.flagBits ==
817 (QMatrix4x4::Translation | QMatrix4x4::Scale)) {
818 return QPointF(xin * matrix.m[0][0] + matrix.m[3][0],
819 yin * matrix.m[1][1] + matrix.m[3][1]);
820 } else if (matrix.flagBits == QMatrix4x4::Scale) {
821 return QPointF(xin * matrix.m[0][0],
822 yin * matrix.m[1][1]);
823 } else {
824 x = xin * matrix.m[0][0] +
825 yin * matrix.m[1][0] +
826 matrix.m[3][0];
827 y = xin * matrix.m[0][1] +
828 yin * matrix.m[1][1] +
829 matrix.m[3][1];
830 w = xin * matrix.m[0][3] +
831 yin * matrix.m[1][3] +
832 matrix.m[3][3];
833 if (w == 1.0f) {
834 return QPointF(qreal(x), qreal(y));
835 } else {
836 return QPointF(qreal(x / w), qreal(y / w));
837 }
838 }
839}
840
841inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
842{
843 QMatrix4x4 m(1);
844 m.m[0][0] = -matrix.m[0][0];
845 m.m[0][1] = -matrix.m[0][1];
846 m.m[0][2] = -matrix.m[0][2];
847 m.m[0][3] = -matrix.m[0][3];
848 m.m[1][0] = -matrix.m[1][0];
849 m.m[1][1] = -matrix.m[1][1];
850 m.m[1][2] = -matrix.m[1][2];
851 m.m[1][3] = -matrix.m[1][3];
852 m.m[2][0] = -matrix.m[2][0];
853 m.m[2][1] = -matrix.m[2][1];
854 m.m[2][2] = -matrix.m[2][2];
855 m.m[2][3] = -matrix.m[2][3];
856 m.m[3][0] = -matrix.m[3][0];
857 m.m[3][1] = -matrix.m[3][1];
858 m.m[3][2] = -matrix.m[3][2];
859 m.m[3][3] = -matrix.m[3][3];
860 return m;
861}
862
863inline QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix)
864{
865 QMatrix4x4 m(1);
866 m.m[0][0] = matrix.m[0][0] * factor;
867 m.m[0][1] = matrix.m[0][1] * factor;
868 m.m[0][2] = matrix.m[0][2] * factor;
869 m.m[0][3] = matrix.m[0][3] * factor;
870 m.m[1][0] = matrix.m[1][0] * factor;
871 m.m[1][1] = matrix.m[1][1] * factor;
872 m.m[1][2] = matrix.m[1][2] * factor;
873 m.m[1][3] = matrix.m[1][3] * factor;
874 m.m[2][0] = matrix.m[2][0] * factor;
875 m.m[2][1] = matrix.m[2][1] * factor;
876 m.m[2][2] = matrix.m[2][2] * factor;
877 m.m[2][3] = matrix.m[2][3] * factor;
878 m.m[3][0] = matrix.m[3][0] * factor;
879 m.m[3][1] = matrix.m[3][1] * factor;
880 m.m[3][2] = matrix.m[3][2] * factor;
881 m.m[3][3] = matrix.m[3][3] * factor;
882 return m;
883}
884
885inline QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor)
886{
887 QMatrix4x4 m(1);
888 m.m[0][0] = matrix.m[0][0] * factor;
889 m.m[0][1] = matrix.m[0][1] * factor;
890 m.m[0][2] = matrix.m[0][2] * factor;
891 m.m[0][3] = matrix.m[0][3] * factor;
892 m.m[1][0] = matrix.m[1][0] * factor;
893 m.m[1][1] = matrix.m[1][1] * factor;
894 m.m[1][2] = matrix.m[1][2] * factor;
895 m.m[1][3] = matrix.m[1][3] * factor;
896 m.m[2][0] = matrix.m[2][0] * factor;
897 m.m[2][1] = matrix.m[2][1] * factor;
898 m.m[2][2] = matrix.m[2][2] * factor;
899 m.m[2][3] = matrix.m[2][3] * factor;
900 m.m[3][0] = matrix.m[3][0] * factor;
901 m.m[3][1] = matrix.m[3][1] * factor;
902 m.m[3][2] = matrix.m[3][2] * factor;
903 m.m[3][3] = matrix.m[3][3] * factor;
904 return m;
905}
906
907inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
908{
909 return qFuzzyCompare(m1.m[0][0], m2.m[0][0]) &&
910 qFuzzyCompare(m1.m[0][1], m2.m[0][1]) &&
911 qFuzzyCompare(m1.m[0][2], m2.m[0][2]) &&
912 qFuzzyCompare(m1.m[0][3], m2.m[0][3]) &&
913 qFuzzyCompare(m1.m[1][0], m2.m[1][0]) &&
914 qFuzzyCompare(m1.m[1][1], m2.m[1][1]) &&
915 qFuzzyCompare(m1.m[1][2], m2.m[1][2]) &&
916 qFuzzyCompare(m1.m[1][3], m2.m[1][3]) &&
917 qFuzzyCompare(m1.m[2][0], m2.m[2][0]) &&
918 qFuzzyCompare(m1.m[2][1], m2.m[2][1]) &&
919 qFuzzyCompare(m1.m[2][2], m2.m[2][2]) &&
920 qFuzzyCompare(m1.m[2][3], m2.m[2][3]) &&
921 qFuzzyCompare(m1.m[3][0], m2.m[3][0]) &&
922 qFuzzyCompare(m1.m[3][1], m2.m[3][1]) &&
923 qFuzzyCompare(m1.m[3][2], m2.m[3][2]) &&
924 qFuzzyCompare(m1.m[3][3], m2.m[3][3]);
925}
926
927inline QPoint QMatrix4x4::map(const QPoint& point) const
928{
929 return *this * point;
930}
931
932inline QPointF QMatrix4x4::map(const QPointF& point) const
933{
934 return *this * point;
935}
936
937#ifndef QT_NO_VECTOR3D
938
939inline QVector3D QMatrix4x4::map(const QVector3D& point) const
940{
941 return *this * point;
942}
943
944inline QVector3D QMatrix4x4::mapVector(const QVector3D& vector) const
945{
946 if (flagBits == Identity || flagBits == Translation) {
947 return vector;
948 } else if (flagBits == Scale || flagBits == (Translation | Scale)) {
949 return QVector3D(vector.x() * m[0][0],
950 vector.y() * m[1][1],
951 vector.z() * m[2][2]);
952 } else {
953 return QVector3D(vector.x() * m[0][0] +
954 vector.y() * m[1][0] +
955 vector.z() * m[2][0],
956 vector.x() * m[0][1] +
957 vector.y() * m[1][1] +
958 vector.z() * m[2][1],
959 vector.x() * m[0][2] +
960 vector.y() * m[1][2] +
961 vector.z() * m[2][2]);
962 }
963}
964
965#endif
966
967#ifndef QT_NO_VECTOR4D
968
969inline QVector4D QMatrix4x4::map(const QVector4D& point) const
970{
971 return *this * point;
972}
973
974#endif
975
976inline qreal *QMatrix4x4::data()
977{
978 // We have to assume that the caller will modify the matrix elements,
979 // so we flip it over to "General" mode.
980 flagBits = General;
981 return m[0];
982}
983
984#ifndef QT_NO_DEBUG_STREAM
985Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
986#endif
987
988#ifndef QT_NO_DATASTREAM
989Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &);
990Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &);
991#endif
992
993template <int N, int M>
994QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal>& matrix)
995{
996 return QMatrix4x4(matrix.constData(), N, M);
997}
998
999template <int N, int M>
1000QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
1001{
1002 QGenericMatrix<N, M, qreal> result;
1003 const qreal *m = matrix.constData();
1004 qreal *values = result.data();
1005 for (int col = 0; col < N; ++col) {
1006 for (int row = 0; row < M; ++row) {
1007 if (col < 4 && row < 4)
1008 values[col * M + row] = m[col * 4 + row];
1009 else if (col == row)
1010 values[col * M + row] = 1.0f;
1011 else
1012 values[col * M + row] = 0.0f;
1013 }
1014 }
1015 return result;
1016}
1017
1018#endif
1019
1020QT_END_NAMESPACE
1021
1022QT_END_HEADER
1023
1024#endif
Note: See TracBrowser for help on using the repository browser.