316QMatrix4x4 QMatrix4x4::inverted(
bool *invertible)
const
319 if (flagBits == Identity) {
323 }
else if (flagBits == Translation) {
325 inv.m[3][0] = -m[3][0];
326 inv.m[3][1] = -m[3][1];
327 inv.m[3][2] = -m[3][2];
328 inv.flagBits = Translation;
332 }
else if (flagBits < Rotation2D) {
334 if (m[0][0] == 0 || m[1][1] == 0 || m[2][2] == 0) {
340 inv.m[0][0] = 1.0f / m[0][0];
341 inv.m[1][1] = 1.0f / m[1][1];
342 inv.m[2][2] = 1.0f / m[2][2];
343 inv.m[3][0] = -m[3][0] * inv.m[0][0];
344 inv.m[3][1] = -m[3][1] * inv.m[1][1];
345 inv.m[3][2] = -m[3][2] * inv.m[2][2];
346 inv.flagBits = flagBits;
351 }
else if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity) {
354 return orthonormalInverse();
355 }
else if (flagBits < Perspective) {
356 QMatrix4x4 inv(Qt::Uninitialized);
359 copyToDoubles(m, mm);
361 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
369 inv.m[0][0] = matrixDet2(mm, 1, 2, 1, 2) * det;
370 inv.m[0][1] = -matrixDet2(mm, 0, 2, 1, 2) * det;
371 inv.m[0][2] = matrixDet2(mm, 0, 1, 1, 2) * det;
373 inv.m[1][0] = -matrixDet2(mm, 1, 2, 0, 2) * det;
374 inv.m[1][1] = matrixDet2(mm, 0, 2, 0, 2) * det;
375 inv.m[1][2] = -matrixDet2(mm, 0, 1, 0, 2) * det;
377 inv.m[2][0] = matrixDet2(mm, 1, 2, 0, 1) * det;
378 inv.m[2][1] = -matrixDet2(mm, 0, 2, 0, 1) * det;
379 inv.m[2][2] = matrixDet2(mm, 0, 1, 0, 1) * det;
381 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];
382 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];
383 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];
385 inv.flagBits = flagBits;
392 QMatrix4x4 inv(Qt::Uninitialized);
395 copyToDoubles(m, mm);
397 double det = matrixDet4(mm);
405 inv.m[0][0] = matrixDet3(mm, 1, 2, 3, 1, 2, 3) * det;
406 inv.m[0][1] = -matrixDet3(mm, 0, 2, 3, 1, 2, 3) * det;
407 inv.m[0][2] = matrixDet3(mm, 0, 1, 3, 1, 2, 3) * det;
408 inv.m[0][3] = -matrixDet3(mm, 0, 1, 2, 1, 2, 3) * det;
409 inv.m[1][0] = -matrixDet3(mm, 1, 2, 3, 0, 2, 3) * det;
410 inv.m[1][1] = matrixDet3(mm, 0, 2, 3, 0, 2, 3) * det;
411 inv.m[1][2] = -matrixDet3(mm, 0, 1, 3, 0, 2, 3) * det;
412 inv.m[1][3] = matrixDet3(mm, 0, 1, 2, 0, 2, 3) * det;
413 inv.m[2][0] = matrixDet3(mm, 1, 2, 3, 0, 1, 3) * det;
414 inv.m[2][1] = -matrixDet3(mm, 0, 2, 3, 0, 1, 3) * det;
415 inv.m[2][2] = matrixDet3(mm, 0, 1, 3, 0, 1, 3) * det;
416 inv.m[2][3] = -matrixDet3(mm, 0, 1, 2, 0, 1, 3) * det;
417 inv.m[3][0] = -matrixDet3(mm, 1, 2, 3, 0, 1, 2) * det;
418 inv.m[3][1] = matrixDet3(mm, 0, 2, 3, 0, 1, 2) * det;
419 inv.m[3][2] = -matrixDet3(mm, 0, 1, 3, 0, 1, 2) * det;
420 inv.m[3][3] = matrixDet3(mm, 0, 1, 2, 0, 1, 2) * det;
421 inv.flagBits = flagBits;
436QMatrix3x3 QMatrix4x4::normalMatrix()
const
441 if (flagBits < Scale) {
444 }
else if (flagBits < Rotation2D) {
446 if (m[0][0] == 0.0f || m[1][1] == 0.0f || m[2][2] == 0.0f)
448 inv.data()[0] = 1.0f / m[0][0];
449 inv.data()[4] = 1.0f / m[1][1];
450 inv.data()[8] = 1.0f / m[2][2];
452 }
else if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity) {
453 float *invm = inv.data();
454 invm[0 + 0 * 3] = m[0][0];
455 invm[1 + 0 * 3] = m[0][1];
456 invm[2 + 0 * 3] = m[0][2];
457 invm[0 + 1 * 3] = m[1][0];
458 invm[1 + 1 * 3] = m[1][1];
459 invm[2 + 1 * 3] = m[1][2];
460 invm[0 + 2 * 3] = m[2][0];
461 invm[1 + 2 * 3] = m[2][1];
462 invm[2 + 2 * 3] = m[2][2];
467 copyToDoubles(m, mm);
468 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
473 float *invm = inv.data();
476 invm[0 + 0 * 3] = (mm[1][1] * mm[2][2] - mm[2][1] * mm[1][2]) * det;
477 invm[1 + 0 * 3] = -(mm[1][0] * mm[2][2] - mm[1][2] * mm[2][0]) * det;
478 invm[2 + 0 * 3] = (mm[1][0] * mm[2][1] - mm[1][1] * mm[2][0]) * det;
479 invm[0 + 1 * 3] = -(mm[0][1] * mm[2][2] - mm[2][1] * mm[0][2]) * det;
480 invm[1 + 1 * 3] = (mm[0][0] * mm[2][2] - mm[0][2] * mm[2][0]) * det;
481 invm[2 + 1 * 3] = -(mm[0][0] * mm[2][1] - mm[0][1] * mm[2][0]) * det;
482 invm[0 + 2 * 3] = (mm[0][1] * mm[1][2] - mm[0][2] * mm[1][1]) * det;
483 invm[1 + 2 * 3] = -(mm[0][0] * mm[1][2] - mm[0][2] * mm[1][0]) * det;
484 invm[2 + 2 * 3] = (mm[0][0] * mm[1][1] - mm[1][0] * mm[0][1]) * det;
739 return qFuzzyCompare(m1.m[0][0], m2.m[0][0]) &&
740 qFuzzyCompare(m1.m[0][1], m2.m[0][1]) &&
741 qFuzzyCompare(m1.m[0][2], m2.m[0][2]) &&
742 qFuzzyCompare(m1.m[0][3], m2.m[0][3]) &&
743 qFuzzyCompare(m1.m[1][0], m2.m[1][0]) &&
744 qFuzzyCompare(m1.m[1][1], m2.m[1][1]) &&
745 qFuzzyCompare(m1.m[1][2], m2.m[1][2]) &&
746 qFuzzyCompare(m1.m[1][3], m2.m[1][3]) &&
747 qFuzzyCompare(m1.m[2][0], m2.m[2][0]) &&
748 qFuzzyCompare(m1.m[2][1], m2.m[2][1]) &&
749 qFuzzyCompare(m1.m[2][2], m2.m[2][2]) &&
750 qFuzzyCompare(m1.m[2][3], m2.m[2][3]) &&
751 qFuzzyCompare(m1.m[3][0], m2.m[3][0]) &&
752 qFuzzyCompare(m1.m[3][1], m2.m[3][1]) &&
753 qFuzzyCompare(m1.m[3][2], m2.m[3][2]) &&
754 qFuzzyCompare(m1.m[3][3], m2.m[3][3]);
1059void QMatrix4x4::rotate(
float angle,
float x,
float y,
float z)
1064 if (angle == 90.0f || angle == -270.0f) {
1067 }
else if (angle == -90.0f || angle == 270.0f) {
1070 }
else if (angle == 180.0f || angle == -180.0f) {
1074 float a = qDegreesToRadians(angle);
1085 m[0][0] = (tmp = m[0][0]) * c + m[1][0] * s;
1086 m[1][0] = m[1][0] * c - tmp * s;
1087 m[0][1] = (tmp = m[0][1]) * c + m[1][1] * s;
1088 m[1][1] = m[1][1] * c - tmp * s;
1089 m[0][2] = (tmp = m[0][2]) * c + m[1][2] * s;
1090 m[1][2] = m[1][2] * c - tmp * s;
1091 m[0][3] = (tmp = m[0][3]) * c + m[1][3] * s;
1092 m[1][3] = m[1][3] * c - tmp * s;
1094 flagBits |= Rotation2D;
1097 }
else if (z == 0.0f) {
1102 m[2][0] = (tmp = m[2][0]) * c + m[0][0] * s;
1103 m[0][0] = m[0][0] * c - tmp * s;
1104 m[2][1] = (tmp = m[2][1]) * c + m[0][1] * s;
1105 m[0][1] = m[0][1] * c - tmp * s;
1106 m[2][2] = (tmp = m[2][2]) * c + m[0][2] * s;
1107 m[0][2] = m[0][2] * c - tmp * s;
1108 m[2][3] = (tmp = m[2][3]) * c + m[0][3] * s;
1109 m[0][3] = m[0][3] * c - tmp * s;
1111 flagBits |= Rotation;
1114 }
else if (y == 0.0f && z == 0.0f) {
1119 m[1][0] = (tmp = m[1][0]) * c + m[2][0] * s;
1120 m[2][0] = m[2][0] * c - tmp * s;
1121 m[1][1] = (tmp = m[1][1]) * c + m[2][1] * s;
1122 m[2][1] = m[2][1] * c - tmp * s;
1123 m[1][2] = (tmp = m[1][2]) * c + m[2][2] * s;
1124 m[2][2] = m[2][2] * c - tmp * s;
1125 m[1][3] = (tmp = m[1][3]) * c + m[2][3] * s;
1126 m[2][3] = m[2][3] * c - tmp * s;
1128 flagBits |= Rotation;
1132 double len =
double(x) *
double(x) +
1133 double(y) *
double(y) +
1134 double(z) *
double(z);
1135 if (!qFuzzyCompare(len, 1.0) && !qFuzzyIsNull(len)) {
1136 len = std::sqrt(len);
1137 x =
float(
double(x) / len);
1138 y =
float(
double(y) / len);
1139 z =
float(
double(z) / len);
1141 float ic = 1.0f - c;
1142 QMatrix4x4 rot(Qt::Uninitialized);
1143 rot.m[0][0] = x * x * ic + c;
1144 rot.m[1][0] = x * y * ic - z * s;
1145 rot.m[2][0] = x * z * ic + y * s;
1147 rot.m[0][1] = y * x * ic + z * s;
1148 rot.m[1][1] = y * y * ic + c;
1149 rot.m[2][1] = y * z * ic - x * s;
1151 rot.m[0][2] = x * z * ic - y * s;
1152 rot.m[1][2] = y * z * ic + x * s;
1153 rot.m[2][2] = z * z * ic + c;
1159 rot.flagBits = Rotation;
1166void QMatrix4x4::projectedRotate(
float angle,
float x,
float y,
float z,
float distanceToPlane)
1170 if (qIsNull(distanceToPlane))
1171 return rotate(angle, x, y, z);
1176 if (angle == 90.0f || angle == -270.0f) {
1179 }
else if (angle == -90.0f || angle == 270.0f) {
1182 }
else if (angle == 180.0f || angle == -180.0f) {
1186 float a = qDegreesToRadians(angle);
1191 const qreal d = 1.0 / distanceToPlane;
1199 m[0][0] = (tmp = m[0][0]) * c + m[1][0] * s;
1200 m[1][0] = m[1][0] * c - tmp * s;
1201 m[0][1] = (tmp = m[0][1]) * c + m[1][1] * s;
1202 m[1][1] = m[1][1] * c - tmp * s;
1203 m[0][2] = (tmp = m[0][2]) * c + m[1][2] * s;
1204 m[1][2] = m[1][2] * c - tmp * s;
1205 m[0][3] = (tmp = m[0][3]) * c + m[1][3] * s;
1206 m[1][3] = m[1][3] * c - tmp * s;
1208 flagBits |= Rotation2D;
1211 }
else if (z == 0.0f) {
1216 m[0][0] = m[0][0] * c + m[3][0] * s;
1217 m[0][1] = m[0][1] * c + m[3][1] * s;
1218 m[0][2] = m[0][2] * c + m[3][2] * s;
1219 m[0][3] = m[0][3] * c + m[3][3] * s;
1223 }
else if (y == 0.0f && z == 0.0f) {
1228 m[1][0] = m[1][0] * c - m[3][0] * s;
1229 m[1][1] = m[1][1] * c - m[3][1] * s;
1230 m[1][2] = m[1][2] * c - m[3][2] * s;
1231 m[1][3] = m[1][3] * c - m[3][3] * s;
1235 double len =
double(x) *
double(x) +
1236 double(y) *
double(y) +
1237 double(z) *
double(z);
1238 if (!qFuzzyCompare(len, 1.0) && !qFuzzyIsNull(len)) {
1239 len = std::sqrt(len);
1240 x =
float(
double(x) / len);
1241 y =
float(
double(y) / len);
1242 z =
float(
double(z) / len);
1244 const float ic = 1.0f - c;
1245 QMatrix4x4 rot(Qt::Uninitialized);
1246 rot.m[0][0] = x * x * ic + c;
1247 rot.m[1][0] = x * y * ic - z * s;
1250 rot.m[0][1] = y * x * ic + z * s;
1251 rot.m[1][1] = y * y * ic + c;
1258 rot.m[0][3] = (x * z * ic - y * s) * -d;
1259 rot.m[1][3] = (y * z * ic + x * s) * -d;
1262 rot.flagBits = General;
1670QTransform QMatrix4x4::toTransform(
float distanceToPlane)
const
1672 if (distanceToPlane == 1024.0f) {
1674 return QTransform(m[0][0], m[0][1], m[0][3] - m[0][2] * inv_dist_to_plane,
1675 m[1][0], m[1][1], m[1][3] - m[1][2] * inv_dist_to_plane,
1676 m[3][0], m[3][1], m[3][3] - m[3][2] * inv_dist_to_plane);
1677 }
else if (distanceToPlane != 0.0f) {
1685 float d = 1.0f / distanceToPlane;
1686 return QTransform(m[0][0], m[0][1], m[0][3] - m[0][2] * d,
1687 m[1][0], m[1][1], m[1][3] - m[1][2] * d,
1688 m[3][0], m[3][1], m[3][3] - m[3][2] * d);
1691 return QTransform(m[0][0], m[0][1], m[0][3],
1692 m[1][0], m[1][1], m[1][3],
1693 m[3][0], m[3][1], m[3][3]);
1763QRect QMatrix4x4::mapRect(
const QRect& rect)
const
1765 if (flagBits < Scale) {
1767 return QRect(qRound(rect.x() + m[3][0]),
1768 qRound(rect.y() + m[3][1]),
1769 rect.width(), rect.height());
1770 }
else if (flagBits < Rotation2D) {
1772 float x = rect.x() * m[0][0] + m[3][0];
1773 float y = rect.y() * m[1][1] + m[3][1];
1774 float w = rect.width() * m[0][0];
1775 float h = rect.height() * m[1][1];
1784 return QRect(qRound(x), qRound(y), qRound(w), qRound(h));
1787 QPoint tl = map(rect.topLeft());
1788 QPoint tr = map(QPoint(rect.x() + rect.width(), rect.y()));
1789 QPoint bl = map(QPoint(rect.x(), rect.y() + rect.height()));
1790 QPoint br = map(QPoint(rect.x() + rect.width(),
1791 rect.y() + rect.height()));
1793 int xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
1794 int xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
1795 int ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
1796 int ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
1798 return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
1809QRectF QMatrix4x4::mapRect(
const QRectF& rect)
const
1811 if (flagBits < Scale) {
1813 return rect.translated(m[3][0], m[3][1]);
1814 }
else if (flagBits < Rotation2D) {
1816 float x = rect.x() * m[0][0] + m[3][0];
1817 float y = rect.y() * m[1][1] + m[3][1];
1818 float w = rect.width() * m[0][0];
1819 float h = rect.height() * m[1][1];
1828 return QRectF(x, y, w, h);
1831 QPointF tl = map(rect.topLeft()); QPointF tr = map(rect.topRight());
1832 QPointF bl = map(rect.bottomLeft()); QPointF br = map(rect.bottomRight());
1834 float xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
1835 float xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
1836 float ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
1837 float ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
1839 return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
1920void QMatrix4x4::optimize()
1924 if (m[0][3] != 0 || m[1][3] != 0 || m[2][3] != 0 || m[3][3] != 1)
1927 flagBits &= ~Perspective;
1930 if (m[3][0] == 0 && m[3][1] == 0 && m[3][2] == 0)
1931 flagBits &= ~Translation;
1934 if (!m[0][2] && !m[1][2] && !m[2][0] && !m[2][1]) {
1935 flagBits &= ~Rotation;
1937 if (!m[0][1] && !m[1][0]) {
1938 flagBits &= ~Rotation2D;
1940 if (m[0][0] == 1 && m[1][1] == 1 && m[2][2] == 1)
1945 copyToDoubles(m, mm);
1946 double det = matrixDet2(mm, 0, 1, 0, 1);
1947 double lenX = mm[0][0] * mm[0][0] + mm[0][1] * mm[0][1];
1948 double lenY = mm[1][0] * mm[1][0] + mm[1][1] * mm[1][1];
1949 double lenZ = mm[2][2];
1950 if (qFuzzyCompare(det, 1.0) && qFuzzyCompare(lenX, 1.0)
1951 && qFuzzyCompare(lenY, 1.0) && qFuzzyCompare(lenZ, 1.0))
1959 copyToDoubles(m, mm);
1960 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
1961 double lenX = mm[0][0] * mm[0][0] + mm[0][1] * mm[0][1] + mm[0][2] * mm[0][2];
1962 double lenY = mm[1][0] * mm[1][0] + mm[1][1] * mm[1][1] + mm[1][2] * mm[1][2];
1963 double lenZ = mm[2][0] * mm[2][0] + mm[2][1] * mm[2][1] + mm[2][2] * mm[2][2];
1964 if (qFuzzyCompare(det, 1.0) && qFuzzyCompare(lenX, 1.0)
1965 && qFuzzyCompare(lenY, 1.0) && qFuzzyCompare(lenZ, 1.0))
1984 QDebugStateSaver saver(dbg);
1987 if (m.flagBits == QMatrix4x4::Identity) {
1989 }
else if (m.flagBits == QMatrix4x4::General) {
1992 if ((m.flagBits & QMatrix4x4::Translation) != 0)
1993 bits +=
"Translation,";
1994 if ((m.flagBits & QMatrix4x4::Scale) != 0)
1996 if ((m.flagBits & QMatrix4x4::Rotation2D) != 0)
1997 bits +=
"Rotation2D,";
1998 if ((m.flagBits & QMatrix4x4::Rotation) != 0)
1999 bits +=
"Rotation,";
2000 if ((m.flagBits & QMatrix4x4::Perspective) != 0)
2001 bits +=
"Perspective,";
2006 dbg.nospace() <<
"QMatrix4x4(type:" << bits.constData() << Qt::endl
2007 << qSetFieldWidth(10)
2008 << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << Qt::endl
2009 << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << Qt::endl
2010 << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << Qt::endl
2011 << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << Qt::endl
2012 << qSetFieldWidth(0) <<
')';