323QMatrix4x4 QMatrix4x4::inverted(
bool *invertible)
const
326 if (flagBits == Identity) {
330 }
else if (flagBits == Translation) {
332 inv.m[3][0] = -m[3][0];
333 inv.m[3][1] = -m[3][1];
334 inv.m[3][2] = -m[3][2];
335 inv.flagBits = Translation;
339 }
else if (flagBits < Rotation2D) {
341 if (m[0][0] == 0 || m[1][1] == 0 || m[2][2] == 0) {
347 inv.m[0][0] = 1.0f / m[0][0];
348 inv.m[1][1] = 1.0f / m[1][1];
349 inv.m[2][2] = 1.0f / m[2][2];
350 inv.m[3][0] = -m[3][0] * inv.m[0][0];
351 inv.m[3][1] = -m[3][1] * inv.m[1][1];
352 inv.m[3][2] = -m[3][2] * inv.m[2][2];
353 inv.flagBits = flagBits;
358 }
else if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity) {
361 return orthonormalInverse();
362 }
else if (flagBits < Perspective) {
364 QMatrix4x4 inv(Qt::Uninitialized);
366 const Double4x4 mm = copyToDoubles(m);
368 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
376 inv.m[0][0] = matrixDet2(mm, 1, 2, 1, 2) * det;
377 inv.m[0][1] = -matrixDet2(mm, 0, 2, 1, 2) * det;
378 inv.m[0][2] = matrixDet2(mm, 0, 1, 1, 2) * det;
380 inv.m[1][0] = -matrixDet2(mm, 1, 2, 0, 2) * det;
381 inv.m[1][1] = matrixDet2(mm, 0, 2, 0, 2) * det;
382 inv.m[1][2] = -matrixDet2(mm, 0, 1, 0, 2) * det;
384 inv.m[2][0] = matrixDet2(mm, 1, 2, 0, 1) * det;
385 inv.m[2][1] = -matrixDet2(mm, 0, 2, 0, 1) * det;
386 inv.m[2][2] = matrixDet2(mm, 0, 1, 0, 1) * det;
388 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];
389 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];
390 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];
392 inv.flagBits = flagBits;
400 QMatrix4x4 inv(Qt::Uninitialized);
402 const Double4x4 mm = copyToDoubles(m);
404 double det = matrixDet4(mm);
412 inv.m[0][0] = matrixDet3(mm, 1, 2, 3, 1, 2, 3) * det;
413 inv.m[0][1] = -matrixDet3(mm, 0, 2, 3, 1, 2, 3) * det;
414 inv.m[0][2] = matrixDet3(mm, 0, 1, 3, 1, 2, 3) * det;
415 inv.m[0][3] = -matrixDet3(mm, 0, 1, 2, 1, 2, 3) * det;
416 inv.m[1][0] = -matrixDet3(mm, 1, 2, 3, 0, 2, 3) * det;
417 inv.m[1][1] = matrixDet3(mm, 0, 2, 3, 0, 2, 3) * det;
418 inv.m[1][2] = -matrixDet3(mm, 0, 1, 3, 0, 2, 3) * det;
419 inv.m[1][3] = matrixDet3(mm, 0, 1, 2, 0, 2, 3) * det;
420 inv.m[2][0] = matrixDet3(mm, 1, 2, 3, 0, 1, 3) * det;
421 inv.m[2][1] = -matrixDet3(mm, 0, 2, 3, 0, 1, 3) * det;
422 inv.m[2][2] = matrixDet3(mm, 0, 1, 3, 0, 1, 3) * det;
423 inv.m[2][3] = -matrixDet3(mm, 0, 1, 2, 0, 1, 3) * det;
424 inv.m[3][0] = -matrixDet3(mm, 1, 2, 3, 0, 1, 2) * det;
425 inv.m[3][1] = matrixDet3(mm, 0, 2, 3, 0, 1, 2) * det;
426 inv.m[3][2] = -matrixDet3(mm, 0, 1, 3, 0, 1, 2) * det;
427 inv.m[3][3] = matrixDet3(mm, 0, 1, 2, 0, 1, 2) * det;
428 inv.flagBits = flagBits;
443QMatrix3x3 QMatrix4x4::normalMatrix()
const
448 if (flagBits < Scale) {
451 }
else if (flagBits < Rotation2D) {
453 if (m[0][0] == 0.0f || m[1][1] == 0.0f || m[2][2] == 0.0f)
455 inv.data()[0] = 1.0f / m[0][0];
456 inv.data()[4] = 1.0f / m[1][1];
457 inv.data()[8] = 1.0f / m[2][2];
459 }
else if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity) {
460 float *invm = inv.data();
461 invm[0 + 0 * 3] = m[0][0];
462 invm[1 + 0 * 3] = m[0][1];
463 invm[2 + 0 * 3] = m[0][2];
464 invm[0 + 1 * 3] = m[1][0];
465 invm[1 + 1 * 3] = m[1][1];
466 invm[2 + 1 * 3] = m[1][2];
467 invm[0 + 2 * 3] = m[2][0];
468 invm[1 + 2 * 3] = m[2][1];
469 invm[2 + 2 * 3] = m[2][2];
473 const Double4x4 mm = copyToDoubles(m);
474 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
479 float *invm = inv.data();
482 invm[0 + 0 * 3] = (mm[1][1] * mm[2][2] - mm[2][1] * mm[1][2]) * det;
483 invm[1 + 0 * 3] = -(mm[1][0] * mm[2][2] - mm[1][2] * mm[2][0]) * det;
484 invm[2 + 0 * 3] = (mm[1][0] * mm[2][1] - mm[1][1] * mm[2][0]) * det;
485 invm[0 + 1 * 3] = -(mm[0][1] * mm[2][2] - mm[2][1] * mm[0][2]) * det;
486 invm[1 + 1 * 3] = (mm[0][0] * mm[2][2] - mm[0][2] * mm[2][0]) * det;
487 invm[2 + 1 * 3] = -(mm[0][0] * mm[2][1] - mm[0][1] * mm[2][0]) * det;
488 invm[0 + 2 * 3] = (mm[0][1] * mm[1][2] - mm[0][2] * mm[1][1]) * det;
489 invm[1 + 2 * 3] = -(mm[0][0] * mm[1][2] - mm[0][2] * mm[1][0]) * det;
490 invm[2 + 2 * 3] = (mm[0][0] * mm[1][1] - mm[1][0] * mm[0][1]) * det;
715QMatrix4x4 operator/(
const QMatrix4x4& matrix,
float divisor)
718 QMatrix4x4 m(Qt::Uninitialized);
719 m.m[0][0] = matrix.m[0][0] / divisor;
720 m.m[0][1] = matrix.m[0][1] / divisor;
721 m.m[0][2] = matrix.m[0][2] / divisor;
722 m.m[0][3] = matrix.m[0][3] / divisor;
723 m.m[1][0] = matrix.m[1][0] / divisor;
724 m.m[1][1] = matrix.m[1][1] / divisor;
725 m.m[1][2] = matrix.m[1][2] / divisor;
726 m.m[1][3] = matrix.m[1][3] / divisor;
727 m.m[2][0] = matrix.m[2][0] / divisor;
728 m.m[2][1] = matrix.m[2][1] / divisor;
729 m.m[2][2] = matrix.m[2][2] / divisor;
730 m.m[2][3] = matrix.m[2][3] / divisor;
731 m.m[3][0] = matrix.m[3][0] / divisor;
732 m.m[3][1] = matrix.m[3][1] / divisor;
733 m.m[3][2] = matrix.m[3][2] / divisor;
734 m.m[3][3] = matrix.m[3][3] / divisor;
735 m.flagBits = QMatrix4x4::General;
747 return QtPrivate::fuzzyCompare(m1.m[0][0], m2.m[0][0])
748 && QtPrivate::fuzzyCompare(m1.m[0][1], m2.m[0][1])
749 && QtPrivate::fuzzyCompare(m1.m[0][2], m2.m[0][2])
750 && QtPrivate::fuzzyCompare(m1.m[0][3], m2.m[0][3])
751 && QtPrivate::fuzzyCompare(m1.m[1][0], m2.m[1][0])
752 && QtPrivate::fuzzyCompare(m1.m[1][1], m2.m[1][1])
753 && QtPrivate::fuzzyCompare(m1.m[1][2], m2.m[1][2])
754 && QtPrivate::fuzzyCompare(m1.m[1][3], m2.m[1][3])
755 && QtPrivate::fuzzyCompare(m1.m[2][0], m2.m[2][0])
756 && QtPrivate::fuzzyCompare(m1.m[2][1], m2.m[2][1])
757 && QtPrivate::fuzzyCompare(m1.m[2][2], m2.m[2][2])
758 && QtPrivate::fuzzyCompare(m1.m[2][3], m2.m[2][3])
759 && QtPrivate::fuzzyCompare(m1.m[3][0], m2.m[3][0])
760 && QtPrivate::fuzzyCompare(m1.m[3][1], m2.m[3][1])
761 && QtPrivate::fuzzyCompare(m1.m[3][2], m2.m[3][2])
762 && QtPrivate::fuzzyCompare(m1.m[3][3], m2.m[3][3]);
1038void QMatrix4x4::rotate(
float angle,
float x,
float y,
float z)
1043 if (angle == 90.0f || angle == -270.0f) {
1046 }
else if (angle == -90.0f || angle == 270.0f) {
1049 }
else if (angle == 180.0f || angle == -180.0f) {
1053 float a = qDegreesToRadians(angle);
1064 m[0][0] = (tmp = m[0][0]) * c + m[1][0] * s;
1065 m[1][0] = m[1][0] * c - tmp * s;
1066 m[0][1] = (tmp = m[0][1]) * c + m[1][1] * s;
1067 m[1][1] = m[1][1] * c - tmp * s;
1068 m[0][2] = (tmp = m[0][2]) * c + m[1][2] * s;
1069 m[1][2] = m[1][2] * c - tmp * s;
1070 m[0][3] = (tmp = m[0][3]) * c + m[1][3] * s;
1071 m[1][3] = m[1][3] * c - tmp * s;
1073 flagBits |= Rotation2D;
1076 }
else if (z == 0.0f) {
1081 m[2][0] = (tmp = m[2][0]) * c + m[0][0] * s;
1082 m[0][0] = m[0][0] * c - tmp * s;
1083 m[2][1] = (tmp = m[2][1]) * c + m[0][1] * s;
1084 m[0][1] = m[0][1] * c - tmp * s;
1085 m[2][2] = (tmp = m[2][2]) * c + m[0][2] * s;
1086 m[0][2] = m[0][2] * c - tmp * s;
1087 m[2][3] = (tmp = m[2][3]) * c + m[0][3] * s;
1088 m[0][3] = m[0][3] * c - tmp * s;
1090 flagBits |= Rotation;
1093 }
else if (y == 0.0f && z == 0.0f) {
1098 m[1][0] = (tmp = m[1][0]) * c + m[2][0] * s;
1099 m[2][0] = m[2][0] * c - tmp * s;
1100 m[1][1] = (tmp = m[1][1]) * c + m[2][1] * s;
1101 m[2][1] = m[2][1] * c - tmp * s;
1102 m[1][2] = (tmp = m[1][2]) * c + m[2][2] * s;
1103 m[2][2] = m[2][2] * c - tmp * s;
1104 m[1][3] = (tmp = m[1][3]) * c + m[2][3] * s;
1105 m[2][3] = m[2][3] * c - tmp * s;
1107 flagBits |= Rotation;
1111 double len =
double(x) *
double(x) +
1112 double(y) *
double(y) +
1113 double(z) *
double(z);
1114 if (!qFuzzyCompare(len, 1.0) && !qFuzzyIsNull(len)) {
1115 len = std::sqrt(len);
1116 x =
float(
double(x) / len);
1117 y =
float(
double(y) / len);
1118 z =
float(
double(z) / len);
1120 float ic = 1.0f - c;
1121 Q_DECL_UNINITIALIZED
1122 QMatrix4x4 rot(Qt::Uninitialized);
1123 rot.m[0][0] = x * x * ic + c;
1124 rot.m[1][0] = x * y * ic - z * s;
1125 rot.m[2][0] = x * z * ic + y * s;
1127 rot.m[0][1] = y * x * ic + z * s;
1128 rot.m[1][1] = y * y * ic + c;
1129 rot.m[2][1] = y * z * ic - x * s;
1131 rot.m[0][2] = x * z * ic - y * s;
1132 rot.m[1][2] = y * z * ic + x * s;
1133 rot.m[2][2] = z * z * ic + c;
1139 rot.flagBits = Rotation;
1146void QMatrix4x4::projectedRotate(
float angle,
float x,
float y,
float z,
float distanceToPlane)
1150 if (qIsNull(distanceToPlane))
1151 return rotate(angle, x, y, z);
1156 if (angle == 90.0f || angle == -270.0f) {
1159 }
else if (angle == -90.0f || angle == 270.0f) {
1162 }
else if (angle == 180.0f || angle == -180.0f) {
1166 float a = qDegreesToRadians(angle);
1171 const qreal d = 1.0 / distanceToPlane;
1179 m[0][0] = (tmp = m[0][0]) * c + m[1][0] * s;
1180 m[1][0] = m[1][0] * c - tmp * s;
1181 m[0][1] = (tmp = m[0][1]) * c + m[1][1] * s;
1182 m[1][1] = m[1][1] * c - tmp * s;
1183 m[0][2] = (tmp = m[0][2]) * c + m[1][2] * s;
1184 m[1][2] = m[1][2] * c - tmp * s;
1185 m[0][3] = (tmp = m[0][3]) * c + m[1][3] * s;
1186 m[1][3] = m[1][3] * c - tmp * s;
1188 flagBits |= Rotation2D;
1191 }
else if (z == 0.0f) {
1196 m[0][0] = m[0][0] * c + m[3][0] * s;
1197 m[0][1] = m[0][1] * c + m[3][1] * s;
1198 m[0][2] = m[0][2] * c + m[3][2] * s;
1199 m[0][3] = m[0][3] * c + m[3][3] * s;
1203 }
else if (y == 0.0f && z == 0.0f) {
1208 m[1][0] = m[1][0] * c - m[3][0] * s;
1209 m[1][1] = m[1][1] * c - m[3][1] * s;
1210 m[1][2] = m[1][2] * c - m[3][2] * s;
1211 m[1][3] = m[1][3] * c - m[3][3] * s;
1215 double len =
double(x) *
double(x) +
1216 double(y) *
double(y) +
1217 double(z) *
double(z);
1218 if (!qFuzzyCompare(len, 1.0) && !qFuzzyIsNull(len)) {
1219 len = std::sqrt(len);
1220 x =
float(
double(x) / len);
1221 y =
float(
double(y) / len);
1222 z =
float(
double(z) / len);
1224 const float ic = 1.0f - c;
1225 Q_DECL_UNINITIALIZED
1226 QMatrix4x4 rot(Qt::Uninitialized);
1227 rot.m[0][0] = x * x * ic + c;
1228 rot.m[1][0] = x * y * ic - z * s;
1231 rot.m[0][1] = y * x * ic + z * s;
1232 rot.m[1][1] = y * y * ic + c;
1239 rot.m[0][3] = (x * z * ic - y * s) * -d;
1240 rot.m[1][3] = (y * z * ic + x * s) * -d;
1243 rot.flagBits = General;
1657QTransform QMatrix4x4::toTransform(
float distanceToPlane)
const
1659 if (distanceToPlane == 1024.0f) {
1661 return QTransform(m[0][0], m[0][1], m[0][3] - m[0][2] * inv_dist_to_plane,
1662 m[1][0], m[1][1], m[1][3] - m[1][2] * inv_dist_to_plane,
1663 m[3][0], m[3][1], m[3][3] - m[3][2] * inv_dist_to_plane);
1664 }
else if (distanceToPlane != 0.0f) {
1672 float d = 1.0f / distanceToPlane;
1673 return QTransform(m[0][0], m[0][1], m[0][3] - m[0][2] * d,
1674 m[1][0], m[1][1], m[1][3] - m[1][2] * d,
1675 m[3][0], m[3][1], m[3][3] - m[3][2] * d);
1678 return QTransform(m[0][0], m[0][1], m[0][3],
1679 m[1][0], m[1][1], m[1][3],
1680 m[3][0], m[3][1], m[3][3]);
1750QRect QMatrix4x4::mapRect(
const QRect& rect)
const
1752 if (flagBits < Scale) {
1754 return QRect(qRound(rect.x() + m[3][0]),
1755 qRound(rect.y() + m[3][1]),
1756 rect.width(), rect.height());
1757 }
else if (flagBits < Rotation2D) {
1759 float x = rect.x() * m[0][0] + m[3][0];
1760 float y = rect.y() * m[1][1] + m[3][1];
1761 float w = rect.width() * m[0][0];
1762 float h = rect.height() * m[1][1];
1771 return QRect(qRound(x), qRound(y), qRound(w), qRound(h));
1774 QPoint tl = map(rect.topLeft());
1775 QPoint tr = map(QPoint(rect.x() + rect.width(), rect.y()));
1776 QPoint bl = map(QPoint(rect.x(), rect.y() + rect.height()));
1777 QPoint br = map(QPoint(rect.x() + rect.width(),
1778 rect.y() + rect.height()));
1780 int xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
1781 int xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
1782 int ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
1783 int ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
1785 return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
1796QRectF QMatrix4x4::mapRect(
const QRectF& rect)
const
1798 if (flagBits < Scale) {
1800 return rect.translated(m[3][0], m[3][1]);
1801 }
else if (flagBits < Rotation2D) {
1803 float x = rect.x() * m[0][0] + m[3][0];
1804 float y = rect.y() * m[1][1] + m[3][1];
1805 float w = rect.width() * m[0][0];
1806 float h = rect.height() * m[1][1];
1815 return QRectF(x, y, w, h);
1818 QPointF tl = map(rect.topLeft()); QPointF tr = map(rect.topRight());
1819 QPointF bl = map(rect.bottomLeft()); QPointF br = map(rect.bottomRight());
1821 float xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
1822 float xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
1823 float ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
1824 float ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
1826 return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
1908void QMatrix4x4::optimize()
1912 if (m[0][3] != 0 || m[1][3] != 0 || m[2][3] != 0 || m[3][3] != 1)
1915 flagBits &= ~Perspective;
1918 if (m[3][0] == 0 && m[3][1] == 0 && m[3][2] == 0)
1919 flagBits &= ~Translation;
1922 if (!m[0][2] && !m[1][2] && !m[2][0] && !m[2][1]) {
1923 flagBits &= ~Rotation;
1925 if (!m[0][1] && !m[1][0]) {
1926 flagBits &= ~Rotation2D;
1928 if (m[0][0] == 1 && m[1][1] == 1 && m[2][2] == 1)
1932 const Double4x4 mm = copyToDoubles(m);
1933 double det = matrixDet2(mm, 0, 1, 0, 1);
1934 double lenX = mm[0][0] * mm[0][0] + mm[0][1] * mm[0][1];
1935 double lenY = mm[1][0] * mm[1][0] + mm[1][1] * mm[1][1];
1936 double lenZ = mm[2][2];
1937 if (qFuzzyCompare(det, 1.0) && qFuzzyCompare(lenX, 1.0)
1938 && qFuzzyCompare(lenY, 1.0) && qFuzzyCompare(lenZ, 1.0))
1945 const Double4x4 mm = copyToDoubles(m);
1946 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
1947 double lenX = mm[0][0] * mm[0][0] + mm[0][1] * mm[0][1] + mm[0][2] * mm[0][2];
1948 double lenY = mm[1][0] * mm[1][0] + mm[1][1] * mm[1][1] + mm[1][2] * mm[1][2];
1949 double lenZ = mm[2][0] * mm[2][0] + mm[2][1] * mm[2][1] + mm[2][2] * mm[2][2];
1950 if (qFuzzyCompare(det, 1.0) && qFuzzyCompare(lenX, 1.0)
1951 && qFuzzyCompare(lenY, 1.0) && qFuzzyCompare(lenZ, 1.0))
1970 QDebugStateSaver saver(dbg);
1973 if (m.flagBits == QMatrix4x4::Identity) {
1975 }
else if (m.flagBits == QMatrix4x4::General) {
1978 if ((m.flagBits & QMatrix4x4::Translation) != 0)
1979 bits +=
"Translation,";
1980 if ((m.flagBits & QMatrix4x4::Scale) != 0)
1982 if ((m.flagBits & QMatrix4x4::Rotation2D) != 0)
1983 bits +=
"Rotation2D,";
1984 if ((m.flagBits & QMatrix4x4::Rotation) != 0)
1985 bits +=
"Rotation,";
1986 if ((m.flagBits & QMatrix4x4::Perspective) != 0)
1987 bits +=
"Perspective,";
1992 dbg.nospace() <<
"QMatrix4x4(type:" << bits.constData() << Qt::endl
1993 << qSetFieldWidth(10)
1994 << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << Qt::endl
1995 << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << Qt::endl
1996 << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << Qt::endl
1997 << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << Qt::endl
1998 << qSetFieldWidth(0) <<
')';