340QMatrix4x4 QMatrix4x4::inverted(
bool *invertible)
const
343 if (flagBits == Identity) {
347 }
else if (flagBits == Translation) {
349 inv.m[3][0] = -m[3][0];
350 inv.m[3][1] = -m[3][1];
351 inv.m[3][2] = -m[3][2];
352 inv.flagBits = Translation;
356 }
else if (flagBits < Rotation2D) {
358 if (m[0][0] == 0 || m[1][1] == 0 || m[2][2] == 0) {
364 inv.m[0][0] = 1.0f / m[0][0];
365 inv.m[1][1] = 1.0f / m[1][1];
366 inv.m[2][2] = 1.0f / m[2][2];
367 inv.m[3][0] = -m[3][0] * inv.m[0][0];
368 inv.m[3][1] = -m[3][1] * inv.m[1][1];
369 inv.m[3][2] = -m[3][2] * inv.m[2][2];
370 inv.flagBits = flagBits;
375 }
else if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity) {
378 return orthonormalInverse();
379 }
else if (flagBits < Perspective) {
381 QMatrix4x4 inv(Qt::Uninitialized);
383 const Double4x4 mm = copyToDoubles(m);
385 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
393 inv.m[0][0] = matrixDet2(mm, 1, 2, 1, 2) * det;
394 inv.m[0][1] = -matrixDet2(mm, 0, 2, 1, 2) * det;
395 inv.m[0][2] = matrixDet2(mm, 0, 1, 1, 2) * det;
397 inv.m[1][0] = -matrixDet2(mm, 1, 2, 0, 2) * det;
398 inv.m[1][1] = matrixDet2(mm, 0, 2, 0, 2) * det;
399 inv.m[1][2] = -matrixDet2(mm, 0, 1, 0, 2) * det;
401 inv.m[2][0] = matrixDet2(mm, 1, 2, 0, 1) * det;
402 inv.m[2][1] = -matrixDet2(mm, 0, 2, 0, 1) * det;
403 inv.m[2][2] = matrixDet2(mm, 0, 1, 0, 1) * det;
405 inv.m[3][0] = -inv.m[0][0] * m[3][0] - inv.m[1][0] * m[3][1] - inv.m[2][0] * m[3][2];
406 inv.m[3][1] = -inv.m[0][1] * m[3][0] - inv.m[1][1] * m[3][1] - inv.m[2][1] * m[3][2];
407 inv.m[3][2] = -inv.m[0][2] * m[3][0] - inv.m[1][2] * m[3][1] - inv.m[2][2] * m[3][2];
409 inv.flagBits = flagBits;
417 QMatrix4x4 inv(Qt::Uninitialized);
419 const Double4x4 mm = copyToDoubles(m);
421 double det = matrixDet4(mm);
429 inv.m[0][0] = matrixDet3(mm, 1, 2, 3, 1, 2, 3) * det;
430 inv.m[0][1] = -matrixDet3(mm, 0, 2, 3, 1, 2, 3) * det;
431 inv.m[0][2] = matrixDet3(mm, 0, 1, 3, 1, 2, 3) * det;
432 inv.m[0][3] = -matrixDet3(mm, 0, 1, 2, 1, 2, 3) * det;
433 inv.m[1][0] = -matrixDet3(mm, 1, 2, 3, 0, 2, 3) * det;
434 inv.m[1][1] = matrixDet3(mm, 0, 2, 3, 0, 2, 3) * det;
435 inv.m[1][2] = -matrixDet3(mm, 0, 1, 3, 0, 2, 3) * det;
436 inv.m[1][3] = matrixDet3(mm, 0, 1, 2, 0, 2, 3) * det;
437 inv.m[2][0] = matrixDet3(mm, 1, 2, 3, 0, 1, 3) * det;
438 inv.m[2][1] = -matrixDet3(mm, 0, 2, 3, 0, 1, 3) * det;
439 inv.m[2][2] = matrixDet3(mm, 0, 1, 3, 0, 1, 3) * det;
440 inv.m[2][3] = -matrixDet3(mm, 0, 1, 2, 0, 1, 3) * det;
441 inv.m[3][0] = -matrixDet3(mm, 1, 2, 3, 0, 1, 2) * det;
442 inv.m[3][1] = matrixDet3(mm, 0, 2, 3, 0, 1, 2) * det;
443 inv.m[3][2] = -matrixDet3(mm, 0, 1, 3, 0, 1, 2) * det;
444 inv.m[3][3] = matrixDet3(mm, 0, 1, 2, 0, 1, 2) * det;
445 inv.flagBits = flagBits;
460QMatrix3x3 QMatrix4x4::normalMatrix()
const
465 if (flagBits < Scale) {
468 }
else if (flagBits < Rotation2D) {
470 if (m[0][0] == 0.0f || m[1][1] == 0.0f || m[2][2] == 0.0f)
472 inv.data()[0] = 1.0f / m[0][0];
473 inv.data()[4] = 1.0f / m[1][1];
474 inv.data()[8] = 1.0f / m[2][2];
476 }
else if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity) {
477 float *invm = inv.data();
478 invm[0 + 0 * 3] = m[0][0];
479 invm[1 + 0 * 3] = m[0][1];
480 invm[2 + 0 * 3] = m[0][2];
481 invm[0 + 1 * 3] = m[1][0];
482 invm[1 + 1 * 3] = m[1][1];
483 invm[2 + 1 * 3] = m[1][2];
484 invm[0 + 2 * 3] = m[2][0];
485 invm[1 + 2 * 3] = m[2][1];
486 invm[2 + 2 * 3] = m[2][2];
490 const Double4x4 mm = copyToDoubles(m);
491 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
496 float *invm = inv.data();
499 invm[0 + 0 * 3] = (mm[1][1] * mm[2][2] - mm[2][1] * mm[1][2]) * det;
500 invm[1 + 0 * 3] = -(mm[1][0] * mm[2][2] - mm[1][2] * mm[2][0]) * det;
501 invm[2 + 0 * 3] = (mm[1][0] * mm[2][1] - mm[1][1] * mm[2][0]) * det;
502 invm[0 + 1 * 3] = -(mm[0][1] * mm[2][2] - mm[2][1] * mm[0][2]) * det;
503 invm[1 + 1 * 3] = (mm[0][0] * mm[2][2] - mm[0][2] * mm[2][0]) * det;
504 invm[2 + 1 * 3] = -(mm[0][0] * mm[2][1] - mm[0][1] * mm[2][0]) * det;
505 invm[0 + 2 * 3] = (mm[0][1] * mm[1][2] - mm[0][2] * mm[1][1]) * det;
506 invm[1 + 2 * 3] = -(mm[0][0] * mm[1][2] - mm[0][2] * mm[1][0]) * det;
507 invm[2 + 2 * 3] = (mm[0][0] * mm[1][1] - mm[1][0] * mm[0][1]) * det;
732QMatrix4x4 operator/(
const QMatrix4x4& matrix,
float divisor)
735 QMatrix4x4 m(Qt::Uninitialized);
736 m.m[0][0] = matrix.m[0][0] / divisor;
737 m.m[0][1] = matrix.m[0][1] / divisor;
738 m.m[0][2] = matrix.m[0][2] / divisor;
739 m.m[0][3] = matrix.m[0][3] / divisor;
740 m.m[1][0] = matrix.m[1][0] / divisor;
741 m.m[1][1] = matrix.m[1][1] / divisor;
742 m.m[1][2] = matrix.m[1][2] / divisor;
743 m.m[1][3] = matrix.m[1][3] / divisor;
744 m.m[2][0] = matrix.m[2][0] / divisor;
745 m.m[2][1] = matrix.m[2][1] / divisor;
746 m.m[2][2] = matrix.m[2][2] / divisor;
747 m.m[2][3] = matrix.m[2][3] / divisor;
748 m.m[3][0] = matrix.m[3][0] / divisor;
749 m.m[3][1] = matrix.m[3][1] / divisor;
750 m.m[3][2] = matrix.m[3][2] / divisor;
751 m.m[3][3] = matrix.m[3][3] / divisor;
752 m.flagBits = QMatrix4x4::General;
764 return QtPrivate::fuzzyCompare(m1.m[0][0], m2.m[0][0])
765 && QtPrivate::fuzzyCompare(m1.m[0][1], m2.m[0][1])
766 && QtPrivate::fuzzyCompare(m1.m[0][2], m2.m[0][2])
767 && QtPrivate::fuzzyCompare(m1.m[0][3], m2.m[0][3])
768 && QtPrivate::fuzzyCompare(m1.m[1][0], m2.m[1][0])
769 && QtPrivate::fuzzyCompare(m1.m[1][1], m2.m[1][1])
770 && QtPrivate::fuzzyCompare(m1.m[1][2], m2.m[1][2])
771 && QtPrivate::fuzzyCompare(m1.m[1][3], m2.m[1][3])
772 && QtPrivate::fuzzyCompare(m1.m[2][0], m2.m[2][0])
773 && QtPrivate::fuzzyCompare(m1.m[2][1], m2.m[2][1])
774 && QtPrivate::fuzzyCompare(m1.m[2][2], m2.m[2][2])
775 && QtPrivate::fuzzyCompare(m1.m[2][3], m2.m[2][3])
776 && QtPrivate::fuzzyCompare(m1.m[3][0], m2.m[3][0])
777 && QtPrivate::fuzzyCompare(m1.m[3][1], m2.m[3][1])
778 && QtPrivate::fuzzyCompare(m1.m[3][2], m2.m[3][2])
779 && QtPrivate::fuzzyCompare(m1.m[3][3], m2.m[3][3]);
1055void QMatrix4x4::rotate(
float angle,
float x,
float y,
float z)
1060 if (angle == 90.0f || angle == -270.0f) {
1063 }
else if (angle == -90.0f || angle == 270.0f) {
1066 }
else if (angle == 180.0f || angle == -180.0f) {
1070 float a = qDegreesToRadians(angle);
1081 m[0][0] = (tmp = m[0][0]) * c + m[1][0] * s;
1082 m[1][0] = m[1][0] * c - tmp * s;
1083 m[0][1] = (tmp = m[0][1]) * c + m[1][1] * s;
1084 m[1][1] = m[1][1] * c - tmp * s;
1085 m[0][2] = (tmp = m[0][2]) * c + m[1][2] * s;
1086 m[1][2] = m[1][2] * c - tmp * s;
1087 m[0][3] = (tmp = m[0][3]) * c + m[1][3] * s;
1088 m[1][3] = m[1][3] * c - tmp * s;
1090 flagBits |= Rotation2D;
1093 }
else if (z == 0.0f) {
1098 m[2][0] = (tmp = m[2][0]) * c + m[0][0] * s;
1099 m[0][0] = m[0][0] * c - tmp * s;
1100 m[2][1] = (tmp = m[2][1]) * c + m[0][1] * s;
1101 m[0][1] = m[0][1] * c - tmp * s;
1102 m[2][2] = (tmp = m[2][2]) * c + m[0][2] * s;
1103 m[0][2] = m[0][2] * c - tmp * s;
1104 m[2][3] = (tmp = m[2][3]) * c + m[0][3] * s;
1105 m[0][3] = m[0][3] * c - tmp * s;
1107 flagBits |= Rotation;
1110 }
else if (y == 0.0f && z == 0.0f) {
1115 m[1][0] = (tmp = m[1][0]) * c + m[2][0] * s;
1116 m[2][0] = m[2][0] * c - tmp * s;
1117 m[1][1] = (tmp = m[1][1]) * c + m[2][1] * s;
1118 m[2][1] = m[2][1] * c - tmp * s;
1119 m[1][2] = (tmp = m[1][2]) * c + m[2][2] * s;
1120 m[2][2] = m[2][2] * c - tmp * s;
1121 m[1][3] = (tmp = m[1][3]) * c + m[2][3] * s;
1122 m[2][3] = m[2][3] * c - tmp * s;
1124 flagBits |= Rotation;
1128 double len =
double(x) *
double(x) +
1129 double(y) *
double(y) +
1130 double(z) *
double(z);
1131 if (!qFuzzyCompare(len, 1.0) && !qFuzzyIsNull(len)) {
1132 len = std::sqrt(len);
1133 x =
float(
double(x) / len);
1134 y =
float(
double(y) / len);
1135 z =
float(
double(z) / len);
1137 float ic = 1.0f - c;
1138 Q_DECL_UNINITIALIZED
1139 QMatrix4x4 rot(Qt::Uninitialized);
1140 rot.m[0][0] = x * x * ic + c;
1141 rot.m[1][0] = x * y * ic - z * s;
1142 rot.m[2][0] = x * z * ic + y * s;
1144 rot.m[0][1] = y * x * ic + z * s;
1145 rot.m[1][1] = y * y * ic + c;
1146 rot.m[2][1] = y * z * ic - x * s;
1148 rot.m[0][2] = x * z * ic - y * s;
1149 rot.m[1][2] = y * z * ic + x * s;
1150 rot.m[2][2] = z * z * ic + c;
1156 rot.flagBits = Rotation;
1163void QMatrix4x4::projectedRotate(
float angle,
float x,
float y,
float z,
float distanceToPlane)
1167 if (qIsNull(distanceToPlane))
1168 return rotate(angle, x, y, z);
1173 if (angle == 90.0f || angle == -270.0f) {
1176 }
else if (angle == -90.0f || angle == 270.0f) {
1179 }
else if (angle == 180.0f || angle == -180.0f) {
1183 float a = qDegreesToRadians(angle);
1188 const qreal d = 1.0 / distanceToPlane;
1196 m[0][0] = (tmp = m[0][0]) * c + m[1][0] * s;
1197 m[1][0] = m[1][0] * c - tmp * s;
1198 m[0][1] = (tmp = m[0][1]) * c + m[1][1] * s;
1199 m[1][1] = m[1][1] * c - tmp * s;
1200 m[0][2] = (tmp = m[0][2]) * c + m[1][2] * s;
1201 m[1][2] = m[1][2] * c - tmp * s;
1202 m[0][3] = (tmp = m[0][3]) * c + m[1][3] * s;
1203 m[1][3] = m[1][3] * c - tmp * s;
1205 flagBits |= Rotation2D;
1208 }
else if (z == 0.0f) {
1213 m[0][0] = m[0][0] * c + m[3][0] * s;
1214 m[0][1] = m[0][1] * c + m[3][1] * s;
1215 m[0][2] = m[0][2] * c + m[3][2] * s;
1216 m[0][3] = m[0][3] * c + m[3][3] * s;
1220 }
else if (y == 0.0f && z == 0.0f) {
1225 m[1][0] = m[1][0] * c - m[3][0] * s;
1226 m[1][1] = m[1][1] * c - m[3][1] * s;
1227 m[1][2] = m[1][2] * c - m[3][2] * s;
1228 m[1][3] = m[1][3] * c - m[3][3] * s;
1232 double len =
double(x) *
double(x) +
1233 double(y) *
double(y) +
1234 double(z) *
double(z);
1235 if (!qFuzzyCompare(len, 1.0) && !qFuzzyIsNull(len)) {
1236 len = std::sqrt(len);
1237 x =
float(
double(x) / len);
1238 y =
float(
double(y) / len);
1239 z =
float(
double(z) / len);
1241 const float ic = 1.0f - c;
1242 Q_DECL_UNINITIALIZED
1243 QMatrix4x4 rot(Qt::Uninitialized);
1244 rot.m[0][0] = x * x * ic + c;
1245 rot.m[1][0] = x * y * ic - z * s;
1248 rot.m[0][1] = y * x * ic + z * s;
1249 rot.m[1][1] = y * y * ic + c;
1256 rot.m[0][3] = (x * z * ic - y * s) * -d;
1257 rot.m[1][3] = (y * z * ic + x * s) * -d;
1260 rot.flagBits = General;
1674QTransform QMatrix4x4::toTransform(
float distanceToPlane)
const
1676 if (distanceToPlane == 1024.0f) {
1678 return QTransform(m[0][0], m[0][1], m[0][3] - m[0][2] * inv_dist_to_plane,
1679 m[1][0], m[1][1], m[1][3] - m[1][2] * inv_dist_to_plane,
1680 m[3][0], m[3][1], m[3][3] - m[3][2] * inv_dist_to_plane);
1681 }
else if (distanceToPlane != 0.0f) {
1689 float d = 1.0f / distanceToPlane;
1690 return QTransform(m[0][0], m[0][1], m[0][3] - m[0][2] * d,
1691 m[1][0], m[1][1], m[1][3] - m[1][2] * d,
1692 m[3][0], m[3][1], m[3][3] - m[3][2] * d);
1695 return QTransform(m[0][0], m[0][1], m[0][3],
1696 m[1][0], m[1][1], m[1][3],
1697 m[3][0], m[3][1], m[3][3]);
1767QRect QMatrix4x4::mapRect(
const QRect& rect)
const
1769 if (flagBits < Scale) {
1771 return QRect(qRound(rect.x() + m[3][0]),
1772 qRound(rect.y() + m[3][1]),
1773 rect.width(), rect.height());
1774 }
else if (flagBits < Rotation2D) {
1776 float x = rect.x() * m[0][0] + m[3][0];
1777 float y = rect.y() * m[1][1] + m[3][1];
1778 float w = rect.width() * m[0][0];
1779 float h = rect.height() * m[1][1];
1788 return QRect(qRound(x), qRound(y), qRound(w), qRound(h));
1791 QPoint tl = map(rect.topLeft());
1792 QPoint tr = map(QPoint(rect.x() + rect.width(), rect.y()));
1793 QPoint bl = map(QPoint(rect.x(), rect.y() + rect.height()));
1794 QPoint br = map(QPoint(rect.x() + rect.width(),
1795 rect.y() + rect.height()));
1797 int xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
1798 int xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
1799 int ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
1800 int ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
1802 return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
1813QRectF QMatrix4x4::mapRect(
const QRectF& rect)
const
1815 if (flagBits < Scale) {
1817 return rect.translated(m[3][0], m[3][1]);
1818 }
else if (flagBits < Rotation2D) {
1820 float x = rect.x() * m[0][0] + m[3][0];
1821 float y = rect.y() * m[1][1] + m[3][1];
1822 float w = rect.width() * m[0][0];
1823 float h = rect.height() * m[1][1];
1832 return QRectF(x, y, w, h);
1835 QPointF tl = map(rect.topLeft()); QPointF tr = map(rect.topRight());
1836 QPointF bl = map(rect.bottomLeft()); QPointF br = map(rect.bottomRight());
1838 float xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
1839 float xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
1840 float ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
1841 float ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
1843 return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
1925void QMatrix4x4::optimize()
1929 if (m[0][3] != 0 || m[1][3] != 0 || m[2][3] != 0 || m[3][3] != 1)
1932 flagBits &= ~Perspective;
1935 if (m[3][0] == 0 && m[3][1] == 0 && m[3][2] == 0)
1936 flagBits &= ~Translation;
1939 if (!m[0][2] && !m[1][2] && !m[2][0] && !m[2][1]) {
1940 flagBits &= ~Rotation;
1942 if (!m[0][1] && !m[1][0]) {
1943 flagBits &= ~Rotation2D;
1945 if (m[0][0] == 1 && m[1][1] == 1 && m[2][2] == 1)
1949 const Double4x4 mm = copyToDoubles(m);
1950 double det = matrixDet2(mm, 0, 1, 0, 1);
1951 double lenX = mm[0][0] * mm[0][0] + mm[0][1] * mm[0][1];
1952 double lenY = mm[1][0] * mm[1][0] + mm[1][1] * mm[1][1];
1953 double lenZ = mm[2][2];
1954 if (qFuzzyCompare(det, 1.0) && qFuzzyCompare(lenX, 1.0)
1955 && qFuzzyCompare(lenY, 1.0) && qFuzzyCompare(lenZ, 1.0))
1962 const Double4x4 mm = copyToDoubles(m);
1963 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
1964 double lenX = mm[0][0] * mm[0][0] + mm[0][1] * mm[0][1] + mm[0][2] * mm[0][2];
1965 double lenY = mm[1][0] * mm[1][0] + mm[1][1] * mm[1][1] + mm[1][2] * mm[1][2];
1966 double lenZ = mm[2][0] * mm[2][0] + mm[2][1] * mm[2][1] + mm[2][2] * mm[2][2];
1967 if (qFuzzyCompare(det, 1.0) && qFuzzyCompare(lenX, 1.0)
1968 && qFuzzyCompare(lenY, 1.0) && qFuzzyCompare(lenZ, 1.0))
1987 QDebugStateSaver saver(dbg);
1990 if (m.flagBits == QMatrix4x4::Identity) {
1992 }
else if (m.flagBits == QMatrix4x4::General) {
1995 if ((m.flagBits & QMatrix4x4::Translation) != 0)
1996 bits +=
"Translation,";
1997 if ((m.flagBits & QMatrix4x4::Scale) != 0)
1999 if ((m.flagBits & QMatrix4x4::Rotation2D) != 0)
2000 bits +=
"Rotation2D,";
2001 if ((m.flagBits & QMatrix4x4::Rotation) != 0)
2002 bits +=
"Rotation,";
2003 if ((m.flagBits & QMatrix4x4::Perspective) != 0)
2004 bits +=
"Perspective,";
2009 dbg.nospace() <<
"QMatrix4x4(type:" << bits.constData() << Qt::endl
2010 << qSetFieldWidth(10)
2011 << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << Qt::endl
2012 << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << Qt::endl
2013 << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << Qt::endl
2014 << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << Qt::endl
2015 << qSetFieldWidth(0) <<
')';