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