Qt 4.8
qmatrix4x4.cpp
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 #include "qmatrix4x4.h"
43 #include <QtCore/qmath.h>
44 #include <QtCore/qvariant.h>
45 #include <QtGui/qmatrix.h>
46 #include <QtGui/qtransform.h>
47 
49 
50 #ifndef QT_NO_MATRIX4X4
51 
64 static const qreal inv_dist_to_plane = 1. / 1024.;
65 
88 {
89  for (int row = 0; row < 4; ++row)
90  for (int col = 0; col < 4; ++col)
91  m[col][row] = values[row * 4 + col];
92  flagBits = General;
93 }
94 
175 QMatrix4x4::QMatrix4x4(const qreal *values, int cols, int rows)
176 {
177  for (int col = 0; col < 4; ++col) {
178  for (int row = 0; row < 4; ++row) {
179  if (col < cols && row < rows)
180  m[col][row] = values[col * rows + row];
181  else if (col == row)
182  m[col][row] = 1.0f;
183  else
184  m[col][row] = 0.0f;
185  }
186  }
187  flagBits = General;
188 }
189 
202 {
203  m[0][0] = matrix.m11();
204  m[0][1] = matrix.m12();
205  m[0][2] = 0.0f;
206  m[0][3] = 0.0f;
207  m[1][0] = matrix.m21();
208  m[1][1] = matrix.m22();
209  m[1][2] = 0.0f;
210  m[1][3] = 0.0f;
211  m[2][0] = 0.0f;
212  m[2][1] = 0.0f;
213  m[2][2] = 1.0f;
214  m[2][3] = 0.0f;
215  m[3][0] = matrix.dx();
216  m[3][1] = matrix.dy();
217  m[3][2] = 0.0f;
218  m[3][3] = 1.0f;
219  flagBits = General;
220 }
221 
234 {
235  m[0][0] = transform.m11();
236  m[0][1] = transform.m12();
237  m[0][2] = 0.0f;
238  m[0][3] = transform.m13();
239  m[1][0] = transform.m21();
240  m[1][1] = transform.m22();
241  m[1][2] = 0.0f;
242  m[1][3] = transform.m23();
243  m[2][0] = 0.0f;
244  m[2][1] = 0.0f;
245  m[2][2] = 1.0f;
246  m[2][3] = 0.0f;
247  m[3][0] = transform.dx();
248  m[3][1] = transform.dy();
249  m[3][2] = 0.0f;
250  m[3][3] = transform.m33();
251  flagBits = General;
252 }
253 
353 // The 4x4 matrix inverse algorithm is based on that described at:
354 // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q24
355 // Some optimization has been done to avoid making copies of 3x3
356 // sub-matrices and to unroll the loops.
357 
358 // Calculate the determinant of a 3x3 sub-matrix.
359 // | A B C |
360 // M = | D E F | det(M) = A * (EI - HF) - B * (DI - GF) + C * (DH - GE)
361 // | G H I |
362 static inline qreal matrixDet3
363  (const qreal m[4][4], int col0, int col1, int col2,
364  int row0, int row1, int row2)
365 {
366  return m[col0][row0] *
367  (m[col1][row1] * m[col2][row2] -
368  m[col1][row2] * m[col2][row1]) -
369  m[col1][row0] *
370  (m[col0][row1] * m[col2][row2] -
371  m[col0][row2] * m[col2][row1]) +
372  m[col2][row0] *
373  (m[col0][row1] * m[col1][row2] -
374  m[col0][row2] * m[col1][row1]);
375 }
376 
377 // Calculate the determinant of a 4x4 matrix.
378 static inline qreal matrixDet4(const qreal m[4][4])
379 {
380  qreal det;
381  det = m[0][0] * matrixDet3(m, 1, 2, 3, 1, 2, 3);
382  det -= m[1][0] * matrixDet3(m, 0, 2, 3, 1, 2, 3);
383  det += m[2][0] * matrixDet3(m, 0, 1, 3, 1, 2, 3);
384  det -= m[3][0] * matrixDet3(m, 0, 1, 2, 1, 2, 3);
385  return det;
386 }
387 
392 {
393  return qreal(matrixDet4(m));
394 }
395 
408 QMatrix4x4 QMatrix4x4::inverted(bool *invertible) const
409 {
410  // Handle some of the easy cases first.
411  if (flagBits == Identity) {
412  if (invertible)
413  *invertible = true;
414  return QMatrix4x4();
415  } else if (flagBits == Translation) {
416  QMatrix4x4 inv;
417  inv.m[3][0] = -m[3][0];
418  inv.m[3][1] = -m[3][1];
419  inv.m[3][2] = -m[3][2];
420  inv.flagBits = Translation;
421  if (invertible)
422  *invertible = true;
423  return inv;
424  } else if (flagBits == Rotation || flagBits == (Rotation | Translation)) {
425  if (invertible)
426  *invertible = true;
427  return orthonormalInverse();
428  }
429 
430  QMatrix4x4 inv(1); // The "1" says to not load the identity.
431 
432  qreal det = matrixDet4(m);
433  if (det == 0.0f) {
434  if (invertible)
435  *invertible = false;
436  return QMatrix4x4();
437  }
438  det = 1.0f / det;
439 
440  inv.m[0][0] = matrixDet3(m, 1, 2, 3, 1, 2, 3) * det;
441  inv.m[0][1] = -matrixDet3(m, 0, 2, 3, 1, 2, 3) * det;
442  inv.m[0][2] = matrixDet3(m, 0, 1, 3, 1, 2, 3) * det;
443  inv.m[0][3] = -matrixDet3(m, 0, 1, 2, 1, 2, 3) * det;
444  inv.m[1][0] = -matrixDet3(m, 1, 2, 3, 0, 2, 3) * det;
445  inv.m[1][1] = matrixDet3(m, 0, 2, 3, 0, 2, 3) * det;
446  inv.m[1][2] = -matrixDet3(m, 0, 1, 3, 0, 2, 3) * det;
447  inv.m[1][3] = matrixDet3(m, 0, 1, 2, 0, 2, 3) * det;
448  inv.m[2][0] = matrixDet3(m, 1, 2, 3, 0, 1, 3) * det;
449  inv.m[2][1] = -matrixDet3(m, 0, 2, 3, 0, 1, 3) * det;
450  inv.m[2][2] = matrixDet3(m, 0, 1, 3, 0, 1, 3) * det;
451  inv.m[2][3] = -matrixDet3(m, 0, 1, 2, 0, 1, 3) * det;
452  inv.m[3][0] = -matrixDet3(m, 1, 2, 3, 0, 1, 2) * det;
453  inv.m[3][1] = matrixDet3(m, 0, 2, 3, 0, 1, 2) * det;
454  inv.m[3][2] = -matrixDet3(m, 0, 1, 3, 0, 1, 2) * det;
455  inv.m[3][3] = matrixDet3(m, 0, 1, 2, 0, 1, 2) * det;
456 
457  if (invertible)
458  *invertible = true;
459  return inv;
460 }
461 
471 {
472  QMatrix3x3 inv;
473 
474  // Handle the simple cases first.
475  if (flagBits == Identity || flagBits == Translation) {
476  return inv;
477  } else if (flagBits == Scale || flagBits == (Translation | Scale)) {
478  if (m[0][0] == 0.0f || m[1][1] == 0.0f || m[2][2] == 0.0f)
479  return inv;
480  inv.data()[0] = 1.0f / m[0][0];
481  inv.data()[4] = 1.0f / m[1][1];
482  inv.data()[8] = 1.0f / m[2][2];
483  return inv;
484  }
485 
486  qreal det = matrixDet3(m, 0, 1, 2, 0, 1, 2);
487  if (det == 0.0f)
488  return inv;
489  det = 1.0f / det;
490 
491  qreal *invm = inv.data();
492 
493  // Invert and transpose in a single step.
494  invm[0 + 0 * 3] = (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * det;
495  invm[1 + 0 * 3] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) * det;
496  invm[2 + 0 * 3] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * det;
497  invm[0 + 1 * 3] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * det;
498  invm[1 + 1 * 3] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * det;
499  invm[2 + 1 * 3] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) * det;
500  invm[0 + 2 * 3] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * det;
501  invm[1 + 2 * 3] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) * det;
502  invm[2 + 2 * 3] = (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * det;
503 
504  return inv;
505 }
506 
511 {
512  QMatrix4x4 result(1); // The "1" says to not load the identity.
513  for (int row = 0; row < 4; ++row) {
514  for (int col = 0; col < 4; ++col) {
515  result.m[col][row] = m[row][col];
516  }
517  }
518  return result;
519 }
520 
561 {
562  m[0][0] /= divisor;
563  m[0][1] /= divisor;
564  m[0][2] /= divisor;
565  m[0][3] /= divisor;
566  m[1][0] /= divisor;
567  m[1][1] /= divisor;
568  m[1][2] /= divisor;
569  m[1][3] /= divisor;
570  m[2][0] /= divisor;
571  m[2][1] /= divisor;
572  m[2][2] /= divisor;
573  m[2][3] /= divisor;
574  m[3][0] /= divisor;
575  m[3][1] /= divisor;
576  m[3][2] /= divisor;
577  m[3][3] /= divisor;
578  flagBits = General;
579  return *this;
580 }
581 
629 #ifndef QT_NO_VECTOR3D
630 
647 #endif
648 
649 #ifndef QT_NO_VECTOR4D
650 
667 #endif
668 
734 QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor)
735 {
736  QMatrix4x4 m(1); // The "1" says to not load the identity.
737  m.m[0][0] = matrix.m[0][0] / divisor;
738  m.m[0][1] = matrix.m[0][1] / divisor;
739  m.m[0][2] = matrix.m[0][2] / divisor;
740  m.m[0][3] = matrix.m[0][3] / divisor;
741  m.m[1][0] = matrix.m[1][0] / divisor;
742  m.m[1][1] = matrix.m[1][1] / divisor;
743  m.m[1][2] = matrix.m[1][2] / divisor;
744  m.m[1][3] = matrix.m[1][3] / divisor;
745  m.m[2][0] = matrix.m[2][0] / divisor;
746  m.m[2][1] = matrix.m[2][1] / divisor;
747  m.m[2][2] = matrix.m[2][2] / divisor;
748  m.m[2][3] = matrix.m[2][3] / divisor;
749  m.m[3][0] = matrix.m[3][0] / divisor;
750  m.m[3][1] = matrix.m[3][1] / divisor;
751  m.m[3][2] = matrix.m[3][2] / divisor;
752  m.m[3][3] = matrix.m[3][3] / divisor;
753  return m;
754 }
755 
767 #ifndef QT_NO_VECTOR3D
768 
775 void QMatrix4x4::scale(const QVector3D& vector)
776 {
777  qreal vx = vector.x();
778  qreal vy = vector.y();
779  qreal vz = vector.z();
780  if (flagBits == Identity) {
781  m[0][0] = vx;
782  m[1][1] = vy;
783  m[2][2] = vz;
784  flagBits = Scale;
785  } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
786  m[0][0] *= vx;
787  m[1][1] *= vy;
788  m[2][2] *= vz;
789  } else if (flagBits == Translation) {
790  m[0][0] = vx;
791  m[1][1] = vy;
792  m[2][2] = vz;
793  flagBits |= Scale;
794  } else {
795  m[0][0] *= vx;
796  m[0][1] *= vx;
797  m[0][2] *= vx;
798  m[0][3] *= vx;
799  m[1][0] *= vy;
800  m[1][1] *= vy;
801  m[1][2] *= vy;
802  m[1][3] *= vy;
803  m[2][0] *= vz;
804  m[2][1] *= vz;
805  m[2][2] *= vz;
806  m[2][3] *= vz;
807  flagBits = General;
808  }
809 }
810 #endif
811 
824 {
825  if (flagBits == Identity) {
826  m[0][0] = x;
827  m[1][1] = y;
828  flagBits = Scale;
829  } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
830  m[0][0] *= x;
831  m[1][1] *= y;
832  } else if (flagBits == Translation) {
833  m[0][0] = x;
834  m[1][1] = y;
835  flagBits |= Scale;
836  } else {
837  m[0][0] *= x;
838  m[0][1] *= x;
839  m[0][2] *= x;
840  m[0][3] *= x;
841  m[1][0] *= y;
842  m[1][1] *= y;
843  m[1][2] *= y;
844  m[1][3] *= y;
845  flagBits = General;
846  }
847 }
848 
861 {
862  if (flagBits == Identity) {
863  m[0][0] = x;
864  m[1][1] = y;
865  m[2][2] = z;
866  flagBits = Scale;
867  } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
868  m[0][0] *= x;
869  m[1][1] *= y;
870  m[2][2] *= z;
871  } else if (flagBits == Translation) {
872  m[0][0] = x;
873  m[1][1] = y;
874  m[2][2] = z;
875  flagBits |= Scale;
876  } else {
877  m[0][0] *= x;
878  m[0][1] *= x;
879  m[0][2] *= x;
880  m[0][3] *= x;
881  m[1][0] *= y;
882  m[1][1] *= y;
883  m[1][2] *= y;
884  m[1][3] *= y;
885  m[2][0] *= z;
886  m[2][1] *= z;
887  m[2][2] *= z;
888  m[2][3] *= z;
889  flagBits = General;
890  }
891 }
892 
905 {
906  if (flagBits == Identity) {
907  m[0][0] = factor;
908  m[1][1] = factor;
909  m[2][2] = factor;
910  flagBits = Scale;
911  } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
912  m[0][0] *= factor;
913  m[1][1] *= factor;
914  m[2][2] *= factor;
915  } else if (flagBits == Translation) {
916  m[0][0] = factor;
917  m[1][1] = factor;
918  m[2][2] = factor;
919  flagBits |= Scale;
920  } else {
921  m[0][0] *= factor;
922  m[0][1] *= factor;
923  m[0][2] *= factor;
924  m[0][3] *= factor;
925  m[1][0] *= factor;
926  m[1][1] *= factor;
927  m[1][2] *= factor;
928  m[1][3] *= factor;
929  m[2][0] *= factor;
930  m[2][1] *= factor;
931  m[2][2] *= factor;
932  m[2][3] *= factor;
933  flagBits = General;
934  }
935 }
936 
937 #ifndef QT_NO_VECTOR3D
938 
944 void QMatrix4x4::translate(const QVector3D& vector)
945 {
946  qreal vx = vector.x();
947  qreal vy = vector.y();
948  qreal vz = vector.z();
949  if (flagBits == Identity) {
950  m[3][0] = vx;
951  m[3][1] = vy;
952  m[3][2] = vz;
954  } else if (flagBits == Translation) {
955  m[3][0] += vx;
956  m[3][1] += vy;
957  m[3][2] += vz;
958  } else if (flagBits == Scale) {
959  m[3][0] = m[0][0] * vx;
960  m[3][1] = m[1][1] * vy;
961  m[3][2] = m[2][2] * vz;
963  } else if (flagBits == (Scale | Translation)) {
964  m[3][0] += m[0][0] * vx;
965  m[3][1] += m[1][1] * vy;
966  m[3][2] += m[2][2] * vz;
967  } else {
968  m[3][0] += m[0][0] * vx + m[1][0] * vy + m[2][0] * vz;
969  m[3][1] += m[0][1] * vx + m[1][1] * vy + m[2][1] * vz;
970  m[3][2] += m[0][2] * vx + m[1][2] * vy + m[2][2] * vz;
971  m[3][3] += m[0][3] * vx + m[1][3] * vy + m[2][3] * vz;
972  if (flagBits == Rotation)
974  else if (flagBits != (Rotation | Translation))
975  flagBits = General;
976  }
977 }
978 
979 #endif
980 
993 {
994  if (flagBits == Identity) {
995  m[3][0] = x;
996  m[3][1] = y;
998  } else if (flagBits == Translation) {
999  m[3][0] += x;
1000  m[3][1] += y;
1001  } else if (flagBits == Scale) {
1002  m[3][0] = m[0][0] * x;
1003  m[3][1] = m[1][1] * y;
1004  m[3][2] = 0.;
1005  flagBits |= Translation;
1006  } else if (flagBits == (Scale | Translation)) {
1007  m[3][0] += m[0][0] * x;
1008  m[3][1] += m[1][1] * y;
1009  } else {
1010  m[3][0] += m[0][0] * x + m[1][0] * y;
1011  m[3][1] += m[0][1] * x + m[1][1] * y;
1012  m[3][2] += m[0][2] * x + m[1][2] * y;
1013  m[3][3] += m[0][3] * x + m[1][3] * y;
1014  if (flagBits == Rotation)
1015  flagBits |= Translation;
1016  else if (flagBits != (Rotation | Translation))
1017  flagBits = General;
1018  }
1019 }
1020 
1033 {
1034  if (flagBits == Identity) {
1035  m[3][0] = x;
1036  m[3][1] = y;
1037  m[3][2] = z;
1039  } else if (flagBits == Translation) {
1040  m[3][0] += x;
1041  m[3][1] += y;
1042  m[3][2] += z;
1043  } else if (flagBits == Scale) {
1044  m[3][0] = m[0][0] * x;
1045  m[3][1] = m[1][1] * y;
1046  m[3][2] = m[2][2] * z;
1047  flagBits |= Translation;
1048  } else if (flagBits == (Scale | Translation)) {
1049  m[3][0] += m[0][0] * x;
1050  m[3][1] += m[1][1] * y;
1051  m[3][2] += m[2][2] * z;
1052  } else {
1053  m[3][0] += m[0][0] * x + m[1][0] * y + m[2][0] * z;
1054  m[3][1] += m[0][1] * x + m[1][1] * y + m[2][1] * z;
1055  m[3][2] += m[0][2] * x + m[1][2] * y + m[2][2] * z;
1056  m[3][3] += m[0][3] * x + m[1][3] * y + m[2][3] * z;
1057  if (flagBits == Rotation)
1058  flagBits |= Translation;
1059  else if (flagBits != (Rotation | Translation))
1060  flagBits = General;
1061  }
1062 }
1063 
1064 #ifndef QT_NO_VECTOR3D
1065 
1073 {
1074  rotate(angle, vector.x(), vector.y(), vector.z());
1075 }
1076 
1077 #endif
1078 
1091 {
1092  if (angle == 0.0f)
1093  return;
1094  QMatrix4x4 m(1); // The "1" says to not load the identity.
1095  qreal c, s, ic;
1096  if (angle == 90.0f || angle == -270.0f) {
1097  s = 1.0f;
1098  c = 0.0f;
1099  } else if (angle == -90.0f || angle == 270.0f) {
1100  s = -1.0f;
1101  c = 0.0f;
1102  } else if (angle == 180.0f || angle == -180.0f) {
1103  s = 0.0f;
1104  c = -1.0f;
1105  } else {
1106  qreal a = angle * M_PI / 180.0f;
1107  c = qCos(a);
1108  s = qSin(a);
1109  }
1110  bool quick = false;
1111  if (x == 0.0f) {
1112  if (y == 0.0f) {
1113  if (z != 0.0f) {
1114  // Rotate around the Z axis.
1115  m.setToIdentity();
1116  m.m[0][0] = c;
1117  m.m[1][1] = c;
1118  if (z < 0.0f) {
1119  m.m[1][0] = s;
1120  m.m[0][1] = -s;
1121  } else {
1122  m.m[1][0] = -s;
1123  m.m[0][1] = s;
1124  }
1125  m.flagBits = General;
1126  quick = true;
1127  }
1128  } else if (z == 0.0f) {
1129  // Rotate around the Y axis.
1130  m.setToIdentity();
1131  m.m[0][0] = c;
1132  m.m[2][2] = c;
1133  if (y < 0.0f) {
1134  m.m[2][0] = -s;
1135  m.m[0][2] = s;
1136  } else {
1137  m.m[2][0] = s;
1138  m.m[0][2] = -s;
1139  }
1140  m.flagBits = General;
1141  quick = true;
1142  }
1143  } else if (y == 0.0f && z == 0.0f) {
1144  // Rotate around the X axis.
1145  m.setToIdentity();
1146  m.m[1][1] = c;
1147  m.m[2][2] = c;
1148  if (x < 0.0f) {
1149  m.m[2][1] = s;
1150  m.m[1][2] = -s;
1151  } else {
1152  m.m[2][1] = -s;
1153  m.m[1][2] = s;
1154  }
1155  m.flagBits = General;
1156  quick = true;
1157  }
1158  if (!quick) {
1159  qreal len = x * x + y * y + z * z;
1160  if (!qFuzzyIsNull(len - 1.0f) && !qFuzzyIsNull(len)) {
1161  len = qSqrt(len);
1162  x /= len;
1163  y /= len;
1164  z /= len;
1165  }
1166  ic = 1.0f - c;
1167  m.m[0][0] = x * x * ic + c;
1168  m.m[1][0] = x * y * ic - z * s;
1169  m.m[2][0] = x * z * ic + y * s;
1170  m.m[3][0] = 0.0f;
1171  m.m[0][1] = y * x * ic + z * s;
1172  m.m[1][1] = y * y * ic + c;
1173  m.m[2][1] = y * z * ic - x * s;
1174  m.m[3][1] = 0.0f;
1175  m.m[0][2] = x * z * ic - y * s;
1176  m.m[1][2] = y * z * ic + x * s;
1177  m.m[2][2] = z * z * ic + c;
1178  m.m[3][2] = 0.0f;
1179  m.m[0][3] = 0.0f;
1180  m.m[1][3] = 0.0f;
1181  m.m[2][3] = 0.0f;
1182  m.m[3][3] = 1.0f;
1183  }
1184  int flags = flagBits;
1185  *this *= m;
1186  if (flags != Identity)
1187  flagBits = flags | Rotation;
1188  else
1189  flagBits = Rotation;
1190 }
1191 
1196 {
1197  // Used by QGraphicsRotation::applyTo() to perform a rotation
1198  // and projection back to 2D in a single step.
1199  if (angle == 0.0f)
1200  return;
1201  QMatrix4x4 m(1); // The "1" says to not load the identity.
1202  qreal c, s, ic;
1203  if (angle == 90.0f || angle == -270.0f) {
1204  s = 1.0f;
1205  c = 0.0f;
1206  } else if (angle == -90.0f || angle == 270.0f) {
1207  s = -1.0f;
1208  c = 0.0f;
1209  } else if (angle == 180.0f || angle == -180.0f) {
1210  s = 0.0f;
1211  c = -1.0f;
1212  } else {
1213  qreal a = angle * M_PI / 180.0f;
1214  c = qCos(a);
1215  s = qSin(a);
1216  }
1217  bool quick = false;
1218  if (x == 0.0f) {
1219  if (y == 0.0f) {
1220  if (z != 0.0f) {
1221  // Rotate around the Z axis.
1222  m.setToIdentity();
1223  m.m[0][0] = c;
1224  m.m[1][1] = c;
1225  if (z < 0.0f) {
1226  m.m[1][0] = s;
1227  m.m[0][1] = -s;
1228  } else {
1229  m.m[1][0] = -s;
1230  m.m[0][1] = s;
1231  }
1232  m.flagBits = General;
1233  quick = true;
1234  }
1235  } else if (z == 0.0f) {
1236  // Rotate around the Y axis.
1237  m.setToIdentity();
1238  m.m[0][0] = c;
1239  m.m[2][2] = 1.0f;
1240  if (y < 0.0f) {
1241  m.m[0][3] = -s * inv_dist_to_plane;
1242  } else {
1243  m.m[0][3] = s * inv_dist_to_plane;
1244  }
1245  m.flagBits = General;
1246  quick = true;
1247  }
1248  } else if (y == 0.0f && z == 0.0f) {
1249  // Rotate around the X axis.
1250  m.setToIdentity();
1251  m.m[1][1] = c;
1252  m.m[2][2] = 1.0f;
1253  if (x < 0.0f) {
1254  m.m[1][3] = s * inv_dist_to_plane;
1255  } else {
1256  m.m[1][3] = -s * inv_dist_to_plane;
1257  }
1258  m.flagBits = General;
1259  quick = true;
1260  }
1261  if (!quick) {
1262  qreal len = x * x + y * y + z * z;
1263  if (!qFuzzyIsNull(len - 1.0f) && !qFuzzyIsNull(len)) {
1264  len = qSqrt(len);
1265  x /= len;
1266  y /= len;
1267  z /= len;
1268  }
1269  ic = 1.0f - c;
1270  m.m[0][0] = x * x * ic + c;
1271  m.m[1][0] = x * y * ic - z * s;
1272  m.m[2][0] = 0.0f;
1273  m.m[3][0] = 0.0f;
1274  m.m[0][1] = y * x * ic + z * s;
1275  m.m[1][1] = y * y * ic + c;
1276  m.m[2][1] = 0.0f;
1277  m.m[3][1] = 0.0f;
1278  m.m[0][2] = 0.0f;
1279  m.m[1][2] = 0.0f;
1280  m.m[2][2] = 1.0f;
1281  m.m[3][2] = 0.0f;
1282  m.m[0][3] = (x * z * ic - y * s) * -inv_dist_to_plane;
1283  m.m[1][3] = (y * z * ic + x * s) * -inv_dist_to_plane;
1284  m.m[2][3] = 0.0f;
1285  m.m[3][3] = 1.0f;
1286  }
1287  int flags = flagBits;
1288  *this *= m;
1289  if (flags != Identity)
1290  flagBits = flags | Rotation;
1291  else
1292  flagBits = Rotation;
1293 }
1294 
1295 #ifndef QT_NO_QUATERNION
1296 
1304 void QMatrix4x4::rotate(const QQuaternion& quaternion)
1305 {
1306  // Algorithm from:
1307  // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54
1308  QMatrix4x4 m(1);
1309  qreal xx = quaternion.x() * quaternion.x();
1310  qreal xy = quaternion.x() * quaternion.y();
1311  qreal xz = quaternion.x() * quaternion.z();
1312  qreal xw = quaternion.x() * quaternion.scalar();
1313  qreal yy = quaternion.y() * quaternion.y();
1314  qreal yz = quaternion.y() * quaternion.z();
1315  qreal yw = quaternion.y() * quaternion.scalar();
1316  qreal zz = quaternion.z() * quaternion.z();
1317  qreal zw = quaternion.z() * quaternion.scalar();
1318  m.m[0][0] = 1.0f - 2 * (yy + zz);
1319  m.m[1][0] = 2 * (xy - zw);
1320  m.m[2][0] = 2 * (xz + yw);
1321  m.m[3][0] = 0.0f;
1322  m.m[0][1] = 2 * (xy + zw);
1323  m.m[1][1] = 1.0f - 2 * (xx + zz);
1324  m.m[2][1] = 2 * (yz - xw);
1325  m.m[3][1] = 0.0f;
1326  m.m[0][2] = 2 * (xz - yw);
1327  m.m[1][2] = 2 * (yz + xw);
1328  m.m[2][2] = 1.0f - 2 * (xx + yy);
1329  m.m[3][2] = 0.0f;
1330  m.m[0][3] = 0.0f;
1331  m.m[1][3] = 0.0f;
1332  m.m[2][3] = 0.0f;
1333  m.m[3][3] = 1.0f;
1334  int flags = flagBits;
1335  *this *= m;
1336  if (flags != Identity)
1337  flagBits = flags | Rotation;
1338  else
1339  flagBits = Rotation;
1340 }
1341 
1342 #endif
1343 
1356 void QMatrix4x4::ortho(const QRect& rect)
1357 {
1358  // Note: rect.right() and rect.bottom() subtract 1 in QRect,
1359  // which gives the location of a pixel within the rectangle,
1360  // instead of the extent of the rectangle. We want the extent.
1361  // QRectF expresses the extent properly.
1362  ortho(rect.x(), rect.x() + rect.width(), rect.y() + rect.height(), rect.y(), -1.0f, 1.0f);
1363 }
1364 
1377 void QMatrix4x4::ortho(const QRectF& rect)
1378 {
1379  ortho(rect.left(), rect.right(), rect.bottom(), rect.top(), -1.0f, 1.0f);
1380 }
1381 
1390 void QMatrix4x4::ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
1391 {
1392  // Bail out if the projection volume is zero-sized.
1393  if (left == right || bottom == top || nearPlane == farPlane)
1394  return;
1395 
1396  // Construct the projection.
1397  qreal width = right - left;
1398  qreal invheight = top - bottom;
1399  qreal clip = farPlane - nearPlane;
1400 #ifndef QT_NO_VECTOR3D
1401  if (clip == 2.0f && (nearPlane + farPlane) == 0.0f) {
1402  // We can express this projection as a translate and scale
1403  // which will be more efficient to modify with further
1404  // transformations than producing a "General" matrix.
1406  (-(left + right) / width,
1407  -(top + bottom) / invheight,
1408  0.0f));
1410  (2.0f / width,
1411  2.0f / invheight,
1412  -1.0f));
1413  return;
1414  }
1415 #endif
1416  QMatrix4x4 m(1);
1417  m.m[0][0] = 2.0f / width;
1418  m.m[1][0] = 0.0f;
1419  m.m[2][0] = 0.0f;
1420  m.m[3][0] = -(left + right) / width;
1421  m.m[0][1] = 0.0f;
1422  m.m[1][1] = 2.0f / invheight;
1423  m.m[2][1] = 0.0f;
1424  m.m[3][1] = -(top + bottom) / invheight;
1425  m.m[0][2] = 0.0f;
1426  m.m[1][2] = 0.0f;
1427  m.m[2][2] = -2.0f / clip;
1428  m.m[3][2] = -(nearPlane + farPlane) / clip;
1429  m.m[0][3] = 0.0f;
1430  m.m[1][3] = 0.0f;
1431  m.m[2][3] = 0.0f;
1432  m.m[3][3] = 1.0f;
1433 
1434  // Apply the projection.
1435  *this *= m;
1436  return;
1437 }
1438 
1447 void QMatrix4x4::frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
1448 {
1449  // Bail out if the projection volume is zero-sized.
1450  if (left == right || bottom == top || nearPlane == farPlane)
1451  return;
1452 
1453  // Construct the projection.
1454  QMatrix4x4 m(1);
1455  qreal width = right - left;
1456  qreal invheight = top - bottom;
1457  qreal clip = farPlane - nearPlane;
1458  m.m[0][0] = 2.0f * nearPlane / width;
1459  m.m[1][0] = 0.0f;
1460  m.m[2][0] = (left + right) / width;
1461  m.m[3][0] = 0.0f;
1462  m.m[0][1] = 0.0f;
1463  m.m[1][1] = 2.0f * nearPlane / invheight;
1464  m.m[2][1] = (top + bottom) / invheight;
1465  m.m[3][1] = 0.0f;
1466  m.m[0][2] = 0.0f;
1467  m.m[1][2] = 0.0f;
1468  m.m[2][2] = -(nearPlane + farPlane) / clip;
1469  m.m[3][2] = -2.0f * nearPlane * farPlane / clip;
1470  m.m[0][3] = 0.0f;
1471  m.m[1][3] = 0.0f;
1472  m.m[2][3] = -1.0f;
1473  m.m[3][3] = 0.0f;
1474 
1475  // Apply the projection.
1476  *this *= m;
1477 }
1478 
1487 void QMatrix4x4::perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane)
1488 {
1489  // Bail out if the projection volume is zero-sized.
1490  if (nearPlane == farPlane || aspect == 0.0f)
1491  return;
1492 
1493  // Construct the projection.
1494  QMatrix4x4 m(1);
1495  qreal radians = (angle / 2.0f) * M_PI / 180.0f;
1496  qreal sine = qSin(radians);
1497  if (sine == 0.0f)
1498  return;
1499  qreal cotan = qCos(radians) / sine;
1500  qreal clip = farPlane - nearPlane;
1501  m.m[0][0] = cotan / aspect;
1502  m.m[1][0] = 0.0f;
1503  m.m[2][0] = 0.0f;
1504  m.m[3][0] = 0.0f;
1505  m.m[0][1] = 0.0f;
1506  m.m[1][1] = cotan;
1507  m.m[2][1] = 0.0f;
1508  m.m[3][1] = 0.0f;
1509  m.m[0][2] = 0.0f;
1510  m.m[1][2] = 0.0f;
1511  m.m[2][2] = -(nearPlane + farPlane) / clip;
1512  m.m[3][2] = -(2.0f * nearPlane * farPlane) / clip;
1513  m.m[0][3] = 0.0f;
1514  m.m[1][3] = 0.0f;
1515  m.m[2][3] = -1.0f;
1516  m.m[3][3] = 0.0f;
1517 
1518  // Apply the projection.
1519  *this *= m;
1520 }
1521 
1522 #ifndef QT_NO_VECTOR3D
1523 
1530 void QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up)
1531 {
1532  QVector3D forward = (center - eye).normalized();
1533  QVector3D side = QVector3D::crossProduct(forward, up).normalized();
1534  QVector3D upVector = QVector3D::crossProduct(side, forward);
1535 
1536  QMatrix4x4 m(1);
1537 
1538  m.m[0][0] = side.x();
1539  m.m[1][0] = side.y();
1540  m.m[2][0] = side.z();
1541  m.m[3][0] = 0.0f;
1542  m.m[0][1] = upVector.x();
1543  m.m[1][1] = upVector.y();
1544  m.m[2][1] = upVector.z();
1545  m.m[3][1] = 0.0f;
1546  m.m[0][2] = -forward.x();
1547  m.m[1][2] = -forward.y();
1548  m.m[2][2] = -forward.z();
1549  m.m[3][2] = 0.0f;
1550  m.m[0][3] = 0.0f;
1551  m.m[1][3] = 0.0f;
1552  m.m[2][3] = 0.0f;
1553  m.m[3][3] = 1.0f;
1554 
1555  *this *= m;
1556  translate(-eye);
1557 }
1558 
1559 #endif
1560 
1570 {
1571  if (flagBits == Scale || flagBits == (Scale | Translation)) {
1572  m[1][1] = -m[1][1];
1573  m[2][2] = -m[2][2];
1574  } else if (flagBits == Translation) {
1575  m[1][1] = -m[1][1];
1576  m[2][2] = -m[2][2];
1577  flagBits |= Scale;
1578  } else if (flagBits == Identity) {
1579  m[1][1] = -1.0f;
1580  m[2][2] = -1.0f;
1581  flagBits = Scale;
1582  } else {
1583  m[1][0] = -m[1][0];
1584  m[1][1] = -m[1][1];
1585  m[1][2] = -m[1][2];
1586  m[1][3] = -m[1][3];
1587  m[2][0] = -m[2][0];
1588  m[2][1] = -m[2][1];
1589  m[2][2] = -m[2][2];
1590  m[2][3] = -m[2][3];
1591  flagBits = General;
1592  }
1593 }
1594 
1600 {
1601  for (int row = 0; row < 4; ++row)
1602  for (int col = 0; col < 4; ++col)
1603  values[row * 4 + col] = qreal(m[col][row]);
1604 }
1605 
1614 {
1615  return QMatrix(m[0][0], m[0][1],
1616  m[1][0], m[1][1],
1617  m[3][0], m[3][1]);
1618 }
1619 
1632 {
1633  return QTransform(m[0][0], m[0][1], m[0][3],
1634  m[1][0], m[1][1], m[1][3],
1635  m[3][0], m[3][1], m[3][3]);
1636 }
1637 
1656 {
1657  if (distanceToPlane == 1024.0f) {
1658  // Optimize the common case with constants.
1659  return QTransform(m[0][0], m[0][1],
1660  m[0][3] - m[0][2] * inv_dist_to_plane,
1661  m[1][0], m[1][1],
1662  m[1][3] - m[1][2] * inv_dist_to_plane,
1663  m[3][0], m[3][1],
1664  m[3][3] - m[3][2] * inv_dist_to_plane);
1665  } else if (distanceToPlane != 0.0f) {
1666  // The following projection matrix is pre-multiplied with "matrix":
1667  // | 1 0 0 0 |
1668  // | 0 1 0 0 |
1669  // | 0 0 1 0 |
1670  // | 0 0 d 1 |
1671  // where d = -1 / distanceToPlane. After projection, row 3 and
1672  // column 3 are dropped to form the final QTransform.
1673  qreal d = 1.0f / distanceToPlane;
1674  return QTransform(m[0][0], m[0][1], m[0][3] - m[0][2] * d,
1675  m[1][0], m[1][1], m[1][3] - m[1][2] * d,
1676  m[3][0], m[3][1], m[3][3] - m[3][2] * d);
1677  } else {
1678  // Orthographic projection: drop row 3 and column 3.
1679  return QTransform(m[0][0], m[0][1], m[0][3],
1680  m[1][0], m[1][1], m[1][3],
1681  m[3][0], m[3][1], m[3][3]);
1682  }
1683 }
1684 
1707 #ifndef QT_NO_VECTOR3D
1708 
1733 #endif
1734 
1735 #ifndef QT_NO_VECTOR4D
1736 
1748 #endif
1749 
1758 QRect QMatrix4x4::mapRect(const QRect& rect) const
1759 {
1760  if (flagBits == (Translation | Scale) || flagBits == Scale) {
1761  qreal x = rect.x() * m[0][0] + m[3][0];
1762  qreal y = rect.y() * m[1][1] + m[3][1];
1763  qreal w = rect.width() * m[0][0];
1764  qreal h = rect.height() * m[1][1];
1765  if (w < 0) {
1766  w = -w;
1767  x -= w;
1768  }
1769  if (h < 0) {
1770  h = -h;
1771  y -= h;
1772  }
1773  return QRect(qRound(x), qRound(y), qRound(w), qRound(h));
1774  } else if (flagBits == Translation) {
1775  return QRect(qRound(rect.x() + m[3][0]),
1776  qRound(rect.y() + m[3][1]),
1777  rect.width(), rect.height());
1778  }
1779 
1780  QPoint tl = map(rect.topLeft());
1781  QPoint tr = map(QPoint(rect.x() + rect.width(), rect.y()));
1782  QPoint bl = map(QPoint(rect.x(), rect.y() + rect.height()));
1783  QPoint br = map(QPoint(rect.x() + rect.width(),
1784  rect.y() + rect.height()));
1785 
1786  int xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
1787  int xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
1788  int ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
1789  int ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
1790 
1791  return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
1792 }
1793 
1803 {
1804  if (flagBits == (Translation | Scale) || flagBits == Scale) {
1805  qreal x = rect.x() * m[0][0] + m[3][0];
1806  qreal y = rect.y() * m[1][1] + m[3][1];
1807  qreal w = rect.width() * m[0][0];
1808  qreal h = rect.height() * m[1][1];
1809  if (w < 0) {
1810  w = -w;
1811  x -= w;
1812  }
1813  if (h < 0) {
1814  h = -h;
1815  y -= h;
1816  }
1817  return QRectF(x, y, w, h);
1818  } else if (flagBits == Translation) {
1819  return rect.translated(m[3][0], m[3][1]);
1820  }
1821 
1822  QPointF tl = map(rect.topLeft()); QPointF tr = map(rect.topRight());
1823  QPointF bl = map(rect.bottomLeft()); QPointF br = map(rect.bottomRight());
1824 
1825  qreal xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
1826  qreal xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
1827  qreal ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
1828  qreal ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
1829 
1830  return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
1831 }
1832 
1857 // Helper routine for inverting orthonormal matrices that consist
1858 // of just rotations and translations.
1860 {
1861  QMatrix4x4 result(1); // The '1' says not to load identity
1862 
1863  result.m[0][0] = m[0][0];
1864  result.m[1][0] = m[0][1];
1865  result.m[2][0] = m[0][2];
1866 
1867  result.m[0][1] = m[1][0];
1868  result.m[1][1] = m[1][1];
1869  result.m[2][1] = m[1][2];
1870 
1871  result.m[0][2] = m[2][0];
1872  result.m[1][2] = m[2][1];
1873  result.m[2][2] = m[2][2];
1874 
1875  result.m[0][3] = 0.0f;
1876  result.m[1][3] = 0.0f;
1877  result.m[2][3] = 0.0f;
1878 
1879  result.m[3][0] = -(result.m[0][0] * m[3][0] + result.m[1][0] * m[3][1] + result.m[2][0] * m[3][2]);
1880  result.m[3][1] = -(result.m[0][1] * m[3][0] + result.m[1][1] * m[3][1] + result.m[2][1] * m[3][2]);
1881  result.m[3][2] = -(result.m[0][2] * m[3][0] + result.m[1][2] * m[3][1] + result.m[2][2] * m[3][2]);
1882  result.m[3][3] = 1.0f;
1883 
1884  return result;
1885 }
1886 
1908 {
1909  // If the last element is not 1, then it can never be special.
1910  if (m[3][3] != 1.0f) {
1911  flagBits = General;
1912  return;
1913  }
1914 
1915  // If the upper three elements m12, m13, and m21 are not all zero,
1916  // or the lower elements below the diagonal are not all zero, then
1917  // the matrix can never be special.
1918  if (m[1][0] != 0.0f || m[2][0] != 0.0f || m[2][1] != 0.0f) {
1919  flagBits = General;
1920  return;
1921  }
1922  if (m[0][1] != 0.0f || m[0][2] != 0.0f || m[0][3] != 0.0f ||
1923  m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][3] != 0.0f) {
1924  flagBits = General;
1925  return;
1926  }
1927 
1928  // Determine what we have in the remaining regions of the matrix.
1929  bool identityAlongDiagonal
1930  = (m[0][0] == 1.0f && m[1][1] == 1.0f && m[2][2] == 1.0f);
1931  bool translationPresent
1932  = (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f);
1933 
1934  // Now determine the special matrix type.
1935  if (translationPresent && identityAlongDiagonal)
1937  else if (translationPresent)
1938  flagBits = (Translation | Scale);
1939  else if (identityAlongDiagonal)
1940  flagBits = Identity;
1941  else
1942  flagBits = Scale;
1943 }
1944 
1948 QMatrix4x4::operator QVariant() const
1949 {
1950  return QVariant(QVariant::Matrix4x4, this);
1951 }
1952 
1953 #ifndef QT_NO_DEBUG_STREAM
1954 
1956 {
1957  // Create a string that represents the matrix type.
1958  QByteArray bits;
1959  if ((m.flagBits & QMatrix4x4::Identity) != 0)
1960  bits += "Identity,";
1961  if ((m.flagBits & QMatrix4x4::General) != 0)
1962  bits += "General,";
1963  if ((m.flagBits & QMatrix4x4::Translation) != 0)
1964  bits += "Translation,";
1965  if ((m.flagBits & QMatrix4x4::Scale) != 0)
1966  bits += "Scale,";
1967  if ((m.flagBits & QMatrix4x4::Rotation) != 0)
1968  bits += "Rotation,";
1969  if (bits.size() > 0)
1970  bits = bits.left(bits.size() - 1);
1971 
1972  // Output in row-major order because it is more human-readable.
1973  dbg.nospace() << "QMatrix4x4(type:" << bits.constData() << endl
1974  << qSetFieldWidth(10)
1975  << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << endl
1976  << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << endl
1977  << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << endl
1978  << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << endl
1979  << qSetFieldWidth(0) << ')';
1980  return dbg.space();
1981 }
1982 
1983 #endif
1984 
1985 #ifndef QT_NO_DATASTREAM
1986 
2001 {
2002  for (int row = 0; row < 4; ++row)
2003  for (int col = 0; col < 4; ++col)
2004  stream << double(matrix(row, col));
2005  return stream;
2006 }
2007 
2022 {
2023  double x;
2024  for (int row = 0; row < 4; ++row) {
2025  for (int col = 0; col < 4; ++col) {
2026  stream >> x;
2027  matrix(row, col) = qreal(x);
2028  }
2029  }
2030  matrix.optimize();
2031  return stream;
2032 }
2033 
2034 #endif // QT_NO_DATASTREAM
2035 
2036 #endif // QT_NO_MATRIX4X4
2037 
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
void translate(const QVector3D &vector)
Multiplies this matrix by another that translates coordinates by the components of vector...
Definition: qmatrix4x4.cpp:944
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:62
double d
Definition: qnumeric_p.h:62
QPointF bottomRight() const
Returns the position of the rectangle&#39;s bottom-right corner.
Definition: qrect.h:540
T * data()
Returns a pointer to the raw data of this matrix.
QMatrix toAffine() const
Returns the conventional Qt 2D affine transformation matrix that corresponds to this matrix...
int flagBits
Definition: qmatrix4x4.h:189
friend Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4 &matrix, qreal divisor)
Returns the result of dividing all elements of matrix by divisor.
Definition: qmatrix4x4.cpp:734
qreal y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:667
qreal dy() const
Returns the vertical translation factor.
Definition: qtransform.h:277
qreal right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:527
The QVector3D class represents a vector or vertex in 3D space.
Definition: qvector3d.h:60
qreal determinant() const
Returns the determinant of this matrix.
Definition: qmatrix4x4.cpp:391
double qreal
Definition: qglobal.h:1193
unsigned char c[8]
Definition: qnumeric_p.h:62
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
qreal x() const
Returns the x coordinate of this quaternion&#39;s vector.
Definition: qquaternion.h:156
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
The QGenericMatrix class is a template class that represents a NxM transformation matrix with N colum...
QMatrix4x4 & operator/=(qreal divisor)
Divides all elements of this matrix by divisor.
Definition: qmatrix4x4.cpp:560
QMatrix4x4()
Constructs an identity matrix.
Definition: qmatrix4x4.h:66
The QMatrix class specifies 2D transformations of a coordinate system.
Definition: qmatrix.h:61
friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m)
QDebug & nospace()
Clears the stream&#39;s internal flag that records whether the last character was a space and returns a r...
Definition: qdebug.h:92
static const uchar inv
Definition: qisciicodec.cpp:91
The Rotation object provides a way to rotate an Item.
qreal m21() const
Returns the horizontal shearing factor.
Definition: qtransform.h:249
qreal dx() const
Returns the horizontal translation factor.
Definition: qmatrix.h:77
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
The QPointF class defines a point in the plane using floating point precision.
Definition: qpoint.h:214
qreal left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:525
void projectedRotate(qreal angle, qreal x, qreal y, qreal z)
qreal m22() const
Returns the vertical scaling factor.
Definition: qtransform.h:253
QMatrix4x4 orthonormalInverse() const
QPointF topLeft() const
Returns the position of the rectangle&#39;s top-left corner.
Definition: qrect.h:539
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
long ASN1_INTEGER_get ASN1_INTEGER * a
void optimize()
Optimize the usage of this matrix from its current elements.
QPointF bottomLeft() const
Returns the position of the rectangle&#39;s bottom-left corner.
Definition: qrect.h:542
qreal x() const
Returns the x coordinate of this point.
Definition: qvector3d.h:161
QRect mapRect(const QRect &rect) const
Maps rect by multiplying this matrix by the corners of rect and then forming a new rectangle from the...
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
qreal m12() const
Returns the vertical shearing factor.
Definition: qmatrix.h:74
QPoint map(const QPoint &point) const
Maps point by multiplying this matrix by point.
Definition: qmatrix4x4.h:923
QMatrix4x4 transposed() const
Returns this matrix, transposed about its diagonal.
Definition: qmatrix4x4.cpp:510
void lookAt(const QVector3D &eye, const QVector3D &center, const QVector3D &up)
Multiplies this matrix by another that applies an eye position transformation.
QDataStream & operator>>(QDataStream &stream, QMatrix4x4 &matrix)
Reads a 4x4 matrix from the given stream into the given matrix and returns a reference to the stream...
#define M_PI
Definition: qmath.h:261
Q_CORE_EXPORT QTextStream & right(QTextStream &s)
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
qreal x() const
Returns the x-coordinate of this point.
Definition: qpoint.h:282
static qreal matrixDet3(const qreal m[4][4], int col0, int col1, int col2, int row0, int row1, int row2)
Definition: qmatrix4x4.cpp:363
qreal m11() const
Returns the horizontal scaling factor.
Definition: qmatrix.h:73
qreal m12() const
Returns the vertical shearing factor.
Definition: qtransform.h:241
qreal scalar() const
Returns the scalar component of this quaternion.
Definition: qquaternion.h:159
qreal m21() const
Returns the horizontal shearing factor.
Definition: qmatrix.h:75
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
static FILE * stream
qreal qSin(qreal v)
Definition: qmath.h:93
qreal height() const
Returns the height of the rectangle.
Definition: qrect.h:710
void setToIdentity()
Sets this matrix to the identity.
Definition: qmatrix4x4.h:324
QVector4D row(int index) const
Returns the elements of row index as a 4D vector.
Definition: qmatrix4x4.h:289
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition: qmatrix4x4.h:63
QVector3D normalized() const
Returns the normalized unit vector form of this vector.
Definition: qvector3d.cpp:247
qreal width() const
Returns the width of the rectangle.
Definition: qrect.h:707
void flipCoordinates()
Flips between right-handed and left-handed coordinate systems by multiplying the y and z co-ordinates...
QByteArray left(int len) const
Returns a byte array that contains the leftmost len bytes of this byte array.
quint16 values[128]
qreal z() const
Returns the z coordinate of this point.
Definition: qvector3d.h:163
QTransform toTransform() const
Returns the conventional Qt 2D transformation matrix that corresponds to this matrix.
qreal m[4][4]
Definition: qmatrix4x4.h:188
qreal y() const
Returns the y coordinate of this quaternion&#39;s vector.
Definition: qquaternion.h:157
Q_CORE_EXPORT QTextStream & center(QTextStream &s)
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
static qreal matrixDet4(const qreal m[4][4])
Definition: qmatrix4x4.cpp:378
void copyDataTo(qreal *values) const
Retrieves the 16 items in this matrix and copies them to values in row-major order.
qreal angle(const QPointF &p1, const QPointF &p2)
The Scale element provides a way to scale an Item.
void rotate(qreal angle, const QVector3D &vector)
Multiples this matrix by another that rotates coordinates through angle degrees about vector...
QMatrix4x4 inverted(bool *invertible=0) const
Returns the inverse of this matrix.
Definition: qmatrix4x4.cpp:408
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
qreal x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:664
qreal z() const
Returns the z coordinate of this quaternion&#39;s vector.
Definition: qquaternion.h:158
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
void ortho(const QRect &rect)
Multiplies this matrix by another that applies an orthographic projection for a window with boundarie...
qreal dy() const
Returns the vertical translation factor.
Definition: qmatrix.h:78
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
qreal y() const
Returns the y coordinate of this point.
Definition: qvector3d.h:162
qreal m23() const
Returns the vertical projection factor.
Definition: qtransform.h:257
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
The QQuaternion class represents a quaternion consisting of a vector and scalar.
Definition: qquaternion.h:59
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
qreal dx() const
Returns the horizontal translation factor.
Definition: qtransform.h:273
void scale(const QVector3D &vector)
Multiplies this matrix by another that scales coordinates by the components of vector.
Definition: qmatrix4x4.cpp:775
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
QMatrix3x3 normalMatrix() const
Returns the normal matrix corresponding to this 4x4 transformation.
Definition: qmatrix4x4.cpp:470
qreal y() const
Returns the y-coordinate of this point.
Definition: qpoint.h:287
qreal top() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:526
static Q_DECL_CONSTEXPR bool qFuzzyIsNull(double d)
Definition: qglobal.h:2043
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:71
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
qreal m13() const
Returns the horizontal projection factor.
Definition: qtransform.h:245
void perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane)
Multiplies this matrix by another that applies a perspective projection.
qreal bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:528
QRectF translated(qreal dx, qreal dy) const
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis...
Definition: qrect.h:740
QPointF topRight() const
Returns the position of the rectangle&#39;s top-right corner.
Definition: qrect.h:541
QTextStreamManipulator qSetFieldWidth(int width)
Definition: qtextstream.h:329
QDebug & space()
Writes a space character to the debug stream and returns a reference to the stream.
Definition: qdebug.h:91
Q_CORE_EXPORT QTextStream & left(QTextStream &s)
qreal qCos(qreal v)
Definition: qmath.h:109
qreal qSqrt(qreal v)
Definition: qmath.h:205
void frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
Multiplies this matrix by another that applies a perspective frustum projection for a window with low...
static const qreal inv_dist_to_plane
Definition: qmatrix4x4.cpp:64
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
qreal m22() const
Returns the vertical scaling factor.
Definition: qmatrix.h:76
qreal m11() const
Returns the horizontal scaling factor.
Definition: qtransform.h:237
qreal m33() const
Returns the division factor.
Definition: qtransform.h:269
The QTransform class specifies 2D transformations of a coordinate system.
Definition: qtransform.h:65
QPoint topLeft() const
Returns the position of the rectangle&#39;s top-left corner.
Definition: qrect.h:288
static QVector3D crossProduct(const QVector3D &v1, const QVector3D &v2)
Returns the cross-product of vectors v1 and v2, which corresponds to the normal vector of a plane def...
Definition: qvector3d.cpp:352
Q_CORE_EXPORT QTextStream & endl(QTextStream &s)