322QMatrix4x4 QMatrix4x4::inverted(
bool *invertible)
const
325 if (flagBits == Identity) {
329 }
else if (flagBits == Translation) {
331 inv.m[3][0] = -m[3][0];
332 inv.m[3][1] = -m[3][1];
333 inv.m[3][2] = -m[3][2];
334 inv.flagBits = Translation;
338 }
else if (flagBits < Rotation2D) {
340 if (m[0][0] == 0 || m[1][1] == 0 || m[2][2] == 0) {
346 inv.m[0][0] = 1.0f / m[0][0];
347 inv.m[1][1] = 1.0f / m[1][1];
348 inv.m[2][2] = 1.0f / m[2][2];
349 inv.m[3][0] = -m[3][0] * inv.m[0][0];
350 inv.m[3][1] = -m[3][1] * inv.m[1][1];
351 inv.m[3][2] = -m[3][2] * inv.m[2][2];
352 inv.flagBits = flagBits;
357 }
else if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity) {
360 return orthonormalInverse();
361 }
else if (flagBits < Perspective) {
363 QMatrix4x4 inv(Qt::Uninitialized);
365 const Double4x4 mm = copyToDoubles(m);
367 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
375 inv.m[0][0] = matrixDet2(mm, 1, 2, 1, 2) * det;
376 inv.m[0][1] = -matrixDet2(mm, 0, 2, 1, 2) * det;
377 inv.m[0][2] = matrixDet2(mm, 0, 1, 1, 2) * det;
379 inv.m[1][0] = -matrixDet2(mm, 1, 2, 0, 2) * det;
380 inv.m[1][1] = matrixDet2(mm, 0, 2, 0, 2) * det;
381 inv.m[1][2] = -matrixDet2(mm, 0, 1, 0, 2) * det;
383 inv.m[2][0] = matrixDet2(mm, 1, 2, 0, 1) * det;
384 inv.m[2][1] = -matrixDet2(mm, 0, 2, 0, 1) * det;
385 inv.m[2][2] = matrixDet2(mm, 0, 1, 0, 1) * det;
387 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];
388 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];
389 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];
391 inv.flagBits = flagBits;
399 QMatrix4x4 inv(Qt::Uninitialized);
401 const Double4x4 mm = copyToDoubles(m);
403 double det = matrixDet4(mm);
411 inv.m[0][0] = matrixDet3(mm, 1, 2, 3, 1, 2, 3) * det;
412 inv.m[0][1] = -matrixDet3(mm, 0, 2, 3, 1, 2, 3) * det;
413 inv.m[0][2] = matrixDet3(mm, 0, 1, 3, 1, 2, 3) * det;
414 inv.m[0][3] = -matrixDet3(mm, 0, 1, 2, 1, 2, 3) * det;
415 inv.m[1][0] = -matrixDet3(mm, 1, 2, 3, 0, 2, 3) * det;
416 inv.m[1][1] = matrixDet3(mm, 0, 2, 3, 0, 2, 3) * det;
417 inv.m[1][2] = -matrixDet3(mm, 0, 1, 3, 0, 2, 3) * det;
418 inv.m[1][3] = matrixDet3(mm, 0, 1, 2, 0, 2, 3) * det;
419 inv.m[2][0] = matrixDet3(mm, 1, 2, 3, 0, 1, 3) * det;
420 inv.m[2][1] = -matrixDet3(mm, 0, 2, 3, 0, 1, 3) * det;
421 inv.m[2][2] = matrixDet3(mm, 0, 1, 3, 0, 1, 3) * det;
422 inv.m[2][3] = -matrixDet3(mm, 0, 1, 2, 0, 1, 3) * det;
423 inv.m[3][0] = -matrixDet3(mm, 1, 2, 3, 0, 1, 2) * det;
424 inv.m[3][1] = matrixDet3(mm, 0, 2, 3, 0, 1, 2) * det;
425 inv.m[3][2] = -matrixDet3(mm, 0, 1, 3, 0, 1, 2) * det;
426 inv.m[3][3] = matrixDet3(mm, 0, 1, 2, 0, 1, 2) * det;
427 inv.flagBits = flagBits;
442QMatrix3x3 QMatrix4x4::normalMatrix()
const
447 if (flagBits < Scale) {
450 }
else if (flagBits < Rotation2D) {
452 if (m[0][0] == 0.0f || m[1][1] == 0.0f || m[2][2] == 0.0f)
454 inv.data()[0] = 1.0f / m[0][0];
455 inv.data()[4] = 1.0f / m[1][1];
456 inv.data()[8] = 1.0f / m[2][2];
458 }
else if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity) {
459 float *invm = inv.data();
460 invm[0 + 0 * 3] = m[0][0];
461 invm[1 + 0 * 3] = m[0][1];
462 invm[2 + 0 * 3] = m[0][2];
463 invm[0 + 1 * 3] = m[1][0];
464 invm[1 + 1 * 3] = m[1][1];
465 invm[2 + 1 * 3] = m[1][2];
466 invm[0 + 2 * 3] = m[2][0];
467 invm[1 + 2 * 3] = m[2][1];
468 invm[2 + 2 * 3] = m[2][2];
472 const Double4x4 mm = copyToDoubles(m);
473 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
478 float *invm = inv.data();
481 invm[0 + 0 * 3] = (mm[1][1] * mm[2][2] - mm[2][1] * mm[1][2]) * det;
482 invm[1 + 0 * 3] = -(mm[1][0] * mm[2][2] - mm[1][2] * mm[2][0]) * det;
483 invm[2 + 0 * 3] = (mm[1][0] * mm[2][1] - mm[1][1] * mm[2][0]) * det;
484 invm[0 + 1 * 3] = -(mm[0][1] * mm[2][2] - mm[2][1] * mm[0][2]) * det;
485 invm[1 + 1 * 3] = (mm[0][0] * mm[2][2] - mm[0][2] * mm[2][0]) * det;
486 invm[2 + 1 * 3] = -(mm[0][0] * mm[2][1] - mm[0][1] * mm[2][0]) * det;
487 invm[0 + 2 * 3] = (mm[0][1] * mm[1][2] - mm[0][2] * mm[1][1]) * det;
488 invm[1 + 2 * 3] = -(mm[0][0] * mm[1][2] - mm[0][2] * mm[1][0]) * det;
489 invm[2 + 2 * 3] = (mm[0][0] * mm[1][1] - mm[1][0] * mm[0][1]) * det;
714QMatrix4x4 operator/(
const QMatrix4x4& matrix,
float divisor)
717 QMatrix4x4 m(Qt::Uninitialized);
718 m.m[0][0] = matrix.m[0][0] / divisor;
719 m.m[0][1] = matrix.m[0][1] / divisor;
720 m.m[0][2] = matrix.m[0][2] / divisor;
721 m.m[0][3] = matrix.m[0][3] / divisor;
722 m.m[1][0] = matrix.m[1][0] / divisor;
723 m.m[1][1] = matrix.m[1][1] / divisor;
724 m.m[1][2] = matrix.m[1][2] / divisor;
725 m.m[1][3] = matrix.m[1][3] / divisor;
726 m.m[2][0] = matrix.m[2][0] / divisor;
727 m.m[2][1] = matrix.m[2][1] / divisor;
728 m.m[2][2] = matrix.m[2][2] / divisor;
729 m.m[2][3] = matrix.m[2][3] / divisor;
730 m.m[3][0] = matrix.m[3][0] / divisor;
731 m.m[3][1] = matrix.m[3][1] / divisor;
732 m.m[3][2] = matrix.m[3][2] / divisor;
733 m.m[3][3] = matrix.m[3][3] / divisor;
734 m.flagBits = QMatrix4x4::General;
746 return QtPrivate::fuzzyCompare(m1.m[0][0], m2.m[0][0])
747 && QtPrivate::fuzzyCompare(m1.m[0][1], m2.m[0][1])
748 && QtPrivate::fuzzyCompare(m1.m[0][2], m2.m[0][2])
749 && QtPrivate::fuzzyCompare(m1.m[0][3], m2.m[0][3])
750 && QtPrivate::fuzzyCompare(m1.m[1][0], m2.m[1][0])
751 && QtPrivate::fuzzyCompare(m1.m[1][1], m2.m[1][1])
752 && QtPrivate::fuzzyCompare(m1.m[1][2], m2.m[1][2])
753 && QtPrivate::fuzzyCompare(m1.m[1][3], m2.m[1][3])
754 && QtPrivate::fuzzyCompare(m1.m[2][0], m2.m[2][0])
755 && QtPrivate::fuzzyCompare(m1.m[2][1], m2.m[2][1])
756 && QtPrivate::fuzzyCompare(m1.m[2][2], m2.m[2][2])
757 && QtPrivate::fuzzyCompare(m1.m[2][3], m2.m[2][3])
758 && QtPrivate::fuzzyCompare(m1.m[3][0], m2.m[3][0])
759 && QtPrivate::fuzzyCompare(m1.m[3][1], m2.m[3][1])
760 && QtPrivate::fuzzyCompare(m1.m[3][2], m2.m[3][2])
761 && QtPrivate::fuzzyCompare(m1.m[3][3], m2.m[3][3]);
1037void QMatrix4x4::rotate(
float angle,
float x,
float y,
float z)
1042 if (angle == 90.0f || angle == -270.0f) {
1045 }
else if (angle == -90.0f || angle == 270.0f) {
1048 }
else if (angle == 180.0f || angle == -180.0f) {
1052 float a = qDegreesToRadians(angle);
1063 m[0][0] = (tmp = m[0][0]) * c + m[1][0] * s;
1064 m[1][0] = m[1][0] * c - tmp * s;
1065 m[0][1] = (tmp = m[0][1]) * c + m[1][1] * s;
1066 m[1][1] = m[1][1] * c - tmp * s;
1067 m[0][2] = (tmp = m[0][2]) * c + m[1][2] * s;
1068 m[1][2] = m[1][2] * c - tmp * s;
1069 m[0][3] = (tmp = m[0][3]) * c + m[1][3] * s;
1070 m[1][3] = m[1][3] * c - tmp * s;
1072 flagBits |= Rotation2D;
1075 }
else if (z == 0.0f) {
1080 m[2][0] = (tmp = m[2][0]) * c + m[0][0] * s;
1081 m[0][0] = m[0][0] * c - tmp * s;
1082 m[2][1] = (tmp = m[2][1]) * c + m[0][1] * s;
1083 m[0][1] = m[0][1] * c - tmp * s;
1084 m[2][2] = (tmp = m[2][2]) * c + m[0][2] * s;
1085 m[0][2] = m[0][2] * c - tmp * s;
1086 m[2][3] = (tmp = m[2][3]) * c + m[0][3] * s;
1087 m[0][3] = m[0][3] * c - tmp * s;
1089 flagBits |= Rotation;
1092 }
else if (y == 0.0f && z == 0.0f) {
1097 m[1][0] = (tmp = m[1][0]) * c + m[2][0] * s;
1098 m[2][0] = m[2][0] * c - tmp * s;
1099 m[1][1] = (tmp = m[1][1]) * c + m[2][1] * s;
1100 m[2][1] = m[2][1] * c - tmp * s;
1101 m[1][2] = (tmp = m[1][2]) * c + m[2][2] * s;
1102 m[2][2] = m[2][2] * c - tmp * s;
1103 m[1][3] = (tmp = m[1][3]) * c + m[2][3] * s;
1104 m[2][3] = m[2][3] * c - tmp * s;
1106 flagBits |= Rotation;
1110 double len =
double(x) *
double(x) +
1111 double(y) *
double(y) +
1112 double(z) *
double(z);
1113 if (!qFuzzyCompare(len, 1.0) && !qFuzzyIsNull(len)) {
1114 len = std::sqrt(len);
1115 x =
float(
double(x) / len);
1116 y =
float(
double(y) / len);
1117 z =
float(
double(z) / len);
1119 float ic = 1.0f - c;
1120 Q_DECL_UNINITIALIZED
1121 QMatrix4x4 rot(Qt::Uninitialized);
1122 rot.m[0][0] = x * x * ic + c;
1123 rot.m[1][0] = x * y * ic - z * s;
1124 rot.m[2][0] = x * z * ic + y * s;
1126 rot.m[0][1] = y * x * ic + z * s;
1127 rot.m[1][1] = y * y * ic + c;
1128 rot.m[2][1] = y * z * ic - x * s;
1130 rot.m[0][2] = x * z * ic - y * s;
1131 rot.m[1][2] = y * z * ic + x * s;
1132 rot.m[2][2] = z * z * ic + c;
1138 rot.flagBits = Rotation;
1145void QMatrix4x4::projectedRotate(
float angle,
float x,
float y,
float z,
float distanceToPlane)
1149 if (qIsNull(distanceToPlane))
1150 return rotate(angle, x, y, z);
1155 if (angle == 90.0f || angle == -270.0f) {
1158 }
else if (angle == -90.0f || angle == 270.0f) {
1161 }
else if (angle == 180.0f || angle == -180.0f) {
1165 float a = qDegreesToRadians(angle);
1170 const qreal d = 1.0 / distanceToPlane;
1178 m[0][0] = (tmp = m[0][0]) * c + m[1][0] * s;
1179 m[1][0] = m[1][0] * c - tmp * s;
1180 m[0][1] = (tmp = m[0][1]) * c + m[1][1] * s;
1181 m[1][1] = m[1][1] * c - tmp * s;
1182 m[0][2] = (tmp = m[0][2]) * c + m[1][2] * s;
1183 m[1][2] = m[1][2] * c - tmp * s;
1184 m[0][3] = (tmp = m[0][3]) * c + m[1][3] * s;
1185 m[1][3] = m[1][3] * c - tmp * s;
1187 flagBits |= Rotation2D;
1190 }
else if (z == 0.0f) {
1195 m[0][0] = m[0][0] * c + m[3][0] * s;
1196 m[0][1] = m[0][1] * c + m[3][1] * s;
1197 m[0][2] = m[0][2] * c + m[3][2] * s;
1198 m[0][3] = m[0][3] * c + m[3][3] * s;
1202 }
else if (y == 0.0f && z == 0.0f) {
1207 m[1][0] = m[1][0] * c - m[3][0] * s;
1208 m[1][1] = m[1][1] * c - m[3][1] * s;
1209 m[1][2] = m[1][2] * c - m[3][2] * s;
1210 m[1][3] = m[1][3] * c - m[3][3] * s;
1214 double len =
double(x) *
double(x) +
1215 double(y) *
double(y) +
1216 double(z) *
double(z);
1217 if (!qFuzzyCompare(len, 1.0) && !qFuzzyIsNull(len)) {
1218 len = std::sqrt(len);
1219 x =
float(
double(x) / len);
1220 y =
float(
double(y) / len);
1221 z =
float(
double(z) / len);
1223 const float ic = 1.0f - c;
1224 Q_DECL_UNINITIALIZED
1225 QMatrix4x4 rot(Qt::Uninitialized);
1226 rot.m[0][0] = x * x * ic + c;
1227 rot.m[1][0] = x * y * ic - z * s;
1230 rot.m[0][1] = y * x * ic + z * s;
1231 rot.m[1][1] = y * y * ic + c;
1238 rot.m[0][3] = (x * z * ic - y * s) * -d;
1239 rot.m[1][3] = (y * z * ic + x * s) * -d;
1242 rot.flagBits = General;
1656QTransform QMatrix4x4::toTransform(
float distanceToPlane)
const
1658 if (distanceToPlane == 1024.0f) {
1660 return QTransform(m[0][0], m[0][1], m[0][3] - m[0][2] * inv_dist_to_plane,
1661 m[1][0], m[1][1], m[1][3] - m[1][2] * inv_dist_to_plane,
1662 m[3][0], m[3][1], m[3][3] - m[3][2] * inv_dist_to_plane);
1663 }
else if (distanceToPlane != 0.0f) {
1671 float d = 1.0f / distanceToPlane;
1672 return QTransform(m[0][0], m[0][1], m[0][3] - m[0][2] * d,
1673 m[1][0], m[1][1], m[1][3] - m[1][2] * d,
1674 m[3][0], m[3][1], m[3][3] - m[3][2] * d);
1677 return QTransform(m[0][0], m[0][1], m[0][3],
1678 m[1][0], m[1][1], m[1][3],
1679 m[3][0], m[3][1], m[3][3]);
1749QRect QMatrix4x4::mapRect(
const QRect& rect)
const
1751 if (flagBits < Scale) {
1753 return QRect(qRound(rect.x() + m[3][0]),
1754 qRound(rect.y() + m[3][1]),
1755 rect.width(), rect.height());
1756 }
else if (flagBits < Rotation2D) {
1758 float x = rect.x() * m[0][0] + m[3][0];
1759 float y = rect.y() * m[1][1] + m[3][1];
1760 float w = rect.width() * m[0][0];
1761 float h = rect.height() * m[1][1];
1770 return QRect(qRound(x), qRound(y), qRound(w), qRound(h));
1773 QPoint tl = map(rect.topLeft());
1774 QPoint tr = map(QPoint(rect.x() + rect.width(), rect.y()));
1775 QPoint bl = map(QPoint(rect.x(), rect.y() + rect.height()));
1776 QPoint br = map(QPoint(rect.x() + rect.width(),
1777 rect.y() + rect.height()));
1779 int xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
1780 int xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
1781 int ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
1782 int ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
1784 return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
1795QRectF QMatrix4x4::mapRect(
const QRectF& rect)
const
1797 if (flagBits < Scale) {
1799 return rect.translated(m[3][0], m[3][1]);
1800 }
else if (flagBits < Rotation2D) {
1802 float x = rect.x() * m[0][0] + m[3][0];
1803 float y = rect.y() * m[1][1] + m[3][1];
1804 float w = rect.width() * m[0][0];
1805 float h = rect.height() * m[1][1];
1814 return QRectF(x, y, w, h);
1817 QPointF tl = map(rect.topLeft()); QPointF tr = map(rect.topRight());
1818 QPointF bl = map(rect.bottomLeft()); QPointF br = map(rect.bottomRight());
1820 float xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
1821 float xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
1822 float ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
1823 float ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
1825 return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
1907void QMatrix4x4::optimize()
1911 if (m[0][3] != 0 || m[1][3] != 0 || m[2][3] != 0 || m[3][3] != 1)
1914 flagBits &= ~Perspective;
1917 if (m[3][0] == 0 && m[3][1] == 0 && m[3][2] == 0)
1918 flagBits &= ~Translation;
1921 if (!m[0][2] && !m[1][2] && !m[2][0] && !m[2][1]) {
1922 flagBits &= ~Rotation;
1924 if (!m[0][1] && !m[1][0]) {
1925 flagBits &= ~Rotation2D;
1927 if (m[0][0] == 1 && m[1][1] == 1 && m[2][2] == 1)
1931 const Double4x4 mm = copyToDoubles(m);
1932 double det = matrixDet2(mm, 0, 1, 0, 1);
1933 double lenX = mm[0][0] * mm[0][0] + mm[0][1] * mm[0][1];
1934 double lenY = mm[1][0] * mm[1][0] + mm[1][1] * mm[1][1];
1935 double lenZ = mm[2][2];
1936 if (qFuzzyCompare(det, 1.0) && qFuzzyCompare(lenX, 1.0)
1937 && qFuzzyCompare(lenY, 1.0) && qFuzzyCompare(lenZ, 1.0))
1944 const Double4x4 mm = copyToDoubles(m);
1945 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
1946 double lenX = mm[0][0] * mm[0][0] + mm[0][1] * mm[0][1] + mm[0][2] * mm[0][2];
1947 double lenY = mm[1][0] * mm[1][0] + mm[1][1] * mm[1][1] + mm[1][2] * mm[1][2];
1948 double lenZ = mm[2][0] * mm[2][0] + mm[2][1] * mm[2][1] + mm[2][2] * mm[2][2];
1949 if (qFuzzyCompare(det, 1.0) && qFuzzyCompare(lenX, 1.0)
1950 && qFuzzyCompare(lenY, 1.0) && qFuzzyCompare(lenZ, 1.0))
1969 QDebugStateSaver saver(dbg);
1972 if (m.flagBits == QMatrix4x4::Identity) {
1974 }
else if (m.flagBits == QMatrix4x4::General) {
1977 if ((m.flagBits & QMatrix4x4::Translation) != 0)
1978 bits +=
"Translation,";
1979 if ((m.flagBits & QMatrix4x4::Scale) != 0)
1981 if ((m.flagBits & QMatrix4x4::Rotation2D) != 0)
1982 bits +=
"Rotation2D,";
1983 if ((m.flagBits & QMatrix4x4::Rotation) != 0)
1984 bits +=
"Rotation,";
1985 if ((m.flagBits & QMatrix4x4::Perspective) != 0)
1986 bits +=
"Perspective,";
1991 dbg.nospace() <<
"QMatrix4x4(type:" << bits.constData() << Qt::endl
1992 << qSetFieldWidth(10)
1993 << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << Qt::endl
1994 << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << Qt::endl
1995 << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << Qt::endl
1996 << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << Qt::endl
1997 << qSetFieldWidth(0) <<
')';