|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the test suite of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include <QtTest/QtTest> |
|
43 #include <QtCore/qmath.h> |
|
44 #include <QtGui/qmatrix4x4.h> |
|
45 |
|
46 class tst_QMatrixNxN : public QObject |
|
47 { |
|
48 Q_OBJECT |
|
49 public: |
|
50 tst_QMatrixNxN() {} |
|
51 ~tst_QMatrixNxN() {} |
|
52 |
|
53 private slots: |
|
54 void create2x2(); |
|
55 void create3x3(); |
|
56 void create4x4(); |
|
57 void create4x3(); |
|
58 |
|
59 void isIdentity2x2(); |
|
60 void isIdentity3x3(); |
|
61 void isIdentity4x4(); |
|
62 void isIdentity4x3(); |
|
63 |
|
64 void compare2x2(); |
|
65 void compare3x3(); |
|
66 void compare4x4(); |
|
67 void compare4x3(); |
|
68 |
|
69 void transposed2x2(); |
|
70 void transposed3x3(); |
|
71 void transposed4x4(); |
|
72 void transposed4x3(); |
|
73 |
|
74 void add2x2_data(); |
|
75 void add2x2(); |
|
76 void add3x3_data(); |
|
77 void add3x3(); |
|
78 void add4x4_data(); |
|
79 void add4x4(); |
|
80 void add4x3_data(); |
|
81 void add4x3(); |
|
82 |
|
83 void subtract2x2_data(); |
|
84 void subtract2x2(); |
|
85 void subtract3x3_data(); |
|
86 void subtract3x3(); |
|
87 void subtract4x4_data(); |
|
88 void subtract4x4(); |
|
89 void subtract4x3_data(); |
|
90 void subtract4x3(); |
|
91 |
|
92 void multiply2x2_data(); |
|
93 void multiply2x2(); |
|
94 void multiply3x3_data(); |
|
95 void multiply3x3(); |
|
96 void multiply4x4_data(); |
|
97 void multiply4x4(); |
|
98 void multiply4x3_data(); |
|
99 void multiply4x3(); |
|
100 |
|
101 void multiplyFactor2x2_data(); |
|
102 void multiplyFactor2x2(); |
|
103 void multiplyFactor3x3_data(); |
|
104 void multiplyFactor3x3(); |
|
105 void multiplyFactor4x4_data(); |
|
106 void multiplyFactor4x4(); |
|
107 void multiplyFactor4x3_data(); |
|
108 void multiplyFactor4x3(); |
|
109 |
|
110 void divideFactor2x2_data(); |
|
111 void divideFactor2x2(); |
|
112 void divideFactor3x3_data(); |
|
113 void divideFactor3x3(); |
|
114 void divideFactor4x4_data(); |
|
115 void divideFactor4x4(); |
|
116 void divideFactor4x3_data(); |
|
117 void divideFactor4x3(); |
|
118 |
|
119 void negate2x2_data(); |
|
120 void negate2x2(); |
|
121 void negate3x3_data(); |
|
122 void negate3x3(); |
|
123 void negate4x4_data(); |
|
124 void negate4x4(); |
|
125 void negate4x3_data(); |
|
126 void negate4x3(); |
|
127 |
|
128 void inverted4x4_data(); |
|
129 void inverted4x4(); |
|
130 |
|
131 void orthonormalInverse4x4(); |
|
132 |
|
133 void scale4x4_data(); |
|
134 void scale4x4(); |
|
135 |
|
136 void translate4x4_data(); |
|
137 void translate4x4(); |
|
138 |
|
139 void rotate4x4_data(); |
|
140 void rotate4x4(); |
|
141 |
|
142 void normalMatrix_data(); |
|
143 void normalMatrix(); |
|
144 |
|
145 void optimizedTransforms(); |
|
146 |
|
147 void ortho(); |
|
148 void frustum(); |
|
149 void perspective(); |
|
150 void flipCoordinates(); |
|
151 |
|
152 void convertGeneric(); |
|
153 |
|
154 void extractAxisRotation_data(); |
|
155 void extractAxisRotation(); |
|
156 |
|
157 void extractTranslation_data(); |
|
158 void extractTranslation(); |
|
159 |
|
160 void inferSpecialType_data(); |
|
161 void inferSpecialType(); |
|
162 |
|
163 void columnsAndRows(); |
|
164 |
|
165 void convertQMatrix(); |
|
166 void convertQTransform(); |
|
167 |
|
168 void fill(); |
|
169 |
|
170 void mapRect_data(); |
|
171 void mapRect(); |
|
172 |
|
173 void mapVector_data(); |
|
174 void mapVector(); |
|
175 |
|
176 void properties(); |
|
177 void metaTypes(); |
|
178 |
|
179 private: |
|
180 static void setMatrix(QMatrix2x2& m, const qreal *values); |
|
181 static void setMatrixDirect(QMatrix2x2& m, const qreal *values); |
|
182 static bool isSame(const QMatrix2x2& m, const qreal *values); |
|
183 static bool isIdentity(const QMatrix2x2& m); |
|
184 |
|
185 static void setMatrix(QMatrix3x3& m, const qreal *values); |
|
186 static void setMatrixDirect(QMatrix3x3& m, const qreal *values); |
|
187 static bool isSame(const QMatrix3x3& m, const qreal *values); |
|
188 static bool isIdentity(const QMatrix3x3& m); |
|
189 |
|
190 static void setMatrix(QMatrix4x4& m, const qreal *values); |
|
191 static void setMatrixDirect(QMatrix4x4& m, const qreal *values); |
|
192 static bool isSame(const QMatrix4x4& m, const qreal *values); |
|
193 static bool isIdentity(const QMatrix4x4& m); |
|
194 |
|
195 static void setMatrix(QMatrix4x3& m, const qreal *values); |
|
196 static void setMatrixDirect(QMatrix4x3& m, const qreal *values); |
|
197 static bool isSame(const QMatrix4x3& m, const qreal *values); |
|
198 static bool isIdentity(const QMatrix4x3& m); |
|
199 }; |
|
200 |
|
201 static const qreal nullValues2[] = |
|
202 {0.0f, 0.0f, |
|
203 0.0f, 0.0f}; |
|
204 |
|
205 static qreal const identityValues2[16] = |
|
206 {1.0f, 0.0f, |
|
207 0.0f, 1.0f}; |
|
208 |
|
209 static const qreal doubleIdentity2[] = |
|
210 {2.0f, 0.0f, |
|
211 0.0f, 2.0f}; |
|
212 |
|
213 static qreal const uniqueValues2[16] = |
|
214 {1.0f, 2.0f, |
|
215 5.0f, 6.0f}; |
|
216 |
|
217 static qreal const transposedValues2[16] = |
|
218 {1.0f, 5.0f, |
|
219 2.0f, 6.0f}; |
|
220 |
|
221 static const qreal nullValues3[] = |
|
222 {0.0f, 0.0f, 0.0f, |
|
223 0.0f, 0.0f, 0.0f, |
|
224 0.0f, 0.0f, 0.0f}; |
|
225 |
|
226 static qreal const identityValues3[16] = |
|
227 {1.0f, 0.0f, 0.0f, |
|
228 0.0f, 1.0f, 0.0f, |
|
229 0.0f, 0.0f, 1.0f}; |
|
230 |
|
231 static const qreal doubleIdentity3[] = |
|
232 {2.0f, 0.0f, 0.0f, |
|
233 0.0f, 2.0f, 0.0f, |
|
234 0.0f, 0.0f, 2.0f}; |
|
235 |
|
236 static qreal const uniqueValues3[16] = |
|
237 {1.0f, 2.0f, 3.0f, |
|
238 5.0f, 6.0f, 7.0f, |
|
239 9.0f, 10.0f, 11.0f}; |
|
240 |
|
241 static qreal const transposedValues3[16] = |
|
242 {1.0f, 5.0f, 9.0f, |
|
243 2.0f, 6.0f, 10.0f, |
|
244 3.0f, 7.0f, 11.0f}; |
|
245 |
|
246 static const qreal nullValues4[] = |
|
247 {0.0f, 0.0f, 0.0f, 0.0f, |
|
248 0.0f, 0.0f, 0.0f, 0.0f, |
|
249 0.0f, 0.0f, 0.0f, 0.0f, |
|
250 0.0f, 0.0f, 0.0f, 0.0f}; |
|
251 |
|
252 static qreal const identityValues4[16] = |
|
253 {1.0f, 0.0f, 0.0f, 0.0f, |
|
254 0.0f, 1.0f, 0.0f, 0.0f, |
|
255 0.0f, 0.0f, 1.0f, 0.0f, |
|
256 0.0f, 0.0f, 0.0f, 1.0f}; |
|
257 |
|
258 static const qreal doubleIdentity4[] = |
|
259 {2.0f, 0.0f, 0.0f, 0.0f, |
|
260 0.0f, 2.0f, 0.0f, 0.0f, |
|
261 0.0f, 0.0f, 2.0f, 0.0f, |
|
262 0.0f, 0.0f, 0.0f, 2.0f}; |
|
263 |
|
264 static qreal const uniqueValues4[16] = |
|
265 {1.0f, 2.0f, 3.0f, 4.0f, |
|
266 5.0f, 6.0f, 7.0f, 8.0f, |
|
267 9.0f, 10.0f, 11.0f, 12.0f, |
|
268 13.0f, 14.0f, 15.0f, 16.0f}; |
|
269 |
|
270 static qreal const transposedValues4[16] = |
|
271 {1.0f, 5.0f, 9.0f, 13.0f, |
|
272 2.0f, 6.0f, 10.0f, 14.0f, |
|
273 3.0f, 7.0f, 11.0f, 15.0f, |
|
274 4.0f, 8.0f, 12.0f, 16.0f}; |
|
275 |
|
276 static const qreal nullValues4x3[] = |
|
277 {0.0f, 0.0f, 0.0f, 0.0f, |
|
278 0.0f, 0.0f, 0.0f, 0.0f, |
|
279 0.0f, 0.0f, 0.0f, 0.0f}; |
|
280 |
|
281 static qreal const identityValues4x3[12] = |
|
282 {1.0f, 0.0f, 0.0f, 0.0f, |
|
283 0.0f, 1.0f, 0.0f, 0.0f, |
|
284 0.0f, 0.0f, 1.0f, 0.0f}; |
|
285 |
|
286 static qreal const doubleIdentity4x3[12] = |
|
287 {2.0f, 0.0f, 0.0f, 0.0f, |
|
288 0.0f, 2.0f, 0.0f, 0.0f, |
|
289 0.0f, 0.0f, 2.0f, 0.0f}; |
|
290 |
|
291 static qreal const uniqueValues4x3[12] = |
|
292 {1.0f, 2.0f, 3.0f, 4.0f, |
|
293 5.0f, 6.0f, 7.0f, 8.0f, |
|
294 9.0f, 10.0f, 11.0f, 12.0f}; |
|
295 |
|
296 static qreal const transposedValues3x4[12] = |
|
297 {1.0f, 5.0f, 9.0f, |
|
298 2.0f, 6.0f, 10.0f, |
|
299 3.0f, 7.0f, 11.0f, |
|
300 4.0f, 8.0f, 12.0f}; |
|
301 |
|
302 // Set a matrix to a specified array of values, which are assumed |
|
303 // to be in row-major order. This sets the values using floating-point. |
|
304 void tst_QMatrixNxN::setMatrix(QMatrix2x2& m, const qreal *values) |
|
305 { |
|
306 for (int row = 0; row < 2; ++row) |
|
307 for (int col = 0; col < 2; ++col) |
|
308 m(row, col) = values[row * 2 + col]; |
|
309 } |
|
310 void tst_QMatrixNxN::setMatrix(QMatrix3x3& m, const qreal *values) |
|
311 { |
|
312 for (int row = 0; row < 3; ++row) |
|
313 for (int col = 0; col < 3; ++col) |
|
314 m(row, col) = values[row * 3 + col]; |
|
315 } |
|
316 void tst_QMatrixNxN::setMatrix(QMatrix4x4& m, const qreal *values) |
|
317 { |
|
318 for (int row = 0; row < 4; ++row) |
|
319 for (int col = 0; col < 4; ++col) |
|
320 m(row, col) = values[row * 4 + col]; |
|
321 } |
|
322 void tst_QMatrixNxN::setMatrix(QMatrix4x3& m, const qreal *values) |
|
323 { |
|
324 for (int row = 0; row < 3; ++row) |
|
325 for (int col = 0; col < 4; ++col) |
|
326 m(row, col) = values[row * 4 + col]; |
|
327 } |
|
328 |
|
329 // Set a matrix to a specified array of values, which are assumed |
|
330 // to be in row-major order. This sets the values directly into |
|
331 // the internal data() array. |
|
332 void tst_QMatrixNxN::setMatrixDirect(QMatrix2x2& m, const qreal *values) |
|
333 { |
|
334 qreal *data = m.data(); |
|
335 for (int row = 0; row < 2; ++row) { |
|
336 for (int col = 0; col < 2; ++col) { |
|
337 data[row + col * 2] = values[row * 2 + col]; |
|
338 } |
|
339 } |
|
340 } |
|
341 void tst_QMatrixNxN::setMatrixDirect(QMatrix3x3& m, const qreal *values) |
|
342 { |
|
343 qreal *data = m.data(); |
|
344 for (int row = 0; row < 3; ++row) { |
|
345 for (int col = 0; col < 3; ++col) { |
|
346 data[row + col * 3] = values[row * 3 + col]; |
|
347 } |
|
348 } |
|
349 } |
|
350 void tst_QMatrixNxN::setMatrixDirect(QMatrix4x4& m, const qreal *values) |
|
351 { |
|
352 qreal *data = m.data(); |
|
353 for (int row = 0; row < 4; ++row) { |
|
354 for (int col = 0; col < 4; ++col) { |
|
355 data[row + col * 4] = values[row * 4 + col]; |
|
356 } |
|
357 } |
|
358 } |
|
359 void tst_QMatrixNxN::setMatrixDirect(QMatrix4x3& m, const qreal *values) |
|
360 { |
|
361 qreal *data = m.data(); |
|
362 for (int row = 0; row < 3; ++row) { |
|
363 for (int col = 0; col < 4; ++col) { |
|
364 data[row + col * 3] = values[row * 4 + col]; |
|
365 } |
|
366 } |
|
367 } |
|
368 |
|
369 // QVector2/3/4D use float internally, which can sometimes lead |
|
370 // to precision issues when converting to and from qreal during |
|
371 // operations involving QMatrix4x4. This fuzzy compare is slightly |
|
372 // "fuzzier" than the default qFuzzyCompare for qreal to compensate. |
|
373 static bool fuzzyCompare(qreal x, qreal y) |
|
374 { |
|
375 return qFuzzyIsNull((float)(x - y)); |
|
376 } |
|
377 |
|
378 static bool fuzzyCompare(const QVector3D &v1, const QVector3D &v2) |
|
379 { |
|
380 if (!fuzzyCompare(v1.x(), v2.x())) |
|
381 return false; |
|
382 if (!fuzzyCompare(v1.y(), v2.y())) |
|
383 return false; |
|
384 if (!fuzzyCompare(v1.z(), v2.z())) |
|
385 return false; |
|
386 return true; |
|
387 } |
|
388 |
|
389 // Determine if a matrix is the same as a specified array of values. |
|
390 // The values are assumed to be specified in row-major order. |
|
391 bool tst_QMatrixNxN::isSame(const QMatrix2x2& m, const qreal *values) |
|
392 { |
|
393 const qreal *mv = m.constData(); |
|
394 for (int row = 0; row < 2; ++row) { |
|
395 for (int col = 0; col < 2; ++col) { |
|
396 // Check the values using the operator() function. |
|
397 if (!fuzzyCompare(m(row, col), values[row * 2 + col])) { |
|
398 qDebug() << "floating-point failure at" << row << col << "actual =" << m(row, col) << "expected =" << values[row * 2 + col]; |
|
399 return false; |
|
400 } |
|
401 |
|
402 // Check the values using direct access, which verifies that the values |
|
403 // are stored internally in column-major order. |
|
404 if (!fuzzyCompare(mv[col * 2 + row], values[row * 2 + col])) { |
|
405 qDebug() << "column floating-point failure at" << row << col << "actual =" << mv[col * 2 + row] << "expected =" << values[row * 2 + col]; |
|
406 return false; |
|
407 } |
|
408 } |
|
409 } |
|
410 return true; |
|
411 } |
|
412 bool tst_QMatrixNxN::isSame(const QMatrix3x3& m, const qreal *values) |
|
413 { |
|
414 const qreal *mv = m.constData(); |
|
415 for (int row = 0; row < 3; ++row) { |
|
416 for (int col = 0; col < 3; ++col) { |
|
417 // Check the values using the operator() access function. |
|
418 if (!fuzzyCompare(m(row, col), values[row * 3 + col])) { |
|
419 qDebug() << "floating-point failure at" << row << col << "actual =" << m(row, col) << "expected =" << values[row * 3 + col]; |
|
420 return false; |
|
421 } |
|
422 |
|
423 // Check the values using direct access, which verifies that the values |
|
424 // are stored internally in column-major order. |
|
425 if (!fuzzyCompare(mv[col * 3 + row], values[row * 3 + col])) { |
|
426 qDebug() << "column floating-point failure at" << row << col << "actual =" << mv[col * 3 + row] << "expected =" << values[row * 3 + col]; |
|
427 return false; |
|
428 } |
|
429 } |
|
430 } |
|
431 return true; |
|
432 } |
|
433 bool tst_QMatrixNxN::isSame(const QMatrix4x4& m, const qreal *values) |
|
434 { |
|
435 const qreal *mv = m.constData(); |
|
436 for (int row = 0; row < 4; ++row) { |
|
437 for (int col = 0; col < 4; ++col) { |
|
438 // Check the values using the operator() access function. |
|
439 if (!fuzzyCompare(m(row, col), values[row * 4 + col])) { |
|
440 qDebug() << "floating-point failure at" << row << col << "actual =" << m(row, col) << "expected =" << values[row * 4 + col]; |
|
441 return false; |
|
442 } |
|
443 |
|
444 // Check the values using direct access, which verifies that the values |
|
445 // are stored internally in column-major order. |
|
446 if (!fuzzyCompare(mv[col * 4 + row], values[row * 4 + col])) { |
|
447 qDebug() << "column floating-point failure at" << row << col << "actual =" << mv[col * 4 + row] << "expected =" << values[row * 4 + col]; |
|
448 return false; |
|
449 } |
|
450 } |
|
451 } |
|
452 return true; |
|
453 } |
|
454 bool tst_QMatrixNxN::isSame(const QMatrix4x3& m, const qreal *values) |
|
455 { |
|
456 const qreal *mv = m.constData(); |
|
457 for (int row = 0; row < 3; ++row) { |
|
458 for (int col = 0; col < 4; ++col) { |
|
459 // Check the values using the operator() access function. |
|
460 if (!fuzzyCompare(m(row, col), values[row * 4 + col])) { |
|
461 qDebug() << "floating-point failure at" << row << col << "actual =" << m(row, col) << "expected =" << values[row * 4 + col]; |
|
462 return false; |
|
463 } |
|
464 |
|
465 // Check the values using direct access, which verifies that the values |
|
466 // are stored internally in column-major order. |
|
467 if (!fuzzyCompare(mv[col * 3 + row], values[row * 4 + col])) { |
|
468 qDebug() << "column floating-point failure at" << row << col << "actual =" << mv[col * 3 + row] << "expected =" << values[row * 4 + col]; |
|
469 return false; |
|
470 } |
|
471 } |
|
472 } |
|
473 return true; |
|
474 } |
|
475 |
|
476 // Determine if a matrix is the identity. |
|
477 bool tst_QMatrixNxN::isIdentity(const QMatrix2x2& m) |
|
478 { |
|
479 return isSame(m, identityValues2); |
|
480 } |
|
481 bool tst_QMatrixNxN::isIdentity(const QMatrix3x3& m) |
|
482 { |
|
483 return isSame(m, identityValues3); |
|
484 } |
|
485 bool tst_QMatrixNxN::isIdentity(const QMatrix4x4& m) |
|
486 { |
|
487 return isSame(m, identityValues4); |
|
488 } |
|
489 bool tst_QMatrixNxN::isIdentity(const QMatrix4x3& m) |
|
490 { |
|
491 return isSame(m, identityValues4x3); |
|
492 } |
|
493 |
|
494 // Test the creation of QMatrix2x2 objects in various ways: |
|
495 // construct, copy, and modify. |
|
496 void tst_QMatrixNxN::create2x2() |
|
497 { |
|
498 QMatrix2x2 m1; |
|
499 QVERIFY(isIdentity(m1)); |
|
500 QVERIFY(m1.isIdentity()); |
|
501 |
|
502 QMatrix2x2 m2; |
|
503 setMatrix(m2, uniqueValues2); |
|
504 QVERIFY(isSame(m2, uniqueValues2)); |
|
505 QVERIFY(!m2.isIdentity()); |
|
506 |
|
507 QMatrix2x2 m3; |
|
508 setMatrixDirect(m3, uniqueValues2); |
|
509 QVERIFY(isSame(m3, uniqueValues2)); |
|
510 |
|
511 QMatrix2x2 m4(m3); |
|
512 QVERIFY(isSame(m4, uniqueValues2)); |
|
513 |
|
514 QMatrix2x2 m5; |
|
515 m5 = m3; |
|
516 QVERIFY(isSame(m5, uniqueValues2)); |
|
517 |
|
518 m5.setIdentity(); |
|
519 QVERIFY(isIdentity(m5)); |
|
520 |
|
521 QMatrix2x2 m6(uniqueValues2); |
|
522 QVERIFY(isSame(m6, uniqueValues2)); |
|
523 qreal vals[4]; |
|
524 m6.toValueArray(vals); |
|
525 for (int index = 0; index < 4; ++index) |
|
526 QCOMPARE(vals[index], uniqueValues2[index]); |
|
527 } |
|
528 |
|
529 // Test the creation of QMatrix3x3 objects in various ways: |
|
530 // construct, copy, and modify. |
|
531 void tst_QMatrixNxN::create3x3() |
|
532 { |
|
533 QMatrix3x3 m1; |
|
534 QVERIFY(isIdentity(m1)); |
|
535 QVERIFY(m1.isIdentity()); |
|
536 |
|
537 QMatrix3x3 m2; |
|
538 setMatrix(m2, uniqueValues3); |
|
539 QVERIFY(isSame(m2, uniqueValues3)); |
|
540 QVERIFY(!m2.isIdentity()); |
|
541 |
|
542 QMatrix3x3 m3; |
|
543 setMatrixDirect(m3, uniqueValues3); |
|
544 QVERIFY(isSame(m3, uniqueValues3)); |
|
545 |
|
546 QMatrix3x3 m4(m3); |
|
547 QVERIFY(isSame(m4, uniqueValues3)); |
|
548 |
|
549 QMatrix3x3 m5; |
|
550 m5 = m3; |
|
551 QVERIFY(isSame(m5, uniqueValues3)); |
|
552 |
|
553 m5.setIdentity(); |
|
554 QVERIFY(isIdentity(m5)); |
|
555 |
|
556 QMatrix3x3 m6(uniqueValues3); |
|
557 QVERIFY(isSame(m6, uniqueValues3)); |
|
558 qreal vals[9]; |
|
559 m6.toValueArray(vals); |
|
560 for (int index = 0; index < 9; ++index) |
|
561 QCOMPARE(vals[index], uniqueValues3[index]); |
|
562 } |
|
563 |
|
564 // Test the creation of QMatrix4x4 objects in various ways: |
|
565 // construct, copy, and modify. |
|
566 void tst_QMatrixNxN::create4x4() |
|
567 { |
|
568 QMatrix4x4 m1; |
|
569 QVERIFY(isIdentity(m1)); |
|
570 QVERIFY(m1.isIdentity()); |
|
571 |
|
572 QMatrix4x4 m2; |
|
573 setMatrix(m2, uniqueValues4); |
|
574 QVERIFY(isSame(m2, uniqueValues4)); |
|
575 QVERIFY(!m2.isIdentity()); |
|
576 |
|
577 QMatrix4x4 m3; |
|
578 setMatrixDirect(m3, uniqueValues4); |
|
579 QVERIFY(isSame(m3, uniqueValues4)); |
|
580 |
|
581 QMatrix4x4 m4(m3); |
|
582 QVERIFY(isSame(m4, uniqueValues4)); |
|
583 |
|
584 QMatrix4x4 m5; |
|
585 m5 = m3; |
|
586 QVERIFY(isSame(m5, uniqueValues4)); |
|
587 |
|
588 m5.setIdentity(); |
|
589 QVERIFY(isIdentity(m5)); |
|
590 |
|
591 QMatrix4x4 m6(uniqueValues4); |
|
592 QVERIFY(isSame(m6, uniqueValues4)); |
|
593 qreal vals[16]; |
|
594 m6.toValueArray(vals); |
|
595 for (int index = 0; index < 16; ++index) |
|
596 QCOMPARE(vals[index], uniqueValues4[index]); |
|
597 |
|
598 QMatrix4x4 m8 |
|
599 (uniqueValues4[0], uniqueValues4[1], uniqueValues4[2], uniqueValues4[3], |
|
600 uniqueValues4[4], uniqueValues4[5], uniqueValues4[6], uniqueValues4[7], |
|
601 uniqueValues4[8], uniqueValues4[9], uniqueValues4[10], uniqueValues4[11], |
|
602 uniqueValues4[12], uniqueValues4[13], uniqueValues4[14], uniqueValues4[15]); |
|
603 QVERIFY(isSame(m8, uniqueValues4)); |
|
604 } |
|
605 |
|
606 // Test the creation of QMatrix4x3 objects in various ways: |
|
607 // construct, copy, and modify. |
|
608 void tst_QMatrixNxN::create4x3() |
|
609 { |
|
610 QMatrix4x3 m1; |
|
611 QVERIFY(isIdentity(m1)); |
|
612 QVERIFY(m1.isIdentity()); |
|
613 |
|
614 QMatrix4x3 m2; |
|
615 setMatrix(m2, uniqueValues4x3); |
|
616 QVERIFY(isSame(m2, uniqueValues4x3)); |
|
617 QVERIFY(!m2.isIdentity()); |
|
618 |
|
619 QMatrix4x3 m3; |
|
620 setMatrixDirect(m3, uniqueValues4x3); |
|
621 QVERIFY(isSame(m3, uniqueValues4x3)); |
|
622 |
|
623 QMatrix4x3 m4(m3); |
|
624 QVERIFY(isSame(m4, uniqueValues4x3)); |
|
625 |
|
626 QMatrix4x3 m5; |
|
627 m5 = m3; |
|
628 QVERIFY(isSame(m5, uniqueValues4x3)); |
|
629 |
|
630 m5.setIdentity(); |
|
631 QVERIFY(isIdentity(m5)); |
|
632 |
|
633 QMatrix4x3 m6(uniqueValues4x3); |
|
634 QVERIFY(isSame(m6, uniqueValues4x3)); |
|
635 qreal vals[12]; |
|
636 m6.toValueArray(vals); |
|
637 for (int index = 0; index < 12; ++index) |
|
638 QCOMPARE(vals[index], uniqueValues4x3[index]); |
|
639 } |
|
640 |
|
641 // Test isIdentity() for 2x2 matrices. |
|
642 void tst_QMatrixNxN::isIdentity2x2() |
|
643 { |
|
644 for (int i = 0; i < 2 * 2; ++i) { |
|
645 QMatrix2x2 m; |
|
646 QVERIFY(m.isIdentity()); |
|
647 m.data()[i] = 42.0f; |
|
648 QVERIFY(!m.isIdentity()); |
|
649 } |
|
650 } |
|
651 |
|
652 // Test isIdentity() for 3x3 matrices. |
|
653 void tst_QMatrixNxN::isIdentity3x3() |
|
654 { |
|
655 for (int i = 0; i < 3 * 3; ++i) { |
|
656 QMatrix3x3 m; |
|
657 QVERIFY(m.isIdentity()); |
|
658 m.data()[i] = 42.0f; |
|
659 QVERIFY(!m.isIdentity()); |
|
660 } |
|
661 } |
|
662 |
|
663 // Test isIdentity() for 4x4 matrices. |
|
664 void tst_QMatrixNxN::isIdentity4x4() |
|
665 { |
|
666 for (int i = 0; i < 4 * 4; ++i) { |
|
667 QMatrix4x4 m; |
|
668 QVERIFY(m.isIdentity()); |
|
669 m.data()[i] = 42.0f; |
|
670 QVERIFY(!m.isIdentity()); |
|
671 } |
|
672 |
|
673 // Force the "Identity" flag bit to be lost and check again. |
|
674 QMatrix4x4 m2; |
|
675 m2.data()[0] = 1.0f; |
|
676 QVERIFY(m2.isIdentity()); |
|
677 } |
|
678 |
|
679 // Test isIdentity() for 4x3 matrices. |
|
680 void tst_QMatrixNxN::isIdentity4x3() |
|
681 { |
|
682 for (int i = 0; i < 4 * 3; ++i) { |
|
683 QMatrix4x3 m; |
|
684 QVERIFY(m.isIdentity()); |
|
685 m.data()[i] = 42.0f; |
|
686 QVERIFY(!m.isIdentity()); |
|
687 } |
|
688 } |
|
689 |
|
690 // Test 2x2 matrix comparisons. |
|
691 void tst_QMatrixNxN::compare2x2() |
|
692 { |
|
693 QMatrix2x2 m1(uniqueValues2); |
|
694 QMatrix2x2 m2(uniqueValues2); |
|
695 QMatrix2x2 m3(transposedValues2); |
|
696 |
|
697 QVERIFY(m1 == m2); |
|
698 QVERIFY(!(m1 != m2)); |
|
699 QVERIFY(m1 != m3); |
|
700 QVERIFY(!(m1 == m3)); |
|
701 } |
|
702 |
|
703 // Test 3x3 matrix comparisons. |
|
704 void tst_QMatrixNxN::compare3x3() |
|
705 { |
|
706 QMatrix3x3 m1(uniqueValues3); |
|
707 QMatrix3x3 m2(uniqueValues3); |
|
708 QMatrix3x3 m3(transposedValues3); |
|
709 |
|
710 QVERIFY(m1 == m2); |
|
711 QVERIFY(!(m1 != m2)); |
|
712 QVERIFY(m1 != m3); |
|
713 QVERIFY(!(m1 == m3)); |
|
714 } |
|
715 |
|
716 // Test 4x4 matrix comparisons. |
|
717 void tst_QMatrixNxN::compare4x4() |
|
718 { |
|
719 QMatrix4x4 m1(uniqueValues4); |
|
720 QMatrix4x4 m2(uniqueValues4); |
|
721 QMatrix4x4 m3(transposedValues4); |
|
722 |
|
723 QVERIFY(m1 == m2); |
|
724 QVERIFY(!(m1 != m2)); |
|
725 QVERIFY(m1 != m3); |
|
726 QVERIFY(!(m1 == m3)); |
|
727 } |
|
728 |
|
729 // Test 4x3 matrix comparisons. |
|
730 void tst_QMatrixNxN::compare4x3() |
|
731 { |
|
732 QMatrix4x3 m1(uniqueValues4x3); |
|
733 QMatrix4x3 m2(uniqueValues4x3); |
|
734 QMatrix4x3 m3(transposedValues3x4); |
|
735 |
|
736 QVERIFY(m1 == m2); |
|
737 QVERIFY(!(m1 != m2)); |
|
738 QVERIFY(m1 != m3); |
|
739 QVERIFY(!(m1 == m3)); |
|
740 } |
|
741 |
|
742 // Test matrix 2x2 transpose operations. |
|
743 void tst_QMatrixNxN::transposed2x2() |
|
744 { |
|
745 // Transposing the identity should result in the identity. |
|
746 QMatrix2x2 m1; |
|
747 QMatrix2x2 m2 = m1.transposed(); |
|
748 QVERIFY(isIdentity(m2)); |
|
749 |
|
750 // Transpose a more interesting matrix that allows us to track |
|
751 // exactly where each source element ends up. |
|
752 QMatrix2x2 m3(uniqueValues2); |
|
753 QMatrix2x2 m4 = m3.transposed(); |
|
754 QVERIFY(isSame(m4, transposedValues2)); |
|
755 |
|
756 // Transpose in-place, just to check that the compiler is sane. |
|
757 m3 = m3.transposed(); |
|
758 QVERIFY(isSame(m3, transposedValues2)); |
|
759 } |
|
760 |
|
761 // Test matrix 3x3 transpose operations. |
|
762 void tst_QMatrixNxN::transposed3x3() |
|
763 { |
|
764 // Transposing the identity should result in the identity. |
|
765 QMatrix3x3 m1; |
|
766 QMatrix3x3 m2 = m1.transposed(); |
|
767 QVERIFY(isIdentity(m2)); |
|
768 |
|
769 // Transpose a more interesting matrix that allows us to track |
|
770 // exactly where each source element ends up. |
|
771 QMatrix3x3 m3(uniqueValues3); |
|
772 QMatrix3x3 m4 = m3.transposed(); |
|
773 QVERIFY(isSame(m4, transposedValues3)); |
|
774 |
|
775 // Transpose in-place, just to check that the compiler is sane. |
|
776 m3 = m3.transposed(); |
|
777 QVERIFY(isSame(m3, transposedValues3)); |
|
778 } |
|
779 |
|
780 // Test matrix 4x4 transpose operations. |
|
781 void tst_QMatrixNxN::transposed4x4() |
|
782 { |
|
783 // Transposing the identity should result in the identity. |
|
784 QMatrix4x4 m1; |
|
785 QMatrix4x4 m2 = m1.transposed(); |
|
786 QVERIFY(isIdentity(m2)); |
|
787 |
|
788 // Transpose a more interesting matrix that allows us to track |
|
789 // exactly where each source element ends up. |
|
790 QMatrix4x4 m3(uniqueValues4); |
|
791 QMatrix4x4 m4 = m3.transposed(); |
|
792 QVERIFY(isSame(m4, transposedValues4)); |
|
793 |
|
794 // Transpose in-place, just to check that the compiler is sane. |
|
795 m3 = m3.transposed(); |
|
796 QVERIFY(isSame(m3, transposedValues4)); |
|
797 } |
|
798 |
|
799 // Test matrix 4x3 transpose operations. |
|
800 void tst_QMatrixNxN::transposed4x3() |
|
801 { |
|
802 QMatrix4x3 m3(uniqueValues4x3); |
|
803 QMatrix3x4 m4 = m3.transposed(); |
|
804 qreal values[12]; |
|
805 m4.toValueArray(values); |
|
806 for (int index = 0; index < 12; ++index) |
|
807 QCOMPARE(values[index], transposedValues3x4[index]); |
|
808 } |
|
809 |
|
810 // Test matrix addition for 2x2 matrices. |
|
811 void tst_QMatrixNxN::add2x2_data() |
|
812 { |
|
813 QTest::addColumn<void *>("m1Values"); |
|
814 QTest::addColumn<void *>("m2Values"); |
|
815 QTest::addColumn<void *>("m3Values"); |
|
816 |
|
817 QTest::newRow("null") |
|
818 << (void *)nullValues2 << (void *)nullValues2 << (void *)nullValues2; |
|
819 |
|
820 QTest::newRow("identity/null") |
|
821 << (void *)identityValues2 << (void *)nullValues2 << (void *)identityValues2; |
|
822 |
|
823 QTest::newRow("identity/identity") |
|
824 << (void *)identityValues2 << (void *)identityValues2 << (void *)doubleIdentity2; |
|
825 |
|
826 static qreal const sumValues[16] = |
|
827 {2.0f, 7.0f, |
|
828 7.0f, 12.0f}; |
|
829 QTest::newRow("unique") |
|
830 << (void *)uniqueValues2 << (void *)transposedValues2 << (void *)sumValues; |
|
831 } |
|
832 void tst_QMatrixNxN::add2x2() |
|
833 { |
|
834 QFETCH(void *, m1Values); |
|
835 QFETCH(void *, m2Values); |
|
836 QFETCH(void *, m3Values); |
|
837 |
|
838 QMatrix2x2 m1((const qreal *)m1Values); |
|
839 QMatrix2x2 m2((const qreal *)m2Values); |
|
840 |
|
841 QMatrix2x2 m4(m1); |
|
842 m4 += m2; |
|
843 QVERIFY(isSame(m4, (const qreal *)m3Values)); |
|
844 |
|
845 QMatrix2x2 m5; |
|
846 m5 = m1 + m2; |
|
847 QVERIFY(isSame(m5, (const qreal *)m3Values)); |
|
848 } |
|
849 |
|
850 // Test matrix addition for 3x3 matrices. |
|
851 void tst_QMatrixNxN::add3x3_data() |
|
852 { |
|
853 QTest::addColumn<void *>("m1Values"); |
|
854 QTest::addColumn<void *>("m2Values"); |
|
855 QTest::addColumn<void *>("m3Values"); |
|
856 |
|
857 QTest::newRow("null") |
|
858 << (void *)nullValues3 << (void *)nullValues3 << (void *)nullValues3; |
|
859 |
|
860 QTest::newRow("identity/null") |
|
861 << (void *)identityValues3 << (void *)nullValues3 << (void *)identityValues3; |
|
862 |
|
863 QTest::newRow("identity/identity") |
|
864 << (void *)identityValues3 << (void *)identityValues3 << (void *)doubleIdentity3; |
|
865 |
|
866 static qreal const sumValues[16] = |
|
867 {2.0f, 7.0f, 12.0f, |
|
868 7.0f, 12.0f, 17.0f, |
|
869 12.0f, 17.0f, 22.0f}; |
|
870 QTest::newRow("unique") |
|
871 << (void *)uniqueValues3 << (void *)transposedValues3 << (void *)sumValues; |
|
872 } |
|
873 void tst_QMatrixNxN::add3x3() |
|
874 { |
|
875 QFETCH(void *, m1Values); |
|
876 QFETCH(void *, m2Values); |
|
877 QFETCH(void *, m3Values); |
|
878 |
|
879 QMatrix3x3 m1((const qreal *)m1Values); |
|
880 QMatrix3x3 m2((const qreal *)m2Values); |
|
881 |
|
882 QMatrix3x3 m4(m1); |
|
883 m4 += m2; |
|
884 QVERIFY(isSame(m4, (const qreal *)m3Values)); |
|
885 |
|
886 QMatrix3x3 m5; |
|
887 m5 = m1 + m2; |
|
888 QVERIFY(isSame(m5, (const qreal *)m3Values)); |
|
889 } |
|
890 |
|
891 // Test matrix addition for 4x4 matrices. |
|
892 void tst_QMatrixNxN::add4x4_data() |
|
893 { |
|
894 QTest::addColumn<void *>("m1Values"); |
|
895 QTest::addColumn<void *>("m2Values"); |
|
896 QTest::addColumn<void *>("m3Values"); |
|
897 |
|
898 QTest::newRow("null") |
|
899 << (void *)nullValues4 << (void *)nullValues4 << (void *)nullValues4; |
|
900 |
|
901 QTest::newRow("identity/null") |
|
902 << (void *)identityValues4 << (void *)nullValues4 << (void *)identityValues4; |
|
903 |
|
904 QTest::newRow("identity/identity") |
|
905 << (void *)identityValues4 << (void *)identityValues4 << (void *)doubleIdentity4; |
|
906 |
|
907 static qreal const sumValues[16] = |
|
908 {2.0f, 7.0f, 12.0f, 17.0f, |
|
909 7.0f, 12.0f, 17.0f, 22.0f, |
|
910 12.0f, 17.0f, 22.0f, 27.0f, |
|
911 17.0f, 22.0f, 27.0f, 32.0f}; |
|
912 QTest::newRow("unique") |
|
913 << (void *)uniqueValues4 << (void *)transposedValues4 << (void *)sumValues; |
|
914 } |
|
915 void tst_QMatrixNxN::add4x4() |
|
916 { |
|
917 QFETCH(void *, m1Values); |
|
918 QFETCH(void *, m2Values); |
|
919 QFETCH(void *, m3Values); |
|
920 |
|
921 QMatrix4x4 m1((const qreal *)m1Values); |
|
922 QMatrix4x4 m2((const qreal *)m2Values); |
|
923 |
|
924 QMatrix4x4 m4(m1); |
|
925 m4 += m2; |
|
926 QVERIFY(isSame(m4, (const qreal *)m3Values)); |
|
927 |
|
928 QMatrix4x4 m5; |
|
929 m5 = m1 + m2; |
|
930 QVERIFY(isSame(m5, (const qreal *)m3Values)); |
|
931 } |
|
932 |
|
933 // Test matrix addition for 4x3 matrices. |
|
934 void tst_QMatrixNxN::add4x3_data() |
|
935 { |
|
936 QTest::addColumn<void *>("m1Values"); |
|
937 QTest::addColumn<void *>("m2Values"); |
|
938 QTest::addColumn<void *>("m3Values"); |
|
939 |
|
940 QTest::newRow("null") |
|
941 << (void *)nullValues4x3 << (void *)nullValues4x3 << (void *)nullValues4x3; |
|
942 |
|
943 QTest::newRow("identity/null") |
|
944 << (void *)identityValues4x3 << (void *)nullValues4x3 << (void *)identityValues4x3; |
|
945 |
|
946 QTest::newRow("identity/identity") |
|
947 << (void *)identityValues4x3 << (void *)identityValues4x3 << (void *)doubleIdentity4x3; |
|
948 |
|
949 static qreal const sumValues[16] = |
|
950 {2.0f, 7.0f, 12.0f, 6.0f, |
|
951 11.0f, 16.0f, 10.0f, 15.0f, |
|
952 20.0f, 14.0f, 19.0f, 24.0f}; |
|
953 QTest::newRow("unique") |
|
954 << (void *)uniqueValues4x3 << (void *)transposedValues3x4 << (void *)sumValues; |
|
955 } |
|
956 void tst_QMatrixNxN::add4x3() |
|
957 { |
|
958 QFETCH(void *, m1Values); |
|
959 QFETCH(void *, m2Values); |
|
960 QFETCH(void *, m3Values); |
|
961 |
|
962 QMatrix4x3 m1((const qreal *)m1Values); |
|
963 QMatrix4x3 m2((const qreal *)m2Values); |
|
964 |
|
965 QMatrix4x3 m4(m1); |
|
966 m4 += m2; |
|
967 QVERIFY(isSame(m4, (const qreal *)m3Values)); |
|
968 |
|
969 QMatrix4x3 m5; |
|
970 m5 = m1 + m2; |
|
971 QVERIFY(isSame(m5, (const qreal *)m3Values)); |
|
972 } |
|
973 |
|
974 // Test matrix subtraction for 2x2 matrices. |
|
975 void tst_QMatrixNxN::subtract2x2_data() |
|
976 { |
|
977 // Use the same test cases as the add test. |
|
978 add2x2_data(); |
|
979 } |
|
980 void tst_QMatrixNxN::subtract2x2() |
|
981 { |
|
982 QFETCH(void *, m1Values); |
|
983 QFETCH(void *, m2Values); |
|
984 QFETCH(void *, m3Values); |
|
985 |
|
986 QMatrix2x2 m1((const qreal *)m1Values); |
|
987 QMatrix2x2 m2((const qreal *)m2Values); |
|
988 QMatrix2x2 m3((const qreal *)m3Values); |
|
989 |
|
990 QMatrix2x2 m4(m3); |
|
991 m4 -= m1; |
|
992 QVERIFY(isSame(m4, (const qreal *)m2Values)); |
|
993 |
|
994 QMatrix2x2 m5; |
|
995 m5 = m3 - m1; |
|
996 QVERIFY(isSame(m5, (const qreal *)m2Values)); |
|
997 |
|
998 QMatrix2x2 m6(m3); |
|
999 m6 -= m2; |
|
1000 QVERIFY(isSame(m6, (const qreal *)m1Values)); |
|
1001 |
|
1002 QMatrix2x2 m7; |
|
1003 m7 = m3 - m2; |
|
1004 QVERIFY(isSame(m7, (const qreal *)m1Values)); |
|
1005 } |
|
1006 |
|
1007 // Test matrix subtraction for 3x3 matrices. |
|
1008 void tst_QMatrixNxN::subtract3x3_data() |
|
1009 { |
|
1010 // Use the same test cases as the add test. |
|
1011 add3x3_data(); |
|
1012 } |
|
1013 void tst_QMatrixNxN::subtract3x3() |
|
1014 { |
|
1015 QFETCH(void *, m1Values); |
|
1016 QFETCH(void *, m2Values); |
|
1017 QFETCH(void *, m3Values); |
|
1018 |
|
1019 QMatrix3x3 m1((const qreal *)m1Values); |
|
1020 QMatrix3x3 m2((const qreal *)m2Values); |
|
1021 QMatrix3x3 m3((const qreal *)m3Values); |
|
1022 |
|
1023 QMatrix3x3 m4(m3); |
|
1024 m4 -= m1; |
|
1025 QVERIFY(isSame(m4, (const qreal *)m2Values)); |
|
1026 |
|
1027 QMatrix3x3 m5; |
|
1028 m5 = m3 - m1; |
|
1029 QVERIFY(isSame(m5, (const qreal *)m2Values)); |
|
1030 |
|
1031 QMatrix3x3 m6(m3); |
|
1032 m6 -= m2; |
|
1033 QVERIFY(isSame(m6, (const qreal *)m1Values)); |
|
1034 |
|
1035 QMatrix3x3 m7; |
|
1036 m7 = m3 - m2; |
|
1037 QVERIFY(isSame(m7, (const qreal *)m1Values)); |
|
1038 } |
|
1039 |
|
1040 // Test matrix subtraction for 4x4 matrices. |
|
1041 void tst_QMatrixNxN::subtract4x4_data() |
|
1042 { |
|
1043 // Use the same test cases as the add test. |
|
1044 add4x4_data(); |
|
1045 } |
|
1046 void tst_QMatrixNxN::subtract4x4() |
|
1047 { |
|
1048 QFETCH(void *, m1Values); |
|
1049 QFETCH(void *, m2Values); |
|
1050 QFETCH(void *, m3Values); |
|
1051 |
|
1052 QMatrix4x4 m1((const qreal *)m1Values); |
|
1053 QMatrix4x4 m2((const qreal *)m2Values); |
|
1054 QMatrix4x4 m3((const qreal *)m3Values); |
|
1055 |
|
1056 QMatrix4x4 m4(m3); |
|
1057 m4 -= m1; |
|
1058 QVERIFY(isSame(m4, (const qreal *)m2Values)); |
|
1059 |
|
1060 QMatrix4x4 m5; |
|
1061 m5 = m3 - m1; |
|
1062 QVERIFY(isSame(m5, (const qreal *)m2Values)); |
|
1063 |
|
1064 QMatrix4x4 m6(m3); |
|
1065 m6 -= m2; |
|
1066 QVERIFY(isSame(m6, (const qreal *)m1Values)); |
|
1067 |
|
1068 QMatrix4x4 m7; |
|
1069 m7 = m3 - m2; |
|
1070 QVERIFY(isSame(m7, (const qreal *)m1Values)); |
|
1071 } |
|
1072 |
|
1073 // Test matrix subtraction for 4x3 matrices. |
|
1074 void tst_QMatrixNxN::subtract4x3_data() |
|
1075 { |
|
1076 // Use the same test cases as the add test. |
|
1077 add4x3_data(); |
|
1078 } |
|
1079 void tst_QMatrixNxN::subtract4x3() |
|
1080 { |
|
1081 QFETCH(void *, m1Values); |
|
1082 QFETCH(void *, m2Values); |
|
1083 QFETCH(void *, m3Values); |
|
1084 |
|
1085 QMatrix4x3 m1((const qreal *)m1Values); |
|
1086 QMatrix4x3 m2((const qreal *)m2Values); |
|
1087 QMatrix4x3 m3((const qreal *)m3Values); |
|
1088 |
|
1089 QMatrix4x3 m4(m3); |
|
1090 m4 -= m1; |
|
1091 QVERIFY(isSame(m4, (const qreal *)m2Values)); |
|
1092 |
|
1093 QMatrix4x3 m5; |
|
1094 m5 = m3 - m1; |
|
1095 QVERIFY(isSame(m5, (const qreal *)m2Values)); |
|
1096 |
|
1097 QMatrix4x3 m6(m3); |
|
1098 m6 -= m2; |
|
1099 QVERIFY(isSame(m6, (const qreal *)m1Values)); |
|
1100 |
|
1101 QMatrix4x3 m7; |
|
1102 m7 = m3 - m2; |
|
1103 QVERIFY(isSame(m7, (const qreal *)m1Values)); |
|
1104 } |
|
1105 |
|
1106 // Test matrix multiplication for 2x2 matrices. |
|
1107 void tst_QMatrixNxN::multiply2x2_data() |
|
1108 { |
|
1109 QTest::addColumn<void *>("m1Values"); |
|
1110 QTest::addColumn<void *>("m2Values"); |
|
1111 QTest::addColumn<void *>("m3Values"); |
|
1112 |
|
1113 QTest::newRow("null") |
|
1114 << (void *)nullValues2 << (void *)nullValues2 << (void *)nullValues2; |
|
1115 |
|
1116 QTest::newRow("null/unique") |
|
1117 << (void *)nullValues2 << (void *)uniqueValues2 << (void *)nullValues2; |
|
1118 |
|
1119 QTest::newRow("unique/null") |
|
1120 << (void *)uniqueValues2 << (void *)nullValues2 << (void *)nullValues2; |
|
1121 |
|
1122 QTest::newRow("unique/identity") |
|
1123 << (void *)uniqueValues2 << (void *)identityValues2 << (void *)uniqueValues2; |
|
1124 |
|
1125 QTest::newRow("identity/unique") |
|
1126 << (void *)identityValues2 << (void *)uniqueValues2 << (void *)uniqueValues2; |
|
1127 |
|
1128 static qreal uniqueResult[4]; |
|
1129 for (int row = 0; row < 2; ++row) { |
|
1130 for (int col = 0; col < 2; ++col) { |
|
1131 qreal sum = 0.0f; |
|
1132 for (int j = 0; j < 2; ++j) |
|
1133 sum += uniqueValues2[row * 2 + j] * transposedValues2[j * 2 + col]; |
|
1134 uniqueResult[row * 2 + col] = sum; |
|
1135 } |
|
1136 } |
|
1137 |
|
1138 QTest::newRow("unique/transposed") |
|
1139 << (void *)uniqueValues2 << (void *)transposedValues2 << (void *)uniqueResult; |
|
1140 } |
|
1141 void tst_QMatrixNxN::multiply2x2() |
|
1142 { |
|
1143 QFETCH(void *, m1Values); |
|
1144 QFETCH(void *, m2Values); |
|
1145 QFETCH(void *, m3Values); |
|
1146 |
|
1147 QMatrix2x2 m1((const qreal *)m1Values); |
|
1148 QMatrix2x2 m2((const qreal *)m2Values); |
|
1149 |
|
1150 QMatrix2x2 m5; |
|
1151 m5 = m1 * m2; |
|
1152 QVERIFY(isSame(m5, (const qreal *)m3Values)); |
|
1153 } |
|
1154 |
|
1155 // Test matrix multiplication for 3x3 matrices. |
|
1156 void tst_QMatrixNxN::multiply3x3_data() |
|
1157 { |
|
1158 QTest::addColumn<void *>("m1Values"); |
|
1159 QTest::addColumn<void *>("m2Values"); |
|
1160 QTest::addColumn<void *>("m3Values"); |
|
1161 |
|
1162 QTest::newRow("null") |
|
1163 << (void *)nullValues3 << (void *)nullValues3 << (void *)nullValues3; |
|
1164 |
|
1165 QTest::newRow("null/unique") |
|
1166 << (void *)nullValues3 << (void *)uniqueValues3 << (void *)nullValues3; |
|
1167 |
|
1168 QTest::newRow("unique/null") |
|
1169 << (void *)uniqueValues3 << (void *)nullValues3 << (void *)nullValues3; |
|
1170 |
|
1171 QTest::newRow("unique/identity") |
|
1172 << (void *)uniqueValues3 << (void *)identityValues3 << (void *)uniqueValues3; |
|
1173 |
|
1174 QTest::newRow("identity/unique") |
|
1175 << (void *)identityValues3 << (void *)uniqueValues3 << (void *)uniqueValues3; |
|
1176 |
|
1177 static qreal uniqueResult[9]; |
|
1178 for (int row = 0; row < 3; ++row) { |
|
1179 for (int col = 0; col < 3; ++col) { |
|
1180 qreal sum = 0.0f; |
|
1181 for (int j = 0; j < 3; ++j) |
|
1182 sum += uniqueValues3[row * 3 + j] * transposedValues3[j * 3 + col]; |
|
1183 uniqueResult[row * 3 + col] = sum; |
|
1184 } |
|
1185 } |
|
1186 |
|
1187 QTest::newRow("unique/transposed") |
|
1188 << (void *)uniqueValues3 << (void *)transposedValues3 << (void *)uniqueResult; |
|
1189 } |
|
1190 void tst_QMatrixNxN::multiply3x3() |
|
1191 { |
|
1192 QFETCH(void *, m1Values); |
|
1193 QFETCH(void *, m2Values); |
|
1194 QFETCH(void *, m3Values); |
|
1195 |
|
1196 QMatrix3x3 m1((const qreal *)m1Values); |
|
1197 QMatrix3x3 m2((const qreal *)m2Values); |
|
1198 |
|
1199 QMatrix3x3 m5; |
|
1200 m5 = m1 * m2; |
|
1201 QVERIFY(isSame(m5, (const qreal *)m3Values)); |
|
1202 } |
|
1203 |
|
1204 // Test matrix multiplication for 4x4 matrices. |
|
1205 void tst_QMatrixNxN::multiply4x4_data() |
|
1206 { |
|
1207 QTest::addColumn<void *>("m1Values"); |
|
1208 QTest::addColumn<void *>("m2Values"); |
|
1209 QTest::addColumn<void *>("m3Values"); |
|
1210 |
|
1211 QTest::newRow("null") |
|
1212 << (void *)nullValues4 << (void *)nullValues4 << (void *)nullValues4; |
|
1213 |
|
1214 QTest::newRow("null/unique") |
|
1215 << (void *)nullValues4 << (void *)uniqueValues4 << (void *)nullValues4; |
|
1216 |
|
1217 QTest::newRow("unique/null") |
|
1218 << (void *)uniqueValues4 << (void *)nullValues4 << (void *)nullValues4; |
|
1219 |
|
1220 QTest::newRow("unique/identity") |
|
1221 << (void *)uniqueValues4 << (void *)identityValues4 << (void *)uniqueValues4; |
|
1222 |
|
1223 QTest::newRow("identity/unique") |
|
1224 << (void *)identityValues4 << (void *)uniqueValues4 << (void *)uniqueValues4; |
|
1225 |
|
1226 static qreal uniqueResult[16]; |
|
1227 for (int row = 0; row < 4; ++row) { |
|
1228 for (int col = 0; col < 4; ++col) { |
|
1229 qreal sum = 0.0f; |
|
1230 for (int j = 0; j < 4; ++j) |
|
1231 sum += uniqueValues4[row * 4 + j] * transposedValues4[j * 4 + col]; |
|
1232 uniqueResult[row * 4 + col] = sum; |
|
1233 } |
|
1234 } |
|
1235 |
|
1236 QTest::newRow("unique/transposed") |
|
1237 << (void *)uniqueValues4 << (void *)transposedValues4 << (void *)uniqueResult; |
|
1238 } |
|
1239 void tst_QMatrixNxN::multiply4x4() |
|
1240 { |
|
1241 QFETCH(void *, m1Values); |
|
1242 QFETCH(void *, m2Values); |
|
1243 QFETCH(void *, m3Values); |
|
1244 |
|
1245 QMatrix4x4 m1((const qreal *)m1Values); |
|
1246 QMatrix4x4 m2((const qreal *)m2Values); |
|
1247 |
|
1248 QMatrix4x4 m4; |
|
1249 m4 = m1; |
|
1250 m4 *= m2; |
|
1251 QVERIFY(isSame(m4, (const qreal *)m3Values)); |
|
1252 |
|
1253 QMatrix4x4 m5; |
|
1254 m5 = m1 * m2; |
|
1255 QVERIFY(isSame(m5, (const qreal *)m3Values)); |
|
1256 } |
|
1257 |
|
1258 // Test matrix multiplication for 4x3 matrices. |
|
1259 void tst_QMatrixNxN::multiply4x3_data() |
|
1260 { |
|
1261 QTest::addColumn<void *>("m1Values"); |
|
1262 QTest::addColumn<void *>("m2Values"); |
|
1263 QTest::addColumn<void *>("m3Values"); |
|
1264 |
|
1265 QTest::newRow("null") |
|
1266 << (void *)nullValues4x3 << (void *)nullValues4x3 << (void *)nullValues3; |
|
1267 |
|
1268 QTest::newRow("null/unique") |
|
1269 << (void *)nullValues4x3 << (void *)uniqueValues4x3 << (void *)nullValues3; |
|
1270 |
|
1271 QTest::newRow("unique/null") |
|
1272 << (void *)uniqueValues4x3 << (void *)nullValues4x3 << (void *)nullValues3; |
|
1273 |
|
1274 static qreal uniqueResult[9]; |
|
1275 for (int row = 0; row < 3; ++row) { |
|
1276 for (int col = 0; col < 3; ++col) { |
|
1277 qreal sum = 0.0f; |
|
1278 for (int j = 0; j < 4; ++j) |
|
1279 sum += uniqueValues4x3[row * 4 + j] * transposedValues3x4[j * 3 + col]; |
|
1280 uniqueResult[row * 3 + col] = sum; |
|
1281 } |
|
1282 } |
|
1283 |
|
1284 QTest::newRow("unique/transposed") |
|
1285 << (void *)uniqueValues4x3 << (void *)transposedValues3x4 << (void *)uniqueResult; |
|
1286 } |
|
1287 void tst_QMatrixNxN::multiply4x3() |
|
1288 { |
|
1289 QFETCH(void *, m1Values); |
|
1290 QFETCH(void *, m2Values); |
|
1291 QFETCH(void *, m3Values); |
|
1292 |
|
1293 QMatrix4x3 m1((const qreal *)m1Values); |
|
1294 QMatrix3x4 m2((const qreal *)m2Values); |
|
1295 |
|
1296 QGenericMatrix<3, 3, qreal> m4; |
|
1297 m4 = m1 * m2; |
|
1298 qreal values[9]; |
|
1299 m4.toValueArray(values); |
|
1300 for (int index = 0; index < 9; ++index) |
|
1301 QCOMPARE(values[index], ((const qreal *)m3Values)[index]); |
|
1302 } |
|
1303 |
|
1304 // Test matrix multiplication by a factor for 2x2 matrices. |
|
1305 void tst_QMatrixNxN::multiplyFactor2x2_data() |
|
1306 { |
|
1307 QTest::addColumn<void *>("m1Values"); |
|
1308 QTest::addColumn<qreal>("factor"); |
|
1309 QTest::addColumn<void *>("m2Values"); |
|
1310 |
|
1311 QTest::newRow("null") |
|
1312 << (void *)nullValues2 << (qreal)1.0f << (void *)nullValues2; |
|
1313 |
|
1314 QTest::newRow("double identity") |
|
1315 << (void *)identityValues2 << (qreal)2.0f << (void *)doubleIdentity2; |
|
1316 |
|
1317 static qreal const values[16] = |
|
1318 {1.0f, 2.0f, |
|
1319 5.0f, 6.0f}; |
|
1320 static qreal const doubleValues[16] = |
|
1321 {2.0f, 4.0f, |
|
1322 10.0f, 12.0f}; |
|
1323 static qreal const negDoubleValues[16] = |
|
1324 {-2.0f, -4.0f, |
|
1325 -10.0f, -12.0f}; |
|
1326 |
|
1327 QTest::newRow("unique") |
|
1328 << (void *)values << (qreal)2.0f << (void *)doubleValues; |
|
1329 |
|
1330 QTest::newRow("neg") |
|
1331 << (void *)values << (qreal)-2.0f << (void *)negDoubleValues; |
|
1332 |
|
1333 QTest::newRow("zero") |
|
1334 << (void *)values << (qreal)0.0f << (void *)nullValues4; |
|
1335 } |
|
1336 void tst_QMatrixNxN::multiplyFactor2x2() |
|
1337 { |
|
1338 QFETCH(void *, m1Values); |
|
1339 QFETCH(qreal, factor); |
|
1340 QFETCH(void *, m2Values); |
|
1341 |
|
1342 QMatrix2x2 m1((const qreal *)m1Values); |
|
1343 |
|
1344 QMatrix2x2 m3; |
|
1345 m3 = m1; |
|
1346 m3 *= factor; |
|
1347 QVERIFY(isSame(m3, (const qreal *)m2Values)); |
|
1348 |
|
1349 QMatrix2x2 m4; |
|
1350 m4 = m1 * factor; |
|
1351 QVERIFY(isSame(m4, (const qreal *)m2Values)); |
|
1352 |
|
1353 QMatrix2x2 m5; |
|
1354 m5 = factor * m1; |
|
1355 QVERIFY(isSame(m5, (const qreal *)m2Values)); |
|
1356 } |
|
1357 |
|
1358 // Test matrix multiplication by a factor for 3x3 matrices. |
|
1359 void tst_QMatrixNxN::multiplyFactor3x3_data() |
|
1360 { |
|
1361 QTest::addColumn<void *>("m1Values"); |
|
1362 QTest::addColumn<qreal>("factor"); |
|
1363 QTest::addColumn<void *>("m2Values"); |
|
1364 |
|
1365 QTest::newRow("null") |
|
1366 << (void *)nullValues3 << (qreal)1.0f << (void *)nullValues3; |
|
1367 |
|
1368 QTest::newRow("double identity") |
|
1369 << (void *)identityValues3 << (qreal)2.0f << (void *)doubleIdentity3; |
|
1370 |
|
1371 static qreal const values[16] = |
|
1372 {1.0f, 2.0f, 3.0f, |
|
1373 5.0f, 6.0f, 7.0f, |
|
1374 9.0f, 10.0f, 11.0f}; |
|
1375 static qreal const doubleValues[16] = |
|
1376 {2.0f, 4.0f, 6.0f, |
|
1377 10.0f, 12.0f, 14.0f, |
|
1378 18.0f, 20.0f, 22.0f}; |
|
1379 static qreal const negDoubleValues[16] = |
|
1380 {-2.0f, -4.0f, -6.0f, |
|
1381 -10.0f, -12.0f, -14.0f, |
|
1382 -18.0f, -20.0f, -22.0f}; |
|
1383 |
|
1384 QTest::newRow("unique") |
|
1385 << (void *)values << (qreal)2.0f << (void *)doubleValues; |
|
1386 |
|
1387 QTest::newRow("neg") |
|
1388 << (void *)values << (qreal)-2.0f << (void *)negDoubleValues; |
|
1389 |
|
1390 QTest::newRow("zero") |
|
1391 << (void *)values << (qreal)0.0f << (void *)nullValues4; |
|
1392 } |
|
1393 void tst_QMatrixNxN::multiplyFactor3x3() |
|
1394 { |
|
1395 QFETCH(void *, m1Values); |
|
1396 QFETCH(qreal, factor); |
|
1397 QFETCH(void *, m2Values); |
|
1398 |
|
1399 QMatrix3x3 m1((const qreal *)m1Values); |
|
1400 |
|
1401 QMatrix3x3 m3; |
|
1402 m3 = m1; |
|
1403 m3 *= factor; |
|
1404 QVERIFY(isSame(m3, (const qreal *)m2Values)); |
|
1405 |
|
1406 QMatrix3x3 m4; |
|
1407 m4 = m1 * factor; |
|
1408 QVERIFY(isSame(m4, (const qreal *)m2Values)); |
|
1409 |
|
1410 QMatrix3x3 m5; |
|
1411 m5 = factor * m1; |
|
1412 QVERIFY(isSame(m5, (const qreal *)m2Values)); |
|
1413 } |
|
1414 |
|
1415 // Test matrix multiplication by a factor for 4x4 matrices. |
|
1416 void tst_QMatrixNxN::multiplyFactor4x4_data() |
|
1417 { |
|
1418 QTest::addColumn<void *>("m1Values"); |
|
1419 QTest::addColumn<qreal>("factor"); |
|
1420 QTest::addColumn<void *>("m2Values"); |
|
1421 |
|
1422 QTest::newRow("null") |
|
1423 << (void *)nullValues4 << (qreal)1.0f << (void *)nullValues4; |
|
1424 |
|
1425 QTest::newRow("double identity") |
|
1426 << (void *)identityValues4 << (qreal)2.0f << (void *)doubleIdentity4; |
|
1427 |
|
1428 static qreal const values[16] = |
|
1429 {1.0f, 2.0f, 3.0f, 4.0f, |
|
1430 5.0f, 6.0f, 7.0f, 8.0f, |
|
1431 9.0f, 10.0f, 11.0f, 12.0f, |
|
1432 13.0f, 14.0f, 15.0f, 16.0f}; |
|
1433 static qreal const doubleValues[16] = |
|
1434 {2.0f, 4.0f, 6.0f, 8.0f, |
|
1435 10.0f, 12.0f, 14.0f, 16.0f, |
|
1436 18.0f, 20.0f, 22.0f, 24.0f, |
|
1437 26.0f, 28.0f, 30.0f, 32.0f}; |
|
1438 static qreal const negDoubleValues[16] = |
|
1439 {-2.0f, -4.0f, -6.0f, -8.0f, |
|
1440 -10.0f, -12.0f, -14.0f, -16.0f, |
|
1441 -18.0f, -20.0f, -22.0f, -24.0f, |
|
1442 -26.0f, -28.0f, -30.0f, -32.0f}; |
|
1443 |
|
1444 QTest::newRow("unique") |
|
1445 << (void *)values << (qreal)2.0f << (void *)doubleValues; |
|
1446 |
|
1447 QTest::newRow("neg") |
|
1448 << (void *)values << (qreal)-2.0f << (void *)negDoubleValues; |
|
1449 |
|
1450 QTest::newRow("zero") |
|
1451 << (void *)values << (qreal)0.0f << (void *)nullValues4; |
|
1452 } |
|
1453 void tst_QMatrixNxN::multiplyFactor4x4() |
|
1454 { |
|
1455 QFETCH(void *, m1Values); |
|
1456 QFETCH(qreal, factor); |
|
1457 QFETCH(void *, m2Values); |
|
1458 |
|
1459 QMatrix4x4 m1((const qreal *)m1Values); |
|
1460 |
|
1461 QMatrix4x4 m3; |
|
1462 m3 = m1; |
|
1463 m3 *= factor; |
|
1464 QVERIFY(isSame(m3, (const qreal *)m2Values)); |
|
1465 |
|
1466 QMatrix4x4 m4; |
|
1467 m4 = m1 * factor; |
|
1468 QVERIFY(isSame(m4, (const qreal *)m2Values)); |
|
1469 |
|
1470 QMatrix4x4 m5; |
|
1471 m5 = factor * m1; |
|
1472 QVERIFY(isSame(m5, (const qreal *)m2Values)); |
|
1473 } |
|
1474 |
|
1475 // Test matrix multiplication by a factor for 4x3 matrices. |
|
1476 void tst_QMatrixNxN::multiplyFactor4x3_data() |
|
1477 { |
|
1478 QTest::addColumn<void *>("m1Values"); |
|
1479 QTest::addColumn<qreal>("factor"); |
|
1480 QTest::addColumn<void *>("m2Values"); |
|
1481 |
|
1482 QTest::newRow("null") |
|
1483 << (void *)nullValues4x3 << (qreal)1.0f << (void *)nullValues4x3; |
|
1484 |
|
1485 QTest::newRow("double identity") |
|
1486 << (void *)identityValues4x3 << (qreal)2.0f << (void *)doubleIdentity4x3; |
|
1487 |
|
1488 static qreal const values[12] = |
|
1489 {1.0f, 2.0f, 3.0f, 4.0f, |
|
1490 5.0f, 6.0f, 7.0f, 8.0f, |
|
1491 9.0f, 10.0f, 11.0f, 12.0f}; |
|
1492 static qreal const doubleValues[12] = |
|
1493 {2.0f, 4.0f, 6.0f, 8.0f, |
|
1494 10.0f, 12.0f, 14.0f, 16.0f, |
|
1495 18.0f, 20.0f, 22.0f, 24.0f}; |
|
1496 static qreal const negDoubleValues[12] = |
|
1497 {-2.0f, -4.0f, -6.0f, -8.0f, |
|
1498 -10.0f, -12.0f, -14.0f, -16.0f, |
|
1499 -18.0f, -20.0f, -22.0f, -24.0f}; |
|
1500 |
|
1501 QTest::newRow("unique") |
|
1502 << (void *)values << (qreal)2.0f << (void *)doubleValues; |
|
1503 |
|
1504 QTest::newRow("neg") |
|
1505 << (void *)values << (qreal)-2.0f << (void *)negDoubleValues; |
|
1506 |
|
1507 QTest::newRow("zero") |
|
1508 << (void *)values << (qreal)0.0f << (void *)nullValues4x3; |
|
1509 } |
|
1510 void tst_QMatrixNxN::multiplyFactor4x3() |
|
1511 { |
|
1512 QFETCH(void *, m1Values); |
|
1513 QFETCH(qreal, factor); |
|
1514 QFETCH(void *, m2Values); |
|
1515 |
|
1516 QMatrix4x3 m1((const qreal *)m1Values); |
|
1517 |
|
1518 QMatrix4x3 m3; |
|
1519 m3 = m1; |
|
1520 m3 *= factor; |
|
1521 QVERIFY(isSame(m3, (const qreal *)m2Values)); |
|
1522 |
|
1523 QMatrix4x3 m4; |
|
1524 m4 = m1 * factor; |
|
1525 QVERIFY(isSame(m4, (const qreal *)m2Values)); |
|
1526 |
|
1527 QMatrix4x3 m5; |
|
1528 m5 = factor * m1; |
|
1529 QVERIFY(isSame(m5, (const qreal *)m2Values)); |
|
1530 } |
|
1531 |
|
1532 // Test matrix division by a factor for 2x2 matrices. |
|
1533 void tst_QMatrixNxN::divideFactor2x2_data() |
|
1534 { |
|
1535 // Use the same test cases as the multiplyFactor test. |
|
1536 multiplyFactor2x2_data(); |
|
1537 } |
|
1538 void tst_QMatrixNxN::divideFactor2x2() |
|
1539 { |
|
1540 QFETCH(void *, m1Values); |
|
1541 QFETCH(qreal, factor); |
|
1542 QFETCH(void *, m2Values); |
|
1543 |
|
1544 if (factor == 0.0f) |
|
1545 return; |
|
1546 |
|
1547 QMatrix2x2 m2((const qreal *)m2Values); |
|
1548 |
|
1549 QMatrix2x2 m3; |
|
1550 m3 = m2; |
|
1551 m3 /= factor; |
|
1552 QVERIFY(isSame(m3, (const qreal *)m1Values)); |
|
1553 |
|
1554 QMatrix2x2 m4; |
|
1555 m4 = m2 / factor; |
|
1556 QVERIFY(isSame(m4, (const qreal *)m1Values)); |
|
1557 } |
|
1558 |
|
1559 // Test matrix division by a factor for 3x3 matrices. |
|
1560 void tst_QMatrixNxN::divideFactor3x3_data() |
|
1561 { |
|
1562 // Use the same test cases as the multiplyFactor test. |
|
1563 multiplyFactor3x3_data(); |
|
1564 } |
|
1565 void tst_QMatrixNxN::divideFactor3x3() |
|
1566 { |
|
1567 QFETCH(void *, m1Values); |
|
1568 QFETCH(qreal, factor); |
|
1569 QFETCH(void *, m2Values); |
|
1570 |
|
1571 if (factor == 0.0f) |
|
1572 return; |
|
1573 |
|
1574 QMatrix3x3 m2((const qreal *)m2Values); |
|
1575 |
|
1576 QMatrix3x3 m3; |
|
1577 m3 = m2; |
|
1578 m3 /= factor; |
|
1579 QVERIFY(isSame(m3, (const qreal *)m1Values)); |
|
1580 |
|
1581 QMatrix3x3 m4; |
|
1582 m4 = m2 / factor; |
|
1583 QVERIFY(isSame(m4, (const qreal *)m1Values)); |
|
1584 } |
|
1585 |
|
1586 // Test matrix division by a factor for 4x4 matrices. |
|
1587 void tst_QMatrixNxN::divideFactor4x4_data() |
|
1588 { |
|
1589 // Use the same test cases as the multiplyFactor test. |
|
1590 multiplyFactor4x4_data(); |
|
1591 } |
|
1592 void tst_QMatrixNxN::divideFactor4x4() |
|
1593 { |
|
1594 QFETCH(void *, m1Values); |
|
1595 QFETCH(qreal, factor); |
|
1596 QFETCH(void *, m2Values); |
|
1597 |
|
1598 if (factor == 0.0f) |
|
1599 return; |
|
1600 |
|
1601 QMatrix4x4 m2((const qreal *)m2Values); |
|
1602 |
|
1603 QMatrix4x4 m3; |
|
1604 m3 = m2; |
|
1605 m3 /= factor; |
|
1606 QVERIFY(isSame(m3, (const qreal *)m1Values)); |
|
1607 |
|
1608 QMatrix4x4 m4; |
|
1609 m4 = m2 / factor; |
|
1610 QVERIFY(isSame(m4, (const qreal *)m1Values)); |
|
1611 } |
|
1612 |
|
1613 // Test matrix division by a factor for 4x3 matrices. |
|
1614 void tst_QMatrixNxN::divideFactor4x3_data() |
|
1615 { |
|
1616 // Use the same test cases as the multiplyFactor test. |
|
1617 multiplyFactor4x3_data(); |
|
1618 } |
|
1619 void tst_QMatrixNxN::divideFactor4x3() |
|
1620 { |
|
1621 QFETCH(void *, m1Values); |
|
1622 QFETCH(qreal, factor); |
|
1623 QFETCH(void *, m2Values); |
|
1624 |
|
1625 if (factor == 0.0f) |
|
1626 return; |
|
1627 |
|
1628 QMatrix4x3 m2((const qreal *)m2Values); |
|
1629 |
|
1630 QMatrix4x3 m3; |
|
1631 m3 = m2; |
|
1632 m3 /= factor; |
|
1633 QVERIFY(isSame(m3, (const qreal *)m1Values)); |
|
1634 |
|
1635 QMatrix4x3 m4; |
|
1636 m4 = m2 / factor; |
|
1637 QVERIFY(isSame(m4, (const qreal *)m1Values)); |
|
1638 } |
|
1639 |
|
1640 // Test matrix negation for 2x2 matrices. |
|
1641 void tst_QMatrixNxN::negate2x2_data() |
|
1642 { |
|
1643 // Use the same test cases as the multiplyFactor test. |
|
1644 multiplyFactor2x2_data(); |
|
1645 } |
|
1646 void tst_QMatrixNxN::negate2x2() |
|
1647 { |
|
1648 QFETCH(void *, m1Values); |
|
1649 |
|
1650 const qreal *values = (const qreal *)m1Values; |
|
1651 |
|
1652 QMatrix2x2 m1(values); |
|
1653 |
|
1654 qreal negated[4]; |
|
1655 for (int index = 0; index < 4; ++index) |
|
1656 negated[index] = -values[index]; |
|
1657 |
|
1658 QMatrix2x2 m2; |
|
1659 m2 = -m1; |
|
1660 QVERIFY(isSame(m2, negated)); |
|
1661 } |
|
1662 |
|
1663 // Test matrix negation for 3x3 matrices. |
|
1664 void tst_QMatrixNxN::negate3x3_data() |
|
1665 { |
|
1666 // Use the same test cases as the multiplyFactor test. |
|
1667 multiplyFactor3x3_data(); |
|
1668 } |
|
1669 void tst_QMatrixNxN::negate3x3() |
|
1670 { |
|
1671 QFETCH(void *, m1Values); |
|
1672 |
|
1673 const qreal *values = (const qreal *)m1Values; |
|
1674 |
|
1675 QMatrix3x3 m1(values); |
|
1676 |
|
1677 qreal negated[9]; |
|
1678 for (int index = 0; index < 9; ++index) |
|
1679 negated[index] = -values[index]; |
|
1680 |
|
1681 QMatrix3x3 m2; |
|
1682 m2 = -m1; |
|
1683 QVERIFY(isSame(m2, negated)); |
|
1684 } |
|
1685 |
|
1686 // Test matrix negation for 4x4 matrices. |
|
1687 void tst_QMatrixNxN::negate4x4_data() |
|
1688 { |
|
1689 // Use the same test cases as the multiplyFactor test. |
|
1690 multiplyFactor4x4_data(); |
|
1691 } |
|
1692 void tst_QMatrixNxN::negate4x4() |
|
1693 { |
|
1694 QFETCH(void *, m1Values); |
|
1695 |
|
1696 const qreal *values = (const qreal *)m1Values; |
|
1697 |
|
1698 QMatrix4x4 m1(values); |
|
1699 |
|
1700 qreal negated[16]; |
|
1701 for (int index = 0; index < 16; ++index) |
|
1702 negated[index] = -values[index]; |
|
1703 |
|
1704 QMatrix4x4 m2; |
|
1705 m2 = -m1; |
|
1706 QVERIFY(isSame(m2, negated)); |
|
1707 } |
|
1708 |
|
1709 // Test matrix negation for 4x3 matrices. |
|
1710 void tst_QMatrixNxN::negate4x3_data() |
|
1711 { |
|
1712 // Use the same test cases as the multiplyFactor test. |
|
1713 multiplyFactor4x3_data(); |
|
1714 } |
|
1715 void tst_QMatrixNxN::negate4x3() |
|
1716 { |
|
1717 QFETCH(void *, m1Values); |
|
1718 |
|
1719 const qreal *values = (const qreal *)m1Values; |
|
1720 |
|
1721 QMatrix4x3 m1(values); |
|
1722 |
|
1723 qreal negated[12]; |
|
1724 for (int index = 0; index < 12; ++index) |
|
1725 negated[index] = -values[index]; |
|
1726 |
|
1727 QMatrix4x3 m2; |
|
1728 m2 = -m1; |
|
1729 QVERIFY(isSame(m2, negated)); |
|
1730 } |
|
1731 |
|
1732 // Matrix inverted. This is a more straight-forward implementation |
|
1733 // of the algorithm at http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q24 |
|
1734 // than the optimized version in the QMatrix4x4 code. Hopefully it is |
|
1735 // easier to verify that this version is the same as the reference. |
|
1736 |
|
1737 struct Matrix3 |
|
1738 { |
|
1739 qreal v[9]; |
|
1740 }; |
|
1741 struct Matrix4 |
|
1742 { |
|
1743 qreal v[16]; |
|
1744 }; |
|
1745 |
|
1746 static qreal m3Determinant(const Matrix3& m) |
|
1747 { |
|
1748 return m.v[0] * (m.v[4] * m.v[8] - m.v[7] * m.v[5]) - |
|
1749 m.v[1] * (m.v[3] * m.v[8] - m.v[6] * m.v[5]) + |
|
1750 m.v[2] * (m.v[3] * m.v[7] - m.v[6] * m.v[4]); |
|
1751 } |
|
1752 |
|
1753 static bool m3Inverse(const Matrix3& min, Matrix3& mout) |
|
1754 { |
|
1755 qreal det = m3Determinant(min); |
|
1756 if (det == 0.0f) |
|
1757 return false; |
|
1758 mout.v[0] = (min.v[4] * min.v[8] - min.v[5] * min.v[7]) / det; |
|
1759 mout.v[1] = -(min.v[1] * min.v[8] - min.v[2] * min.v[7]) / det; |
|
1760 mout.v[2] = (min.v[1] * min.v[5] - min.v[4] * min.v[2]) / det; |
|
1761 mout.v[3] = -(min.v[3] * min.v[8] - min.v[5] * min.v[6]) / det; |
|
1762 mout.v[4] = (min.v[0] * min.v[8] - min.v[6] * min.v[2]) / det; |
|
1763 mout.v[5] = -(min.v[0] * min.v[5] - min.v[3] * min.v[2]) / det; |
|
1764 mout.v[6] = (min.v[3] * min.v[7] - min.v[6] * min.v[4]) / det; |
|
1765 mout.v[7] = -(min.v[0] * min.v[7] - min.v[6] * min.v[1]) / det; |
|
1766 mout.v[8] = (min.v[0] * min.v[4] - min.v[1] * min.v[3]) / det; |
|
1767 return true; |
|
1768 } |
|
1769 |
|
1770 static void m3Transpose(Matrix3& m) |
|
1771 { |
|
1772 qSwap(m.v[1], m.v[3]); |
|
1773 qSwap(m.v[2], m.v[6]); |
|
1774 qSwap(m.v[5], m.v[7]); |
|
1775 } |
|
1776 |
|
1777 static void m4Submatrix(const Matrix4& min, Matrix3& mout, int i, int j) |
|
1778 { |
|
1779 for (int di = 0; di < 3; ++di) { |
|
1780 for (int dj = 0; dj < 3; ++dj) { |
|
1781 int si = di + ((di >= i) ? 1 : 0); |
|
1782 int sj = dj + ((dj >= j) ? 1 : 0); |
|
1783 mout.v[di * 3 + dj] = min.v[si * 4 + sj]; |
|
1784 } |
|
1785 } |
|
1786 } |
|
1787 |
|
1788 static qreal m4Determinant(const Matrix4& m) |
|
1789 { |
|
1790 qreal det; |
|
1791 qreal result = 0.0f; |
|
1792 qreal i = 1.0f; |
|
1793 Matrix3 msub; |
|
1794 for (int n = 0; n < 4; ++n, i *= -1.0f) { |
|
1795 m4Submatrix(m, msub, 0, n); |
|
1796 det = m3Determinant(msub); |
|
1797 result += m.v[n] * det * i; |
|
1798 } |
|
1799 return result; |
|
1800 } |
|
1801 |
|
1802 static void m4Inverse(const Matrix4& min, Matrix4& mout) |
|
1803 { |
|
1804 qreal det = m4Determinant(min); |
|
1805 Matrix3 msub; |
|
1806 for (int i = 0; i < 4; ++i) { |
|
1807 for (int j = 0; j < 4; ++j) { |
|
1808 qreal sign = 1.0f - ((i + j) % 2) * 2.0f; |
|
1809 m4Submatrix(min, msub, i, j); |
|
1810 mout.v[i + j * 4] = (m3Determinant(msub) * sign) / det; |
|
1811 } |
|
1812 } |
|
1813 } |
|
1814 |
|
1815 // Test matrix inverted for 4x4 matrices. |
|
1816 void tst_QMatrixNxN::inverted4x4_data() |
|
1817 { |
|
1818 QTest::addColumn<void *>("m1Values"); |
|
1819 QTest::addColumn<void *>("m2Values"); |
|
1820 QTest::addColumn<bool>("invertible"); |
|
1821 |
|
1822 QTest::newRow("null") |
|
1823 << (void *)nullValues4 << (void *)identityValues4 << false; |
|
1824 |
|
1825 QTest::newRow("identity") |
|
1826 << (void *)identityValues4 << (void *)identityValues4 << true; |
|
1827 |
|
1828 QTest::newRow("unique") |
|
1829 << (void *)uniqueValues4 << (void *)identityValues4 << false; |
|
1830 |
|
1831 static Matrix4 const invertible = { |
|
1832 {5.0f, 0.0f, 0.0f, 2.0f, |
|
1833 0.0f, 6.0f, 0.0f, 3.0f, |
|
1834 0.0f, 0.0f, 7.0f, 4.0f, |
|
1835 0.0f, 0.0f, 0.0f, 1.0f} |
|
1836 }; |
|
1837 static Matrix4 inverted; |
|
1838 m4Inverse(invertible, inverted); |
|
1839 |
|
1840 QTest::newRow("invertible") |
|
1841 << (void *)invertible.v << (void *)inverted.v << true; |
|
1842 |
|
1843 static Matrix4 const translate = { |
|
1844 {1.0f, 0.0f, 0.0f, 2.0f, |
|
1845 0.0f, 1.0f, 0.0f, 3.0f, |
|
1846 0.0f, 0.0f, 1.0f, 4.0f, |
|
1847 0.0f, 0.0f, 0.0f, 1.0f} |
|
1848 }; |
|
1849 static Matrix4 const inverseTranslate = { |
|
1850 {1.0f, 0.0f, 0.0f, -2.0f, |
|
1851 0.0f, 1.0f, 0.0f, -3.0f, |
|
1852 0.0f, 0.0f, 1.0f, -4.0f, |
|
1853 0.0f, 0.0f, 0.0f, 1.0f} |
|
1854 }; |
|
1855 |
|
1856 QTest::newRow("translate") |
|
1857 << (void *)translate.v << (void *)inverseTranslate.v << true; |
|
1858 } |
|
1859 void tst_QMatrixNxN::inverted4x4() |
|
1860 { |
|
1861 QFETCH(void *, m1Values); |
|
1862 QFETCH(void *, m2Values); |
|
1863 QFETCH(bool, invertible); |
|
1864 |
|
1865 QMatrix4x4 m1((const qreal *)m1Values); |
|
1866 |
|
1867 if (invertible) |
|
1868 QVERIFY(m1.determinant() != 0.0f); |
|
1869 else |
|
1870 QVERIFY(m1.determinant() == 0.0f); |
|
1871 |
|
1872 Matrix4 m1alt; |
|
1873 memcpy(m1alt.v, (const qreal *)m1Values, sizeof(m1alt.v)); |
|
1874 |
|
1875 QCOMPARE(m1.determinant(), m4Determinant(m1alt)); |
|
1876 |
|
1877 QMatrix4x4 m2; |
|
1878 bool inv; |
|
1879 m2 = m1.inverted(&inv); |
|
1880 QVERIFY(isSame(m2, (const qreal *)m2Values)); |
|
1881 |
|
1882 if (invertible) { |
|
1883 QVERIFY(inv); |
|
1884 |
|
1885 Matrix4 m2alt; |
|
1886 m4Inverse(m1alt, m2alt); |
|
1887 QVERIFY(isSame(m2, m2alt.v)); |
|
1888 |
|
1889 QMatrix4x4 m3; |
|
1890 m3 = m1 * m2; |
|
1891 QVERIFY(isIdentity(m3)); |
|
1892 |
|
1893 QMatrix4x4 m4; |
|
1894 m4 = m2 * m1; |
|
1895 QVERIFY(isIdentity(m4)); |
|
1896 } else { |
|
1897 QVERIFY(!inv); |
|
1898 } |
|
1899 |
|
1900 // Test again, after inferring the special matrix type. |
|
1901 m1.inferSpecialType(); |
|
1902 m2 = m1.inverted(&inv); |
|
1903 QVERIFY(isSame(m2, (const qreal *)m2Values)); |
|
1904 QCOMPARE(inv, invertible); |
|
1905 } |
|
1906 |
|
1907 void tst_QMatrixNxN::orthonormalInverse4x4() |
|
1908 { |
|
1909 QMatrix4x4 m1; |
|
1910 QVERIFY(qFuzzyCompare(m1.inverted(), m1)); |
|
1911 |
|
1912 QMatrix4x4 m2; |
|
1913 m2.rotate(45.0, 1.0, 0.0, 0.0); |
|
1914 m2.translate(10.0, 0.0, 0.0); |
|
1915 |
|
1916 // Use inferSpecialType() to drop the internal flags that |
|
1917 // mark the matrix as orthonormal. This will force inverted() |
|
1918 // to compute m3.inverted() the long way. We can then compare |
|
1919 // the result to what the faster algorithm produces on m2. |
|
1920 QMatrix4x4 m3 = m2; |
|
1921 m3.inferSpecialType(); |
|
1922 bool invertible; |
|
1923 QVERIFY(qFuzzyCompare(m2.inverted(&invertible), m3.inverted())); |
|
1924 QVERIFY(invertible); |
|
1925 |
|
1926 QMatrix4x4 m4; |
|
1927 m4.rotate(45.0, 0.0, 1.0, 0.0); |
|
1928 QMatrix4x4 m5 = m4; |
|
1929 m5.inferSpecialType(); |
|
1930 QVERIFY(qFuzzyCompare(m4.inverted(), m5.inverted())); |
|
1931 |
|
1932 QMatrix4x4 m6; |
|
1933 m1.rotate(88, 0.0, 0.0, 1.0); |
|
1934 m1.translate(-20.0, 20.0, 15.0); |
|
1935 m1.rotate(25, 1.0, 0.0, 0.0); |
|
1936 QMatrix4x4 m7 = m6; |
|
1937 m7.inferSpecialType(); |
|
1938 QVERIFY(qFuzzyCompare(m6.inverted(), m7.inverted())); |
|
1939 } |
|
1940 |
|
1941 // Test the generation and use of 4x4 scale matrices. |
|
1942 void tst_QMatrixNxN::scale4x4_data() |
|
1943 { |
|
1944 QTest::addColumn<qreal>("x"); |
|
1945 QTest::addColumn<qreal>("y"); |
|
1946 QTest::addColumn<qreal>("z"); |
|
1947 QTest::addColumn<void *>("resultValues"); |
|
1948 |
|
1949 static const qreal nullScale[] = |
|
1950 {0.0f, 0.0f, 0.0f, 0.0f, |
|
1951 0.0f, 0.0f, 0.0f, 0.0f, |
|
1952 0.0f, 0.0f, 0.0f, 0.0f, |
|
1953 0.0f, 0.0f, 0.0f, 1.0f}; |
|
1954 QTest::newRow("null") |
|
1955 << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (void *)nullScale; |
|
1956 |
|
1957 QTest::newRow("identity") |
|
1958 << (qreal)1.0f << (qreal)1.0f << (qreal)1.0f << (void *)identityValues4; |
|
1959 |
|
1960 static const qreal doubleScale[] = |
|
1961 {2.0f, 0.0f, 0.0f, 0.0f, |
|
1962 0.0f, 2.0f, 0.0f, 0.0f, |
|
1963 0.0f, 0.0f, 2.0f, 0.0f, |
|
1964 0.0f, 0.0f, 0.0f, 1.0f}; |
|
1965 QTest::newRow("double") |
|
1966 << (qreal)2.0f << (qreal)2.0f << (qreal)2.0f << (void *)doubleScale; |
|
1967 |
|
1968 static const qreal complexScale[] = |
|
1969 {2.0f, 0.0f, 0.0f, 0.0f, |
|
1970 0.0f, 11.0f, 0.0f, 0.0f, |
|
1971 0.0f, 0.0f, -6.5f, 0.0f, |
|
1972 0.0f, 0.0f, 0.0f, 1.0f}; |
|
1973 QTest::newRow("complex") |
|
1974 << (qreal)2.0f << (qreal)11.0f << (qreal)-6.5f << (void *)complexScale; |
|
1975 |
|
1976 static const qreal complexScale2D[] = |
|
1977 {2.0f, 0.0f, 0.0f, 0.0f, |
|
1978 0.0f, -11.0f, 0.0f, 0.0f, |
|
1979 0.0f, 0.0f, 1.0f, 0.0f, |
|
1980 0.0f, 0.0f, 0.0f, 1.0f}; |
|
1981 QTest::newRow("complex2D") |
|
1982 << (qreal)2.0f << (qreal)-11.0f << (qreal)1.0f << (void *)complexScale2D; |
|
1983 } |
|
1984 void tst_QMatrixNxN::scale4x4() |
|
1985 { |
|
1986 QFETCH(qreal, x); |
|
1987 QFETCH(qreal, y); |
|
1988 QFETCH(qreal, z); |
|
1989 QFETCH(void *, resultValues); |
|
1990 |
|
1991 QMatrix4x4 result((const qreal *)resultValues); |
|
1992 |
|
1993 QMatrix4x4 m1; |
|
1994 m1.scale(QVector3D(x, y, z)); |
|
1995 QVERIFY(isSame(m1, (const qreal *)resultValues)); |
|
1996 |
|
1997 QMatrix4x4 m2; |
|
1998 m2.scale(x, y, z); |
|
1999 QVERIFY(isSame(m2, (const qreal *)resultValues)); |
|
2000 |
|
2001 if (z == 1.0f) { |
|
2002 QMatrix4x4 m2b; |
|
2003 m2b.scale(x, y); |
|
2004 QVERIFY(m2b == m2); |
|
2005 } |
|
2006 |
|
2007 QVector3D v1(2.0f, 3.0f, -4.0f); |
|
2008 QVector3D v2 = m1 * v1; |
|
2009 QCOMPARE(v2.x(), (qreal)(2.0f * x)); |
|
2010 QCOMPARE(v2.y(), (qreal)(3.0f * y)); |
|
2011 QCOMPARE(v2.z(), (qreal)(-4.0f * z)); |
|
2012 |
|
2013 v2 = v1 * m1; |
|
2014 QCOMPARE(v2.x(), (qreal)(2.0f * x)); |
|
2015 QCOMPARE(v2.y(), (qreal)(3.0f * y)); |
|
2016 QCOMPARE(v2.z(), (qreal)(-4.0f * z)); |
|
2017 |
|
2018 QVector4D v3(2.0f, 3.0f, -4.0f, 34.0f); |
|
2019 QVector4D v4 = m1 * v3; |
|
2020 QCOMPARE(v4.x(), (qreal)(2.0f * x)); |
|
2021 QCOMPARE(v4.y(), (qreal)(3.0f * y)); |
|
2022 QCOMPARE(v4.z(), (qreal)(-4.0f * z)); |
|
2023 QCOMPARE(v4.w(), (qreal)34.0f); |
|
2024 |
|
2025 v4 = v3 * m1; |
|
2026 QCOMPARE(v4.x(), (qreal)(2.0f * x)); |
|
2027 QCOMPARE(v4.y(), (qreal)(3.0f * y)); |
|
2028 QCOMPARE(v4.z(), (qreal)(-4.0f * z)); |
|
2029 QCOMPARE(v4.w(), (qreal)34.0f); |
|
2030 |
|
2031 QPoint p1(2, 3); |
|
2032 QPoint p2 = m1 * p1; |
|
2033 QCOMPARE(p2.x(), (int)(2.0f * x)); |
|
2034 QCOMPARE(p2.y(), (int)(3.0f * y)); |
|
2035 |
|
2036 p2 = p1 * m1; |
|
2037 QCOMPARE(p2.x(), (int)(2.0f * x)); |
|
2038 QCOMPARE(p2.y(), (int)(3.0f * y)); |
|
2039 |
|
2040 QPointF p3(2.0f, 3.0f); |
|
2041 QPointF p4 = m1 * p3; |
|
2042 QCOMPARE(p4.x(), (qreal)(2.0f * x)); |
|
2043 QCOMPARE(p4.y(), (qreal)(3.0f * y)); |
|
2044 |
|
2045 p4 = p3 * m1; |
|
2046 QCOMPARE(p4.x(), (qreal)(2.0f * x)); |
|
2047 QCOMPARE(p4.y(), (qreal)(3.0f * y)); |
|
2048 |
|
2049 QMatrix4x4 m3(uniqueValues4); |
|
2050 QMatrix4x4 m4(m3); |
|
2051 m4.scale(x, y, z); |
|
2052 QVERIFY(m4 == m3 * m1); |
|
2053 |
|
2054 if (x == y && y == z) { |
|
2055 QMatrix4x4 m5; |
|
2056 m5.scale(x); |
|
2057 QVERIFY(isSame(m5, (const qreal *)resultValues)); |
|
2058 } |
|
2059 |
|
2060 if (z == 1.0f) { |
|
2061 QMatrix4x4 m4b(m3); |
|
2062 m4b.scale(x, y); |
|
2063 QVERIFY(m4b == m4); |
|
2064 } |
|
2065 |
|
2066 // Test coverage when the special matrix type is unknown. |
|
2067 |
|
2068 QMatrix4x4 m6; |
|
2069 m6(0, 0) = 1.0f; |
|
2070 m6.scale(QVector3D(x, y, z)); |
|
2071 QVERIFY(isSame(m6, (const qreal *)resultValues)); |
|
2072 |
|
2073 QMatrix4x4 m7; |
|
2074 m7(0, 0) = 1.0f; |
|
2075 m7.scale(x, y, z); |
|
2076 QVERIFY(isSame(m7, (const qreal *)resultValues)); |
|
2077 |
|
2078 if (x == y && y == z) { |
|
2079 QMatrix4x4 m8; |
|
2080 m8(0, 0) = 1.0f; |
|
2081 m8.scale(x); |
|
2082 QVERIFY(isSame(m8, (const qreal *)resultValues)); |
|
2083 |
|
2084 m8.inferSpecialType(); |
|
2085 m8.scale(1.0f); |
|
2086 QVERIFY(isSame(m8, (const qreal *)resultValues)); |
|
2087 |
|
2088 QMatrix4x4 m9; |
|
2089 m9.translate(0.0f, 0.0f, 0.0f); |
|
2090 m9.scale(x); |
|
2091 QVERIFY(isSame(m9, (const qreal *)resultValues)); |
|
2092 } |
|
2093 } |
|
2094 |
|
2095 // Test the generation and use of 4x4 translation matrices. |
|
2096 void tst_QMatrixNxN::translate4x4_data() |
|
2097 { |
|
2098 QTest::addColumn<qreal>("x"); |
|
2099 QTest::addColumn<qreal>("y"); |
|
2100 QTest::addColumn<qreal>("z"); |
|
2101 QTest::addColumn<void *>("resultValues"); |
|
2102 |
|
2103 QTest::newRow("null") |
|
2104 << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (void *)identityValues4; |
|
2105 |
|
2106 static const qreal identityTranslate[] = |
|
2107 {1.0f, 0.0f, 0.0f, 1.0f, |
|
2108 0.0f, 1.0f, 0.0f, 1.0f, |
|
2109 0.0f, 0.0f, 1.0f, 1.0f, |
|
2110 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2111 QTest::newRow("identity") |
|
2112 << (qreal)1.0f << (qreal)1.0f << (qreal)1.0f << (void *)identityTranslate; |
|
2113 |
|
2114 static const qreal complexTranslate[] = |
|
2115 {1.0f, 0.0f, 0.0f, 2.0f, |
|
2116 0.0f, 1.0f, 0.0f, 11.0f, |
|
2117 0.0f, 0.0f, 1.0f, -6.5f, |
|
2118 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2119 QTest::newRow("complex") |
|
2120 << (qreal)2.0f << (qreal)11.0f << (qreal)-6.5f << (void *)complexTranslate; |
|
2121 |
|
2122 static const qreal complexTranslate2D[] = |
|
2123 {1.0f, 0.0f, 0.0f, 2.0f, |
|
2124 0.0f, 1.0f, 0.0f, -11.0f, |
|
2125 0.0f, 0.0f, 1.0f, 0.0f, |
|
2126 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2127 QTest::newRow("complex2D") |
|
2128 << (qreal)2.0f << (qreal)-11.0f << (qreal)0.0f << (void *)complexTranslate2D; |
|
2129 } |
|
2130 void tst_QMatrixNxN::translate4x4() |
|
2131 { |
|
2132 QFETCH(qreal, x); |
|
2133 QFETCH(qreal, y); |
|
2134 QFETCH(qreal, z); |
|
2135 QFETCH(void *, resultValues); |
|
2136 |
|
2137 QMatrix4x4 result((const qreal *)resultValues); |
|
2138 |
|
2139 QMatrix4x4 m1; |
|
2140 m1.translate(QVector3D(x, y, z)); |
|
2141 QVERIFY(isSame(m1, (const qreal *)resultValues)); |
|
2142 |
|
2143 QMatrix4x4 m2; |
|
2144 m2.translate(x, y, z); |
|
2145 QVERIFY(isSame(m2, (const qreal *)resultValues)); |
|
2146 |
|
2147 if (z == 0.0f) { |
|
2148 QMatrix4x4 m2b; |
|
2149 m2b.translate(x, y); |
|
2150 QVERIFY(m2b == m2); |
|
2151 } |
|
2152 |
|
2153 QVector3D v1(2.0f, 3.0f, -4.0f); |
|
2154 QVector3D v2 = m1 * v1; |
|
2155 QCOMPARE(v2.x(), (qreal)(2.0f + x)); |
|
2156 QCOMPARE(v2.y(), (qreal)(3.0f + y)); |
|
2157 QCOMPARE(v2.z(), (qreal)(-4.0f + z)); |
|
2158 |
|
2159 QVector4D v3(2.0f, 3.0f, -4.0f, 1.0f); |
|
2160 QVector4D v4 = m1 * v3; |
|
2161 QCOMPARE(v4.x(), (qreal)(2.0f + x)); |
|
2162 QCOMPARE(v4.y(), (qreal)(3.0f + y)); |
|
2163 QCOMPARE(v4.z(), (qreal)(-4.0f + z)); |
|
2164 QCOMPARE(v4.w(), (qreal)1.0f); |
|
2165 |
|
2166 QVector4D v5(2.0f, 3.0f, -4.0f, 34.0f); |
|
2167 QVector4D v6 = m1 * v5; |
|
2168 QCOMPARE(v6.x(), (qreal)(2.0f + x * 34.0f)); |
|
2169 QCOMPARE(v6.y(), (qreal)(3.0f + y * 34.0f)); |
|
2170 QCOMPARE(v6.z(), (qreal)(-4.0f + z * 34.0f)); |
|
2171 QCOMPARE(v6.w(), (qreal)34.0f); |
|
2172 |
|
2173 QPoint p1(2, 3); |
|
2174 QPoint p2 = m1 * p1; |
|
2175 QCOMPARE(p2.x(), (int)(2.0f + x)); |
|
2176 QCOMPARE(p2.y(), (int)(3.0f + y)); |
|
2177 |
|
2178 QPointF p3(2.0f, 3.0f); |
|
2179 QPointF p4 = m1 * p3; |
|
2180 QCOMPARE(p4.x(), (qreal)(2.0f + x)); |
|
2181 QCOMPARE(p4.y(), (qreal)(3.0f + y)); |
|
2182 |
|
2183 QMatrix4x4 m3(uniqueValues4); |
|
2184 QMatrix4x4 m4(m3); |
|
2185 m4.translate(x, y, z); |
|
2186 QVERIFY(m4 == m3 * m1); |
|
2187 |
|
2188 if (z == 0.0f) { |
|
2189 QMatrix4x4 m4b(m3); |
|
2190 m4b.translate(x, y); |
|
2191 QVERIFY(m4b == m4); |
|
2192 } |
|
2193 } |
|
2194 |
|
2195 // Test the generation and use of 4x4 rotation matrices. |
|
2196 void tst_QMatrixNxN::rotate4x4_data() |
|
2197 { |
|
2198 QTest::addColumn<qreal>("angle"); |
|
2199 QTest::addColumn<qreal>("x"); |
|
2200 QTest::addColumn<qreal>("y"); |
|
2201 QTest::addColumn<qreal>("z"); |
|
2202 QTest::addColumn<void *>("resultValues"); |
|
2203 |
|
2204 static const qreal nullRotate[] = |
|
2205 {0.0f, 0.0f, 0.0f, 0.0f, |
|
2206 0.0f, 0.0f, 0.0f, 0.0f, |
|
2207 0.0f, 0.0f, 0.0f, 0.0f, |
|
2208 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2209 QTest::newRow("null") |
|
2210 << (qreal)90.0f |
|
2211 << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f |
|
2212 << (void *)nullRotate; |
|
2213 |
|
2214 static const qreal noRotate[] = |
|
2215 {1.0f, 0.0f, 0.0f, 0.0f, |
|
2216 0.0f, 1.0f, 0.0f, 0.0f, |
|
2217 0.0f, 0.0f, 1.0f, 0.0f, |
|
2218 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2219 QTest::newRow("zerodegrees") |
|
2220 << (qreal)0.0f |
|
2221 << (qreal)2.0f << (qreal)3.0f << (qreal)-4.0f |
|
2222 << (void *)noRotate; |
|
2223 |
|
2224 static const qreal xRotate[] = |
|
2225 {1.0f, 0.0f, 0.0f, 0.0f, |
|
2226 0.0f, 0.0f, -1.0f, 0.0f, |
|
2227 0.0f, 1.0f, 0.0f, 0.0f, |
|
2228 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2229 QTest::newRow("xrotate") |
|
2230 << (qreal)90.0f |
|
2231 << (qreal)1.0f << (qreal)0.0f << (qreal)0.0f |
|
2232 << (void *)xRotate; |
|
2233 |
|
2234 static const qreal xRotateNeg[] = |
|
2235 {1.0f, 0.0f, 0.0f, 0.0f, |
|
2236 0.0f, 0.0f, 1.0f, 0.0f, |
|
2237 0.0f, -1.0f, 0.0f, 0.0f, |
|
2238 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2239 QTest::newRow("-xrotate") |
|
2240 << (qreal)90.0f |
|
2241 << (qreal)-1.0f << (qreal)0.0f << (qreal)0.0f |
|
2242 << (void *)xRotateNeg; |
|
2243 |
|
2244 static const qreal yRotate[] = |
|
2245 {0.0f, 0.0f, 1.0f, 0.0f, |
|
2246 0.0f, 1.0f, 0.0f, 0.0f, |
|
2247 -1.0f, 0.0f, 0.0f, 0.0f, |
|
2248 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2249 QTest::newRow("yrotate") |
|
2250 << (qreal)90.0f |
|
2251 << (qreal)0.0f << (qreal)1.0f << (qreal)0.0f |
|
2252 << (void *)yRotate; |
|
2253 |
|
2254 static const qreal yRotateNeg[] = |
|
2255 {0.0f, 0.0f, -1.0f, 0.0f, |
|
2256 0.0f, 1.0f, 0.0f, 0.0f, |
|
2257 1.0f, 0.0f, 0.0f, 0.0f, |
|
2258 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2259 QTest::newRow("-yrotate") |
|
2260 << (qreal)90.0f |
|
2261 << (qreal)0.0f << (qreal)-1.0f << (qreal)0.0f |
|
2262 << (void *)yRotateNeg; |
|
2263 |
|
2264 static const qreal zRotate[] = |
|
2265 {0.0f, -1.0f, 0.0f, 0.0f, |
|
2266 1.0f, 0.0f, 0.0f, 0.0f, |
|
2267 0.0f, 0.0f, 1.0f, 0.0f, |
|
2268 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2269 QTest::newRow("zrotate") |
|
2270 << (qreal)90.0f |
|
2271 << (qreal)0.0f << (qreal)0.0f << (qreal)1.0f |
|
2272 << (void *)zRotate; |
|
2273 |
|
2274 static const qreal zRotateNeg[] = |
|
2275 {0.0f, 1.0f, 0.0f, 0.0f, |
|
2276 -1.0f, 0.0f, 0.0f, 0.0f, |
|
2277 0.0f, 0.0f, 1.0f, 0.0f, |
|
2278 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2279 QTest::newRow("-zrotate") |
|
2280 << (qreal)90.0f |
|
2281 << (qreal)0.0f << (qreal)0.0f << (qreal)-1.0f |
|
2282 << (void *)zRotateNeg; |
|
2283 |
|
2284 // Algorithm from http://en.wikipedia.org/wiki/Rotation_matrix. |
|
2285 // Deliberately different from the one in the code for cross-checking. |
|
2286 static qreal complexRotate[16]; |
|
2287 qreal x = 1.0f; |
|
2288 qreal y = 2.0f; |
|
2289 qreal z = -6.0f; |
|
2290 qreal angle = -45.0f; |
|
2291 qreal c = qCos(angle * M_PI / 180.0f); |
|
2292 qreal s = qSin(angle * M_PI / 180.0f); |
|
2293 qreal len = qSqrt(x * x + y * y + z * z); |
|
2294 qreal xu = x / len; |
|
2295 qreal yu = y / len; |
|
2296 qreal zu = z / len; |
|
2297 complexRotate[0] = (qreal)((1 - xu * xu) * c + xu * xu); |
|
2298 complexRotate[1] = (qreal)(-zu * s - xu * yu * c + xu * yu); |
|
2299 complexRotate[2] = (qreal)(yu * s - xu * zu * c + xu * zu); |
|
2300 complexRotate[3] = 0; |
|
2301 complexRotate[4] = (qreal)(zu * s - xu * yu * c + xu * yu); |
|
2302 complexRotate[5] = (qreal)((1 - yu * yu) * c + yu * yu); |
|
2303 complexRotate[6] = (qreal)(-xu * s - yu * zu * c + yu * zu); |
|
2304 complexRotate[7] = 0; |
|
2305 complexRotate[8] = (qreal)(-yu * s - xu * zu * c + xu * zu); |
|
2306 complexRotate[9] = (qreal)(xu * s - yu * zu * c + yu * zu); |
|
2307 complexRotate[10] = (qreal)((1 - zu * zu) * c + zu * zu); |
|
2308 complexRotate[11] = 0; |
|
2309 complexRotate[12] = 0; |
|
2310 complexRotate[13] = 0; |
|
2311 complexRotate[14] = 0; |
|
2312 complexRotate[15] = 1; |
|
2313 |
|
2314 QTest::newRow("complex") |
|
2315 << (qreal)angle |
|
2316 << (qreal)x << (qreal)y << (qreal)z |
|
2317 << (void *)complexRotate; |
|
2318 } |
|
2319 void tst_QMatrixNxN::rotate4x4() |
|
2320 { |
|
2321 QFETCH(qreal, angle); |
|
2322 QFETCH(qreal, x); |
|
2323 QFETCH(qreal, y); |
|
2324 QFETCH(qreal, z); |
|
2325 QFETCH(void *, resultValues); |
|
2326 |
|
2327 QMatrix4x4 m1; |
|
2328 m1.rotate(angle, QVector3D(x, y, z)); |
|
2329 QVERIFY(isSame(m1, (const qreal *)resultValues)); |
|
2330 |
|
2331 QMatrix4x4 m2; |
|
2332 m2.rotate(angle, x, y, z); |
|
2333 QVERIFY(isSame(m2, (const qreal *)resultValues)); |
|
2334 |
|
2335 QMatrix4x4 m3(uniqueValues4); |
|
2336 QMatrix4x4 m4(m3); |
|
2337 m4.rotate(angle, x, y, z); |
|
2338 QVERIFY(qFuzzyCompare(m4, m3 * m1)); |
|
2339 |
|
2340 // Null vectors don't make sense for quaternion rotations. |
|
2341 if (x != 0 || y != 0 || z != 0) { |
|
2342 QMatrix4x4 m5; |
|
2343 m5.rotate(QQuaternion::fromAxisAndAngle(QVector3D(x, y, z), angle)); |
|
2344 QVERIFY(isSame(m5, (const qreal *)resultValues)); |
|
2345 } |
|
2346 |
|
2347 #define ROTATE4(xin,yin,zin,win,xout,yout,zout,wout) \ |
|
2348 do { \ |
|
2349 xout = ((const qreal *)resultValues)[0] * xin + \ |
|
2350 ((const qreal *)resultValues)[1] * yin + \ |
|
2351 ((const qreal *)resultValues)[2] * zin + \ |
|
2352 ((const qreal *)resultValues)[3] * win; \ |
|
2353 yout = ((const qreal *)resultValues)[4] * xin + \ |
|
2354 ((const qreal *)resultValues)[5] * yin + \ |
|
2355 ((const qreal *)resultValues)[6] * zin + \ |
|
2356 ((const qreal *)resultValues)[7] * win; \ |
|
2357 zout = ((const qreal *)resultValues)[8] * xin + \ |
|
2358 ((const qreal *)resultValues)[9] * yin + \ |
|
2359 ((const qreal *)resultValues)[10] * zin + \ |
|
2360 ((const qreal *)resultValues)[11] * win; \ |
|
2361 wout = ((const qreal *)resultValues)[12] * xin + \ |
|
2362 ((const qreal *)resultValues)[13] * yin + \ |
|
2363 ((const qreal *)resultValues)[14] * zin + \ |
|
2364 ((const qreal *)resultValues)[15] * win; \ |
|
2365 } while (0) |
|
2366 |
|
2367 // Rotate various test vectors using the straight-forward approach. |
|
2368 qreal v1x, v1y, v1z, v1w; |
|
2369 ROTATE4(2.0f, 3.0f, -4.0f, 1.0f, v1x, v1y, v1z, v1w); |
|
2370 v1x /= v1w; |
|
2371 v1y /= v1w; |
|
2372 v1z /= v1w; |
|
2373 qreal v3x, v3y, v3z, v3w; |
|
2374 ROTATE4(2.0f, 3.0f, -4.0f, 1.0f, v3x, v3y, v3z, v3w); |
|
2375 qreal v5x, v5y, v5z, v5w; |
|
2376 ROTATE4(2.0f, 3.0f, -4.0f, 34.0f, v5x, v5y, v5z, v5w); |
|
2377 qreal p1x, p1y, p1z, p1w; |
|
2378 ROTATE4(2.0f, 3.0f, 0.0f, 1.0f, p1x, p1y, p1z, p1w); |
|
2379 p1x /= p1w; |
|
2380 p1y /= p1w; |
|
2381 p1z /= p1w; |
|
2382 |
|
2383 QVector3D v1(2.0f, 3.0f, -4.0f); |
|
2384 QVector3D v2 = m1 * v1; |
|
2385 QVERIFY(fuzzyCompare(v2.x(), v1x)); |
|
2386 QVERIFY(fuzzyCompare(v2.y(), v1y)); |
|
2387 QVERIFY(fuzzyCompare(v2.z(), v1z)); |
|
2388 |
|
2389 QVector4D v3(2.0f, 3.0f, -4.0f, 1.0f); |
|
2390 QVector4D v4 = m1 * v3; |
|
2391 QVERIFY(fuzzyCompare(v4.x(), v3x)); |
|
2392 QVERIFY(fuzzyCompare(v4.y(), v3y)); |
|
2393 QVERIFY(fuzzyCompare(v4.z(), v3z)); |
|
2394 QVERIFY(fuzzyCompare(v4.w(), v3w)); |
|
2395 |
|
2396 QVector4D v5(2.0f, 3.0f, -4.0f, 34.0f); |
|
2397 QVector4D v6 = m1 * v5; |
|
2398 QVERIFY(fuzzyCompare(v6.x(), v5x)); |
|
2399 QVERIFY(fuzzyCompare(v6.y(), v5y)); |
|
2400 QVERIFY(fuzzyCompare(v6.z(), v5z)); |
|
2401 QVERIFY(fuzzyCompare(v6.w(), v5w)); |
|
2402 |
|
2403 QPoint p1(2, 3); |
|
2404 QPoint p2 = m1 * p1; |
|
2405 QCOMPARE(p2.x(), qRound(p1x)); |
|
2406 QCOMPARE(p2.y(), qRound(p1y)); |
|
2407 |
|
2408 QPointF p3(2.0f, 3.0f); |
|
2409 QPointF p4 = m1 * p3; |
|
2410 QVERIFY(fuzzyCompare(p4.x(), p1x)); |
|
2411 QVERIFY(fuzzyCompare(p4.y(), p1y)); |
|
2412 |
|
2413 if (x != 0 || y != 0 || z != 0) { |
|
2414 QQuaternion q = QQuaternion::fromAxisAndAngle(QVector3D(x, y, z), angle); |
|
2415 QVector3D vq = q.rotateVector(v1); |
|
2416 QVERIFY(fuzzyCompare(vq.x(), v1x)); |
|
2417 QVERIFY(fuzzyCompare(vq.y(), v1y)); |
|
2418 QVERIFY(fuzzyCompare(vq.z(), v1z)); |
|
2419 } |
|
2420 } |
|
2421 |
|
2422 static bool isSame(const QMatrix3x3& m1, const Matrix3& m2) |
|
2423 { |
|
2424 for (int row = 0; row < 3; ++row) { |
|
2425 for (int col = 0; col < 3; ++col) { |
|
2426 if (!fuzzyCompare(m1(row, col), m2.v[row * 3 + col])) |
|
2427 return false; |
|
2428 } |
|
2429 } |
|
2430 return true; |
|
2431 } |
|
2432 |
|
2433 // Test the computation of normal matrices from 4x4 transformation matrices. |
|
2434 void tst_QMatrixNxN::normalMatrix_data() |
|
2435 { |
|
2436 QTest::addColumn<void *>("mValues"); |
|
2437 |
|
2438 QTest::newRow("identity") |
|
2439 << (void *)identityValues4; |
|
2440 QTest::newRow("unique") |
|
2441 << (void *)uniqueValues4; // Not invertible because determinant == 0. |
|
2442 |
|
2443 static qreal const translateValues[16] = |
|
2444 {1.0f, 0.0f, 0.0f, 4.0f, |
|
2445 0.0f, 1.0f, 0.0f, 5.0f, |
|
2446 0.0f, 0.0f, 1.0f, -3.0f, |
|
2447 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2448 static qreal const scaleValues[16] = |
|
2449 {2.0f, 0.0f, 0.0f, 0.0f, |
|
2450 0.0f, 7.0f, 0.0f, 0.0f, |
|
2451 0.0f, 0.0f, 9.0f, 0.0f, |
|
2452 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2453 static qreal const bothValues[16] = |
|
2454 {2.0f, 0.0f, 0.0f, 4.0f, |
|
2455 0.0f, 7.0f, 0.0f, 5.0f, |
|
2456 0.0f, 0.0f, 9.0f, -3.0f, |
|
2457 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2458 static qreal const nullScaleValues1[16] = |
|
2459 {0.0f, 0.0f, 0.0f, 4.0f, |
|
2460 0.0f, 7.0f, 0.0f, 5.0f, |
|
2461 0.0f, 0.0f, 9.0f, -3.0f, |
|
2462 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2463 static qreal const nullScaleValues2[16] = |
|
2464 {2.0f, 0.0f, 0.0f, 4.0f, |
|
2465 0.0f, 0.0f, 0.0f, 5.0f, |
|
2466 0.0f, 0.0f, 9.0f, -3.0f, |
|
2467 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2468 static qreal const nullScaleValues3[16] = |
|
2469 {2.0f, 0.0f, 0.0f, 4.0f, |
|
2470 0.0f, 7.0f, 0.0f, 5.0f, |
|
2471 0.0f, 0.0f, 0.0f, -3.0f, |
|
2472 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2473 |
|
2474 QTest::newRow("translate") << (void *)translateValues; |
|
2475 QTest::newRow("scale") << (void *)scaleValues; |
|
2476 QTest::newRow("both") << (void *)bothValues; |
|
2477 QTest::newRow("null scale 1") << (void *)nullScaleValues1; |
|
2478 QTest::newRow("null scale 2") << (void *)nullScaleValues2; |
|
2479 QTest::newRow("null scale 3") << (void *)nullScaleValues3; |
|
2480 } |
|
2481 void tst_QMatrixNxN::normalMatrix() |
|
2482 { |
|
2483 QFETCH(void *, mValues); |
|
2484 const qreal *values = (const qreal *)mValues; |
|
2485 |
|
2486 // Compute the expected answer the long way. |
|
2487 Matrix3 min; |
|
2488 Matrix3 answer; |
|
2489 min.v[0] = values[0]; |
|
2490 min.v[1] = values[1]; |
|
2491 min.v[2] = values[2]; |
|
2492 min.v[3] = values[4]; |
|
2493 min.v[4] = values[5]; |
|
2494 min.v[5] = values[6]; |
|
2495 min.v[6] = values[8]; |
|
2496 min.v[7] = values[9]; |
|
2497 min.v[8] = values[10]; |
|
2498 bool invertible = m3Inverse(min, answer); |
|
2499 m3Transpose(answer); |
|
2500 |
|
2501 // Perform the test. |
|
2502 QMatrix4x4 m1(values); |
|
2503 QMatrix3x3 n1 = m1.normalMatrix(); |
|
2504 |
|
2505 if (invertible) |
|
2506 QVERIFY(::isSame(n1, answer)); |
|
2507 else |
|
2508 QVERIFY(isIdentity(n1)); |
|
2509 |
|
2510 // Perform the test again, after inferring special matrix types. |
|
2511 // This tests the optimized paths in the normalMatrix() function. |
|
2512 m1.inferSpecialType(); |
|
2513 n1 = m1.normalMatrix(); |
|
2514 |
|
2515 if (invertible) |
|
2516 QVERIFY(::isSame(n1, answer)); |
|
2517 else |
|
2518 QVERIFY(isIdentity(n1)); |
|
2519 } |
|
2520 |
|
2521 // Test optimized transformations on 4x4 matrices. |
|
2522 void tst_QMatrixNxN::optimizedTransforms() |
|
2523 { |
|
2524 static qreal const translateValues[16] = |
|
2525 {1.0f, 0.0f, 0.0f, 4.0f, |
|
2526 0.0f, 1.0f, 0.0f, 5.0f, |
|
2527 0.0f, 0.0f, 1.0f, -3.0f, |
|
2528 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2529 static qreal const translateDoubleValues[16] = |
|
2530 {1.0f, 0.0f, 0.0f, 8.0f, |
|
2531 0.0f, 1.0f, 0.0f, 10.0f, |
|
2532 0.0f, 0.0f, 1.0f, -6.0f, |
|
2533 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2534 static qreal const scaleValues[16] = |
|
2535 {2.0f, 0.0f, 0.0f, 0.0f, |
|
2536 0.0f, 7.0f, 0.0f, 0.0f, |
|
2537 0.0f, 0.0f, 9.0f, 0.0f, |
|
2538 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2539 static qreal const scaleDoubleValues[16] = |
|
2540 {4.0f, 0.0f, 0.0f, 0.0f, |
|
2541 0.0f, 49.0f, 0.0f, 0.0f, |
|
2542 0.0f, 0.0f, 81.0f, 0.0f, |
|
2543 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2544 static qreal const bothValues[16] = |
|
2545 {2.0f, 0.0f, 0.0f, 4.0f, |
|
2546 0.0f, 7.0f, 0.0f, 5.0f, |
|
2547 0.0f, 0.0f, 9.0f, -3.0f, |
|
2548 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2549 static qreal const bothReverseValues[16] = |
|
2550 {2.0f, 0.0f, 0.0f, 4.0f * 2.0f, |
|
2551 0.0f, 7.0f, 0.0f, 5.0f * 7.0f, |
|
2552 0.0f, 0.0f, 9.0f, -3.0f * 9.0f, |
|
2553 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2554 static qreal const bothThenTranslateValues[16] = |
|
2555 {2.0f, 0.0f, 0.0f, 4.0f + 2.0f * 4.0f, |
|
2556 0.0f, 7.0f, 0.0f, 5.0f + 7.0f * 5.0f, |
|
2557 0.0f, 0.0f, 9.0f, -3.0f + 9.0f * -3.0f, |
|
2558 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2559 static qreal const bothThenScaleValues[16] = |
|
2560 {4.0f, 0.0f, 0.0f, 4.0f, |
|
2561 0.0f, 49.0f, 0.0f, 5.0f, |
|
2562 0.0f, 0.0f, 81.0f, -3.0f, |
|
2563 0.0f, 0.0f, 0.0f, 1.0f}; |
|
2564 |
|
2565 QMatrix4x4 translate(translateValues); |
|
2566 QMatrix4x4 scale(scaleValues); |
|
2567 QMatrix4x4 both(bothValues); |
|
2568 |
|
2569 QMatrix4x4 m1; |
|
2570 m1.translate(4.0f, 5.0f, -3.0f); |
|
2571 QVERIFY(isSame(m1, translateValues)); |
|
2572 m1.translate(4.0f, 5.0f, -3.0f); |
|
2573 QVERIFY(isSame(m1, translateDoubleValues)); |
|
2574 |
|
2575 QMatrix4x4 m2; |
|
2576 m2.translate(QVector3D(4.0f, 5.0f, -3.0f)); |
|
2577 QVERIFY(isSame(m2, translateValues)); |
|
2578 m2.translate(QVector3D(4.0f, 5.0f, -3.0f)); |
|
2579 QVERIFY(isSame(m2, translateDoubleValues)); |
|
2580 |
|
2581 QMatrix4x4 m3; |
|
2582 m3.scale(2.0f, 7.0f, 9.0f); |
|
2583 QVERIFY(isSame(m3, scaleValues)); |
|
2584 m3.scale(2.0f, 7.0f, 9.0f); |
|
2585 QVERIFY(isSame(m3, scaleDoubleValues)); |
|
2586 |
|
2587 QMatrix4x4 m4; |
|
2588 m4.scale(QVector3D(2.0f, 7.0f, 9.0f)); |
|
2589 QVERIFY(isSame(m4, scaleValues)); |
|
2590 m4.scale(QVector3D(2.0f, 7.0f, 9.0f)); |
|
2591 QVERIFY(isSame(m4, scaleDoubleValues)); |
|
2592 |
|
2593 QMatrix4x4 m5; |
|
2594 m5.translate(4.0f, 5.0f, -3.0f); |
|
2595 m5.scale(2.0f, 7.0f, 9.0f); |
|
2596 QVERIFY(isSame(m5, bothValues)); |
|
2597 m5.translate(4.0f, 5.0f, -3.0f); |
|
2598 QVERIFY(isSame(m5, bothThenTranslateValues)); |
|
2599 |
|
2600 QMatrix4x4 m6; |
|
2601 m6.translate(QVector3D(4.0f, 5.0f, -3.0f)); |
|
2602 m6.scale(QVector3D(2.0f, 7.0f, 9.0f)); |
|
2603 QVERIFY(isSame(m6, bothValues)); |
|
2604 m6.translate(QVector3D(4.0f, 5.0f, -3.0f)); |
|
2605 QVERIFY(isSame(m6, bothThenTranslateValues)); |
|
2606 |
|
2607 QMatrix4x4 m7; |
|
2608 m7.scale(2.0f, 7.0f, 9.0f); |
|
2609 m7.translate(4.0f, 5.0f, -3.0f); |
|
2610 QVERIFY(isSame(m7, bothReverseValues)); |
|
2611 |
|
2612 QMatrix4x4 m8; |
|
2613 m8.scale(QVector3D(2.0f, 7.0f, 9.0f)); |
|
2614 m8.translate(QVector3D(4.0f, 5.0f, -3.0f)); |
|
2615 QVERIFY(isSame(m8, bothReverseValues)); |
|
2616 |
|
2617 QMatrix4x4 m9; |
|
2618 m9.translate(4.0f, 5.0f, -3.0f); |
|
2619 m9.scale(2.0f, 7.0f, 9.0f); |
|
2620 QVERIFY(isSame(m9, bothValues)); |
|
2621 m9.scale(2.0f, 7.0f, 9.0f); |
|
2622 QVERIFY(isSame(m9, bothThenScaleValues)); |
|
2623 |
|
2624 QMatrix4x4 m10; |
|
2625 m10.translate(QVector3D(4.0f, 5.0f, -3.0f)); |
|
2626 m10.scale(QVector3D(2.0f, 7.0f, 9.0f)); |
|
2627 QVERIFY(isSame(m10, bothValues)); |
|
2628 m10.scale(QVector3D(2.0f, 7.0f, 9.0f)); |
|
2629 QVERIFY(isSame(m10, bothThenScaleValues)); |
|
2630 } |
|
2631 |
|
2632 // Test orthographic projections. |
|
2633 void tst_QMatrixNxN::ortho() |
|
2634 { |
|
2635 QMatrix4x4 m1; |
|
2636 m1.ortho(QRect(0, 0, 300, 150)); |
|
2637 QPointF p1 = m1 * QPointF(0, 0); |
|
2638 QPointF p2 = m1 * QPointF(300, 0); |
|
2639 QPointF p3 = m1 * QPointF(0, 150); |
|
2640 QPointF p4 = m1 * QPointF(300, 150); |
|
2641 QVector3D p5 = m1 * QVector3D(300, 150, 1); |
|
2642 QVERIFY(fuzzyCompare(p1.x(), -1.0)); |
|
2643 QVERIFY(fuzzyCompare(p1.y(), 1.0)); |
|
2644 QVERIFY(fuzzyCompare(p2.x(), 1.0)); |
|
2645 QVERIFY(fuzzyCompare(p2.y(), 1.0)); |
|
2646 QVERIFY(fuzzyCompare(p3.x(), -1.0)); |
|
2647 QVERIFY(fuzzyCompare(p3.y(), -1.0)); |
|
2648 QVERIFY(fuzzyCompare(p4.x(), 1.0)); |
|
2649 QVERIFY(fuzzyCompare(p4.y(), -1.0)); |
|
2650 QVERIFY(fuzzyCompare(p5.x(), (qreal)1.0)); |
|
2651 QVERIFY(fuzzyCompare(p5.y(), (qreal)-1.0)); |
|
2652 QVERIFY(fuzzyCompare(p5.z(), (qreal)-1.0)); |
|
2653 |
|
2654 QMatrix4x4 m2; |
|
2655 m2.ortho(QRectF(0, 0, 300, 150)); |
|
2656 p1 = m2 * QPointF(0, 0); |
|
2657 p2 = m2 * QPointF(300, 0); |
|
2658 p3 = m2 * QPointF(0, 150); |
|
2659 p4 = m2 * QPointF(300, 150); |
|
2660 p5 = m2 * QVector3D(300, 150, 1); |
|
2661 QVERIFY(fuzzyCompare(p1.x(), -1.0)); |
|
2662 QVERIFY(fuzzyCompare(p1.y(), 1.0)); |
|
2663 QVERIFY(fuzzyCompare(p2.x(), 1.0)); |
|
2664 QVERIFY(fuzzyCompare(p2.y(), 1.0)); |
|
2665 QVERIFY(fuzzyCompare(p3.x(), -1.0)); |
|
2666 QVERIFY(fuzzyCompare(p3.y(), -1.0)); |
|
2667 QVERIFY(fuzzyCompare(p4.x(), 1.0)); |
|
2668 QVERIFY(fuzzyCompare(p4.y(), -1.0)); |
|
2669 QVERIFY(fuzzyCompare(p5.x(), (qreal)1.0)); |
|
2670 QVERIFY(fuzzyCompare(p5.y(), (qreal)-1.0)); |
|
2671 QVERIFY(fuzzyCompare(p5.z(), (qreal)-1.0)); |
|
2672 |
|
2673 QMatrix4x4 m3; |
|
2674 m3.ortho(0, 300, 150, 0, -1, 1); |
|
2675 p1 = m3 * QPointF(0, 0); |
|
2676 p2 = m3 * QPointF(300, 0); |
|
2677 p3 = m3 * QPointF(0, 150); |
|
2678 p4 = m3 * QPointF(300, 150); |
|
2679 p5 = m3 * QVector3D(300, 150, 1); |
|
2680 QVERIFY(fuzzyCompare(p1.x(), -1.0)); |
|
2681 QVERIFY(fuzzyCompare(p1.y(), 1.0)); |
|
2682 QVERIFY(fuzzyCompare(p2.x(), 1.0)); |
|
2683 QVERIFY(fuzzyCompare(p2.y(), 1.0)); |
|
2684 QVERIFY(fuzzyCompare(p3.x(), -1.0)); |
|
2685 QVERIFY(fuzzyCompare(p3.y(), -1.0)); |
|
2686 QVERIFY(fuzzyCompare(p4.x(), 1.0)); |
|
2687 QVERIFY(fuzzyCompare(p4.y(), -1.0)); |
|
2688 QVERIFY(fuzzyCompare(p5.x(), (qreal)1.0)); |
|
2689 QVERIFY(fuzzyCompare(p5.y(), (qreal)-1.0)); |
|
2690 QVERIFY(fuzzyCompare(p5.z(), (qreal)-1.0)); |
|
2691 |
|
2692 QMatrix4x4 m4; |
|
2693 m4.ortho(0, 300, 150, 0, -2, 3); |
|
2694 p1 = m4 * QPointF(0, 0); |
|
2695 p2 = m4 * QPointF(300, 0); |
|
2696 p3 = m4 * QPointF(0, 150); |
|
2697 p4 = m4 * QPointF(300, 150); |
|
2698 p5 = m4 * QVector3D(300, 150, 1); |
|
2699 QVERIFY(fuzzyCompare(p1.x(), -1.0)); |
|
2700 QVERIFY(fuzzyCompare(p1.y(), 1.0)); |
|
2701 QVERIFY(fuzzyCompare(p2.x(), 1.0)); |
|
2702 QVERIFY(fuzzyCompare(p2.y(), 1.0)); |
|
2703 QVERIFY(fuzzyCompare(p3.x(), -1.0)); |
|
2704 QVERIFY(fuzzyCompare(p3.y(), -1.0)); |
|
2705 QVERIFY(fuzzyCompare(p4.x(), 1.0)); |
|
2706 QVERIFY(fuzzyCompare(p4.y(), -1.0)); |
|
2707 QVERIFY(fuzzyCompare(p5.x(), (qreal)1.0)); |
|
2708 QVERIFY(fuzzyCompare(p5.y(), (qreal)-1.0)); |
|
2709 QVERIFY(fuzzyCompare(p5.z(), (qreal)-0.6)); |
|
2710 |
|
2711 // An empty view volume should leave the matrix alone. |
|
2712 QMatrix4x4 m5; |
|
2713 m5.ortho(0, 0, 150, 0, -2, 3); |
|
2714 QVERIFY(m5.isIdentity()); |
|
2715 m5.ortho(0, 300, 150, 150, -2, 3); |
|
2716 QVERIFY(m5.isIdentity()); |
|
2717 m5.ortho(0, 300, 150, 0, 2, 2); |
|
2718 QVERIFY(m5.isIdentity()); |
|
2719 } |
|
2720 |
|
2721 // Test perspective frustum projections. |
|
2722 void tst_QMatrixNxN::frustum() |
|
2723 { |
|
2724 QMatrix4x4 m1; |
|
2725 m1.frustum(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f); |
|
2726 QVector3D p1 = m1 * QVector3D(-1.0f, -1.0f, 1.0f); |
|
2727 QVector3D p2 = m1 * QVector3D(1.0f, -1.0f, 1.0f); |
|
2728 QVector3D p3 = m1 * QVector3D(-1.0f, 1.0f, 1.0f); |
|
2729 QVector3D p4 = m1 * QVector3D(1.0f, 1.0f, 1.0f); |
|
2730 QVector3D p5 = m1 * QVector3D(0.0f, 0.0f, 2.0f); |
|
2731 QVERIFY(fuzzyCompare(p1.x(), -1.0f)); |
|
2732 QVERIFY(fuzzyCompare(p1.y(), -1.0f)); |
|
2733 QVERIFY(fuzzyCompare(p1.z(), -1.0f)); |
|
2734 QVERIFY(fuzzyCompare(p2.x(), 1.0f)); |
|
2735 QVERIFY(fuzzyCompare(p2.y(), -1.0f)); |
|
2736 QVERIFY(fuzzyCompare(p2.z(), -1.0f)); |
|
2737 QVERIFY(fuzzyCompare(p3.x(), -1.0f)); |
|
2738 QVERIFY(fuzzyCompare(p3.y(), 1.0f)); |
|
2739 QVERIFY(fuzzyCompare(p3.z(), -1.0f)); |
|
2740 QVERIFY(fuzzyCompare(p4.x(), 1.0f)); |
|
2741 QVERIFY(fuzzyCompare(p4.y(), 1.0f)); |
|
2742 QVERIFY(fuzzyCompare(p4.z(), -1.0f)); |
|
2743 QVERIFY(fuzzyCompare(p5.x(), 0.0f)); |
|
2744 QVERIFY(fuzzyCompare(p5.y(), 0.0f)); |
|
2745 QVERIFY(fuzzyCompare(p5.z(), -0.5f)); |
|
2746 |
|
2747 // An empty view volume should leave the matrix alone. |
|
2748 QMatrix4x4 m5; |
|
2749 m5.frustum(0, 0, 150, 0, -2, 3); |
|
2750 QVERIFY(m5.isIdentity()); |
|
2751 m5.frustum(0, 300, 150, 150, -2, 3); |
|
2752 QVERIFY(m5.isIdentity()); |
|
2753 m5.frustum(0, 300, 150, 0, 2, 2); |
|
2754 QVERIFY(m5.isIdentity()); |
|
2755 } |
|
2756 |
|
2757 // Test perspective field-of-view projections. |
|
2758 void tst_QMatrixNxN::perspective() |
|
2759 { |
|
2760 QMatrix4x4 m1; |
|
2761 m1.perspective(45.0f, 1.0f, -1.0f, 1.0f); |
|
2762 QVector3D p1 = m1 * QVector3D(-1.0f, -1.0f, 1.0f); |
|
2763 QVector3D p2 = m1 * QVector3D(1.0f, -1.0f, 1.0f); |
|
2764 QVector3D p3 = m1 * QVector3D(-1.0f, 1.0f, 1.0f); |
|
2765 QVector3D p4 = m1 * QVector3D(1.0f, 1.0f, 1.0f); |
|
2766 QVector3D p5 = m1 * QVector3D(0.0f, 0.0f, 2.0f); |
|
2767 QVERIFY(fuzzyCompare(p1.x(), 2.41421)); |
|
2768 QVERIFY(fuzzyCompare(p1.y(), 2.41421)); |
|
2769 QVERIFY(fuzzyCompare(p1.z(), -1)); |
|
2770 QVERIFY(fuzzyCompare(p2.x(), -2.41421)); |
|
2771 QVERIFY(fuzzyCompare(p2.y(), 2.41421)); |
|
2772 QVERIFY(fuzzyCompare(p2.z(), -1.0f)); |
|
2773 QVERIFY(fuzzyCompare(p3.x(), 2.41421)); |
|
2774 QVERIFY(fuzzyCompare(p3.y(), -2.41421)); |
|
2775 QVERIFY(fuzzyCompare(p3.z(), -1.0f)); |
|
2776 QVERIFY(fuzzyCompare(p4.x(), -2.41421)); |
|
2777 QVERIFY(fuzzyCompare(p4.y(), -2.41421)); |
|
2778 QVERIFY(fuzzyCompare(p4.z(), -1.0f)); |
|
2779 QVERIFY(fuzzyCompare(p5.x(), 0.0f)); |
|
2780 QVERIFY(fuzzyCompare(p5.y(), 0.0f)); |
|
2781 QVERIFY(fuzzyCompare(p5.z(), -0.5f)); |
|
2782 |
|
2783 // An empty view volume should leave the matrix alone. |
|
2784 QMatrix4x4 m5; |
|
2785 m5.perspective(45.0f, 1.0f, 0.0f, 0.0f); |
|
2786 QVERIFY(m5.isIdentity()); |
|
2787 m5.perspective(45.0f, 0.0f, -1.0f, 1.0f); |
|
2788 QVERIFY(m5.isIdentity()); |
|
2789 m5.perspective(0.0f, 1.0f, -1.0f, 1.0f); |
|
2790 QVERIFY(m5.isIdentity()); |
|
2791 } |
|
2792 |
|
2793 // Test left-handed vs right-handed coordinate flipping. |
|
2794 void tst_QMatrixNxN::flipCoordinates() |
|
2795 { |
|
2796 QMatrix4x4 m1; |
|
2797 m1.flipCoordinates(); |
|
2798 QVector3D p1 = m1 * QVector3D(2, 3, 4); |
|
2799 QVERIFY(p1 == QVector3D(2, -3, -4)); |
|
2800 |
|
2801 QMatrix4x4 m2; |
|
2802 m2.scale(2.0f, 3.0f, 1.0f); |
|
2803 m2.flipCoordinates(); |
|
2804 QVector3D p2 = m2 * QVector3D(2, 3, 4); |
|
2805 QVERIFY(p2 == QVector3D(4, -9, -4)); |
|
2806 |
|
2807 QMatrix4x4 m3; |
|
2808 m3.translate(2.0f, 3.0f, 1.0f); |
|
2809 m3.flipCoordinates(); |
|
2810 QVector3D p3 = m3 * QVector3D(2, 3, 4); |
|
2811 QVERIFY(p3 == QVector3D(4, 0, -3)); |
|
2812 |
|
2813 QMatrix4x4 m4; |
|
2814 m4.rotate(90.0f, 0.0f, 0.0f, 1.0f); |
|
2815 m4.flipCoordinates(); |
|
2816 QVector3D p4 = m4 * QVector3D(2, 3, 4); |
|
2817 QVERIFY(p4 == QVector3D(3, 2, -4)); |
|
2818 } |
|
2819 |
|
2820 // Test conversion of generic matrices to and from the non-generic types. |
|
2821 void tst_QMatrixNxN::convertGeneric() |
|
2822 { |
|
2823 QMatrix4x3 m1(uniqueValues4x3); |
|
2824 |
|
2825 static qreal const unique4x4[16] = { |
|
2826 1.0f, 2.0f, 3.0f, 4.0f, |
|
2827 5.0f, 6.0f, 7.0f, 8.0f, |
|
2828 9.0f, 10.0f, 11.0f, 12.0f, |
|
2829 0.0f, 0.0f, 0.0f, 1.0f |
|
2830 }; |
|
2831 #if !defined(QT_NO_MEMBER_TEMPLATES) |
|
2832 QMatrix4x4 m4(m1); |
|
2833 QVERIFY(isSame(m4, unique4x4)); |
|
2834 #endif |
|
2835 QMatrix4x4 m5 = qGenericMatrixToMatrix4x4(m1); |
|
2836 QVERIFY(isSame(m5, unique4x4)); |
|
2837 |
|
2838 static qreal const conv4x4[12] = { |
|
2839 1.0f, 2.0f, 3.0f, 4.0f, |
|
2840 5.0f, 6.0f, 7.0f, 8.0f, |
|
2841 9.0f, 10.0f, 11.0f, 12.0f |
|
2842 }; |
|
2843 QMatrix4x4 m9(uniqueValues4); |
|
2844 #if !defined(QT_NO_MEMBER_TEMPLATES) |
|
2845 QMatrix4x3 m10 = m9.toGenericMatrix<4, 3>(); |
|
2846 QVERIFY(isSame(m10, conv4x4)); |
|
2847 #endif |
|
2848 |
|
2849 QMatrix4x3 m11 = qGenericMatrixFromMatrix4x4<4, 3>(m9); |
|
2850 QVERIFY(isSame(m11, conv4x4)); |
|
2851 } |
|
2852 |
|
2853 void tst_QMatrixNxN::extractAxisRotation_data() |
|
2854 { |
|
2855 QTest::addColumn<float>("x"); |
|
2856 QTest::addColumn<float>("y"); |
|
2857 QTest::addColumn<float>("z"); |
|
2858 QTest::addColumn<float>("angle"); |
|
2859 |
|
2860 QTest::newRow("1, 0, 0, 0 deg") << 1.0f << 0.0f << 0.0f << 0.0f; |
|
2861 QTest::newRow("1, 0, 0, 90 deg") << 1.0f << 0.0f << 0.0f << 90.0f; |
|
2862 QTest::newRow("1, 0, 0, 270 deg") << 1.0f << 0.0f << 0.0f << 270.0f; |
|
2863 QTest::newRow("1, 0, 0, 45 deg") << 1.0f << 0.0f << 0.0f << 45.0f; |
|
2864 QTest::newRow("1, 0, 0, 120 deg") << 1.0f << 0.0f << 0.0f << 120.0f; |
|
2865 QTest::newRow("1, 0, 0, 300 deg") << 1.0f << 0.0f << 0.0f << 300.0f; |
|
2866 |
|
2867 QTest::newRow("0, 1, 0, 90 deg") << 0.0f << 1.0f << 0.0f << 90.0f; |
|
2868 QTest::newRow("0, 1, 0, 270 deg") << 0.0f << 1.0f << 0.0f << 270.0f; |
|
2869 QTest::newRow("0, 1, 0, 45 deg") << 0.0f << 1.0f << 0.0f << 45.0f; |
|
2870 QTest::newRow("0, 1, 0, 120 deg") << 0.0f << 1.0f << 0.0f << 120.0f; |
|
2871 QTest::newRow("0, 1, 0, 300 deg") << 0.0f << 1.0f << 0.0f << 300.0f; |
|
2872 |
|
2873 QTest::newRow("0, 0, 1, 90 deg") << 0.0f << 0.0f << 1.0f << 90.0f; |
|
2874 QTest::newRow("0, 0, 1, 270 deg") << 0.0f << 0.0f << 1.0f << 270.0f; |
|
2875 QTest::newRow("0, 0, 1, 45 deg") << 0.0f << 0.0f << 1.0f << 45.0f; |
|
2876 QTest::newRow("0, 0, 1, 120 deg") << 0.0f << 0.0f << 1.0f << 120.0f; |
|
2877 QTest::newRow("0, 0, 1, 300 deg") << 0.0f << 0.0f << 1.0f << 300.0f; |
|
2878 |
|
2879 QTest::newRow("1, 1, 1, 90 deg") << 1.0f << 1.0f << 1.0f << 90.0f; |
|
2880 QTest::newRow("1, 1, 1, 270 deg") << 1.0f << 1.0f << 1.0f << 270.0f; |
|
2881 QTest::newRow("1, 1, 1, 45 deg") << 1.0f << 1.0f << 1.0f << 45.0f; |
|
2882 QTest::newRow("1, 1, 1, 120 deg") << 1.0f << 1.0f << 1.0f << 120.0f; |
|
2883 QTest::newRow("1, 1, 1, 300 deg") << 1.0f << 1.0f << 1.0f << 300.0f; |
|
2884 } |
|
2885 |
|
2886 void tst_QMatrixNxN::extractAxisRotation() |
|
2887 { |
|
2888 QFETCH(float, x); |
|
2889 QFETCH(float, y); |
|
2890 QFETCH(float, z); |
|
2891 QFETCH(float, angle); |
|
2892 |
|
2893 QMatrix4x4 m; |
|
2894 QVector3D origAxis(x, y, z); |
|
2895 |
|
2896 m.rotate(angle, x, y, z); |
|
2897 |
|
2898 origAxis.normalize(); |
|
2899 QVector3D extractedAxis; |
|
2900 qreal extractedAngle; |
|
2901 |
|
2902 m.extractAxisRotation(extractedAngle, extractedAxis); |
|
2903 |
|
2904 if (angle > 180) { |
|
2905 QVERIFY(fuzzyCompare(360.0f - angle, extractedAngle)); |
|
2906 QVERIFY(fuzzyCompare(extractedAxis, -origAxis)); |
|
2907 } else { |
|
2908 QVERIFY(fuzzyCompare(angle, extractedAngle)); |
|
2909 QVERIFY(fuzzyCompare(extractedAxis, origAxis)); |
|
2910 } |
|
2911 } |
|
2912 |
|
2913 void tst_QMatrixNxN::extractTranslation_data() |
|
2914 { |
|
2915 QTest::addColumn<QMatrix4x4>("rotation"); |
|
2916 QTest::addColumn<float>("x"); |
|
2917 QTest::addColumn<float>("y"); |
|
2918 QTest::addColumn<float>("z"); |
|
2919 |
|
2920 static QMatrix4x4 m1; |
|
2921 |
|
2922 QTest::newRow("identity, 100, 50, 25") |
|
2923 << m1 << 100.0f << 50.0f << 250.0f; |
|
2924 |
|
2925 m1.rotate(45.0, 1.0, 0.0, 0.0); |
|
2926 QTest::newRow("rotX 45 + 100, 50, 25") << m1 << 100.0f << 50.0f << 25.0f; |
|
2927 |
|
2928 m1.setIdentity(); |
|
2929 m1.rotate(45.0, 0.0, 1.0, 0.0); |
|
2930 QTest::newRow("rotY 45 + 100, 50, 25") << m1 << 100.0f << 50.0f << 25.0f; |
|
2931 |
|
2932 m1.setIdentity(); |
|
2933 m1.rotate(75, 0.0, 0.0, 1.0); |
|
2934 m1.rotate(25, 1.0, 0.0, 0.0); |
|
2935 m1.rotate(45, 0.0, 1.0, 0.0); |
|
2936 QTest::newRow("rotZ 75, rotX 25, rotY 45, 100, 50, 25") << m1 << 100.0f << 50.0f << 25.0f; |
|
2937 } |
|
2938 |
|
2939 void tst_QMatrixNxN::extractTranslation() |
|
2940 { |
|
2941 QFETCH(QMatrix4x4, rotation); |
|
2942 QFETCH(float, x); |
|
2943 QFETCH(float, y); |
|
2944 QFETCH(float, z); |
|
2945 |
|
2946 rotation.translate(x, y, z); |
|
2947 |
|
2948 QVector3D vec = rotation.extractTranslation(); |
|
2949 |
|
2950 QVERIFY(fuzzyCompare(vec.x(), x)); |
|
2951 QVERIFY(fuzzyCompare(vec.y(), y)); |
|
2952 QVERIFY(fuzzyCompare(vec.z(), z)); |
|
2953 |
|
2954 QMatrix4x4 lookAt; |
|
2955 QVector3D eye(1.5f, -2.5f, 2.5f); |
|
2956 lookAt.lookAt(eye, |
|
2957 QVector3D(10.0f, 10.0f, 10.0f), |
|
2958 QVector3D(0.0f, 1.0f, 0.0f)); |
|
2959 |
|
2960 QVector3D extEye = lookAt.extractTranslation(); |
|
2961 |
|
2962 QVERIFY(fuzzyCompare(eye.x(), -extEye.x())); |
|
2963 QVERIFY(fuzzyCompare(eye.y(), -extEye.y())); |
|
2964 QVERIFY(fuzzyCompare(eye.z(), -extEye.z())); |
|
2965 } |
|
2966 |
|
2967 // Copy of "flagBits" in qmatrix4x4.h. |
|
2968 enum { |
|
2969 Identity = 0x0001, // Identity matrix |
|
2970 General = 0x0002, // General matrix, unknown contents |
|
2971 Translation = 0x0004, // Contains a simple translation |
|
2972 Scale = 0x0008, // Contains a simple scale |
|
2973 Rotation = 0x0010 // Contains a simple rotation |
|
2974 }; |
|
2975 |
|
2976 // Structure that allows direct access to "flagBits" for testing. |
|
2977 struct Matrix4x4 |
|
2978 { |
|
2979 qreal m[4][4]; |
|
2980 int flagBits; |
|
2981 }; |
|
2982 |
|
2983 // Test the inferring of special matrix types. |
|
2984 void tst_QMatrixNxN::inferSpecialType_data() |
|
2985 { |
|
2986 QTest::addColumn<void *>("mValues"); |
|
2987 QTest::addColumn<int>("flagBits"); |
|
2988 |
|
2989 QTest::newRow("null") |
|
2990 << (void *)nullValues4 << (int)General; |
|
2991 QTest::newRow("identity") |
|
2992 << (void *)identityValues4 << (int)Identity; |
|
2993 QTest::newRow("unique") |
|
2994 << (void *)uniqueValues4 << (int)General; |
|
2995 |
|
2996 static qreal scaleValues[16] = { |
|
2997 2.0f, 0.0f, 0.0f, 0.0f, |
|
2998 0.0f, 3.0f, 0.0f, 0.0f, |
|
2999 0.0f, 0.0f, 4.0f, 0.0f, |
|
3000 0.0f, 0.0f, 0.0f, 1.0f |
|
3001 }; |
|
3002 QTest::newRow("scale") |
|
3003 << (void *)scaleValues << (int)Scale; |
|
3004 |
|
3005 static qreal translateValues[16] = { |
|
3006 1.0f, 0.0f, 0.0f, 2.0f, |
|
3007 0.0f, 1.0f, 0.0f, 3.0f, |
|
3008 0.0f, 0.0f, 1.0f, 4.0f, |
|
3009 0.0f, 0.0f, 0.0f, 1.0f |
|
3010 }; |
|
3011 QTest::newRow("scale") |
|
3012 << (void *)translateValues << (int)Translation; |
|
3013 |
|
3014 static qreal bothValues[16] = { |
|
3015 1.0f, 0.0f, 0.0f, 2.0f, |
|
3016 0.0f, 2.0f, 0.0f, 0.0f, |
|
3017 0.0f, 0.0f, 1.0f, 4.0f, |
|
3018 0.0f, 0.0f, 0.0f, 1.0f |
|
3019 }; |
|
3020 QTest::newRow("both") |
|
3021 << (void *)bothValues << (int)(Scale | Translation); |
|
3022 |
|
3023 static qreal belowValues[16] = { |
|
3024 1.0f, 0.0f, 0.0f, 0.0f, |
|
3025 0.0f, 1.0f, 0.0f, 0.0f, |
|
3026 0.0f, 0.0f, 1.0f, 0.0f, |
|
3027 4.0f, 0.0f, 0.0f, 1.0f |
|
3028 }; |
|
3029 QTest::newRow("below") |
|
3030 << (void *)belowValues << (int)General; |
|
3031 } |
|
3032 void tst_QMatrixNxN::inferSpecialType() |
|
3033 { |
|
3034 QFETCH(void *, mValues); |
|
3035 QFETCH(int, flagBits); |
|
3036 |
|
3037 QMatrix4x4 m((const qreal *)mValues); |
|
3038 m.inferSpecialType(); |
|
3039 |
|
3040 QCOMPARE(reinterpret_cast<Matrix4x4 *>(&m)->flagBits, flagBits); |
|
3041 } |
|
3042 |
|
3043 void tst_QMatrixNxN::columnsAndRows() |
|
3044 { |
|
3045 QMatrix4x4 m1(uniqueValues4); |
|
3046 |
|
3047 QVERIFY(m1.column(0) == QVector4D(1, 5, 9, 13)); |
|
3048 QVERIFY(m1.column(1) == QVector4D(2, 6, 10, 14)); |
|
3049 QVERIFY(m1.column(2) == QVector4D(3, 7, 11, 15)); |
|
3050 QVERIFY(m1.column(3) == QVector4D(4, 8, 12, 16)); |
|
3051 |
|
3052 QVERIFY(m1.row(0) == QVector4D(1, 2, 3, 4)); |
|
3053 QVERIFY(m1.row(1) == QVector4D(5, 6, 7, 8)); |
|
3054 QVERIFY(m1.row(2) == QVector4D(9, 10, 11, 12)); |
|
3055 QVERIFY(m1.row(3) == QVector4D(13, 14, 15, 16)); |
|
3056 |
|
3057 m1.setColumn(0, QVector4D(-1, -5, -9, -13)); |
|
3058 m1.setColumn(1, QVector4D(-2, -6, -10, -14)); |
|
3059 m1.setColumn(2, QVector4D(-3, -7, -11, -15)); |
|
3060 m1.setColumn(3, QVector4D(-4, -8, -12, -16)); |
|
3061 |
|
3062 QVERIFY(m1.column(0) == QVector4D(-1, -5, -9, -13)); |
|
3063 QVERIFY(m1.column(1) == QVector4D(-2, -6, -10, -14)); |
|
3064 QVERIFY(m1.column(2) == QVector4D(-3, -7, -11, -15)); |
|
3065 QVERIFY(m1.column(3) == QVector4D(-4, -8, -12, -16)); |
|
3066 |
|
3067 QVERIFY(m1.row(0) == QVector4D(-1, -2, -3, -4)); |
|
3068 QVERIFY(m1.row(1) == QVector4D(-5, -6, -7, -8)); |
|
3069 QVERIFY(m1.row(2) == QVector4D(-9, -10, -11, -12)); |
|
3070 QVERIFY(m1.row(3) == QVector4D(-13, -14, -15, -16)); |
|
3071 |
|
3072 m1.setRow(0, QVector4D(1, 5, 9, 13)); |
|
3073 m1.setRow(1, QVector4D(2, 6, 10, 14)); |
|
3074 m1.setRow(2, QVector4D(3, 7, 11, 15)); |
|
3075 m1.setRow(3, QVector4D(4, 8, 12, 16)); |
|
3076 |
|
3077 QVERIFY(m1.column(0) == QVector4D(1, 2, 3, 4)); |
|
3078 QVERIFY(m1.column(1) == QVector4D(5, 6, 7, 8)); |
|
3079 QVERIFY(m1.column(2) == QVector4D(9, 10, 11, 12)); |
|
3080 QVERIFY(m1.column(3) == QVector4D(13, 14, 15, 16)); |
|
3081 |
|
3082 QVERIFY(m1.row(0) == QVector4D(1, 5, 9, 13)); |
|
3083 QVERIFY(m1.row(1) == QVector4D(2, 6, 10, 14)); |
|
3084 QVERIFY(m1.row(2) == QVector4D(3, 7, 11, 15)); |
|
3085 QVERIFY(m1.row(3) == QVector4D(4, 8, 12, 16)); |
|
3086 } |
|
3087 |
|
3088 // Test converting QMatrix objects into QMatrix4x4 and then |
|
3089 // checking that transformations in the original perform the |
|
3090 // equivalent transformations in the new matrix. |
|
3091 void tst_QMatrixNxN::convertQMatrix() |
|
3092 { |
|
3093 QMatrix m1; |
|
3094 m1.translate(-3.5, 2.0); |
|
3095 QPointF p1 = m1.map(QPointF(100.0, 150.0)); |
|
3096 QCOMPARE(p1.x(), 100.0 - 3.5); |
|
3097 QCOMPARE(p1.y(), 150.0 + 2.0); |
|
3098 |
|
3099 QMatrix4x4 m2(m1); |
|
3100 QPointF p2 = m2 * QPointF(100.0, 150.0); |
|
3101 QCOMPARE((double)p2.x(), 100.0 - 3.5); |
|
3102 QCOMPARE((double)p2.y(), 150.0 + 2.0); |
|
3103 QVERIFY(m1 == m2.toAffine()); |
|
3104 |
|
3105 QMatrix m3; |
|
3106 m3.scale(1.5, -2.0); |
|
3107 QPointF p3 = m3.map(QPointF(100.0, 150.0)); |
|
3108 QCOMPARE(p3.x(), 1.5 * 100.0); |
|
3109 QCOMPARE(p3.y(), -2.0 * 150.0); |
|
3110 |
|
3111 QMatrix4x4 m4(m3); |
|
3112 QPointF p4 = m4 * QPointF(100.0, 150.0); |
|
3113 QCOMPARE((double)p4.x(), 1.5 * 100.0); |
|
3114 QCOMPARE((double)p4.y(), -2.0 * 150.0); |
|
3115 QVERIFY(m3 == m4.toAffine()); |
|
3116 |
|
3117 QMatrix m5; |
|
3118 m5.rotate(45.0); |
|
3119 QPointF p5 = m5.map(QPointF(100.0, 150.0)); |
|
3120 |
|
3121 QMatrix4x4 m6(m5); |
|
3122 QPointF p6 = m6 * QPointF(100.0, 150.0); |
|
3123 QVERIFY(fuzzyCompare(p5.x(), p6.x())); |
|
3124 QVERIFY(fuzzyCompare(p5.y(), p6.y())); |
|
3125 |
|
3126 QMatrix m7 = m6.toAffine(); |
|
3127 QVERIFY(fuzzyCompare(m5.m11(), m7.m11())); |
|
3128 QVERIFY(fuzzyCompare(m5.m12(), m7.m12())); |
|
3129 QVERIFY(fuzzyCompare(m5.m21(), m7.m21())); |
|
3130 QVERIFY(fuzzyCompare(m5.m22(), m7.m22())); |
|
3131 QVERIFY(fuzzyCompare(m5.dx(), m7.dx())); |
|
3132 QVERIFY(fuzzyCompare(m5.dy(), m7.dy())); |
|
3133 } |
|
3134 |
|
3135 // Test converting QTransform objects into QMatrix4x4 and then |
|
3136 // checking that transformations in the original perform the |
|
3137 // equivalent transformations in the new matrix. |
|
3138 void tst_QMatrixNxN::convertQTransform() |
|
3139 { |
|
3140 QTransform m1; |
|
3141 m1.translate(-3.5, 2.0); |
|
3142 QPointF p1 = m1.map(QPointF(100.0, 150.0)); |
|
3143 QCOMPARE(p1.x(), 100.0 - 3.5); |
|
3144 QCOMPARE(p1.y(), 150.0 + 2.0); |
|
3145 |
|
3146 QMatrix4x4 m2(m1); |
|
3147 QPointF p2 = m2 * QPointF(100.0, 150.0); |
|
3148 QCOMPARE((double)p2.x(), 100.0 - 3.5); |
|
3149 QCOMPARE((double)p2.y(), 150.0 + 2.0); |
|
3150 QVERIFY(m1 == m2.toTransform()); |
|
3151 |
|
3152 QTransform m3; |
|
3153 m3.scale(1.5, -2.0); |
|
3154 QPointF p3 = m3.map(QPointF(100.0, 150.0)); |
|
3155 QCOMPARE(p3.x(), 1.5 * 100.0); |
|
3156 QCOMPARE(p3.y(), -2.0 * 150.0); |
|
3157 |
|
3158 QMatrix4x4 m4(m3); |
|
3159 QPointF p4 = m4 * QPointF(100.0, 150.0); |
|
3160 QCOMPARE((double)p4.x(), 1.5 * 100.0); |
|
3161 QCOMPARE((double)p4.y(), -2.0 * 150.0); |
|
3162 QVERIFY(m3 == m4.toTransform()); |
|
3163 |
|
3164 QTransform m5; |
|
3165 m5.rotate(45.0); |
|
3166 QPointF p5 = m5.map(QPointF(100.0, 150.0)); |
|
3167 |
|
3168 QMatrix4x4 m6(m5); |
|
3169 QPointF p6 = m6 * QPointF(100.0, 150.0); |
|
3170 QVERIFY(fuzzyCompare(p5.x(), p6.x())); |
|
3171 QVERIFY(fuzzyCompare(p5.y(), p6.y())); |
|
3172 |
|
3173 QTransform m7 = m6.toTransform(); |
|
3174 QVERIFY(fuzzyCompare(m5.m11(), m7.m11())); |
|
3175 QVERIFY(fuzzyCompare(m5.m12(), m7.m12())); |
|
3176 QVERIFY(fuzzyCompare(m5.m21(), m7.m21())); |
|
3177 QVERIFY(fuzzyCompare(m5.m22(), m7.m22())); |
|
3178 QVERIFY(fuzzyCompare(m5.dx(), m7.dx())); |
|
3179 QVERIFY(fuzzyCompare(m5.dy(), m7.dy())); |
|
3180 QVERIFY(fuzzyCompare(m5.m13(), m7.m13())); |
|
3181 QVERIFY(fuzzyCompare(m5.m23(), m7.m23())); |
|
3182 QVERIFY(fuzzyCompare(m5.m33(), m7.m33())); |
|
3183 } |
|
3184 |
|
3185 // Test filling matrices with specific values. |
|
3186 void tst_QMatrixNxN::fill() |
|
3187 { |
|
3188 QMatrix4x4 m1; |
|
3189 m1.fill(0.0f); |
|
3190 QVERIFY(isSame(m1, nullValues4)); |
|
3191 |
|
3192 static const qreal fillValues4[] = |
|
3193 {2.5f, 2.5f, 2.5f, 2.5f, |
|
3194 2.5f, 2.5f, 2.5f, 2.5f, |
|
3195 2.5f, 2.5f, 2.5f, 2.5f, |
|
3196 2.5f, 2.5f, 2.5f, 2.5f}; |
|
3197 m1.fill(2.5f); |
|
3198 QVERIFY(isSame(m1, fillValues4)); |
|
3199 |
|
3200 QMatrix4x3 m2; |
|
3201 m2.fill(0.0f); |
|
3202 QVERIFY(isSame(m2, nullValues4x3)); |
|
3203 |
|
3204 static const qreal fillValues4x3[] = |
|
3205 {2.5f, 2.5f, 2.5f, 2.5f, |
|
3206 2.5f, 2.5f, 2.5f, 2.5f, |
|
3207 2.5f, 2.5f, 2.5f, 2.5f}; |
|
3208 m2.fill(2.5f); |
|
3209 QVERIFY(isSame(m2, fillValues4x3)); |
|
3210 } |
|
3211 |
|
3212 // Test the mapRect() function for QRect and QRectF. |
|
3213 void tst_QMatrixNxN::mapRect_data() |
|
3214 { |
|
3215 QTest::addColumn<qreal>("x"); |
|
3216 QTest::addColumn<qreal>("y"); |
|
3217 QTest::addColumn<qreal>("width"); |
|
3218 QTest::addColumn<qreal>("height"); |
|
3219 |
|
3220 QTest::newRow("null") |
|
3221 << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f << (qreal)0.0f; |
|
3222 QTest::newRow("rect") |
|
3223 << (qreal)1.0f << (qreal)-20.5f << (qreal)100.0f << (qreal)63.75f; |
|
3224 } |
|
3225 void tst_QMatrixNxN::mapRect() |
|
3226 { |
|
3227 QFETCH(qreal, x); |
|
3228 QFETCH(qreal, y); |
|
3229 QFETCH(qreal, width); |
|
3230 QFETCH(qreal, height); |
|
3231 |
|
3232 QRectF rect(x, y, width, height); |
|
3233 QRect recti(qRound(x), qRound(y), qRound(width), qRound(height)); |
|
3234 |
|
3235 QMatrix4x4 m1; |
|
3236 QVERIFY(m1.mapRect(rect) == rect); |
|
3237 QVERIFY(m1.mapRect(recti) == recti); |
|
3238 |
|
3239 QMatrix4x4 m2; |
|
3240 m2.translate(-100.5f, 64.0f); |
|
3241 QRectF translated = rect.translated(-100.5f, 64.0f); |
|
3242 QRect translatedi = QRect(qRound(recti.x() - 100.5f), recti.y() + 64, |
|
3243 recti.width(), recti.height()); |
|
3244 QVERIFY(m2.mapRect(rect) == translated); |
|
3245 QVERIFY(m2.mapRect(recti) == translatedi); |
|
3246 |
|
3247 QMatrix4x4 m3; |
|
3248 m3.scale(-100.5f, 64.0f); |
|
3249 qreal scalex = x * -100.5f; |
|
3250 qreal scaley = y * 64.0f; |
|
3251 qreal scalewid = width * -100.5f; |
|
3252 qreal scaleht = height * 64.0f; |
|
3253 if (scalewid < 0.0f) { |
|
3254 scalewid = -scalewid; |
|
3255 scalex -= scalewid; |
|
3256 } |
|
3257 if (scaleht < 0.0f) { |
|
3258 scaleht = -scaleht; |
|
3259 scaley -= scaleht; |
|
3260 } |
|
3261 QRectF scaled(scalex, scaley, scalewid, scaleht); |
|
3262 QVERIFY(m3.mapRect(rect) == scaled); |
|
3263 scalex = recti.x() * -100.5f; |
|
3264 scaley = recti.y() * 64.0f; |
|
3265 scalewid = recti.width() * -100.5f; |
|
3266 scaleht = recti.height() * 64.0f; |
|
3267 if (scalewid < 0.0f) { |
|
3268 scalewid = -scalewid; |
|
3269 scalex -= scalewid; |
|
3270 } |
|
3271 if (scaleht < 0.0f) { |
|
3272 scaleht = -scaleht; |
|
3273 scaley -= scaleht; |
|
3274 } |
|
3275 QRect scaledi(qRound(scalex), qRound(scaley), |
|
3276 qRound(scalewid), qRound(scaleht)); |
|
3277 QVERIFY(m3.mapRect(recti) == scaledi); |
|
3278 |
|
3279 QMatrix4x4 m4; |
|
3280 m4.translate(-100.5f, 64.0f); |
|
3281 m4.scale(-2.5f, 4.0f); |
|
3282 qreal transx1 = x * -2.5f - 100.5f; |
|
3283 qreal transy1 = y * 4.0f + 64.0f; |
|
3284 qreal transx2 = (x + width) * -2.5f - 100.5f; |
|
3285 qreal transy2 = (y + height) * 4.0f + 64.0f; |
|
3286 if (transx1 > transx2) |
|
3287 qSwap(transx1, transx2); |
|
3288 if (transy1 > transy2) |
|
3289 qSwap(transy1, transy2); |
|
3290 QRectF trans(transx1, transy1, transx2 - transx1, transy2 - transy1); |
|
3291 QVERIFY(m4.mapRect(rect) == trans); |
|
3292 transx1 = recti.x() * -2.5f - 100.5f; |
|
3293 transy1 = recti.y() * 4.0f + 64.0f; |
|
3294 transx2 = (recti.x() + recti.width()) * -2.5f - 100.5f; |
|
3295 transy2 = (recti.y() + recti.height()) * 4.0f + 64.0f; |
|
3296 if (transx1 > transx2) |
|
3297 qSwap(transx1, transx2); |
|
3298 if (transy1 > transy2) |
|
3299 qSwap(transy1, transy2); |
|
3300 QRect transi(qRound(transx1), qRound(transy1), |
|
3301 qRound(transx2) - qRound(transx1), |
|
3302 qRound(transy2) - qRound(transy1)); |
|
3303 QVERIFY(m4.mapRect(recti) == transi); |
|
3304 |
|
3305 m4.rotate(45.0f, 0.0f, 0.0f, 1.0f); |
|
3306 |
|
3307 QTransform t4; |
|
3308 t4.translate(-100.5f, 64.0f); |
|
3309 t4.scale(-2.5f, 4.0f); |
|
3310 t4.rotate(45.0f); |
|
3311 QRectF mr = m4.mapRect(rect); |
|
3312 QRectF tr = t4.mapRect(rect); |
|
3313 QVERIFY(fuzzyCompare(mr.x(), tr.x())); |
|
3314 QVERIFY(fuzzyCompare(mr.y(), tr.y())); |
|
3315 QVERIFY(fuzzyCompare(mr.width(), tr.width())); |
|
3316 QVERIFY(fuzzyCompare(mr.height(), tr.height())); |
|
3317 |
|
3318 QRect mri = m4.mapRect(recti); |
|
3319 QRect tri = t4.mapRect(recti); |
|
3320 QVERIFY(mri == tri); |
|
3321 } |
|
3322 |
|
3323 void tst_QMatrixNxN::mapVector_data() |
|
3324 { |
|
3325 QTest::addColumn<void *>("mValues"); |
|
3326 |
|
3327 QTest::newRow("null") |
|
3328 << (void *)nullValues4; |
|
3329 |
|
3330 QTest::newRow("identity") |
|
3331 << (void *)identityValues4; |
|
3332 |
|
3333 QTest::newRow("unique") |
|
3334 << (void *)uniqueValues4; |
|
3335 |
|
3336 static const qreal scale[] = |
|
3337 {2.0f, 0.0f, 0.0f, 0.0f, |
|
3338 0.0f, 11.0f, 0.0f, 0.0f, |
|
3339 0.0f, 0.0f, -6.5f, 0.0f, |
|
3340 0.0f, 0.0f, 0.0f, 1.0f}; |
|
3341 QTest::newRow("scale") |
|
3342 << (void *)scale; |
|
3343 |
|
3344 static const qreal scaleTranslate[] = |
|
3345 {2.0f, 0.0f, 0.0f, 1.0f, |
|
3346 0.0f, 11.0f, 0.0f, 2.0f, |
|
3347 0.0f, 0.0f, -6.5f, 3.0f, |
|
3348 0.0f, 0.0f, 0.0f, 1.0f}; |
|
3349 QTest::newRow("scaleTranslate") |
|
3350 << (void *)scaleTranslate; |
|
3351 |
|
3352 static const qreal translate[] = |
|
3353 {1.0f, 0.0f, 0.0f, 1.0f, |
|
3354 0.0f, 1.0f, 0.0f, 2.0f, |
|
3355 0.0f, 0.0f, 1.0f, 3.0f, |
|
3356 0.0f, 0.0f, 0.0f, 1.0f}; |
|
3357 QTest::newRow("translate") |
|
3358 << (void *)translate; |
|
3359 } |
|
3360 void tst_QMatrixNxN::mapVector() |
|
3361 { |
|
3362 QFETCH(void *, mValues); |
|
3363 |
|
3364 QMatrix4x4 m1((const qreal *)mValues); |
|
3365 m1.inferSpecialType(); |
|
3366 |
|
3367 QVector3D v(3.5f, -1.0f, 2.5f); |
|
3368 |
|
3369 QVector3D expected |
|
3370 (v.x() * m1(0, 0) + v.y() * m1(0, 1) + v.z() * m1(0, 2), |
|
3371 v.x() * m1(1, 0) + v.y() * m1(1, 1) + v.z() * m1(1, 2), |
|
3372 v.x() * m1(2, 0) + v.y() * m1(2, 1) + v.z() * m1(2, 2)); |
|
3373 |
|
3374 QVector3D actual = m1.mapVector(v); |
|
3375 |
|
3376 QVERIFY(fuzzyCompare(actual.x(), expected.x())); |
|
3377 QVERIFY(fuzzyCompare(actual.y(), expected.y())); |
|
3378 QVERIFY(fuzzyCompare(actual.z(), expected.z())); |
|
3379 } |
|
3380 |
|
3381 class tst_QMatrixNxN4x4Properties : public QObject |
|
3382 { |
|
3383 Q_OBJECT |
|
3384 Q_PROPERTY(QMatrix4x4 matrix READ matrix WRITE setMatrix) |
|
3385 public: |
|
3386 tst_QMatrixNxN4x4Properties(QObject *parent = 0) : QObject(parent) {} |
|
3387 |
|
3388 QMatrix4x4 matrix() const { return m; } |
|
3389 void setMatrix(const QMatrix4x4& value) { m = value; } |
|
3390 |
|
3391 private: |
|
3392 QMatrix4x4 m; |
|
3393 }; |
|
3394 |
|
3395 // Test getting and setting matrix properties via the metaobject system. |
|
3396 void tst_QMatrixNxN::properties() |
|
3397 { |
|
3398 tst_QMatrixNxN4x4Properties obj; |
|
3399 |
|
3400 QMatrix4x4 m1(uniqueValues4); |
|
3401 obj.setMatrix(m1); |
|
3402 |
|
3403 QMatrix4x4 m2 = qVariantValue<QMatrix4x4>(obj.property("matrix")); |
|
3404 QVERIFY(isSame(m2, uniqueValues4)); |
|
3405 |
|
3406 QMatrix4x4 m3(transposedValues4); |
|
3407 obj.setProperty("matrix", qVariantFromValue(m3)); |
|
3408 |
|
3409 m2 = qVariantValue<QMatrix4x4>(obj.property("matrix")); |
|
3410 QVERIFY(isSame(m2, transposedValues4)); |
|
3411 } |
|
3412 |
|
3413 void tst_QMatrixNxN::metaTypes() |
|
3414 { |
|
3415 QVERIFY(QMetaType::type("QMatrix4x4") == QMetaType::QMatrix4x4); |
|
3416 |
|
3417 QCOMPARE(QByteArray(QMetaType::typeName(QMetaType::QMatrix4x4)), |
|
3418 QByteArray("QMatrix4x4")); |
|
3419 |
|
3420 QVERIFY(QMetaType::isRegistered(QMetaType::QMatrix4x4)); |
|
3421 |
|
3422 QVERIFY(qMetaTypeId<QMatrix4x4>() == QMetaType::QMatrix4x4); |
|
3423 } |
|
3424 |
|
3425 QTEST_APPLESS_MAIN(tst_QMatrixNxN) |
|
3426 |
|
3427 #include "tst_qmatrixnxn.moc" |