5#include <QtCore/qmath.h>
7#include <QtCore/qdatastream.h>
15 for (
int col = 0; col < 4; ++col)
22 for (
int col = 0; col < 4; ++col) {
24 if (col < cols &&
row < rows)
35static inline double matrixDet2(
const double m[4][4],
int col0,
int col1,
int row0,
int row1)
37 return m[col0][row0] *
m[col1][row1] -
m[col0][row1] *
m[col1][row0];
41 (
const double m[4][4],
int col0,
int col1,
int col2,
42 int row0,
int row1,
int row2)
44 return m[col0][row0] *
matrixDet2(
m, col1, col2, row1, row2)
61 if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity)
64 if (flagBits < Rotation2D)
65 return m[0][0] *
m[1][1] *
m[2][2];
66 if (flagBits < Perspective)
74 if (flagBits == Identity) {
78 }
else if (flagBits == Translation) {
80 inv.m[3][0] = -
m[3][0];
81 inv.m[3][1] = -
m[3][1];
82 inv.m[3][2] = -
m[3][2];
83 inv.flagBits = Translation;
87 }
else if (flagBits < Rotation2D) {
89 if (
m[0][0] == 0 ||
m[1][1] == 0 ||
m[2][2] == 0) {
95 inv.m[0][0] = 1.0 /
m[0][0];
96 inv.m[1][1] = 1.0 /
m[1][1];
97 inv.m[2][2] = 1.0 /
m[2][2];
98 inv.m[3][0] = -
m[3][0] * inv.m[0][0];
99 inv.m[3][1] = -
m[3][1] * inv.m[1][1];
100 inv.m[3][2] = -
m[3][2] * inv.m[2][2];
101 inv.flagBits = flagBits;
106 }
else if ((flagBits & ~(Translation | Rotation2D | Rotation)) == Identity) {
109 return orthonormalInverse();
110 }
else if (flagBits < Perspective) {
133 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];
134 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];
135 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];
137 inv.flagBits = flagBits;
154 inv.m[0][0] =
matrixDet3(
m, 1, 2, 3, 1, 2, 3) * det;
155 inv.m[0][1] = -
matrixDet3(
m, 0, 2, 3, 1, 2, 3) * det;
156 inv.m[0][2] =
matrixDet3(
m, 0, 1, 3, 1, 2, 3) * det;
157 inv.m[0][3] = -
matrixDet3(
m, 0, 1, 2, 1, 2, 3) * det;
158 inv.m[1][0] = -
matrixDet3(
m, 1, 2, 3, 0, 2, 3) * det;
159 inv.m[1][1] =
matrixDet3(
m, 0, 2, 3, 0, 2, 3) * det;
160 inv.m[1][2] = -
matrixDet3(
m, 0, 1, 3, 0, 2, 3) * det;
161 inv.m[1][3] =
matrixDet3(
m, 0, 1, 2, 0, 2, 3) * det;
162 inv.m[2][0] =
matrixDet3(
m, 1, 2, 3, 0, 1, 3) * det;
163 inv.m[2][1] = -
matrixDet3(
m, 0, 2, 3, 0, 1, 3) * det;
164 inv.m[2][2] =
matrixDet3(
m, 0, 1, 3, 0, 1, 3) * det;
165 inv.m[2][3] = -
matrixDet3(
m, 0, 1, 2, 0, 1, 3) * det;
166 inv.m[3][0] = -
matrixDet3(
m, 1, 2, 3, 0, 1, 2) * det;
167 inv.m[3][1] =
matrixDet3(
m, 0, 2, 3, 0, 1, 2) * det;
168 inv.m[3][2] = -
matrixDet3(
m, 0, 1, 3, 0, 1, 2) * det;
169 inv.m[3][3] =
matrixDet3(
m, 0, 1, 2, 0, 1, 2) * det;
170 inv.flagBits = flagBits;
181 for (
int col = 0; col < 4; ++col) {
186 result.flagBits = (flagBits & Translation ? General : flagBits);
231 m.flagBits = QDoubleMatrix4x4::General;
240 if (flagBits < Scale) {
244 }
else if (flagBits < Rotation2D) {
248 }
else if (flagBits < Rotation) {
273 if (flagBits < Scale) {
276 }
else if (flagBits < Rotation2D) {
279 }
else if (flagBits < Rotation) {
299 if (flagBits < Scale) {
303 }
else if (flagBits < Rotation2D) {
307 }
else if (flagBits < Rotation) {
332 if (flagBits < Scale) {
336 }
else if (flagBits < Rotation2D) {
340 }
else if (flagBits < Rotation) {
368 if (flagBits == Identity) {
372 }
else if (flagBits == Translation) {
376 }
else if (flagBits == Scale) {
377 m[3][0] =
m[0][0] * vx;
378 m[3][1] =
m[1][1] * vy;
379 m[3][2] =
m[2][2] * vz;
380 }
else if (flagBits == (Translation | Scale)) {
381 m[3][0] +=
m[0][0] * vx;
382 m[3][1] +=
m[1][1] * vy;
383 m[3][2] +=
m[2][2] * vz;
384 }
else if (flagBits < Rotation) {
385 m[3][0] +=
m[0][0] * vx +
m[1][0] * vy;
386 m[3][1] +=
m[0][1] * vx +
m[1][1] * vy;
387 m[3][2] +=
m[2][2] * vz;
389 m[3][0] +=
m[0][0] * vx +
m[1][0] * vy +
m[2][0] * vz;
390 m[3][1] +=
m[0][1] * vx +
m[1][1] * vy +
m[2][1] * vz;
391 m[3][2] +=
m[0][2] * vx +
m[1][2] * vy +
m[2][2] * vz;
392 m[3][3] +=
m[0][3] * vx +
m[1][3] * vy +
m[2][3] * vz;
394 flagBits |= Translation;
399 if (flagBits == Identity) {
402 }
else if (flagBits == Translation) {
405 }
else if (flagBits == Scale) {
406 m[3][0] =
m[0][0] *
x;
407 m[3][1] =
m[1][1] *
y;
408 }
else if (flagBits == (Translation | Scale)) {
409 m[3][0] +=
m[0][0] *
x;
410 m[3][1] +=
m[1][1] *
y;
411 }
else if (flagBits < Rotation) {
412 m[3][0] +=
m[0][0] *
x +
m[1][0] *
y;
413 m[3][1] +=
m[0][1] *
x +
m[1][1] *
y;
415 m[3][0] +=
m[0][0] *
x +
m[1][0] *
y;
416 m[3][1] +=
m[0][1] *
x +
m[1][1] *
y;
417 m[3][2] +=
m[0][2] *
x +
m[1][2] *
y;
418 m[3][3] +=
m[0][3] *
x +
m[1][3] *
y;
420 flagBits |= Translation;
425 if (flagBits == Identity) {
429 }
else if (flagBits == Translation) {
433 }
else if (flagBits == Scale) {
434 m[3][0] =
m[0][0] *
x;
435 m[3][1] =
m[1][1] *
y;
436 m[3][2] =
m[2][2] *
z;
437 }
else if (flagBits == (Translation | Scale)) {
438 m[3][0] +=
m[0][0] *
x;
439 m[3][1] +=
m[1][1] *
y;
440 m[3][2] +=
m[2][2] *
z;
441 }
else if (flagBits < Rotation) {
442 m[3][0] +=
m[0][0] *
x +
m[1][0] *
y;
443 m[3][1] +=
m[0][1] *
x +
m[1][1] *
y;
444 m[3][2] +=
m[2][2] *
z;
446 m[3][0] +=
m[0][0] *
x +
m[1][0] *
y +
m[2][0] *
z;
447 m[3][1] +=
m[0][1] *
x +
m[1][1] *
y +
m[2][1] *
z;
448 m[3][2] +=
m[0][2] *
x +
m[1][2] *
y +
m[2][2] *
z;
449 m[3][3] +=
m[0][3] *
x +
m[1][3] *
y +
m[2][3] *
z;
451 flagBits |= Translation;
467 }
else if (
angle == -90.0 ||
angle == 270.0) {
470 }
else if (
angle == 180.0 ||
angle == -180.0) {
485 m[0][0] = (tmp =
m[0][0]) *
c +
m[1][0] *
s;
486 m[1][0] =
m[1][0] *
c - tmp *
s;
487 m[0][1] = (tmp =
m[0][1]) *
c +
m[1][1] *
s;
488 m[1][1] =
m[1][1] *
c - tmp *
s;
489 m[0][2] = (tmp =
m[0][2]) *
c +
m[1][2] *
s;
490 m[1][2] =
m[1][2] *
c - tmp *
s;
491 m[0][3] = (tmp =
m[0][3]) *
c +
m[1][3] *
s;
492 m[1][3] =
m[1][3] *
c - tmp *
s;
494 flagBits |= Rotation2D;
497 }
else if (
z == 0.0) {
502 m[2][0] = (tmp =
m[2][0]) *
c +
m[0][0] *
s;
503 m[0][0] =
m[0][0] *
c - tmp *
s;
504 m[2][1] = (tmp =
m[2][1]) *
c +
m[0][1] *
s;
505 m[0][1] =
m[0][1] *
c - tmp *
s;
506 m[2][2] = (tmp =
m[2][2]) *
c +
m[0][2] *
s;
507 m[0][2] =
m[0][2] *
c - tmp *
s;
508 m[2][3] = (tmp =
m[2][3]) *
c +
m[0][3] *
s;
509 m[0][3] =
m[0][3] *
c - tmp *
s;
511 flagBits |= Rotation;
514 }
else if (
y == 0.0 &&
z == 0.0) {
519 m[1][0] = (tmp =
m[1][0]) *
c +
m[2][0] *
s;
520 m[2][0] =
m[2][0] *
c - tmp *
s;
521 m[1][1] = (tmp =
m[1][1]) *
c +
m[2][1] *
s;
522 m[2][1] =
m[2][1] *
c - tmp *
s;
523 m[1][2] = (tmp =
m[1][2]) *
c +
m[2][2] *
s;
524 m[2][2] =
m[2][2] *
c - tmp *
s;
525 m[1][3] = (tmp =
m[1][3]) *
c +
m[2][3] *
s;
526 m[2][3] =
m[2][3] *
c - tmp *
s;
528 flagBits |= Rotation;
532 double len = double(
x) * double(
x) +
533 double(
y) * double(
y) +
534 double(
z) * double(
z);
537 x = double(
double(
x) /
len);
538 y = double(
double(
y) /
len);
539 z = double(
double(
z) /
len);
543 rot.m[0][0] =
x *
x * ic +
c;
544 rot.m[1][0] =
x *
y * ic -
z *
s;
545 rot.m[2][0] =
x *
z * ic +
y *
s;
547 rot.m[0][1] =
y *
x * ic +
z *
s;
548 rot.m[1][1] =
y *
y * ic +
c;
549 rot.m[2][1] =
y *
z * ic -
x *
s;
551 rot.m[0][2] =
x *
z * ic -
y *
s;
552 rot.m[1][2] =
y *
z * ic +
x *
s;
553 rot.m[2][2] =
z *
z * ic +
c;
559 rot.flagBits = Rotation;
563void QDoubleMatrix4x4::projectedRotate(
double angle,
double x,
double y,
double z,
564 double distanceToPlane)
576 }
else if (
angle == -90.0 ||
angle == 270.0) {
579 }
else if (
angle == 180.0 ||
angle == -180.0) {
588 const double d = 1.0 / distanceToPlane;
596 m[0][0] = (tmp =
m[0][0]) *
c +
m[1][0] *
s;
597 m[1][0] =
m[1][0] *
c - tmp *
s;
598 m[0][1] = (tmp =
m[0][1]) *
c +
m[1][1] *
s;
599 m[1][1] =
m[1][1] *
c - tmp *
s;
600 m[0][2] = (tmp =
m[0][2]) *
c +
m[1][2] *
s;
601 m[1][2] =
m[1][2] *
c - tmp *
s;
602 m[0][3] = (tmp =
m[0][3]) *
c +
m[1][3] *
s;
603 m[1][3] =
m[1][3] *
c - tmp *
s;
605 flagBits |= Rotation2D;
608 }
else if (
z == 0.0) {
613 m[0][0] =
m[0][0] *
c +
m[3][0] *
s;
614 m[0][1] =
m[0][1] *
c +
m[3][1] *
s;
615 m[0][2] =
m[0][2] *
c +
m[3][2] *
s;
616 m[0][3] =
m[0][3] *
c +
m[3][3] *
s;
620 }
else if (
y == 0.0 &&
z == 0.0) {
625 m[1][0] =
m[1][0] *
c -
m[3][0] *
s;
626 m[1][1] =
m[1][1] *
c -
m[3][1] *
s;
627 m[1][2] =
m[1][2] *
c -
m[3][2] *
s;
628 m[1][3] =
m[1][3] *
c -
m[3][3] *
s;
632 double len = double(
x) * double(
x) +
633 double(
y) * double(
y) +
634 double(
z) * double(
z);
637 x = double(
double(
x) /
len);
638 y = double(
double(
y) /
len);
639 z = double(
double(
z) /
len);
643 rot.m[0][0] =
x *
x * ic +
c;
644 rot.m[1][0] =
x *
y * ic -
z *
s;
647 rot.m[0][1] =
y *
x * ic +
z *
s;
648 rot.m[1][1] =
y *
y * ic +
c;
655 rot.m[0][3] = (
x *
z * ic -
y *
s) * -
d;
656 rot.m[1][3] = (
y *
z * ic +
x *
s) * -
d;
659 rot.flagBits = General;
686 double clip = farPlane - nearPlane;
693 m.m[1][1] = 2.0 / invheight;
698 m.m[2][2] = -2.0 / clip;
699 m.m[3][2] = -(nearPlane + farPlane) / clip;
704 m.flagBits = Translation | Scale;
720 double clip = farPlane - nearPlane;
721 m.m[0][0] = 2.0 * nearPlane /
width;
726 m.m[1][1] = 2.0 * nearPlane / invheight;
731 m.m[2][2] = -(nearPlane + farPlane) / clip;
732 m.m[3][2] = -2.0 * nearPlane * farPlane / clip;
737 m.flagBits = General;
746 if (nearPlane == farPlane || aspectRatio == 0.0)
752 double sine = std::sin(radians);
755 double cotan = std::cos(radians) / sine;
756 double clip = farPlane - nearPlane;
757 m.m[0][0] = cotan / aspectRatio;
767 m.m[2][2] = -(nearPlane + farPlane) / clip;
768 m.m[3][2] = -(2.0 * nearPlane * farPlane) / clip;
773 m.flagBits = General;
790 m.m[0][0] = side.
x();
791 m.m[1][0] = side.
y();
792 m.m[2][0] = side.
z();
794 m.m[0][1] = upVector.
x();
795 m.m[1][1] = upVector.
y();
796 m.m[2][1] = upVector.
z();
798 m.m[0][2] = -forward.
x();
799 m.m[1][2] = -forward.
y();
800 m.m[2][2] = -forward.
z();
806 m.flagBits = Rotation;
815 const double h2 =
height / 2.0;
828 m.m[2][2] = (farPlane - nearPlane) / 2.0;
829 m.m[3][2] = (nearPlane + farPlane) / 2.0;
834 m.flagBits = General;
844 if (flagBits < Rotation2D) {
864 for (
int col = 0; col < 4; ++col)
870 if (flagBits < Scale) {
875 }
else if (flagBits < Rotation2D) {
877 double x =
rect.x() *
m[0][0] +
m[3][0];
878 double y =
rect.y() *
m[1][1] +
m[3][1];
879 double w =
rect.width() *
m[0][0];
880 double h =
rect.height() *
m[1][1];
903 return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
908 if (flagBits < Scale) {
910 return rect.translated(
m[3][0],
m[3][1]);
911 }
else if (flagBits < Rotation2D) {
913 double x =
rect.x() *
m[0][0] +
m[3][0];
914 double y =
rect.y() *
m[1][1] +
m[3][1];
915 double w =
rect.width() *
m[0][0];
916 double h =
rect.height() *
m[1][1];
964 result.flagBits = flagBits;
973 if (
m[0][3] != 0 ||
m[1][3] != 0 ||
m[2][3] != 0 ||
m[3][3] != 1)
976 flagBits &= ~Perspective;
979 if (
m[3][0] == 0 &&
m[3][1] == 0 &&
m[3][2] == 0)
980 flagBits &= ~Translation;
983 if (!
m[0][2] && !
m[1][2] && !
m[2][0] && !
m[2][1]) {
984 flagBits &= ~Rotation;
986 if (!
m[0][1] && !
m[1][0]) {
987 flagBits &= ~Rotation2D;
989 if (
m[0][0] == 1 &&
m[1][1] == 1 &&
m[2][2] == 1)
994 double lenX =
m[0][0] *
m[0][0] +
m[0][1] *
m[0][1];
995 double lenY =
m[1][0] *
m[1][0] +
m[1][1] *
m[1][1];
996 double lenZ =
m[2][2];
1006 double lenX =
m[0][0] *
m[0][0] +
m[0][1] *
m[0][1] +
m[0][2] *
m[0][2];
1007 double lenY =
m[1][0] *
m[1][0] +
m[1][1] *
m[1][1] +
m[1][2] *
m[1][2];
1008 double lenZ =
m[2][0] *
m[2][0] +
m[2][1] *
m[2][1] +
m[2][2] *
m[2][2];
1017#ifndef QT_NO_DEBUG_STREAM
1024 if (
m.flagBits == QDoubleMatrix4x4::Identity) {
1026 }
else if (
m.flagBits == QDoubleMatrix4x4::General) {
1029 if ((
m.flagBits & QDoubleMatrix4x4::Translation) != 0)
1030 bits +=
"Translation,";
1031 if ((
m.flagBits & QDoubleMatrix4x4::Scale) != 0)
1033 if ((
m.flagBits & QDoubleMatrix4x4::Rotation2D) != 0)
1034 bits +=
"Rotation2D,";
1035 if ((
m.flagBits & QDoubleMatrix4x4::Rotation) != 0)
1036 bits +=
"Rotation,";
1037 if ((
m.flagBits & QDoubleMatrix4x4::Perspective) != 0)
1038 bits +=
"Perspective,";
1039 if (!
bits.isEmpty())
1044 dbg.nospace() <<
"QDoubleMatrix4x4(type:" <<
bits.constData() <<
Qt::endl
1046 <<
m(0, 0) <<
m(0, 1) <<
m(0, 2) <<
m(0, 3) <<
Qt::endl
1047 <<
m(1, 0) <<
m(1, 1) <<
m(1, 2) <<
m(1, 3) <<
Qt::endl
1048 <<
m(2, 0) <<
m(2, 1) <<
m(2, 2) <<
m(2, 3) <<
Qt::endl
1049 <<
m(3, 0) <<
m(3, 1) <<
m(3, 2) <<
m(3, 3) <<
Qt::endl
1056#ifndef QT_NO_DATASTREAM
1061 for (
int col = 0; col < 4; ++col)
1070 for (
int col = 0; col < 4; ++col) {
\inmodule QtCore\reentrant
QDoubleMatrix4x4 transposed() const
void translate(const QDoubleVector3D &vector)
void viewport(const QRectF &rect)
void copyDataTo(double *values) const
void frustum(double left, double right, double bottom, double top, double nearPlane, double farPlane)
double determinant() const
friend bool qFuzzyCompare(const QDoubleMatrix4x4 &m1, const QDoubleMatrix4x4 &m2)
QDoubleMatrix4x4 inverted(bool *invertible=nullptr) const
void scale(const QDoubleVector3D &vector)
QRect mapRect(const QRect &rect) const
QDoubleMatrix4x4 & operator/=(double divisor)
void ortho(const QRect &rect)
void lookAt(const QDoubleVector3D &eye, const QDoubleVector3D ¢er, const QDoubleVector3D &up)
void perspective(double verticalAngle, double aspectRatio, double nearPlane, double farPlane)
void rotate(double angle, const QDoubleVector3D &vector)
Q_DECL_CONSTEXPR double x() const
Q_DECL_CONSTEXPR double y() const
Q_DECL_CONSTEXPR double z() const
QDoubleVector3D normalized() const
static Q_DECL_CONSTEXPR QDoubleVector3D crossProduct(const QDoubleVector3D &v1, const QDoubleVector3D &v2)
\inmodule QtCore\reentrant
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
\inmodule QtCore\reentrant
constexpr int x() const noexcept
Returns the x coordinate of this point.
constexpr int y() const noexcept
Returns the y coordinate of this point.
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
QMap< QString, QString > map
[6]
Combined button and popup list for selecting options.
QTextStream & endl(QTextStream &stream)
Writes '\n' to the stream and flushes the stream.
static double matrixDet4(const double m[4][4])
QDoubleMatrix4x4 operator/(const QDoubleMatrix4x4 &matrix, double divisor)
QDebug operator<<(QDebug dbg, const QDoubleMatrix4x4 &m)
static double matrixDet2(const double m[4][4], int col0, int col1, int row0, int row1)
QDataStream & operator>>(QDataStream &stream, QDoubleMatrix4x4 &matrix)
static double matrixDet3(const double m[4][4], int col0, int col1, int col2, int row0, int row1, int row2)
bool qFuzzyIsNull(qfloat16 f) noexcept
bool qIsNull(qfloat16 f) noexcept
int qRound(qfloat16 d) noexcept
constexpr float qDegreesToRadians(float degrees)
static double matrixDet4(const double m[4][4])
static double matrixDet2(const double m[4][4], int col0, int col1, int row0, int row1)
static double matrixDet3(const double m[4][4], int col0, int col1, int col2, int row0, int row1, int row2)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qMax(const T &a, const T &b)
GLenum GLsizei GLsizei GLint * values
[15]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLboolean GLboolean GLboolean GLboolean a
[7]
GLdouble GLdouble GLdouble GLdouble top
GLfloat GLfloat GLfloat GLfloat h
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
GLenum GLenum GLsizei void * row
QTextStreamManipulator qSetFieldWidth(int width)