QtGui/qmatrix4x4.h Source File

qmatrix4x4.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
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 
52 
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:
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>
75 
76  QMatrix4x4(const qreal *values, int cols, int rows);
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();
176  inline const qreal *data() const { return *m; }
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.
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 
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>
225 Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
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>
244 {
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
923 inline QPoint QMatrix4x4::map(const QPoint& point) const
924 {
925  return *this * point;
926 }
927 
928 inline QPointF QMatrix4x4::map(const QPointF& point) const
929 {
930  return *this * point;
931 }
932 
933 #ifndef QT_NO_VECTOR3D
934 
935 inline QVector3D QMatrix4x4::map(const QVector3D& point) const
936 {
937  return *this * point;
938 }
939 
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 
965 inline QVector4D QMatrix4x4::map(const QVector4D& point) const
966 {
967  return *this * point;
968 }
969 
970 #endif
971 
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>
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>
997 QT_DEPRECATED QGenericMatrix<N, M, qreal> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
998 {
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 
1019 
1021 
1022 #endif
QMatrix4x4 & operator*=(const QMatrix4x4 &other)
Definition: qmatrix4x4.h:410
GLuint GLenum matrix
Definition: GLee.h:6572
bool operator==(const QMatrix4x4 &other) const
Definition: qmatrix4x4.h:445
GLenum GLint GLint y
Definition: GLee.h:876
#define QT_END_NAMESPACE
Definition: qglobal.h:128
GLdouble GLdouble z
Definition: GLee.h:1393
QByteArray & operator+=(QByteArray &a, const QStringBuilder< A, B > &b)
#define QT_BEGIN_HEADER
Definition: qglobal.h:141
QFuture< void > map(Sequence &sequence, MapFunctor map)
bool qFuzzyCompare(const QMatrix4x4 &m1, const QMatrix4x4 &m2)
Definition: qmatrix4x4.h:903
const qreal & operator()(int row, int column) const
Definition: qmatrix4x4.h:260
bool operator!=(const QMatrix4x4 &other) const
Definition: qmatrix4x4.h:465
QVector4D row(int index) const
Definition: qmatrix4x4.h:289
void fill(qreal value)
Definition: qmatrix4x4.h:345
QPoint map(const QPoint &point) const
Definition: qmatrix4x4.h:923
qreal x() const
Definition: qvector4d.h:158
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
Definition: qdebug.h:62
Q_DECLARE_TYPEINFO(QMatrix4x4, Q_MOVABLE_TYPE)
const qreal * constData() const
Definition: qmatrix4x4.h:177
bool operator==(const Attribute &cA, const AttributeInstance< type > &cB)
This operator compares the two attributes and NOT their values.
Definition: node.h:577
Definition: qpoint.h:53
qreal y() const
Definition: qpoint.h:287
qreal w() const
Definition: qvector4d.h:161
int y() const
Definition: qpoint.h:131
qreal y() const
Definition: qvector4d.h:159
GLenum GLenum GLvoid * row
Definition: GLee.h:893
void setRow(int index, const QVector4D &value)
Definition: qmatrix4x4.h:295
void setToIdentity()
Definition: qmatrix4x4.h:324
#define QT_BEGIN_NAMESPACE
Definition: qglobal.h:127
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: GLee.h:880
QGenericMatrix< N, M, qreal > toGenericMatrix() const
Definition: qmatrix4x4.h:243
bool isIdentity() const
Definition: qmatrix4x4.h:307
qreal z() const
Definition: qvector4d.h:160
Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4 &matrix, qreal divisor)
QMatrix4x4 operator+(const QMatrix4x4 &m1, const QMatrix4x4 &m2)
Definition: qmatrix4x4.h:485
GLuint GLenum GLenum transform
Definition: GLee.h:6572
qreal x() const
Definition: qvector3d.h:161
GLenum GLint x
Definition: GLee.h:876
QMatrix4x4 & operator-=(const QMatrix4x4 &other)
Definition: qmatrix4x4.h:388
Q_CORE_EXPORT QTextStream & center(QTextStream &s)
qreal * data()
Definition: qmatrix4x4.h:972
bool operator!=(const QByteArray &a1, const QByteArray &a2)
Definition: qbytearray.h:533
qreal y() const
Definition: qvector3d.h:162
qreal x() const
Definition: qpoint.h:282
qreal z() const
Definition: qvector3d.h:163
QVector3D mapVector(const QVector3D &vector) const
Definition: qmatrix4x4.h:940
GLsizei const GLfloat * value
Definition: GLee.h:1742
Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m)
Definition: qrect.h:58
Definition: qrect.h:511
GLenum GLenum GLvoid GLvoid * column
Definition: GLee.h:893
Q_GUI_EXPORT QDataStream & operator>>(QDataStream &, QMatrix4x4 &)
void setColumn(int index, const QVector4D &value)
Definition: qmatrix4x4.h:279
int x() const
Definition: qpoint.h:128
QMatrix4x4 operator-(const QMatrix4x4 &m1, const QMatrix4x4 &m2)
Definition: qmatrix4x4.h:507
const qreal * data() const
Definition: qmatrix4x4.h:176
QMatrix4x4 operator*(const QMatrix4x4 &m1, const QMatrix4x4 &m2)
Definition: qmatrix4x4.h:529
QVector4D column(int index) const
Definition: qmatrix4x4.h:273
GLubyte GLubyte GLubyte GLubyte w
Definition: GLee.h:1775
GLboolean GLenum GLenum GLvoid * values
Definition: GLee.h:895
GLXDrawable int64_t int64_t divisor
Definition: GLee.h:10690
GLenum GLenum GLenum GLenum GLenum scale
Definition: GLee.h:5777
QMatrix4x4 & operator+=(const QMatrix4x4 &other)
Definition: qmatrix4x4.h:366
Q_CORE_EXPORT QTextStream & left(QTextStream &s)
#define QT_END_HEADER
Definition: qglobal.h:142
GLclampf f
Definition: GLee.h:9303
const T * constData() const
GLuint index
Definition: GLee.h:1704