318QMatrix4x4 QMatrix4x4::inverted(
bool *invertible)
const
321 if (flagBits == Identity) {
325 }
else if (flagBits == Translation) {
327 inv.m[3][0] = -m[3][0];
328 inv.m[3][1] = -m[3][1];
329 inv.m[3][2] = -m[3][2];
330 inv.flagBits = Translation;
334 }
else if (flagBits < Rotation2D) {
336 if (m[0][0] == 0 || m[1][1] == 0 || m[2][2] == 0) {
342 inv.m[0][0] = 1.0f / m[0][0];
343 inv.m[1][1] = 1.0f / m[1][1];
344 inv.m[2][2] = 1.0f / m[2][2];
345 inv.m[3][0] = -m[3][0] * inv.m[0][0];
346 inv.m[3][1] = -m[3][1] * inv.m[1][1];
347 inv.m[3][2] = -m[3][2] * inv.m[2][2];
348 inv.flagBits = flagBits;
353 }
else if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity) {
356 return orthonormalInverse();
357 }
else if (flagBits < Perspective) {
358 QMatrix4x4 inv(Qt::Uninitialized);
361 copyToDoubles(m, mm);
363 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
371 inv.m[0][0] = matrixDet2(mm, 1, 2, 1, 2) * det;
372 inv.m[0][1] = -matrixDet2(mm, 0, 2, 1, 2) * det;
373 inv.m[0][2] = matrixDet2(mm, 0, 1, 1, 2) * det;
375 inv.m[1][0] = -matrixDet2(mm, 1, 2, 0, 2) * det;
376 inv.m[1][1] = matrixDet2(mm, 0, 2, 0, 2) * det;
377 inv.m[1][2] = -matrixDet2(mm, 0, 1, 0, 2) * det;
379 inv.m[2][0] = matrixDet2(mm, 1, 2, 0, 1) * det;
380 inv.m[2][1] = -matrixDet2(mm, 0, 2, 0, 1) * det;
381 inv.m[2][2] = matrixDet2(mm, 0, 1, 0, 1) * det;
383 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];
384 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];
385 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];
387 inv.flagBits = flagBits;
394 QMatrix4x4 inv(Qt::Uninitialized);
397 copyToDoubles(m, mm);
399 double det = matrixDet4(mm);
407 inv.m[0][0] = matrixDet3(mm, 1, 2, 3, 1, 2, 3) * det;
408 inv.m[0][1] = -matrixDet3(mm, 0, 2, 3, 1, 2, 3) * det;
409 inv.m[0][2] = matrixDet3(mm, 0, 1, 3, 1, 2, 3) * det;
410 inv.m[0][3] = -matrixDet3(mm, 0, 1, 2, 1, 2, 3) * det;
411 inv.m[1][0] = -matrixDet3(mm, 1, 2, 3, 0, 2, 3) * det;
412 inv.m[1][1] = matrixDet3(mm, 0, 2, 3, 0, 2, 3) * det;
413 inv.m[1][2] = -matrixDet3(mm, 0, 1, 3, 0, 2, 3) * det;
414 inv.m[1][3] = matrixDet3(mm, 0, 1, 2, 0, 2, 3) * det;
415 inv.m[2][0] = matrixDet3(mm, 1, 2, 3, 0, 1, 3) * det;
416 inv.m[2][1] = -matrixDet3(mm, 0, 2, 3, 0, 1, 3) * det;
417 inv.m[2][2] = matrixDet3(mm, 0, 1, 3, 0, 1, 3) * det;
418 inv.m[2][3] = -matrixDet3(mm, 0, 1, 2, 0, 1, 3) * det;
419 inv.m[3][0] = -matrixDet3(mm, 1, 2, 3, 0, 1, 2) * det;
420 inv.m[3][1] = matrixDet3(mm, 0, 2, 3, 0, 1, 2) * det;
421 inv.m[3][2] = -matrixDet3(mm, 0, 1, 3, 0, 1, 2) * det;
422 inv.m[3][3] = matrixDet3(mm, 0, 1, 2, 0, 1, 2) * det;
423 inv.flagBits = flagBits;
438QMatrix3x3 QMatrix4x4::normalMatrix()
const
443 if (flagBits < Scale) {
446 }
else if (flagBits < Rotation2D) {
448 if (m[0][0] == 0.0f || m[1][1] == 0.0f || m[2][2] == 0.0f)
450 inv.data()[0] = 1.0f / m[0][0];
451 inv.data()[4] = 1.0f / m[1][1];
452 inv.data()[8] = 1.0f / m[2][2];
454 }
else if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity) {
455 float *invm = inv.data();
456 invm[0 + 0 * 3] = m[0][0];
457 invm[1 + 0 * 3] = m[0][1];
458 invm[2 + 0 * 3] = m[0][2];
459 invm[0 + 1 * 3] = m[1][0];
460 invm[1 + 1 * 3] = m[1][1];
461 invm[2 + 1 * 3] = m[1][2];
462 invm[0 + 2 * 3] = m[2][0];
463 invm[1 + 2 * 3] = m[2][1];
464 invm[2 + 2 * 3] = m[2][2];
469 copyToDoubles(m, mm);
470 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
475 float *invm = inv.data();
478 invm[0 + 0 * 3] = (mm[1][1] * mm[2][2] - mm[2][1] * mm[1][2]) * det;
479 invm[1 + 0 * 3] = -(mm[1][0] * mm[2][2] - mm[1][2] * mm[2][0]) * det;
480 invm[2 + 0 * 3] = (mm[1][0] * mm[2][1] - mm[1][1] * mm[2][0]) * det;
481 invm[0 + 1 * 3] = -(mm[0][1] * mm[2][2] - mm[2][1] * mm[0][2]) * det;
482 invm[1 + 1 * 3] = (mm[0][0] * mm[2][2] - mm[0][2] * mm[2][0]) * det;
483 invm[2 + 1 * 3] = -(mm[0][0] * mm[2][1] - mm[0][1] * mm[2][0]) * det;
484 invm[0 + 2 * 3] = (mm[0][1] * mm[1][2] - mm[0][2] * mm[1][1]) * det;
485 invm[1 + 2 * 3] = -(mm[0][0] * mm[1][2] - mm[0][2] * mm[1][0]) * det;
486 invm[2 + 2 * 3] = (mm[0][0] * mm[1][1] - mm[1][0] * mm[0][1]) * det;
741 return qFuzzyCompare(m1.m[0][0], m2.m[0][0]) &&
742 qFuzzyCompare(m1.m[0][1], m2.m[0][1]) &&
743 qFuzzyCompare(m1.m[0][2], m2.m[0][2]) &&
744 qFuzzyCompare(m1.m[0][3], m2.m[0][3]) &&
745 qFuzzyCompare(m1.m[1][0], m2.m[1][0]) &&
746 qFuzzyCompare(m1.m[1][1], m2.m[1][1]) &&
747 qFuzzyCompare(m1.m[1][2], m2.m[1][2]) &&
748 qFuzzyCompare(m1.m[1][3], m2.m[1][3]) &&
749 qFuzzyCompare(m1.m[2][0], m2.m[2][0]) &&
750 qFuzzyCompare(m1.m[2][1], m2.m[2][1]) &&
751 qFuzzyCompare(m1.m[2][2], m2.m[2][2]) &&
752 qFuzzyCompare(m1.m[2][3], m2.m[2][3]) &&
753 qFuzzyCompare(m1.m[3][0], m2.m[3][0]) &&
754 qFuzzyCompare(m1.m[3][1], m2.m[3][1]) &&
755 qFuzzyCompare(m1.m[3][2], m2.m[3][2]) &&
756 qFuzzyCompare(m1.m[3][3], m2.m[3][3]);
1061void QMatrix4x4::rotate(
float angle,
float x,
float y,
float z)
1066 if (angle == 90.0f || angle == -270.0f) {
1069 }
else if (angle == -90.0f || angle == 270.0f) {
1072 }
else if (angle == 180.0f || angle == -180.0f) {
1076 float a = qDegreesToRadians(angle);
1087 m[0][0] = (tmp = m[0][0]) * c + m[1][0] * s;
1088 m[1][0] = m[1][0] * c - tmp * s;
1089 m[0][1] = (tmp = m[0][1]) * c + m[1][1] * s;
1090 m[1][1] = m[1][1] * c - tmp * s;
1091 m[0][2] = (tmp = m[0][2]) * c + m[1][2] * s;
1092 m[1][2] = m[1][2] * c - tmp * s;
1093 m[0][3] = (tmp = m[0][3]) * c + m[1][3] * s;
1094 m[1][3] = m[1][3] * c - tmp * s;
1096 flagBits |= Rotation2D;
1099 }
else if (z == 0.0f) {
1104 m[2][0] = (tmp = m[2][0]) * c + m[0][0] * s;
1105 m[0][0] = m[0][0] * c - tmp * s;
1106 m[2][1] = (tmp = m[2][1]) * c + m[0][1] * s;
1107 m[0][1] = m[0][1] * c - tmp * s;
1108 m[2][2] = (tmp = m[2][2]) * c + m[0][2] * s;
1109 m[0][2] = m[0][2] * c - tmp * s;
1110 m[2][3] = (tmp = m[2][3]) * c + m[0][3] * s;
1111 m[0][3] = m[0][3] * c - tmp * s;
1113 flagBits |= Rotation;
1116 }
else if (y == 0.0f && z == 0.0f) {
1121 m[1][0] = (tmp = m[1][0]) * c + m[2][0] * s;
1122 m[2][0] = m[2][0] * c - tmp * s;
1123 m[1][1] = (tmp = m[1][1]) * c + m[2][1] * s;
1124 m[2][1] = m[2][1] * c - tmp * s;
1125 m[1][2] = (tmp = m[1][2]) * c + m[2][2] * s;
1126 m[2][2] = m[2][2] * c - tmp * s;
1127 m[1][3] = (tmp = m[1][3]) * c + m[2][3] * s;
1128 m[2][3] = m[2][3] * c - tmp * s;
1130 flagBits |= Rotation;
1134 double len =
double(x) *
double(x) +
1135 double(y) *
double(y) +
1136 double(z) *
double(z);
1137 if (!qFuzzyCompare(len, 1.0) && !qFuzzyIsNull(len)) {
1138 len = std::sqrt(len);
1139 x =
float(
double(x) / len);
1140 y =
float(
double(y) / len);
1141 z =
float(
double(z) / len);
1143 float ic = 1.0f - c;
1144 QMatrix4x4 rot(Qt::Uninitialized);
1145 rot.m[0][0] = x * x * ic + c;
1146 rot.m[1][0] = x * y * ic - z * s;
1147 rot.m[2][0] = x * z * ic + y * s;
1149 rot.m[0][1] = y * x * ic + z * s;
1150 rot.m[1][1] = y * y * ic + c;
1151 rot.m[2][1] = y * z * ic - x * s;
1153 rot.m[0][2] = x * z * ic - y * s;
1154 rot.m[1][2] = y * z * ic + x * s;
1155 rot.m[2][2] = z * z * ic + c;
1161 rot.flagBits = Rotation;
1168void QMatrix4x4::projectedRotate(
float angle,
float x,
float y,
float z,
float distanceToPlane)
1172 if (qIsNull(distanceToPlane))
1173 return rotate(angle, x, y, z);
1178 if (angle == 90.0f || angle == -270.0f) {
1181 }
else if (angle == -90.0f || angle == 270.0f) {
1184 }
else if (angle == 180.0f || angle == -180.0f) {
1188 float a = qDegreesToRadians(angle);
1193 const qreal d = 1.0 / distanceToPlane;
1201 m[0][0] = (tmp = m[0][0]) * c + m[1][0] * s;
1202 m[1][0] = m[1][0] * c - tmp * s;
1203 m[0][1] = (tmp = m[0][1]) * c + m[1][1] * s;
1204 m[1][1] = m[1][1] * c - tmp * s;
1205 m[0][2] = (tmp = m[0][2]) * c + m[1][2] * s;
1206 m[1][2] = m[1][2] * c - tmp * s;
1207 m[0][3] = (tmp = m[0][3]) * c + m[1][3] * s;
1208 m[1][3] = m[1][3] * c - tmp * s;
1210 flagBits |= Rotation2D;
1213 }
else if (z == 0.0f) {
1218 m[0][0] = m[0][0] * c + m[3][0] * s;
1219 m[0][1] = m[0][1] * c + m[3][1] * s;
1220 m[0][2] = m[0][2] * c + m[3][2] * s;
1221 m[0][3] = m[0][3] * c + m[3][3] * s;
1225 }
else if (y == 0.0f && z == 0.0f) {
1230 m[1][0] = m[1][0] * c - m[3][0] * s;
1231 m[1][1] = m[1][1] * c - m[3][1] * s;
1232 m[1][2] = m[1][2] * c - m[3][2] * s;
1233 m[1][3] = m[1][3] * c - m[3][3] * s;
1237 double len =
double(x) *
double(x) +
1238 double(y) *
double(y) +
1239 double(z) *
double(z);
1240 if (!qFuzzyCompare(len, 1.0) && !qFuzzyIsNull(len)) {
1241 len = std::sqrt(len);
1242 x =
float(
double(x) / len);
1243 y =
float(
double(y) / len);
1244 z =
float(
double(z) / len);
1246 const float ic = 1.0f - c;
1247 QMatrix4x4 rot(Qt::Uninitialized);
1248 rot.m[0][0] = x * x * ic + c;
1249 rot.m[1][0] = x * y * ic - z * s;
1252 rot.m[0][1] = y * x * ic + z * s;
1253 rot.m[1][1] = y * y * ic + c;
1260 rot.m[0][3] = (x * z * ic - y * s) * -d;
1261 rot.m[1][3] = (y * z * ic + x * s) * -d;
1264 rot.flagBits = General;
1672QTransform QMatrix4x4::toTransform(
float distanceToPlane)
const
1674 if (distanceToPlane == 1024.0f) {
1676 return QTransform(m[0][0], m[0][1], m[0][3] - m[0][2] * inv_dist_to_plane,
1677 m[1][0], m[1][1], m[1][3] - m[1][2] * inv_dist_to_plane,
1678 m[3][0], m[3][1], m[3][3] - m[3][2] * inv_dist_to_plane);
1679 }
else if (distanceToPlane != 0.0f) {
1687 float d = 1.0f / distanceToPlane;
1688 return QTransform(m[0][0], m[0][1], m[0][3] - m[0][2] * d,
1689 m[1][0], m[1][1], m[1][3] - m[1][2] * d,
1690 m[3][0], m[3][1], m[3][3] - m[3][2] * d);
1693 return QTransform(m[0][0], m[0][1], m[0][3],
1694 m[1][0], m[1][1], m[1][3],
1695 m[3][0], m[3][1], m[3][3]);
1765QRect QMatrix4x4::mapRect(
const QRect& rect)
const
1767 if (flagBits < Scale) {
1769 return QRect(qRound(rect.x() + m[3][0]),
1770 qRound(rect.y() + m[3][1]),
1771 rect.width(), rect.height());
1772 }
else if (flagBits < Rotation2D) {
1774 float x = rect.x() * m[0][0] + m[3][0];
1775 float y = rect.y() * m[1][1] + m[3][1];
1776 float w = rect.width() * m[0][0];
1777 float h = rect.height() * m[1][1];
1786 return QRect(qRound(x), qRound(y), qRound(w), qRound(h));
1789 QPoint tl = map(rect.topLeft());
1790 QPoint tr = map(QPoint(rect.x() + rect.width(), rect.y()));
1791 QPoint bl = map(QPoint(rect.x(), rect.y() + rect.height()));
1792 QPoint br = map(QPoint(rect.x() + rect.width(),
1793 rect.y() + rect.height()));
1795 int xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
1796 int xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
1797 int ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
1798 int ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
1800 return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
1811QRectF QMatrix4x4::mapRect(
const QRectF& rect)
const
1813 if (flagBits < Scale) {
1815 return rect.translated(m[3][0], m[3][1]);
1816 }
else if (flagBits < Rotation2D) {
1818 float x = rect.x() * m[0][0] + m[3][0];
1819 float y = rect.y() * m[1][1] + m[3][1];
1820 float w = rect.width() * m[0][0];
1821 float h = rect.height() * m[1][1];
1830 return QRectF(x, y, w, h);
1833 QPointF tl = map(rect.topLeft()); QPointF tr = map(rect.topRight());
1834 QPointF bl = map(rect.bottomLeft()); QPointF br = map(rect.bottomRight());
1836 float xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
1837 float xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
1838 float ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
1839 float ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
1841 return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
1922void QMatrix4x4::optimize()
1926 if (m[0][3] != 0 || m[1][3] != 0 || m[2][3] != 0 || m[3][3] != 1)
1929 flagBits &= ~Perspective;
1932 if (m[3][0] == 0 && m[3][1] == 0 && m[3][2] == 0)
1933 flagBits &= ~Translation;
1936 if (!m[0][2] && !m[1][2] && !m[2][0] && !m[2][1]) {
1937 flagBits &= ~Rotation;
1939 if (!m[0][1] && !m[1][0]) {
1940 flagBits &= ~Rotation2D;
1942 if (m[0][0] == 1 && m[1][1] == 1 && m[2][2] == 1)
1947 copyToDoubles(m, mm);
1948 double det = matrixDet2(mm, 0, 1, 0, 1);
1949 double lenX = mm[0][0] * mm[0][0] + mm[0][1] * mm[0][1];
1950 double lenY = mm[1][0] * mm[1][0] + mm[1][1] * mm[1][1];
1951 double lenZ = mm[2][2];
1952 if (qFuzzyCompare(det, 1.0) && qFuzzyCompare(lenX, 1.0)
1953 && qFuzzyCompare(lenY, 1.0) && qFuzzyCompare(lenZ, 1.0))
1961 copyToDoubles(m, mm);
1962 double det = matrixDet3(mm, 0, 1, 2, 0, 1, 2);
1963 double lenX = mm[0][0] * mm[0][0] + mm[0][1] * mm[0][1] + mm[0][2] * mm[0][2];
1964 double lenY = mm[1][0] * mm[1][0] + mm[1][1] * mm[1][1] + mm[1][2] * mm[1][2];
1965 double lenZ = mm[2][0] * mm[2][0] + mm[2][1] * mm[2][1] + mm[2][2] * mm[2][2];
1966 if (qFuzzyCompare(det, 1.0) && qFuzzyCompare(lenX, 1.0)
1967 && qFuzzyCompare(lenY, 1.0) && qFuzzyCompare(lenZ, 1.0))
1986 QDebugStateSaver saver(dbg);
1989 if (m.flagBits == QMatrix4x4::Identity) {
1991 }
else if (m.flagBits == QMatrix4x4::General) {
1994 if ((m.flagBits & QMatrix4x4::Translation) != 0)
1995 bits +=
"Translation,";
1996 if ((m.flagBits & QMatrix4x4::Scale) != 0)
1998 if ((m.flagBits & QMatrix4x4::Rotation2D) != 0)
1999 bits +=
"Rotation2D,";
2000 if ((m.flagBits & QMatrix4x4::Rotation) != 0)
2001 bits +=
"Rotation,";
2002 if ((m.flagBits & QMatrix4x4::Perspective) != 0)
2003 bits +=
"Perspective,";
2008 dbg.nospace() <<
"QMatrix4x4(type:" << bits.constData() << Qt::endl
2009 << qSetFieldWidth(10)
2010 << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << Qt::endl
2011 << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << Qt::endl
2012 << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << Qt::endl
2013 << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << Qt::endl
2014 << qSetFieldWidth(0) <<
')';