1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QMATRIX4X4_H |
5 | #define QMATRIX4X4_H |
6 | |
7 | #include <QtGui/qtguiglobal.h> |
8 | #include <QtGui/qvector3d.h> |
9 | #include <QtGui/qvector4d.h> |
10 | #include <QtGui/qquaternion.h> |
11 | #include <QtGui/qgenericmatrix.h> |
12 | #include <QtCore/qrect.h> |
13 | |
14 | class tst_QMatrixNxN; |
15 | |
16 | QT_BEGIN_NAMESPACE |
17 | |
18 | |
19 | #ifndef QT_NO_MATRIX4X4 |
20 | |
21 | class QTransform; |
22 | class QVariant; |
23 | |
24 | class Q_GUI_EXPORT QMatrix4x4 |
25 | { |
26 | public: |
27 | inline QMatrix4x4() { setToIdentity(); } |
28 | explicit QMatrix4x4(Qt::Initialization) : flagBits(General) {} |
29 | explicit QMatrix4x4(const float *values); |
30 | inline QMatrix4x4(float m11, float m12, float m13, float m14, |
31 | float m21, float m22, float m23, float m24, |
32 | float m31, float m32, float m33, float m34, |
33 | float m41, float m42, float m43, float m44); |
34 | |
35 | template <int N, int M> |
36 | explicit QMatrix4x4(const QGenericMatrix<N, M, float>& matrix); |
37 | |
38 | QMatrix4x4(const float *values, int cols, int rows); |
39 | QMatrix4x4(const QTransform& transform); |
40 | |
41 | inline const float& operator()(int row, int column) const; |
42 | inline float& operator()(int row, int column); |
43 | |
44 | #ifndef QT_NO_VECTOR4D |
45 | inline QVector4D column(int index) const; |
46 | inline void setColumn(int index, const QVector4D& value); |
47 | |
48 | inline QVector4D row(int index) const; |
49 | inline void setRow(int index, const QVector4D& value); |
50 | #endif |
51 | |
52 | inline bool isAffine() const; |
53 | |
54 | inline bool isIdentity() const; |
55 | inline void setToIdentity(); |
56 | |
57 | inline void fill(float value); |
58 | |
59 | double determinant() const; |
60 | QMatrix4x4 inverted(bool *invertible = nullptr) const; |
61 | QMatrix4x4 transposed() const; |
62 | QMatrix3x3 normalMatrix() const; |
63 | |
64 | inline QMatrix4x4& operator+=(const QMatrix4x4& other); |
65 | inline QMatrix4x4& operator-=(const QMatrix4x4& other); |
66 | inline QMatrix4x4& operator*=(const QMatrix4x4& other); |
67 | inline QMatrix4x4& operator*=(float factor); |
68 | QMatrix4x4& operator/=(float divisor); |
69 | inline bool operator==(const QMatrix4x4& other) const; |
70 | inline bool operator!=(const QMatrix4x4& other) const; |
71 | |
72 | friend QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2); |
73 | friend QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2); |
74 | friend QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2); |
75 | #ifndef QT_NO_VECTOR3D |
76 | #if QT_DEPRECATED_SINCE(6, 1) |
77 | friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector); |
78 | friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix); |
79 | #endif |
80 | #endif |
81 | #ifndef QT_NO_VECTOR4D |
82 | friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix); |
83 | friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector); |
84 | #endif |
85 | friend QPoint operator*(const QPoint& point, const QMatrix4x4& matrix); |
86 | friend QPointF operator*(const QPointF& point, const QMatrix4x4& matrix); |
87 | friend QMatrix4x4 operator-(const QMatrix4x4& matrix); |
88 | #if QT_DEPRECATED_SINCE(6, 1) |
89 | friend QPoint operator*(const QMatrix4x4& matrix, const QPoint& point); |
90 | friend QPointF operator*(const QMatrix4x4& matrix, const QPointF& point); |
91 | #endif |
92 | friend QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix); |
93 | friend QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor); |
94 | friend Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor); |
95 | |
96 | friend Q_GUI_EXPORT bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2); |
97 | |
98 | #ifndef QT_NO_VECTOR3D |
99 | void scale(const QVector3D& vector); |
100 | void translate(const QVector3D& vector); |
101 | void rotate(float angle, const QVector3D& vector); |
102 | #endif |
103 | void scale(float x, float y); |
104 | void scale(float x, float y, float z); |
105 | void scale(float factor); |
106 | void translate(float x, float y); |
107 | void translate(float x, float y, float z); |
108 | void rotate(float angle, float x, float y, float z = 0.0f); |
109 | #ifndef QT_NO_QUATERNION |
110 | void rotate(const QQuaternion& quaternion); |
111 | #endif |
112 | |
113 | void ortho(const QRect& rect); |
114 | void ortho(const QRectF& rect); |
115 | void ortho(float left, float right, float bottom, float top, float nearPlane, float farPlane); |
116 | void frustum(float left, float right, float bottom, float top, float nearPlane, float farPlane); |
117 | void perspective(float verticalAngle, float aspectRatio, float nearPlane, float farPlane); |
118 | #ifndef QT_NO_VECTOR3D |
119 | void lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up); |
120 | #endif |
121 | void viewport(const QRectF &rect); |
122 | void viewport(float left, float bottom, float width, float height, float nearPlane = 0.0f, float farPlane = 1.0f); |
123 | void flipCoordinates(); |
124 | |
125 | void copyDataTo(float *values) const; |
126 | |
127 | QTransform toTransform() const; |
128 | QTransform toTransform(float distanceToPlane) const; |
129 | |
130 | inline QPoint map(const QPoint& point) const; |
131 | inline QPointF map(const QPointF& point) const; |
132 | #ifndef QT_NO_VECTOR3D |
133 | inline QVector3D map(const QVector3D& point) const; |
134 | inline QVector3D mapVector(const QVector3D& vector) const; |
135 | #endif |
136 | #ifndef QT_NO_VECTOR4D |
137 | inline QVector4D map(const QVector4D& point) const; |
138 | #endif |
139 | QRect mapRect(const QRect& rect) const; |
140 | QRectF mapRect(const QRectF& rect) const; |
141 | |
142 | template <int N, int M> |
143 | QGenericMatrix<N, M, float> toGenericMatrix() const; |
144 | |
145 | inline float *data(); |
146 | inline const float *data() const { return *m; } |
147 | inline const float *constData() const { return *m; } |
148 | |
149 | void optimize(); |
150 | |
151 | operator QVariant() const; |
152 | |
153 | #ifndef QT_NO_DEBUG_STREAM |
154 | friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m); |
155 | #endif |
156 | |
157 | #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0) |
158 | void projectedRotate(float angle, float x, float y, float z, float distanceToPlane); |
159 | // ### Qt7: Remove |
160 | void projectedRotate(float angle, float x, float y, float z); |
161 | #else |
162 | void projectedRotate(float angle, float x, float y, float z, float distanceToPlane = 1024.0); |
163 | #endif |
164 | |
165 | // When matrices are multiplied, the flag bits are or-ed together. |
166 | // Note that the ordering of the bit values matters. (ident < t < s < r2d < r < p) |
167 | enum Flag { |
168 | Identity = 0x0000, // Identity matrix |
169 | Translation = 0x0001, // Contains a translation |
170 | Scale = 0x0002, // Contains a scale |
171 | Rotation2D = 0x0004, // Contains a rotation about the Z axis |
172 | Rotation = 0x0008, // Contains an arbitrary rotation |
173 | Perspective = 0x0010, // Last row is different from (0, 0, 0, 1) |
174 | General = 0x001f // General matrix, unknown contents |
175 | }; |
176 | Q_DECLARE_FLAGS(Flags, Flag) |
177 | |
178 | Flags flags() const { return flagBits; } |
179 | |
180 | private: |
181 | float m[4][4]; // Column-major order to match OpenGL. |
182 | Flags flagBits; |
183 | |
184 | QMatrix4x4 orthonormalInverse() const; |
185 | |
186 | friend class ::tst_QMatrixNxN; // for access to flagBits |
187 | }; |
188 | |
189 | Q_DECLARE_OPERATORS_FOR_FLAGS(QMatrix4x4::Flags) |
190 | |
191 | QT_WARNING_PUSH |
192 | QT_WARNING_DISABLE_FLOAT_COMPARE |
193 | |
194 | Q_DECLARE_TYPEINFO(QMatrix4x4, Q_PRIMITIVE_TYPE); |
195 | |
196 | inline QMatrix4x4::QMatrix4x4 |
197 | (float m11, float m12, float m13, float m14, |
198 | float m21, float m22, float m23, float m24, |
199 | float m31, float m32, float m33, float m34, |
200 | float m41, float m42, float m43, float m44) |
201 | { |
202 | m[0][0] = m11; m[0][1] = m21; m[0][2] = m31; m[0][3] = m41; |
203 | m[1][0] = m12; m[1][1] = m22; m[1][2] = m32; m[1][3] = m42; |
204 | m[2][0] = m13; m[2][1] = m23; m[2][2] = m33; m[2][3] = m43; |
205 | m[3][0] = m14; m[3][1] = m24; m[3][2] = m34; m[3][3] = m44; |
206 | flagBits = General; |
207 | } |
208 | |
209 | template <int N, int M> |
210 | Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4 |
211 | (const QGenericMatrix<N, M, float>& matrix) |
212 | { |
213 | const float *values = matrix.constData(); |
214 | for (int matrixCol = 0; matrixCol < 4; ++matrixCol) { |
215 | for (int matrixRow = 0; matrixRow < 4; ++matrixRow) { |
216 | if (matrixCol < N && matrixRow < M) |
217 | m[matrixCol][matrixRow] = values[matrixCol * M + matrixRow]; |
218 | else if (matrixCol == matrixRow) |
219 | m[matrixCol][matrixRow] = 1.0f; |
220 | else |
221 | m[matrixCol][matrixRow] = 0.0f; |
222 | } |
223 | } |
224 | flagBits = General; |
225 | } |
226 | |
227 | template <int N, int M> |
228 | QGenericMatrix<N, M, float> QMatrix4x4::toGenericMatrix() const |
229 | { |
230 | QGenericMatrix<N, M, float> result; |
231 | float *values = result.data(); |
232 | for (int matrixCol = 0; matrixCol < N; ++matrixCol) { |
233 | for (int matrixRow = 0; matrixRow < M; ++matrixRow) { |
234 | if (matrixCol < 4 && matrixRow < 4) |
235 | values[matrixCol * M + matrixRow] = m[matrixCol][matrixRow]; |
236 | else if (matrixCol == matrixRow) |
237 | values[matrixCol * M + matrixRow] = 1.0f; |
238 | else |
239 | values[matrixCol * M + matrixRow] = 0.0f; |
240 | } |
241 | } |
242 | return result; |
243 | } |
244 | |
245 | inline const float& QMatrix4x4::operator()(int aRow, int aColumn) const |
246 | { |
247 | Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4); |
248 | return m[aColumn][aRow]; |
249 | } |
250 | |
251 | inline float& QMatrix4x4::operator()(int aRow, int aColumn) |
252 | { |
253 | Q_ASSERT(aRow >= 0 && aRow < 4 && aColumn >= 0 && aColumn < 4); |
254 | flagBits = General; |
255 | return m[aColumn][aRow]; |
256 | } |
257 | |
258 | #ifndef QT_NO_VECTOR4D |
259 | inline QVector4D QMatrix4x4::column(int index) const |
260 | { |
261 | Q_ASSERT(index >= 0 && index < 4); |
262 | return QVector4D(m[index][0], m[index][1], m[index][2], m[index][3]); |
263 | } |
264 | |
265 | inline void QMatrix4x4::setColumn(int index, const QVector4D& value) |
266 | { |
267 | Q_ASSERT(index >= 0 && index < 4); |
268 | m[index][0] = value.x(); |
269 | m[index][1] = value.y(); |
270 | m[index][2] = value.z(); |
271 | m[index][3] = value.w(); |
272 | flagBits = General; |
273 | } |
274 | |
275 | inline QVector4D QMatrix4x4::row(int index) const |
276 | { |
277 | Q_ASSERT(index >= 0 && index < 4); |
278 | return QVector4D(m[0][index], m[1][index], m[2][index], m[3][index]); |
279 | } |
280 | |
281 | inline void QMatrix4x4::setRow(int index, const QVector4D& value) |
282 | { |
283 | Q_ASSERT(index >= 0 && index < 4); |
284 | m[0][index] = value.x(); |
285 | m[1][index] = value.y(); |
286 | m[2][index] = value.z(); |
287 | m[3][index] = value.w(); |
288 | flagBits = General; |
289 | } |
290 | #endif |
291 | |
292 | Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, float divisor); |
293 | |
294 | inline bool QMatrix4x4::isAffine() const |
295 | { |
296 | return m[0][3] == 0.0f && m[1][3] == 0.0f && m[2][3] == 0.0f && m[3][3] == 1.0f; |
297 | } |
298 | |
299 | inline bool QMatrix4x4::isIdentity() const |
300 | { |
301 | if (flagBits == Identity) |
302 | return true; |
303 | if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f) |
304 | return false; |
305 | if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f) |
306 | return false; |
307 | if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f) |
308 | return false; |
309 | if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f) |
310 | return false; |
311 | if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f) |
312 | return false; |
313 | return (m[3][3] == 1.0f); |
314 | } |
315 | |
316 | inline void QMatrix4x4::setToIdentity() |
317 | { |
318 | m[0][0] = 1.0f; |
319 | m[0][1] = 0.0f; |
320 | m[0][2] = 0.0f; |
321 | m[0][3] = 0.0f; |
322 | m[1][0] = 0.0f; |
323 | m[1][1] = 1.0f; |
324 | m[1][2] = 0.0f; |
325 | m[1][3] = 0.0f; |
326 | m[2][0] = 0.0f; |
327 | m[2][1] = 0.0f; |
328 | m[2][2] = 1.0f; |
329 | m[2][3] = 0.0f; |
330 | m[3][0] = 0.0f; |
331 | m[3][1] = 0.0f; |
332 | m[3][2] = 0.0f; |
333 | m[3][3] = 1.0f; |
334 | flagBits = Identity; |
335 | } |
336 | |
337 | inline void QMatrix4x4::fill(float value) |
338 | { |
339 | m[0][0] = value; |
340 | m[0][1] = value; |
341 | m[0][2] = value; |
342 | m[0][3] = value; |
343 | m[1][0] = value; |
344 | m[1][1] = value; |
345 | m[1][2] = value; |
346 | m[1][3] = value; |
347 | m[2][0] = value; |
348 | m[2][1] = value; |
349 | m[2][2] = value; |
350 | m[2][3] = value; |
351 | m[3][0] = value; |
352 | m[3][1] = value; |
353 | m[3][2] = value; |
354 | m[3][3] = value; |
355 | flagBits = General; |
356 | } |
357 | |
358 | inline QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other) |
359 | { |
360 | m[0][0] += other.m[0][0]; |
361 | m[0][1] += other.m[0][1]; |
362 | m[0][2] += other.m[0][2]; |
363 | m[0][3] += other.m[0][3]; |
364 | m[1][0] += other.m[1][0]; |
365 | m[1][1] += other.m[1][1]; |
366 | m[1][2] += other.m[1][2]; |
367 | m[1][3] += other.m[1][3]; |
368 | m[2][0] += other.m[2][0]; |
369 | m[2][1] += other.m[2][1]; |
370 | m[2][2] += other.m[2][2]; |
371 | m[2][3] += other.m[2][3]; |
372 | m[3][0] += other.m[3][0]; |
373 | m[3][1] += other.m[3][1]; |
374 | m[3][2] += other.m[3][2]; |
375 | m[3][3] += other.m[3][3]; |
376 | flagBits = General; |
377 | return *this; |
378 | } |
379 | |
380 | inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other) |
381 | { |
382 | m[0][0] -= other.m[0][0]; |
383 | m[0][1] -= other.m[0][1]; |
384 | m[0][2] -= other.m[0][2]; |
385 | m[0][3] -= other.m[0][3]; |
386 | m[1][0] -= other.m[1][0]; |
387 | m[1][1] -= other.m[1][1]; |
388 | m[1][2] -= other.m[1][2]; |
389 | m[1][3] -= other.m[1][3]; |
390 | m[2][0] -= other.m[2][0]; |
391 | m[2][1] -= other.m[2][1]; |
392 | m[2][2] -= other.m[2][2]; |
393 | m[2][3] -= other.m[2][3]; |
394 | m[3][0] -= other.m[3][0]; |
395 | m[3][1] -= other.m[3][1]; |
396 | m[3][2] -= other.m[3][2]; |
397 | m[3][3] -= other.m[3][3]; |
398 | flagBits = General; |
399 | return *this; |
400 | } |
401 | |
402 | inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& o) |
403 | { |
404 | const QMatrix4x4 other = o; // prevent aliasing when &o == this ### Qt 6: take o by value |
405 | flagBits |= other.flagBits; |
406 | |
407 | if (flagBits.toInt() < Rotation2D) { |
408 | m[3][0] += m[0][0] * other.m[3][0]; |
409 | m[3][1] += m[1][1] * other.m[3][1]; |
410 | m[3][2] += m[2][2] * other.m[3][2]; |
411 | |
412 | m[0][0] *= other.m[0][0]; |
413 | m[1][1] *= other.m[1][1]; |
414 | m[2][2] *= other.m[2][2]; |
415 | return *this; |
416 | } |
417 | |
418 | float m0, m1, m2; |
419 | m0 = m[0][0] * other.m[0][0] |
420 | + m[1][0] * other.m[0][1] |
421 | + m[2][0] * other.m[0][2] |
422 | + m[3][0] * other.m[0][3]; |
423 | m1 = m[0][0] * other.m[1][0] |
424 | + m[1][0] * other.m[1][1] |
425 | + m[2][0] * other.m[1][2] |
426 | + m[3][0] * other.m[1][3]; |
427 | m2 = m[0][0] * other.m[2][0] |
428 | + m[1][0] * other.m[2][1] |
429 | + m[2][0] * other.m[2][2] |
430 | + m[3][0] * other.m[2][3]; |
431 | m[3][0] = m[0][0] * other.m[3][0] |
432 | + m[1][0] * other.m[3][1] |
433 | + m[2][0] * other.m[3][2] |
434 | + m[3][0] * other.m[3][3]; |
435 | m[0][0] = m0; |
436 | m[1][0] = m1; |
437 | m[2][0] = m2; |
438 | |
439 | m0 = m[0][1] * other.m[0][0] |
440 | + m[1][1] * other.m[0][1] |
441 | + m[2][1] * other.m[0][2] |
442 | + m[3][1] * other.m[0][3]; |
443 | m1 = m[0][1] * other.m[1][0] |
444 | + m[1][1] * other.m[1][1] |
445 | + m[2][1] * other.m[1][2] |
446 | + m[3][1] * other.m[1][3]; |
447 | m2 = m[0][1] * other.m[2][0] |
448 | + m[1][1] * other.m[2][1] |
449 | + m[2][1] * other.m[2][2] |
450 | + m[3][1] * other.m[2][3]; |
451 | m[3][1] = m[0][1] * other.m[3][0] |
452 | + m[1][1] * other.m[3][1] |
453 | + m[2][1] * other.m[3][2] |
454 | + m[3][1] * other.m[3][3]; |
455 | m[0][1] = m0; |
456 | m[1][1] = m1; |
457 | m[2][1] = m2; |
458 | |
459 | m0 = m[0][2] * other.m[0][0] |
460 | + m[1][2] * other.m[0][1] |
461 | + m[2][2] * other.m[0][2] |
462 | + m[3][2] * other.m[0][3]; |
463 | m1 = m[0][2] * other.m[1][0] |
464 | + m[1][2] * other.m[1][1] |
465 | + m[2][2] * other.m[1][2] |
466 | + m[3][2] * other.m[1][3]; |
467 | m2 = m[0][2] * other.m[2][0] |
468 | + m[1][2] * other.m[2][1] |
469 | + m[2][2] * other.m[2][2] |
470 | + m[3][2] * other.m[2][3]; |
471 | m[3][2] = m[0][2] * other.m[3][0] |
472 | + m[1][2] * other.m[3][1] |
473 | + m[2][2] * other.m[3][2] |
474 | + m[3][2] * other.m[3][3]; |
475 | m[0][2] = m0; |
476 | m[1][2] = m1; |
477 | m[2][2] = m2; |
478 | |
479 | m0 = m[0][3] * other.m[0][0] |
480 | + m[1][3] * other.m[0][1] |
481 | + m[2][3] * other.m[0][2] |
482 | + m[3][3] * other.m[0][3]; |
483 | m1 = m[0][3] * other.m[1][0] |
484 | + m[1][3] * other.m[1][1] |
485 | + m[2][3] * other.m[1][2] |
486 | + m[3][3] * other.m[1][3]; |
487 | m2 = m[0][3] * other.m[2][0] |
488 | + m[1][3] * other.m[2][1] |
489 | + m[2][3] * other.m[2][2] |
490 | + m[3][3] * other.m[2][3]; |
491 | m[3][3] = m[0][3] * other.m[3][0] |
492 | + m[1][3] * other.m[3][1] |
493 | + m[2][3] * other.m[3][2] |
494 | + m[3][3] * other.m[3][3]; |
495 | m[0][3] = m0; |
496 | m[1][3] = m1; |
497 | m[2][3] = m2; |
498 | return *this; |
499 | } |
500 | |
501 | inline QMatrix4x4& QMatrix4x4::operator*=(float factor) |
502 | { |
503 | m[0][0] *= factor; |
504 | m[0][1] *= factor; |
505 | m[0][2] *= factor; |
506 | m[0][3] *= factor; |
507 | m[1][0] *= factor; |
508 | m[1][1] *= factor; |
509 | m[1][2] *= factor; |
510 | m[1][3] *= factor; |
511 | m[2][0] *= factor; |
512 | m[2][1] *= factor; |
513 | m[2][2] *= factor; |
514 | m[2][3] *= factor; |
515 | m[3][0] *= factor; |
516 | m[3][1] *= factor; |
517 | m[3][2] *= factor; |
518 | m[3][3] *= factor; |
519 | flagBits = General; |
520 | return *this; |
521 | } |
522 | |
523 | inline bool QMatrix4x4::operator==(const QMatrix4x4& other) const |
524 | { |
525 | return m[0][0] == other.m[0][0] && |
526 | m[0][1] == other.m[0][1] && |
527 | m[0][2] == other.m[0][2] && |
528 | m[0][3] == other.m[0][3] && |
529 | m[1][0] == other.m[1][0] && |
530 | m[1][1] == other.m[1][1] && |
531 | m[1][2] == other.m[1][2] && |
532 | m[1][3] == other.m[1][3] && |
533 | m[2][0] == other.m[2][0] && |
534 | m[2][1] == other.m[2][1] && |
535 | m[2][2] == other.m[2][2] && |
536 | m[2][3] == other.m[2][3] && |
537 | m[3][0] == other.m[3][0] && |
538 | m[3][1] == other.m[3][1] && |
539 | m[3][2] == other.m[3][2] && |
540 | m[3][3] == other.m[3][3]; |
541 | } |
542 | |
543 | inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const |
544 | { |
545 | return m[0][0] != other.m[0][0] || |
546 | m[0][1] != other.m[0][1] || |
547 | m[0][2] != other.m[0][2] || |
548 | m[0][3] != other.m[0][3] || |
549 | m[1][0] != other.m[1][0] || |
550 | m[1][1] != other.m[1][1] || |
551 | m[1][2] != other.m[1][2] || |
552 | m[1][3] != other.m[1][3] || |
553 | m[2][0] != other.m[2][0] || |
554 | m[2][1] != other.m[2][1] || |
555 | m[2][2] != other.m[2][2] || |
556 | m[2][3] != other.m[2][3] || |
557 | m[3][0] != other.m[3][0] || |
558 | m[3][1] != other.m[3][1] || |
559 | m[3][2] != other.m[3][2] || |
560 | m[3][3] != other.m[3][3]; |
561 | } |
562 | |
563 | inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2) |
564 | { |
565 | QMatrix4x4 m(Qt::Uninitialized); |
566 | m.m[0][0] = m1.m[0][0] + m2.m[0][0]; |
567 | m.m[0][1] = m1.m[0][1] + m2.m[0][1]; |
568 | m.m[0][2] = m1.m[0][2] + m2.m[0][2]; |
569 | m.m[0][3] = m1.m[0][3] + m2.m[0][3]; |
570 | m.m[1][0] = m1.m[1][0] + m2.m[1][0]; |
571 | m.m[1][1] = m1.m[1][1] + m2.m[1][1]; |
572 | m.m[1][2] = m1.m[1][2] + m2.m[1][2]; |
573 | m.m[1][3] = m1.m[1][3] + m2.m[1][3]; |
574 | m.m[2][0] = m1.m[2][0] + m2.m[2][0]; |
575 | m.m[2][1] = m1.m[2][1] + m2.m[2][1]; |
576 | m.m[2][2] = m1.m[2][2] + m2.m[2][2]; |
577 | m.m[2][3] = m1.m[2][3] + m2.m[2][3]; |
578 | m.m[3][0] = m1.m[3][0] + m2.m[3][0]; |
579 | m.m[3][1] = m1.m[3][1] + m2.m[3][1]; |
580 | m.m[3][2] = m1.m[3][2] + m2.m[3][2]; |
581 | m.m[3][3] = m1.m[3][3] + m2.m[3][3]; |
582 | return m; |
583 | } |
584 | |
585 | inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2) |
586 | { |
587 | QMatrix4x4 m(Qt::Uninitialized); |
588 | m.m[0][0] = m1.m[0][0] - m2.m[0][0]; |
589 | m.m[0][1] = m1.m[0][1] - m2.m[0][1]; |
590 | m.m[0][2] = m1.m[0][2] - m2.m[0][2]; |
591 | m.m[0][3] = m1.m[0][3] - m2.m[0][3]; |
592 | m.m[1][0] = m1.m[1][0] - m2.m[1][0]; |
593 | m.m[1][1] = m1.m[1][1] - m2.m[1][1]; |
594 | m.m[1][2] = m1.m[1][2] - m2.m[1][2]; |
595 | m.m[1][3] = m1.m[1][3] - m2.m[1][3]; |
596 | m.m[2][0] = m1.m[2][0] - m2.m[2][0]; |
597 | m.m[2][1] = m1.m[2][1] - m2.m[2][1]; |
598 | m.m[2][2] = m1.m[2][2] - m2.m[2][2]; |
599 | m.m[2][3] = m1.m[2][3] - m2.m[2][3]; |
600 | m.m[3][0] = m1.m[3][0] - m2.m[3][0]; |
601 | m.m[3][1] = m1.m[3][1] - m2.m[3][1]; |
602 | m.m[3][2] = m1.m[3][2] - m2.m[3][2]; |
603 | m.m[3][3] = m1.m[3][3] - m2.m[3][3]; |
604 | return m; |
605 | } |
606 | |
607 | inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2) |
608 | { |
609 | QMatrix4x4::Flags flagBits = m1.flagBits | m2.flagBits; |
610 | if (flagBits.toInt() < QMatrix4x4::Rotation2D) { |
611 | QMatrix4x4 m = m1; |
612 | m.m[3][0] += m.m[0][0] * m2.m[3][0]; |
613 | m.m[3][1] += m.m[1][1] * m2.m[3][1]; |
614 | m.m[3][2] += m.m[2][2] * m2.m[3][2]; |
615 | |
616 | m.m[0][0] *= m2.m[0][0]; |
617 | m.m[1][1] *= m2.m[1][1]; |
618 | m.m[2][2] *= m2.m[2][2]; |
619 | m.flagBits = flagBits; |
620 | return m; |
621 | } |
622 | |
623 | QMatrix4x4 m(Qt::Uninitialized); |
624 | m.m[0][0] = m1.m[0][0] * m2.m[0][0] |
625 | + m1.m[1][0] * m2.m[0][1] |
626 | + m1.m[2][0] * m2.m[0][2] |
627 | + m1.m[3][0] * m2.m[0][3]; |
628 | m.m[0][1] = m1.m[0][1] * m2.m[0][0] |
629 | + m1.m[1][1] * m2.m[0][1] |
630 | + m1.m[2][1] * m2.m[0][2] |
631 | + m1.m[3][1] * m2.m[0][3]; |
632 | m.m[0][2] = m1.m[0][2] * m2.m[0][0] |
633 | + m1.m[1][2] * m2.m[0][1] |
634 | + m1.m[2][2] * m2.m[0][2] |
635 | + m1.m[3][2] * m2.m[0][3]; |
636 | m.m[0][3] = m1.m[0][3] * m2.m[0][0] |
637 | + m1.m[1][3] * m2.m[0][1] |
638 | + m1.m[2][3] * m2.m[0][2] |
639 | + m1.m[3][3] * m2.m[0][3]; |
640 | |
641 | m.m[1][0] = m1.m[0][0] * m2.m[1][0] |
642 | + m1.m[1][0] * m2.m[1][1] |
643 | + m1.m[2][0] * m2.m[1][2] |
644 | + m1.m[3][0] * m2.m[1][3]; |
645 | m.m[1][1] = m1.m[0][1] * m2.m[1][0] |
646 | + m1.m[1][1] * m2.m[1][1] |
647 | + m1.m[2][1] * m2.m[1][2] |
648 | + m1.m[3][1] * m2.m[1][3]; |
649 | m.m[1][2] = m1.m[0][2] * m2.m[1][0] |
650 | + m1.m[1][2] * m2.m[1][1] |
651 | + m1.m[2][2] * m2.m[1][2] |
652 | + m1.m[3][2] * m2.m[1][3]; |
653 | m.m[1][3] = m1.m[0][3] * m2.m[1][0] |
654 | + m1.m[1][3] * m2.m[1][1] |
655 | + m1.m[2][3] * m2.m[1][2] |
656 | + m1.m[3][3] * m2.m[1][3]; |
657 | |
658 | m.m[2][0] = m1.m[0][0] * m2.m[2][0] |
659 | + m1.m[1][0] * m2.m[2][1] |
660 | + m1.m[2][0] * m2.m[2][2] |
661 | + m1.m[3][0] * m2.m[2][3]; |
662 | m.m[2][1] = m1.m[0][1] * m2.m[2][0] |
663 | + m1.m[1][1] * m2.m[2][1] |
664 | + m1.m[2][1] * m2.m[2][2] |
665 | + m1.m[3][1] * m2.m[2][3]; |
666 | m.m[2][2] = m1.m[0][2] * m2.m[2][0] |
667 | + m1.m[1][2] * m2.m[2][1] |
668 | + m1.m[2][2] * m2.m[2][2] |
669 | + m1.m[3][2] * m2.m[2][3]; |
670 | m.m[2][3] = m1.m[0][3] * m2.m[2][0] |
671 | + m1.m[1][3] * m2.m[2][1] |
672 | + m1.m[2][3] * m2.m[2][2] |
673 | + m1.m[3][3] * m2.m[2][3]; |
674 | |
675 | m.m[3][0] = m1.m[0][0] * m2.m[3][0] |
676 | + m1.m[1][0] * m2.m[3][1] |
677 | + m1.m[2][0] * m2.m[3][2] |
678 | + m1.m[3][0] * m2.m[3][3]; |
679 | m.m[3][1] = m1.m[0][1] * m2.m[3][0] |
680 | + m1.m[1][1] * m2.m[3][1] |
681 | + m1.m[2][1] * m2.m[3][2] |
682 | + m1.m[3][1] * m2.m[3][3]; |
683 | m.m[3][2] = m1.m[0][2] * m2.m[3][0] |
684 | + m1.m[1][2] * m2.m[3][1] |
685 | + m1.m[2][2] * m2.m[3][2] |
686 | + m1.m[3][2] * m2.m[3][3]; |
687 | m.m[3][3] = m1.m[0][3] * m2.m[3][0] |
688 | + m1.m[1][3] * m2.m[3][1] |
689 | + m1.m[2][3] * m2.m[3][2] |
690 | + m1.m[3][3] * m2.m[3][3]; |
691 | m.flagBits = flagBits; |
692 | return m; |
693 | } |
694 | |
695 | #ifndef QT_NO_VECTOR3D |
696 | |
697 | #if QT_DEPRECATED_SINCE(6, 1) |
698 | |
699 | QT_DEPRECATED_VERSION_X_6_1("Extend the QVector3D to a QVector4D with 1.0 as the w coordinate before multiplying" ) |
700 | inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix) |
701 | { |
702 | float x, y, z, w; |
703 | x = vector.x() * matrix.m[0][0] + |
704 | vector.y() * matrix.m[0][1] + |
705 | vector.z() * matrix.m[0][2] + |
706 | matrix.m[0][3]; |
707 | y = vector.x() * matrix.m[1][0] + |
708 | vector.y() * matrix.m[1][1] + |
709 | vector.z() * matrix.m[1][2] + |
710 | matrix.m[1][3]; |
711 | z = vector.x() * matrix.m[2][0] + |
712 | vector.y() * matrix.m[2][1] + |
713 | vector.z() * matrix.m[2][2] + |
714 | matrix.m[2][3]; |
715 | w = vector.x() * matrix.m[3][0] + |
716 | vector.y() * matrix.m[3][1] + |
717 | vector.z() * matrix.m[3][2] + |
718 | matrix.m[3][3]; |
719 | if (w == 1.0f) |
720 | return QVector3D(x, y, z); |
721 | else |
722 | return QVector3D(x / w, y / w, z / w); |
723 | } |
724 | |
725 | QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(vector) instead" ) |
726 | inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector) |
727 | { |
728 | return matrix.map(point: vector); |
729 | } |
730 | |
731 | #endif |
732 | |
733 | #endif |
734 | |
735 | #ifndef QT_NO_VECTOR4D |
736 | |
737 | inline QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix) |
738 | { |
739 | float x, y, z, w; |
740 | x = vector.x() * matrix.m[0][0] + |
741 | vector.y() * matrix.m[0][1] + |
742 | vector.z() * matrix.m[0][2] + |
743 | vector.w() * matrix.m[0][3]; |
744 | y = vector.x() * matrix.m[1][0] + |
745 | vector.y() * matrix.m[1][1] + |
746 | vector.z() * matrix.m[1][2] + |
747 | vector.w() * matrix.m[1][3]; |
748 | z = vector.x() * matrix.m[2][0] + |
749 | vector.y() * matrix.m[2][1] + |
750 | vector.z() * matrix.m[2][2] + |
751 | vector.w() * matrix.m[2][3]; |
752 | w = vector.x() * matrix.m[3][0] + |
753 | vector.y() * matrix.m[3][1] + |
754 | vector.z() * matrix.m[3][2] + |
755 | vector.w() * matrix.m[3][3]; |
756 | return QVector4D(x, y, z, w); |
757 | } |
758 | |
759 | inline QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector) |
760 | { |
761 | float x, y, z, w; |
762 | x = vector.x() * matrix.m[0][0] + |
763 | vector.y() * matrix.m[1][0] + |
764 | vector.z() * matrix.m[2][0] + |
765 | vector.w() * matrix.m[3][0]; |
766 | y = vector.x() * matrix.m[0][1] + |
767 | vector.y() * matrix.m[1][1] + |
768 | vector.z() * matrix.m[2][1] + |
769 | vector.w() * matrix.m[3][1]; |
770 | z = vector.x() * matrix.m[0][2] + |
771 | vector.y() * matrix.m[1][2] + |
772 | vector.z() * matrix.m[2][2] + |
773 | vector.w() * matrix.m[3][2]; |
774 | w = vector.x() * matrix.m[0][3] + |
775 | vector.y() * matrix.m[1][3] + |
776 | vector.z() * matrix.m[2][3] + |
777 | vector.w() * matrix.m[3][3]; |
778 | return QVector4D(x, y, z, w); |
779 | } |
780 | |
781 | #endif |
782 | |
783 | inline QPoint operator*(const QPoint& point, const QMatrix4x4& matrix) |
784 | { |
785 | float xin, yin; |
786 | float x, y, w; |
787 | xin = point.x(); |
788 | yin = point.y(); |
789 | x = xin * matrix.m[0][0] + |
790 | yin * matrix.m[0][1] + |
791 | matrix.m[0][3]; |
792 | y = xin * matrix.m[1][0] + |
793 | yin * matrix.m[1][1] + |
794 | matrix.m[1][3]; |
795 | w = xin * matrix.m[3][0] + |
796 | yin * matrix.m[3][1] + |
797 | matrix.m[3][3]; |
798 | if (w == 1.0f) |
799 | return QPoint(qRound(f: x), qRound(f: y)); |
800 | else |
801 | return QPoint(qRound(f: x / w), qRound(f: y / w)); |
802 | } |
803 | |
804 | inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix) |
805 | { |
806 | float xin, yin; |
807 | float x, y, w; |
808 | xin = float(point.x()); |
809 | yin = float(point.y()); |
810 | x = xin * matrix.m[0][0] + |
811 | yin * matrix.m[0][1] + |
812 | matrix.m[0][3]; |
813 | y = xin * matrix.m[1][0] + |
814 | yin * matrix.m[1][1] + |
815 | matrix.m[1][3]; |
816 | w = xin * matrix.m[3][0] + |
817 | yin * matrix.m[3][1] + |
818 | matrix.m[3][3]; |
819 | if (w == 1.0f) { |
820 | return QPointF(qreal(x), qreal(y)); |
821 | } else { |
822 | return QPointF(qreal(x / w), qreal(y / w)); |
823 | } |
824 | } |
825 | |
826 | #if QT_DEPRECATED_SINCE(6, 1) |
827 | |
828 | QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(point) instead" ) |
829 | inline QPoint operator*(const QMatrix4x4& matrix, const QPoint& point) |
830 | { |
831 | return matrix.map(point); |
832 | } |
833 | |
834 | QT_DEPRECATED_VERSION_X_6_1("Use matrix.map(point) instead" ) |
835 | inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point) |
836 | { |
837 | return matrix.map(point); |
838 | } |
839 | |
840 | #endif |
841 | |
842 | inline QMatrix4x4 operator-(const QMatrix4x4& matrix) |
843 | { |
844 | QMatrix4x4 m(Qt::Uninitialized); |
845 | m.m[0][0] = -matrix.m[0][0]; |
846 | m.m[0][1] = -matrix.m[0][1]; |
847 | m.m[0][2] = -matrix.m[0][2]; |
848 | m.m[0][3] = -matrix.m[0][3]; |
849 | m.m[1][0] = -matrix.m[1][0]; |
850 | m.m[1][1] = -matrix.m[1][1]; |
851 | m.m[1][2] = -matrix.m[1][2]; |
852 | m.m[1][3] = -matrix.m[1][3]; |
853 | m.m[2][0] = -matrix.m[2][0]; |
854 | m.m[2][1] = -matrix.m[2][1]; |
855 | m.m[2][2] = -matrix.m[2][2]; |
856 | m.m[2][3] = -matrix.m[2][3]; |
857 | m.m[3][0] = -matrix.m[3][0]; |
858 | m.m[3][1] = -matrix.m[3][1]; |
859 | m.m[3][2] = -matrix.m[3][2]; |
860 | m.m[3][3] = -matrix.m[3][3]; |
861 | return m; |
862 | } |
863 | |
864 | inline QMatrix4x4 operator*(float factor, const QMatrix4x4& matrix) |
865 | { |
866 | QMatrix4x4 m(Qt::Uninitialized); |
867 | m.m[0][0] = matrix.m[0][0] * factor; |
868 | m.m[0][1] = matrix.m[0][1] * factor; |
869 | m.m[0][2] = matrix.m[0][2] * factor; |
870 | m.m[0][3] = matrix.m[0][3] * factor; |
871 | m.m[1][0] = matrix.m[1][0] * factor; |
872 | m.m[1][1] = matrix.m[1][1] * factor; |
873 | m.m[1][2] = matrix.m[1][2] * factor; |
874 | m.m[1][3] = matrix.m[1][3] * factor; |
875 | m.m[2][0] = matrix.m[2][0] * factor; |
876 | m.m[2][1] = matrix.m[2][1] * factor; |
877 | m.m[2][2] = matrix.m[2][2] * factor; |
878 | m.m[2][3] = matrix.m[2][3] * factor; |
879 | m.m[3][0] = matrix.m[3][0] * factor; |
880 | m.m[3][1] = matrix.m[3][1] * factor; |
881 | m.m[3][2] = matrix.m[3][2] * factor; |
882 | m.m[3][3] = matrix.m[3][3] * factor; |
883 | return m; |
884 | } |
885 | |
886 | inline QMatrix4x4 operator*(const QMatrix4x4& matrix, float factor) |
887 | { |
888 | QMatrix4x4 m(Qt::Uninitialized); |
889 | m.m[0][0] = matrix.m[0][0] * factor; |
890 | m.m[0][1] = matrix.m[0][1] * factor; |
891 | m.m[0][2] = matrix.m[0][2] * factor; |
892 | m.m[0][3] = matrix.m[0][3] * factor; |
893 | m.m[1][0] = matrix.m[1][0] * factor; |
894 | m.m[1][1] = matrix.m[1][1] * factor; |
895 | m.m[1][2] = matrix.m[1][2] * factor; |
896 | m.m[1][3] = matrix.m[1][3] * factor; |
897 | m.m[2][0] = matrix.m[2][0] * factor; |
898 | m.m[2][1] = matrix.m[2][1] * factor; |
899 | m.m[2][2] = matrix.m[2][2] * factor; |
900 | m.m[2][3] = matrix.m[2][3] * factor; |
901 | m.m[3][0] = matrix.m[3][0] * factor; |
902 | m.m[3][1] = matrix.m[3][1] * factor; |
903 | m.m[3][2] = matrix.m[3][2] * factor; |
904 | m.m[3][3] = matrix.m[3][3] * factor; |
905 | return m; |
906 | } |
907 | |
908 | inline QPoint QMatrix4x4::map(const QPoint& point) const |
909 | { |
910 | float xin, yin; |
911 | float x, y, w; |
912 | xin = point.x(); |
913 | yin = point.y(); |
914 | if (flagBits == QMatrix4x4::Identity) { |
915 | return point; |
916 | } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) { |
917 | // Translation | Scale |
918 | return QPoint(qRound(f: xin * m[0][0] + m[3][0]), |
919 | qRound(f: yin * m[1][1] + m[3][1])); |
920 | } else if (flagBits.toInt() < QMatrix4x4::Perspective) { |
921 | return QPoint(qRound(f: xin * m[0][0] + yin * m[1][0] + m[3][0]), |
922 | qRound(f: xin * m[0][1] + yin * m[1][1] + m[3][1])); |
923 | } else { |
924 | x = xin * m[0][0] + |
925 | yin * m[1][0] + |
926 | m[3][0]; |
927 | y = xin * m[0][1] + |
928 | yin * m[1][1] + |
929 | m[3][1]; |
930 | w = xin * m[0][3] + |
931 | yin * m[1][3] + |
932 | m[3][3]; |
933 | if (w == 1.0f) |
934 | return QPoint(qRound(f: x), qRound(f: y)); |
935 | else |
936 | return QPoint(qRound(f: x / w), qRound(f: y / w)); |
937 | } |
938 | } |
939 | |
940 | inline QPointF QMatrix4x4::map(const QPointF& point) const |
941 | { |
942 | qreal xin, yin; |
943 | qreal x, y, w; |
944 | xin = point.x(); |
945 | yin = point.y(); |
946 | if (flagBits == QMatrix4x4::Identity) { |
947 | return point; |
948 | } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) { |
949 | // Translation | Scale |
950 | return QPointF(xin * qreal(m[0][0]) + qreal(m[3][0]), |
951 | yin * qreal(m[1][1]) + qreal(m[3][1])); |
952 | } else if (flagBits.toInt() < QMatrix4x4::Perspective) { |
953 | return QPointF(xin * qreal(m[0][0]) + yin * qreal(m[1][0]) + |
954 | qreal(m[3][0]), |
955 | xin * qreal(m[0][1]) + yin * qreal(m[1][1]) + |
956 | qreal(m[3][1])); |
957 | } else { |
958 | x = xin * qreal(m[0][0]) + |
959 | yin * qreal(m[1][0]) + |
960 | qreal(m[3][0]); |
961 | y = xin * qreal(m[0][1]) + |
962 | yin * qreal(m[1][1]) + |
963 | qreal(m[3][1]); |
964 | w = xin * qreal(m[0][3]) + |
965 | yin * qreal(m[1][3]) + |
966 | qreal(m[3][3]); |
967 | if (w == 1.0) { |
968 | return QPointF(qreal(x), qreal(y)); |
969 | } else { |
970 | return QPointF(qreal(x / w), qreal(y / w)); |
971 | } |
972 | } |
973 | } |
974 | |
975 | #ifndef QT_NO_VECTOR3D |
976 | |
977 | inline QVector3D QMatrix4x4::map(const QVector3D& point) const |
978 | { |
979 | float x, y, z, w; |
980 | if (flagBits == QMatrix4x4::Identity) { |
981 | return point; |
982 | } else if (flagBits.toInt() < QMatrix4x4::Rotation2D) { |
983 | // Translation | Scale |
984 | return QVector3D(point.x() * m[0][0] + m[3][0], |
985 | point.y() * m[1][1] + m[3][1], |
986 | point.z() * m[2][2] + m[3][2]); |
987 | } else if (flagBits.toInt() < QMatrix4x4::Rotation) { |
988 | // Translation | Scale | Rotation2D |
989 | return QVector3D(point.x() * m[0][0] + point.y() * m[1][0] + m[3][0], |
990 | point.x() * m[0][1] + point.y() * m[1][1] + m[3][1], |
991 | point.z() * m[2][2] + m[3][2]); |
992 | } else { |
993 | x = point.x() * m[0][0] + |
994 | point.y() * m[1][0] + |
995 | point.z() * m[2][0] + |
996 | m[3][0]; |
997 | y = point.x() * m[0][1] + |
998 | point.y() * m[1][1] + |
999 | 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(left: float(rect.x()), bottom: float(rect.y()), width: float(rect.width()), height: 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 |
1079 | |