Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtGui/qmatrix4x4.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // Copyright (C) 2016 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #ifndef QMATRIX4X4_H
0005 #define QMATRIX4X4_H
0006 
0007 #include <QtGui/qtguiglobal.h>
0008 #include <QtGui/qvector3d.h>
0009 #include <QtGui/qvector4d.h>
0010 #include <QtGui/qquaternion.h>
0011 #include <QtGui/qgenericmatrix.h>
0012 #include <QtCore/qrect.h>
0013 
0014 class tst_QMatrixNxN;
0015 
0016 QT_BEGIN_NAMESPACE
0017 
0018 
0019 #ifndef QT_NO_MATRIX4X4
0020 
0021 class QTransform;
0022 class QVariant;
0023 
0024 class Q_GUI_EXPORT QMatrix4x4
0025 {
0026 public:
0027     inline QMatrix4x4() { setToIdentity(); }
0028     explicit QMatrix4x4(Qt::Initialization) : flagBits(General) {}
0029     explicit QMatrix4x4(const float *values);
0030     inline QMatrix4x4(float m11, float m12, float m13, float m14,
0031                       float m21, float m22, float m23, float m24,
0032                       float m31, float m32, float m33, float m34,
0033                       float m41, float m42, float m43, float m44);
0034 
0035     template <int N, int M>
0036     explicit QMatrix4x4(const QGenericMatrix<N, M, float>& matrix);
0037 
0038     QMatrix4x4(const float *values, int cols, int rows);
0039     QMatrix4x4(const QTransform& transform);
0040 
0041     inline const float& operator()(int row, int column) const;
0042     inline float& operator()(int row, int column);
0043 
0044 #ifndef QT_NO_VECTOR4D
0045     inline QVector4D column(int index) const;
0046     inline void setColumn(int index, const QVector4D& value);
0047 
0048     inline QVector4D row(int index) const;
0049     inline void setRow(int index, const QVector4D& value);
0050 #endif
0051 
0052     inline bool isAffine() const;
0053 
0054     inline bool isIdentity() const;
0055     inline void setToIdentity();
0056 
0057     inline void fill(float value);
0058 
0059     double determinant() const;
0060     QMatrix4x4 inverted(bool *invertible = nullptr) const;
0061     QMatrix4x4 transposed() const;
0062     QMatrix3x3 normalMatrix() const;
0063 
0064     inline QMatrix4x4& operator+=(const QMatrix4x4& other);
0065     inline QMatrix4x4& operator-=(const QMatrix4x4& other);
0066     inline QMatrix4x4& operator*=(const QMatrix4x4& other);
0067     inline QMatrix4x4& operator*=(float factor);
0068     QMatrix4x4& operator/=(float divisor);
0069     inline bool operator==(const QMatrix4x4& other) const;
0070     inline bool operator!=(const QMatrix4x4& other) const;
0071 
0072     friend QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2);
0073     friend QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2);
0074     friend QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2);
0075 #ifndef QT_NO_VECTOR3D
0076 #if QT_DEPRECATED_SINCE(6, 1)
0077     friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector);
0078     friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix);
0079 #endif
0080 #endif
0081 #ifndef QT_NO_VECTOR4D
0082     friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix);
0083     friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector);
0084 #endif
0085     friend QPoint operator*(const QPoint& point, const QMatrix4x4& matrix);
0086     friend QPointF operator*(const QPointF& point, const QMatrix4x4& matrix);
0087     friend QMatrix4x4 operator-(const QMatrix4x4& matrix);
0088 #if QT_DEPRECATED_SINCE(6, 1)
0089     friend QPoint operator*(const QMatrix4x4& matrix, const QPoint& point);
0090     friend QPointF operator*(const QMatrix4x4& matrix, const QPointF& point);
0091 #endif
0092     friend QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix);
0093     friend QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor);
0094     friend Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor);
0095 
0096     friend Q_GUI_EXPORT bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2);
0097 
0098 #ifndef QT_NO_VECTOR3D
0099     void scale(const QVector3D& vector);
0100     void translate(const QVector3D& vector);
0101     void rotate(float angle, const QVector3D& vector);
0102 #endif
0103     void scale(float x, float y);
0104     void scale(float x, float y, float z);
0105     void scale(float factor);
0106     void translate(float x, float y);
0107     void translate(float x, float y, float z);
0108     void rotate(float angle, float x, float y, float z = 0.0f);
0109 #ifndef QT_NO_QUATERNION
0110     void rotate(const QQuaternion& quaternion);
0111 #endif
0112 
0113     void ortho(const QRect& rect);
0114     void ortho(const QRectF& rect);
0115     void ortho(float left, float right, float bottom, float top, float nearPlane, float farPlane);
0116     void frustum(float left, float right, float bottom, float top, float nearPlane, float farPlane);
0117     void perspective(float verticalAngle, float aspectRatio, float nearPlane, float farPlane);
0118 #ifndef QT_NO_VECTOR3D
0119     void lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up);
0120 #endif
0121     void viewport(const QRectF &rect);
0122     void viewport(float left, float bottom, float width, float height, float nearPlane = 0.0f, float farPlane = 1.0f);
0123     void flipCoordinates();
0124 
0125     void copyDataTo(float *values) const;
0126 
0127     QTransform toTransform() const;
0128     QTransform toTransform(float distanceToPlane) const;
0129 
0130     inline QPoint map(const QPoint& point) const;
0131     inline QPointF map(const QPointF& point) const;
0132 #ifndef QT_NO_VECTOR3D
0133     inline QVector3D map(const QVector3D& point) const;
0134     inline QVector3D mapVector(const QVector3D& vector) const;
0135 #endif
0136 #ifndef QT_NO_VECTOR4D
0137     inline QVector4D map(const QVector4D& point) const;
0138 #endif
0139     QRect mapRect(const QRect& rect) const;
0140     QRectF mapRect(const QRectF& rect) const;
0141 
0142     template <int N, int M>
0143     QGenericMatrix<N, M, float> toGenericMatrix() const;
0144 
0145     inline float *data();
0146     inline const float *data() const { return *m; }
0147     inline const float *constData() const { return *m; }
0148 
0149     void optimize();
0150 
0151     operator QVariant() const;
0152 
0153 #ifndef QT_NO_DEBUG_STREAM
0154     friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
0155 #endif
0156 
0157 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
0158     void projectedRotate(float angle, float x, float y, float z, float distanceToPlane);
0159     // ### Qt7: Remove
0160     void projectedRotate(float angle, float x, float y, float z);
0161 #else
0162     void projectedRotate(float angle, float x, float y, float z, float distanceToPlane = 1024.0);
0163 #endif
0164 
0165     // When matrices are multiplied, the flag bits are or-ed together.
0166     // Note that the ordering of the bit values matters. (ident < t < s < r2d < r < p)
0167     enum Flag {
0168         Identity        = 0x0000, // Identity matrix
0169         Translation     = 0x0001, // Contains a translation
0170         Scale           = 0x0002, // Contains a scale
0171         Rotation2D      = 0x0004, // Contains a rotation about the Z axis
0172         Rotation        = 0x0008, // Contains an arbitrary rotation
0173         Perspective     = 0x0010, // Last row is different from (0, 0, 0, 1)
0174         General         = 0x001f  // General matrix, unknown contents
0175     };
0176     Q_DECLARE_FLAGS(Flags, Flag)
0177 
0178     Flags flags() const { return flagBits; }
0179 
0180 private:
0181     float m[4][4];          // Column-major order to match OpenGL.
0182     Flags flagBits;
0183 
0184     QMatrix4x4 orthonormalInverse() const;
0185 
0186     friend class ::tst_QMatrixNxN; // for access to flagBits
0187 };
0188 
0189 Q_DECLARE_OPERATORS_FOR_FLAGS(QMatrix4x4::Flags)
0190 
0191 QT_WARNING_PUSH
0192 QT_WARNING_DISABLE_FLOAT_COMPARE
0193 
0194 Q_DECLARE_TYPEINFO(QMatrix4x4, Q_PRIMITIVE_TYPE);
0195 
0196 inline QMatrix4x4::QMatrix4x4
0197         (float m11, float m12, float m13, float m14,
0198          float m21, float m22, float m23, float m24,
0199          float m31, float m32, float m33, float m34,
0200          float m41, float m42, float m43, float m44)
0201 {
0202     m[0][0] = m11; m[0][1] = m21; m[0][2] = m31; m[0][3] = m41;
0203     m[1][0] = m12; m[1][1] = m22; m[1][2] = m32; m[1][3] = m42;
0204     m[2][0] = m13; m[2][1] = m23; m[2][2] = m33; m[2][3] = m43;
0205     m[3][0] = m14; m[3][1] = m24; m[3][2] = m34; m[3][3] = m44;
0206     flagBits = General;
0207 }
0208 
0209 template <int N, int M>
0210 Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
0211     (const QGenericMatrix<N, M, float>& matrix)
0212 {
0213     const float *values = matrix.constData();
0214     for (int matrixCol = 0; matrixCol < 4; ++matrixCol) {
0215         for (int matrixRow = 0; matrixRow < 4; ++matrixRow) {
0216             if (matrixCol < N && matrixRow < M)
0217                 m[matrixCol][matrixRow] = values[matrixCol * M + matrixRow];
0218             else if (matrixCol == matrixRow)
0219                 m[matrixCol][matrixRow] = 1.0f;
0220             else
0221                 m[matrixCol][matrixRow] = 0.0f;
0222         }
0223     }
0224     flagBits = General;
0225 }
0226 
0227 template <int N, int M>
0228 QGenericMatrix<N, M, float> QMatrix4x4::toGenericMatrix() const
0229 {
0230     QGenericMatrix<N, M, float> result;
0231     float *values = result.data();
0232     for (int matrixCol = 0; matrixCol < N; ++matrixCol) {
0233         for (int matrixRow = 0; matrixRow < M; ++matrixRow) {
0234             if (matrixCol < 4 && matrixRow < 4)
0235                 values[matrixCol * M + matrixRow] = m[matrixCol][matrixRow];
0236             else if (matrixCol == matrixRow)
0237                 values[matrixCol * M + matrixRow] = 1.0f;
0238             else
0239                 values[matrixCol * M + matrixRow] = 0.0f;
0240         }
0241     }
0242     return result;
0243 }
0244 
0245 inline const float& QMatrix4x4::operator()(int aRow, int aColumn) const
0246 {
0247     Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
0248     return m[aColumn][aRow];
0249 }
0250 
0251 inline float& QMatrix4x4::operator()(int aRow, int aColumn)
0252 {
0253     Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4);
0254     flagBits = General;
0255     return m[aColumn][aRow];
0256 }
0257 
0258 #ifndef QT_NO_VECTOR4D
0259 inline QVector4D QMatrix4x4::column(int index) const
0260 {
0261     Q_ASSERT(index >= 0 && index < 4);
0262     return QVector4D(m[index][0], m[index][1], m[index][2], m[index][3]);
0263 }
0264 
0265 inline void QMatrix4x4::setColumn(int index, const QVector4D& value)
0266 {
0267     Q_ASSERT(index >= 0 && index < 4);
0268     m[index][0] = value.x();
0269     m[index][1] = value.y();
0270     m[index][2] = value.z();
0271     m[index][3] = value.w();
0272     flagBits = General;
0273 }
0274 
0275 inline QVector4D QMatrix4x4::row(int index) const
0276 {
0277     Q_ASSERT(index >= 0 && index < 4);
0278     return QVector4D(m[0][index], m[1][index], m[2][index], m[3][index]);
0279 }
0280 
0281 inline void QMatrix4x4::setRow(int index, const QVector4D& value)
0282 {
0283     Q_ASSERT(index >= 0 && index < 4);
0284     m[0][index] = value.x();
0285     m[1][index] = value.y();
0286     m[2][index] = value.z();
0287     m[3][index] = value.w();
0288     flagBits = General;
0289 }
0290 #endif
0291 
0292 Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor);
0293 
0294 inline bool QMatrix4x4::isAffine() const
0295 {
0296     return m[0][3] == 0.0f && m[1][3] == 0.0f && m[2][3] == 0.0f && m[3][3] == 1.0f;
0297 }
0298 
0299 inline bool QMatrix4x4::isIdentity() const
0300 {
0301     if (flagBits == Identity)
0302         return true;
0303     if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
0304         return false;
0305     if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f)
0306         return false;
0307     if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f)
0308         return false;
0309     if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f)
0310         return false;
0311     if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f)
0312         return false;
0313     return (m[3][3] == 1.0f);
0314 }
0315 
0316 inline void QMatrix4x4::setToIdentity()
0317 {
0318     m[0][0] = 1.0f;
0319     m[0][1] = 0.0f;
0320     m[0][2] = 0.0f;
0321     m[0][3] = 0.0f;
0322     m[1][0] = 0.0f;
0323     m[1][1] = 1.0f;
0324     m[1][2] = 0.0f;
0325     m[1][3] = 0.0f;
0326     m[2][0] = 0.0f;
0327     m[2][1] = 0.0f;
0328     m[2][2] = 1.0f;
0329     m[2][3] = 0.0f;
0330     m[3][0] = 0.0f;
0331     m[3][1] = 0.0f;
0332     m[3][2] = 0.0f;
0333     m[3][3] = 1.0f;
0334     flagBits = Identity;
0335 }
0336 
0337 inline void QMatrix4x4::fill(float value)
0338 {
0339     m[0][0] = value;
0340     m[0][1] = value;
0341     m[0][2] = value;
0342     m[0][3] = value;
0343     m[1][0] = value;
0344     m[1][1] = value;
0345     m[1][2] = value;
0346     m[1][3] = value;
0347     m[2][0] = value;
0348     m[2][1] = value;
0349     m[2][2] = value;
0350     m[2][3] = value;
0351     m[3][0] = value;
0352     m[3][1] = value;
0353     m[3][2] = value;
0354     m[3][3] = value;
0355     flagBits = General;
0356 }
0357 
0358 inline QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
0359 {
0360     m[0][0] += other.m[0][0];
0361     m[0][1] += other.m[0][1];
0362     m[0][2] += other.m[0][2];
0363     m[0][3] += other.m[0][3];
0364     m[1][0] += other.m[1][0];
0365     m[1][1] += other.m[1][1];
0366     m[1][2] += other.m[1][2];
0367     m[1][3] += other.m[1][3];
0368     m[2][0] += other.m[2][0];
0369     m[2][1] += other.m[2][1];
0370     m[2][2] += other.m[2][2];
0371     m[2][3] += other.m[2][3];
0372     m[3][0] += other.m[3][0];
0373     m[3][1] += other.m[3][1];
0374     m[3][2] += other.m[3][2];
0375     m[3][3] += other.m[3][3];
0376     flagBits = General;
0377     return *this;
0378 }
0379 
0380 inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
0381 {
0382     m[0][0] -= other.m[0][0];
0383     m[0][1] -= other.m[0][1];
0384     m[0][2] -= other.m[0][2];
0385     m[0][3] -= other.m[0][3];
0386     m[1][0] -= other.m[1][0];
0387     m[1][1] -= other.m[1][1];
0388     m[1][2] -= other.m[1][2];
0389     m[1][3] -= other.m[1][3];
0390     m[2][0] -= other.m[2][0];
0391     m[2][1] -= other.m[2][1];
0392     m[2][2] -= other.m[2][2];
0393     m[2][3] -= other.m[2][3];
0394     m[3][0] -= other.m[3][0];
0395     m[3][1] -= other.m[3][1];
0396     m[3][2] -= other.m[3][2];
0397     m[3][3] -= other.m[3][3];
0398     flagBits = General;
0399     return *this;
0400 }
0401 
0402 inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& o)
0403 {
0404     const QMatrix4x4 other = o; // prevent aliasing when &o == this ### Qt 6: take o by value
0405     flagBits |= other.flagBits;
0406 
0407     if (flagBits.toInt() < Rotation2D) {
0408         m[3][0] += m[0][0] * other.m[3][0];
0409         m[3][1] += m[1][1] * other.m[3][1];
0410         m[3][2] += m[2][2] * other.m[3][2];
0411 
0412         m[0][0] *= other.m[0][0];
0413         m[1][1] *= other.m[1][1];
0414         m[2][2] *= other.m[2][2];
0415         return *this;
0416     }
0417 
0418     float m0, m1, m2;
0419     m0 = m[0][0] * other.m[0][0]
0420             + m[1][0] * other.m[0][1]
0421             + m[2][0] * other.m[0][2]
0422             + m[3][0] * other.m[0][3];
0423     m1 = m[0][0] * other.m[1][0]
0424             + m[1][0] * other.m[1][1]
0425             + m[2][0] * other.m[1][2]
0426             + m[3][0] * other.m[1][3];
0427     m2 = m[0][0] * other.m[2][0]
0428             + m[1][0] * other.m[2][1]
0429             + m[2][0] * other.m[2][2]
0430             + m[3][0] * other.m[2][3];
0431     m[3][0] = m[0][0] * other.m[3][0]
0432             + m[1][0] * other.m[3][1]
0433             + m[2][0] * other.m[3][2]
0434             + m[3][0] * other.m[3][3];
0435     m[0][0] = m0;
0436     m[1][0] = m1;
0437     m[2][0] = m2;
0438 
0439     m0 = m[0][1] * other.m[0][0]
0440             + m[1][1] * other.m[0][1]
0441             + m[2][1] * other.m[0][2]
0442             + m[3][1] * other.m[0][3];
0443     m1 = m[0][1] * other.m[1][0]
0444             + m[1][1] * other.m[1][1]
0445             + m[2][1] * other.m[1][2]
0446             + m[3][1] * other.m[1][3];
0447     m2 = m[0][1] * other.m[2][0]
0448             + m[1][1] * other.m[2][1]
0449             + m[2][1] * other.m[2][2]
0450             + m[3][1] * other.m[2][3];
0451     m[3][1] = m[0][1] * other.m[3][0]
0452             + m[1][1] * other.m[3][1]
0453             + m[2][1] * other.m[3][2]
0454             + m[3][1] * other.m[3][3];
0455     m[0][1] = m0;
0456     m[1][1] = m1;
0457     m[2][1] = m2;
0458 
0459     m0 = m[0][2] * other.m[0][0]
0460             + m[1][2] * other.m[0][1]
0461             + m[2][2] * other.m[0][2]
0462             + m[3][2] * other.m[0][3];
0463     m1 = m[0][2] * other.m[1][0]
0464             + m[1][2] * other.m[1][1]
0465             + m[2][2] * other.m[1][2]
0466             + m[3][2] * other.m[1][3];
0467     m2 = m[0][2] * other.m[2][0]
0468             + m[1][2] * other.m[2][1]
0469             + m[2][2] * other.m[2][2]
0470             + m[3][2] * other.m[2][3];
0471     m[3][2] = m[0][2] * other.m[3][0]
0472             + m[1][2] * other.m[3][1]
0473             + m[2][2] * other.m[3][2]
0474             + m[3][2] * other.m[3][3];
0475     m[0][2] = m0;
0476     m[1][2] = m1;
0477     m[2][2] = m2;
0478 
0479     m0 = m[0][3] * other.m[0][0]
0480             + m[1][3] * other.m[0][1]
0481             + m[2][3] * other.m[0][2]
0482             + m[3][3] * other.m[0][3];
0483     m1 = m[0][3] * other.m[1][0]
0484             + m[1][3] * other.m[1][1]
0485             + m[2][3] * other.m[1][2]
0486             + m[3][3] * other.m[1][3];
0487     m2 = m[0][3] * other.m[2][0]
0488             + m[1][3] * other.m[2][1]
0489             + m[2][3] * other.m[2][2]
0490             + m[3][3] * other.m[2][3];
0491     m[3][3] = m[0][3] * other.m[3][0]
0492             + m[1][3] * other.m[3][1]
0493             + m[2][3] * other.m[3][2]
0494             + m[3][3] * other.m[3][3];
0495     m[0][3] = m0;
0496     m[1][3] = m1;
0497     m[2][3] = m2;
0498     return *this;
0499 }
0500 
0501 inline QMatrix4x4& QMatrix4x4::operator*=(float factor)
0502 {
0503     m[0][0] *= factor;
0504     m[0][1] *= factor;
0505     m[0][2] *= factor;
0506     m[0][3] *= factor;
0507     m[1][0] *= factor;
0508     m[1][1] *= factor;
0509     m[1][2] *= factor;
0510     m[1][3] *= factor;
0511     m[2][0] *= factor;
0512     m[2][1] *= factor;
0513     m[2][2] *= factor;
0514     m[2][3] *= factor;
0515     m[3][0] *= factor;
0516     m[3][1] *= factor;
0517     m[3][2] *= factor;
0518     m[3][3] *= factor;
0519     flagBits = General;
0520     return *this;
0521 }
0522 
0523 inline bool QMatrix4x4::operator==(const QMatrix4x4& other) const
0524 {
0525     return m[0][0] == other.m[0][0] &&
0526            m[0][1] == other.m[0][1] &&
0527            m[0][2] == other.m[0][2] &&
0528            m[0][3] == other.m[0][3] &&
0529            m[1][0] == other.m[1][0] &&
0530            m[1][1] == other.m[1][1] &&
0531            m[1][2] == other.m[1][2] &&
0532            m[1][3] == other.m[1][3] &&
0533            m[2][0] == other.m[2][0] &&
0534            m[2][1] == other.m[2][1] &&
0535            m[2][2] == other.m[2][2] &&
0536            m[2][3] == other.m[2][3] &&
0537            m[3][0] == other.m[3][0] &&
0538            m[3][1] == other.m[3][1] &&
0539            m[3][2] == other.m[3][2] &&
0540            m[3][3] == other.m[3][3];
0541 }
0542 
0543 inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
0544 {
0545     return m[0][0] != other.m[0][0] ||
0546            m[0][1] != other.m[0][1] ||
0547            m[0][2] != other.m[0][2] ||
0548            m[0][3] != other.m[0][3] ||
0549            m[1][0] != other.m[1][0] ||
0550            m[1][1] != other.m[1][1] ||
0551            m[1][2] != other.m[1][2] ||
0552            m[1][3] != other.m[1][3] ||
0553            m[2][0] != other.m[2][0] ||
0554            m[2][1] != other.m[2][1] ||
0555            m[2][2] != other.m[2][2] ||
0556            m[2][3] != other.m[2][3] ||
0557            m[3][0] != other.m[3][0] ||
0558            m[3][1] != other.m[3][1] ||
0559            m[3][2] != other.m[3][2] ||
0560            m[3][3] != other.m[3][3];
0561 }
0562 
0563 inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
0564 {
0565     QMatrix4x4 m(Qt::Uninitialized);
0566     m.m[0][0] = m1.m[0][0] + m2.m[0][0];
0567     m.m[0][1] = m1.m[0][1] + m2.m[0][1];
0568     m.m[0][2] = m1.m[0][2] + m2.m[0][2];
0569     m.m[0][3] = m1.m[0][3] + m2.m[0][3];
0570     m.m[1][0] = m1.m[1][0] + m2.m[1][0];
0571     m.m[1][1] = m1.m[1][1] + m2.m[1][1];
0572     m.m[1][2] = m1.m[1][2] + m2.m[1][2];
0573     m.m[1][3] = m1.m[1][3] + m2.m[1][3];
0574     m.m[2][0] = m1.m[2][0] + m2.m[2][0];
0575     m.m[2][1] = m1.m[2][1] + m2.m[2][1];
0576     m.m[2][2] = m1.m[2][2] + m2.m[2][2];
0577     m.m[2][3] = m1.m[2][3] + m2.m[2][3];
0578     m.m[3][0] = m1.m[3][0] + m2.m[3][0];
0579     m.m[3][1] = m1.m[3][1] + m2.m[3][1];
0580     m.m[3][2] = m1.m[3][2] + m2.m[3][2];
0581     m.m[3][3] = m1.m[3][3] + m2.m[3][3];
0582     return m;
0583 }
0584 
0585 inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
0586 {
0587     QMatrix4x4 m(Qt::Uninitialized);
0588     m.m[0][0] = m1.m[0][0] - m2.m[0][0];
0589     m.m[0][1] = m1.m[0][1] - m2.m[0][1];
0590     m.m[0][2] = m1.m[0][2] - m2.m[0][2];
0591     m.m[0][3] = m1.m[0][3] - m2.m[0][3];
0592     m.m[1][0] = m1.m[1][0] - m2.m[1][0];
0593     m.m[1][1] = m1.m[1][1] - m2.m[1][1];
0594     m.m[1][2] = m1.m[1][2] - m2.m[1][2];
0595     m.m[1][3] = m1.m[1][3] - m2.m[1][3];
0596     m.m[2][0] = m1.m[2][0] - m2.m[2][0];
0597     m.m[2][1] = m1.m[2][1] - m2.m[2][1];
0598     m.m[2][2] = m1.m[2][2] - m2.m[2][2];
0599     m.m[2][3] = m1.m[2][3] - m2.m[2][3];
0600     m.m[3][0] = m1.m[3][0] - m2.m[3][0];
0601     m.m[3][1] = m1.m[3][1] - m2.m[3][1];
0602     m.m[3][2] = m1.m[3][2] - m2.m[3][2];
0603     m.m[3][3] = m1.m[3][3] - m2.m[3][3];
0604     return m;
0605 }
0606 
0607 inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
0608 {
0609     QMatrix4x4::Flags flagBits = m1.flagBits | m2.flagBits;
0610     if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
0611         QMatrix4x4 m = m1;
0612         m.m[3][0] += m.m[0][0] * m2.m[3][0];
0613         m.m[3][1] += m.m[1][1] * m2.m[3][1];
0614         m.m[3][2] += m.m[2][2] * m2.m[3][2];
0615 
0616         m.m[0][0] *= m2.m[0][0];
0617         m.m[1][1] *= m2.m[1][1];
0618         m.m[2][2] *= m2.m[2][2];
0619         m.flagBits = flagBits;
0620         return m;
0621     }
0622 
0623     QMatrix4x4 m(Qt::Uninitialized);
0624     m.m[0][0] = m1.m[0][0] * m2.m[0][0]
0625               + m1.m[1][0] * m2.m[0][1]
0626               + m1.m[2][0] * m2.m[0][2]
0627               + m1.m[3][0] * m2.m[0][3];
0628     m.m[0][1] = m1.m[0][1] * m2.m[0][0]
0629               + m1.m[1][1] * m2.m[0][1]
0630               + m1.m[2][1] * m2.m[0][2]
0631               + m1.m[3][1] * m2.m[0][3];
0632     m.m[0][2] = m1.m[0][2] * m2.m[0][0]
0633               + m1.m[1][2] * m2.m[0][1]
0634               + m1.m[2][2] * m2.m[0][2]
0635               + m1.m[3][2] * m2.m[0][3];
0636     m.m[0][3] = m1.m[0][3] * m2.m[0][0]
0637               + m1.m[1][3] * m2.m[0][1]
0638               + m1.m[2][3] * m2.m[0][2]
0639               + m1.m[3][3] * m2.m[0][3];
0640 
0641     m.m[1][0] = m1.m[0][0] * m2.m[1][0]
0642               + m1.m[1][0] * m2.m[1][1]
0643               + m1.m[2][0] * m2.m[1][2]
0644               + m1.m[3][0] * m2.m[1][3];
0645     m.m[1][1] = m1.m[0][1] * m2.m[1][0]
0646               + m1.m[1][1] * m2.m[1][1]
0647               + m1.m[2][1] * m2.m[1][2]
0648               + m1.m[3][1] * m2.m[1][3];
0649     m.m[1][2] = m1.m[0][2] * m2.m[1][0]
0650               + m1.m[1][2] * m2.m[1][1]
0651               + m1.m[2][2] * m2.m[1][2]
0652               + m1.m[3][2] * m2.m[1][3];
0653     m.m[1][3] = m1.m[0][3] * m2.m[1][0]
0654               + m1.m[1][3] * m2.m[1][1]
0655               + m1.m[2][3] * m2.m[1][2]
0656               + m1.m[3][3] * m2.m[1][3];
0657 
0658     m.m[2][0] = m1.m[0][0] * m2.m[2][0]
0659               + m1.m[1][0] * m2.m[2][1]
0660               + m1.m[2][0] * m2.m[2][2]
0661               + m1.m[3][0] * m2.m[2][3];
0662     m.m[2][1] = m1.m[0][1] * m2.m[2][0]
0663               + m1.m[1][1] * m2.m[2][1]
0664               + m1.m[2][1] * m2.m[2][2]
0665               + m1.m[3][1] * m2.m[2][3];
0666     m.m[2][2] = m1.m[0][2] * m2.m[2][0]
0667               + m1.m[1][2] * m2.m[2][1]
0668               + m1.m[2][2] * m2.m[2][2]
0669               + m1.m[3][2] * m2.m[2][3];
0670     m.m[2][3] = m1.m[0][3] * m2.m[2][0]
0671               + m1.m[1][3] * m2.m[2][1]
0672               + m1.m[2][3] * m2.m[2][2]
0673               + m1.m[3][3] * m2.m[2][3];
0674 
0675     m.m[3][0] = m1.m[0][0] * m2.m[3][0]
0676               + m1.m[1][0] * m2.m[3][1]
0677               + m1.m[2][0] * m2.m[3][2]
0678               + m1.m[3][0] * m2.m[3][3];
0679     m.m[3][1] = m1.m[0][1] * m2.m[3][0]
0680               + m1.m[1][1] * m2.m[3][1]
0681               + m1.m[2][1] * m2.m[3][2]
0682               + m1.m[3][1] * m2.m[3][3];
0683     m.m[3][2] = m1.m[0][2] * m2.m[3][0]
0684               + m1.m[1][2] * m2.m[3][1]
0685               + m1.m[2][2] * m2.m[3][2]
0686               + m1.m[3][2] * m2.m[3][3];
0687     m.m[3][3] = m1.m[0][3] * m2.m[3][0]
0688               + m1.m[1][3] * m2.m[3][1]
0689               + m1.m[2][3] * m2.m[3][2]
0690               + m1.m[3][3] * m2.m[3][3];
0691     m.flagBits = flagBits;
0692     return m;
0693 }
0694 
0695 #ifndef QT_NO_VECTOR3D
0696 
0697 #if QT_DEPRECATED_SINCE(6, 1)
0698 
0699 QT_DEPRECATED_VERSION_X_6_1("Extend the QVector3D to a QVector4D with 1.0 as the w coordinate before multiplying")
0700 inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
0701 {
0702     float x, y, z, w;
0703     x = vector.x() * matrix.m[0][0] +
0704         vector.y() * matrix.m[0][1] +
0705         vector.z() * matrix.m[0][2] +
0706         matrix.m[0][3];
0707     y = vector.x() * matrix.m[1][0] +
0708         vector.y() * matrix.m[1][1] +
0709         vector.z() * matrix.m[1][2] +
0710         matrix.m[1][3];
0711     z = vector.x() * matrix.m[2][0] +
0712         vector.y() * matrix.m[2][1] +
0713         vector.z() * matrix.m[2][2] +
0714         matrix.m[2][3];
0715     w = vector.x() * matrix.m[3][0] +
0716         vector.y() * matrix.m[3][1] +
0717         vector.z() * matrix.m[3][2] +
0718         matrix.m[3][3];
0719     if (w == 1.0f)
0720         return QVector3D(x, y, z);
0721     else
0722         return QVector3D(x / w, y / w, z / w);
0723 }
0724 
0725 QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(vector) instead")
0726 inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
0727 {
0728     return matrix.map(vector);
0729 }
0730 
0731 #endif
0732 
0733 #endif
0734 
0735 #ifndef QT_NO_VECTOR4D
0736 
0737 inline QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
0738 {
0739     float x, y, z, w;
0740     x = vector.x() * matrix.m[0][0] +
0741         vector.y() * matrix.m[0][1] +
0742         vector.z() * matrix.m[0][2] +
0743         vector.w() * matrix.m[0][3];
0744     y = vector.x() * matrix.m[1][0] +
0745         vector.y() * matrix.m[1][1] +
0746         vector.z() * matrix.m[1][2] +
0747         vector.w() * matrix.m[1][3];
0748     z = vector.x() * matrix.m[2][0] +
0749         vector.y() * matrix.m[2][1] +
0750         vector.z() * matrix.m[2][2] +
0751         vector.w() * matrix.m[2][3];
0752     w = vector.x() * matrix.m[3][0] +
0753         vector.y() * matrix.m[3][1] +
0754         vector.z() * matrix.m[3][2] +
0755         vector.w() * matrix.m[3][3];
0756     return QVector4D(x, y, z, w);
0757 }
0758 
0759 inline QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
0760 {
0761     float x, y, z, w;
0762     x = vector.x() * matrix.m[0][0] +
0763         vector.y() * matrix.m[1][0] +
0764         vector.z() * matrix.m[2][0] +
0765         vector.w() * matrix.m[3][0];
0766     y = vector.x() * matrix.m[0][1] +
0767         vector.y() * matrix.m[1][1] +
0768         vector.z() * matrix.m[2][1] +
0769         vector.w() * matrix.m[3][1];
0770     z = vector.x() * matrix.m[0][2] +
0771         vector.y() * matrix.m[1][2] +
0772         vector.z() * matrix.m[2][2] +
0773         vector.w() * matrix.m[3][2];
0774     w = vector.x() * matrix.m[0][3] +
0775         vector.y() * matrix.m[1][3] +
0776         vector.z() * matrix.m[2][3] +
0777         vector.w() * matrix.m[3][3];
0778     return QVector4D(x, y, z, w);
0779 }
0780 
0781 #endif
0782 
0783 inline QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
0784 {
0785     float xin, yin;
0786     float x, y, w;
0787     xin = point.x();
0788     yin = point.y();
0789     x = xin * matrix.m[0][0] +
0790         yin * matrix.m[0][1] +
0791         matrix.m[0][3];
0792     y = xin * matrix.m[1][0] +
0793         yin * matrix.m[1][1] +
0794         matrix.m[1][3];
0795     w = xin * matrix.m[3][0] +
0796         yin * matrix.m[3][1] +
0797         matrix.m[3][3];
0798     if (w == 1.0f)
0799         return QPoint(qRound(x), qRound(y));
0800     else
0801         return QPoint(qRound(x / w), qRound(y / w));
0802 }
0803 
0804 inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
0805 {
0806     float xin, yin;
0807     float x, y, w;
0808     xin = float(point.x());
0809     yin = float(point.y());
0810     x = xin * matrix.m[0][0] +
0811         yin * matrix.m[0][1] +
0812         matrix.m[0][3];
0813     y = xin * matrix.m[1][0] +
0814         yin * matrix.m[1][1] +
0815         matrix.m[1][3];
0816     w = xin * matrix.m[3][0] +
0817         yin * matrix.m[3][1] +
0818         matrix.m[3][3];
0819     if (w == 1.0f) {
0820         return QPointF(qreal(x), qreal(y));
0821     } else {
0822         return QPointF(qreal(x / w), qreal(y / w));
0823     }
0824 }
0825 
0826 #if QT_DEPRECATED_SINCE(6, 1)
0827 
0828 QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(point) instead")
0829 inline QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
0830 {
0831     return matrix.map(point);
0832 }
0833 
0834 QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(point) instead")
0835 inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
0836 {
0837     return matrix.map(point);
0838 }
0839 
0840 #endif
0841 
0842 inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
0843 {
0844     QMatrix4x4 m(Qt::Uninitialized);
0845     m.m[0][0] = -matrix.m[0][0];
0846     m.m[0][1] = -matrix.m[0][1];
0847     m.m[0][2] = -matrix.m[0][2];
0848     m.m[0][3] = -matrix.m[0][3];
0849     m.m[1][0] = -matrix.m[1][0];
0850     m.m[1][1] = -matrix.m[1][1];
0851     m.m[1][2] = -matrix.m[1][2];
0852     m.m[1][3] = -matrix.m[1][3];
0853     m.m[2][0] = -matrix.m[2][0];
0854     m.m[2][1] = -matrix.m[2][1];
0855     m.m[2][2] = -matrix.m[2][2];
0856     m.m[2][3] = -matrix.m[2][3];
0857     m.m[3][0] = -matrix.m[3][0];
0858     m.m[3][1] = -matrix.m[3][1];
0859     m.m[3][2] = -matrix.m[3][2];
0860     m.m[3][3] = -matrix.m[3][3];
0861     return m;
0862 }
0863 
0864 inline QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix)
0865 {
0866     QMatrix4x4 m(Qt::Uninitialized);
0867     m.m[0][0] = matrix.m[0][0] * factor;
0868     m.m[0][1] = matrix.m[0][1] * factor;
0869     m.m[0][2] = matrix.m[0][2] * factor;
0870     m.m[0][3] = matrix.m[0][3] * factor;
0871     m.m[1][0] = matrix.m[1][0] * factor;
0872     m.m[1][1] = matrix.m[1][1] * factor;
0873     m.m[1][2] = matrix.m[1][2] * factor;
0874     m.m[1][3] = matrix.m[1][3] * factor;
0875     m.m[2][0] = matrix.m[2][0] * factor;
0876     m.m[2][1] = matrix.m[2][1] * factor;
0877     m.m[2][2] = matrix.m[2][2] * factor;
0878     m.m[2][3] = matrix.m[2][3] * factor;
0879     m.m[3][0] = matrix.m[3][0] * factor;
0880     m.m[3][1] = matrix.m[3][1] * factor;
0881     m.m[3][2] = matrix.m[3][2] * factor;
0882     m.m[3][3] = matrix.m[3][3] * factor;
0883     return m;
0884 }
0885 
0886 inline QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor)
0887 {
0888     QMatrix4x4 m(Qt::Uninitialized);
0889     m.m[0][0] = matrix.m[0][0] * factor;
0890     m.m[0][1] = matrix.m[0][1] * factor;
0891     m.m[0][2] = matrix.m[0][2] * factor;
0892     m.m[0][3] = matrix.m[0][3] * factor;
0893     m.m[1][0] = matrix.m[1][0] * factor;
0894     m.m[1][1] = matrix.m[1][1] * factor;
0895     m.m[1][2] = matrix.m[1][2] * factor;
0896     m.m[1][3] = matrix.m[1][3] * factor;
0897     m.m[2][0] = matrix.m[2][0] * factor;
0898     m.m[2][1] = matrix.m[2][1] * factor;
0899     m.m[2][2] = matrix.m[2][2] * factor;
0900     m.m[2][3] = matrix.m[2][3] * factor;
0901     m.m[3][0] = matrix.m[3][0] * factor;
0902     m.m[3][1] = matrix.m[3][1] * factor;
0903     m.m[3][2] = matrix.m[3][2] * factor;
0904     m.m[3][3] = matrix.m[3][3] * factor;
0905     return m;
0906 }
0907 
0908 inline QPoint QMatrix4x4::map(const QPoint& point) const
0909 {
0910     float xin, yin;
0911     float x, y, w;
0912     xin = point.x();
0913     yin = point.y();
0914     if (flagBits == QMatrix4x4::Identity) {
0915         return point;
0916     } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
0917         // Translation | Scale
0918         return QPoint(qRound(xin * m[0][0] + m[3][0]),
0919                       qRound(yin * m[1][1] + m[3][1]));
0920     } else if (flagBits.toInt() < QMatrix4x4::Perspective) {
0921         return QPoint(qRound(xin * m[0][0] + yin * m[1][0] + m[3][0]),
0922                       qRound(xin * m[0][1] + yin * m[1][1] + m[3][1]));
0923     } else {
0924         x = xin * m[0][0] +
0925             yin * m[1][0] +
0926             m[3][0];
0927         y = xin * m[0][1] +
0928             yin * m[1][1] +
0929             m[3][1];
0930         w = xin * m[0][3] +
0931             yin * m[1][3] +
0932             m[3][3];
0933         if (w == 1.0f)
0934             return QPoint(qRound(x), qRound(y));
0935         else
0936             return QPoint(qRound(x / w), qRound(y / w));
0937     }
0938 }
0939 
0940 inline QPointF QMatrix4x4::map(const QPointF& point) const
0941 {
0942     qreal xin, yin;
0943     qreal x, y, w;
0944     xin = point.x();
0945     yin = point.y();
0946     if (flagBits == QMatrix4x4::Identity) {
0947         return point;
0948     } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
0949         // Translation | Scale
0950         return QPointF(xin * qreal(m[0][0]) + qreal(m[3][0]),
0951                        yin * qreal(m[1][1]) + qreal(m[3][1]));
0952     } else if (flagBits.toInt() < QMatrix4x4::Perspective) {
0953         return QPointF(xin * qreal(m[0][0]) + yin * qreal(m[1][0]) +
0954                        qreal(m[3][0]),
0955                        xin * qreal(m[0][1]) + yin * qreal(m[1][1]) +
0956                        qreal(m[3][1]));
0957     } else {
0958         x = xin * qreal(m[0][0]) +
0959             yin * qreal(m[1][0]) +
0960             qreal(m[3][0]);
0961         y = xin * qreal(m[0][1]) +
0962             yin * qreal(m[1][1]) +
0963             qreal(m[3][1]);
0964         w = xin * qreal(m[0][3]) +
0965             yin * qreal(m[1][3]) +
0966             qreal(m[3][3]);
0967         if (w == 1.0) {
0968             return QPointF(qreal(x), qreal(y));
0969         } else {
0970             return QPointF(qreal(x / w), qreal(y / w));
0971         }
0972     }
0973 }
0974 
0975 #ifndef QT_NO_VECTOR3D
0976 
0977 inline QVector3D QMatrix4x4::map(const QVector3D& point) const
0978 {
0979     float x, y, z, w;
0980     if (flagBits == QMatrix4x4::Identity) {
0981         return point;
0982     } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) {
0983         // Translation | Scale
0984         return QVector3D(point.x() * m[0][0] + m[3][0],
0985                          point.y() * m[1][1] + m[3][1],
0986                          point.z() * m[2][2] + m[3][2]);
0987     } else if (flagBits.toInt() < QMatrix4x4::Rotation) {
0988         // Translation | Scale | Rotation2D
0989         return QVector3D(point.x() * m[0][0] + point.y() * m[1][0] + m[3][0],
0990                          point.x() * m[0][1] + point.y() * m[1][1] + m[3][1],
0991                          point.z() * m[2][2] + m[3][2]);
0992     } else {
0993         x = point.x() * m[0][0] +
0994             point.y() * m[1][0] +
0995             point.z() * m[2][0] +
0996             m[3][0];
0997         y = point.x() * m[0][1] +
0998             point.y() * m[1][1] +
0999             point.z() * m[2][1] +
1000             m[3][1];
1001         z = point.x() * m[0][2] +
1002             point.y() * m[1][2] +
1003             point.z() * m[2][2] +
1004             m[3][2];
1005         w = point.x() * m[0][3] +
1006             point.y() * m[1][3] +
1007             point.z() * m[2][3] +
1008             m[3][3];
1009         if (w == 1.0f)
1010             return QVector3D(x, y, z);
1011         else
1012             return QVector3D(x / w, y / w, z / w);
1013     }
1014 }
1015 
1016 inline QVector3D QMatrix4x4::mapVector(const QVector3D& vector) const
1017 {
1018     if (flagBits.toInt() < Scale) {
1019         // Translation
1020         return vector;
1021     } else if (flagBits.toInt() < Rotation2D) {
1022         // Translation | Scale
1023         return QVector3D(vector.x() * m[0][0],
1024                          vector.y() * m[1][1],
1025                          vector.z() * m[2][2]);
1026     } else {
1027         return QVector3D(vector.x() * m[0][0] +
1028                          vector.y() * m[1][0] +
1029                          vector.z() * m[2][0],
1030                          vector.x() * m[0][1] +
1031                          vector.y() * m[1][1] +
1032                          vector.z() * m[2][1],
1033                          vector.x() * m[0][2] +
1034                          vector.y() * m[1][2] +
1035                          vector.z() * m[2][2]);
1036     }
1037 }
1038 
1039 #endif
1040 
1041 #ifndef QT_NO_VECTOR4D
1042 
1043 inline QVector4D QMatrix4x4::map(const QVector4D& point) const
1044 {
1045     return *this * point;
1046 }
1047 
1048 #endif
1049 
1050 inline float *QMatrix4x4::data()
1051 {
1052     // We have to assume that the caller will modify the matrix elements,
1053     // so we flip it over to "General" mode.
1054     flagBits = General;
1055     return *m;
1056 }
1057 
1058 inline void QMatrix4x4::viewport(const QRectF &rect)
1059 {
1060     viewport(float(rect.x()), float(rect.y()), float(rect.width()), float(rect.height()));
1061 }
1062 
1063 QT_WARNING_POP
1064 
1065 #ifndef QT_NO_DEBUG_STREAM
1066 Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
1067 #endif
1068 
1069 #ifndef QT_NO_DATASTREAM
1070 Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &);
1071 Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &);
1072 #endif
1073 
1074 #endif
1075 
1076 QT_END_NAMESPACE
1077 
1078 #endif