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

Last change on this file since 858 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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