| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
| 4 | ** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). | 
| 5 | ** Contact: https://www.qt.io/licensing/ | 
| 6 | ** | 
| 7 | ** This file is part of the Qt3D module of the Qt Toolkit. | 
| 8 | ** | 
| 9 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | 
| 10 | ** Commercial License Usage | 
| 11 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 12 | ** accordance with the commercial license agreement provided with the | 
| 13 | ** Software or, alternatively, in accordance with the terms contained in | 
| 14 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 15 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 16 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 17 | ** | 
| 18 | ** GNU General Public License Usage | 
| 19 | ** Alternatively, this file may be used under the terms of the GNU | 
| 20 | ** General Public License version 3 as published by the Free Software | 
| 21 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
| 22 | ** included in the packaging of this file. Please review the following | 
| 23 | ** information to ensure the GNU General Public License requirements will | 
| 24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
| 25 | ** | 
| 26 | ** $QT_END_LICENSE$ | 
| 27 | ** | 
| 28 | ****************************************************************************/ | 
| 29 |  | 
| 30 | #include <QtTest/QtTest> | 
| 31 | #include <Qt3DRender/private/qray3d_p.h> | 
| 32 |  | 
| 33 | class tst_QRay3D : public QObject | 
| 34 | { | 
| 35 |     Q_OBJECT | 
| 36 | public: | 
| 37 |     tst_QRay3D() {} | 
| 38 |     ~tst_QRay3D() {} | 
| 39 |  | 
| 40 | private Q_SLOTS: | 
| 41 |     void create_data(); | 
| 42 |     void create(); | 
| 43 |     void projection_data(); | 
| 44 |     void projection(); | 
| 45 |     void point_data(); | 
| 46 |     void point(); | 
| 47 |     void contains_point_data(); | 
| 48 |     void contains_point(); | 
| 49 |     void contains_ray_data(); | 
| 50 |     void contains_ray(); | 
| 51 |     void distance_data(); | 
| 52 |     void distance(); | 
| 53 |     void compare(); | 
| 54 |     void dataStream(); | 
| 55 |     void transform_data(); | 
| 56 |     void transform(); | 
| 57 |     void properties(); | 
| 58 |     void metaTypes(); | 
| 59 |     void shouldNotAllowNullDirection(); | 
| 60 | }; | 
| 61 |  | 
| 62 | // Fix the problem where a compared value happens to be zero (and | 
| 63 | // you cannot always predict this, and should not predict it | 
| 64 | // since then you produce self-fulling prophecies instead of tests). | 
| 65 | // In that case qFuzzyCompare has a completely strict criterion since | 
| 66 | // it finds the "fudge factor" by multiplying by zero... | 
| 67 | static inline bool fuzzyCompare(float p1, float p2) | 
| 68 | { | 
| 69 |     float fac = qMin(a: qAbs(t: p1), b: qAbs(t: p2)); | 
| 70 |     return (qAbs(t: p1 - p2) <= (qIsNull(f: fac) ? 0.00001f : 0.00001f * fac)); | 
| 71 | } | 
| 72 |  | 
| 73 | static inline bool fuzzyCompare(const Vector3D &lhs, const Vector3D &rhs) | 
| 74 | { | 
| 75 |     if (fuzzyCompare(p1: lhs.x(), p2: rhs.x()) && | 
| 76 |             fuzzyCompare(p1: lhs.y(), p2: rhs.y()) && | 
| 77 |             fuzzyCompare(p1: lhs.z(), p2: rhs.z())) | 
| 78 |         return true; | 
| 79 | #ifndef QT_NO_DEBUG_STREAM | 
| 80 |     qWarning() << "actual:"  << lhs; | 
| 81 |     qWarning() << "expected:"  << rhs; | 
| 82 | #endif | 
| 83 |     return false; | 
| 84 | } | 
| 85 |  | 
| 86 | void tst_QRay3D::create_data() | 
| 87 | { | 
| 88 |     QTest::addColumn<Vector3D>(name: "point" ); | 
| 89 |     QTest::addColumn<Vector3D>(name: "direction" ); | 
| 90 |  | 
| 91 |     // normalized direction vectors | 
| 92 |     QTest::newRow(dataTag: "line on x-axis from origin" ) | 
| 93 |             << Vector3D() | 
| 94 |             << Vector3D(1.0f, 0.0f, 0.0f); | 
| 95 |  | 
| 96 |     QTest::newRow(dataTag: "line parallel -z-axis from 3,3,3" ) | 
| 97 |             << Vector3D(3.0f, 3.0f, 3.0f) | 
| 98 |             << Vector3D(0.0f, 0.0f, -1.0f); | 
| 99 |  | 
| 100 |     QTest::newRow(dataTag: "vertical line (parallel to y-axis)" ) | 
| 101 |             << Vector3D(0.5f, 0.0f, 0.5f) | 
| 102 |             << Vector3D(0.0f, 1.0f, 0.0f); | 
| 103 |  | 
| 104 |     QTest::newRow(dataTag: "equidistant from all 3 axes" ) | 
| 105 |             << Vector3D(0.5f, 0.0f, 0.5f) | 
| 106 |             << Vector3D(0.57735026919f, 0.57735026919f, 0.57735026919f); | 
| 107 |  | 
| 108 |     // non-normalized direction vectors | 
| 109 |     QTest::newRow(dataTag: "line on x-axis from origin - B" ) | 
| 110 |             << Vector3D() | 
| 111 |             << Vector3D(2.0f, 0.0f, 0.0f).normalized(); | 
| 112 |  | 
| 113 |     QTest::newRow(dataTag: "line parallel -z-axis from 3,3,3 - B" ) | 
| 114 |             << Vector3D(3.0f, 3.0f, 3.0f) | 
| 115 |             << Vector3D(0.0f, 0.0f, -0.7f).normalized(); | 
| 116 |  | 
| 117 |     QTest::newRow(dataTag: "vertical line (parallel to y-axis) - B" ) | 
| 118 |             << Vector3D(0.5f, 0.0f, 0.5f) | 
| 119 |             << Vector3D(0.0f, 5.3f, 0.0f).normalized(); | 
| 120 |  | 
| 121 |     QTest::newRow(dataTag: "equidistant from all 3 axes - B" ) | 
| 122 |             << Vector3D(0.5f, 0.0f, 0.5f) | 
| 123 |             << Vector3D(1.0f, 1.0f, 1.0f).normalized(); | 
| 124 |  | 
| 125 |     QTest::newRow(dataTag: "negative direction" ) | 
| 126 |             << Vector3D(-3.0f, -3.0f, -3.0f) | 
| 127 |             << Vector3D(-1.2f, -1.8f, -2.4f).normalized(); | 
| 128 | } | 
| 129 |  | 
| 130 | void tst_QRay3D::create() | 
| 131 | { | 
| 132 |     QFETCH(Vector3D, point); | 
| 133 |     QFETCH(Vector3D, direction); | 
| 134 |     Qt3DRender::RayCasting::QRay3D ray(point, direction); | 
| 135 |     QVERIFY(fuzzyCompare(ray.direction(), direction)); | 
| 136 |     QVERIFY(fuzzyCompare(ray.origin(), point)); | 
| 137 |  | 
| 138 |     Qt3DRender::RayCasting::QRay3D ray2; | 
| 139 |     QCOMPARE(ray2.origin(), Vector3D(0, 0, 0)); | 
| 140 |     QCOMPARE(ray2.direction(), Vector3D(0, 0, 1)); | 
| 141 |     ray2.setOrigin(point); | 
| 142 |     ray2.setDirection(direction); | 
| 143 |     QVERIFY(fuzzyCompare(ray.direction(), direction)); | 
| 144 |     QVERIFY(fuzzyCompare(ray.origin(), point)); | 
| 145 | } | 
| 146 |  | 
| 147 | void tst_QRay3D::projection_data() | 
| 148 | { | 
| 149 |     QTest::addColumn<Vector3D>(name: "point" ); | 
| 150 |     QTest::addColumn<Vector3D>(name: "direction" ); | 
| 151 |     QTest::addColumn<Vector3D>(name: "vector" ); | 
| 152 |     QTest::addColumn<Vector3D>(name: "expected" ); | 
| 153 |  | 
| 154 |     QTest::newRow(dataTag: "line on x-axis from origin" ) | 
| 155 |             << Vector3D() | 
| 156 |             << Vector3D(2.0f, 0.0f, 0.0f) | 
| 157 |             << Vector3D(0.6f, 0.0f, 0.0f) | 
| 158 |             << Vector3D(0.6f, 0.0f, 0.0f); | 
| 159 |  | 
| 160 |     QTest::newRow(dataTag: "line parallel -z-axis from 3,3,3" ) | 
| 161 |             << Vector3D(3.0f, 3.0f, 3.0f) | 
| 162 |             << Vector3D(0.0f, 0.0f, -0.7f) | 
| 163 |             << Vector3D(3.0f, 3.0f, 2.4f) | 
| 164 |             << Vector3D(0.0f, 0.0f, 2.4f); | 
| 165 |  | 
| 166 |     QTest::newRow(dataTag: "vertical line (parallel to y-axis)" ) | 
| 167 |             << Vector3D(0.5f, 0.0f, 0.5f) | 
| 168 |             << Vector3D(0.0f, 5.3f, 0.0f) | 
| 169 |             << Vector3D(0.5f, 0.6f, 0.5f) | 
| 170 |             << Vector3D(0.0f, 0.6f, 0.0f); | 
| 171 |  | 
| 172 |     QTest::newRow(dataTag: "equidistant from all 3 axes, project y-axis (with some z & x)" ) | 
| 173 |             << Vector3D(0.5f, 0.0f, 0.5f) | 
| 174 |             << Vector3D(1.0f, 1.0f, 1.0f) | 
| 175 |             << Vector3D(0.5f, 5.0f, 0.5f) | 
| 176 |             << Vector3D(2.0f, 2.0f, 2.0f); | 
| 177 |  | 
| 178 |     QTest::newRow(dataTag: "negative direction line, project +ve y-axis (with some z & x)" ) | 
| 179 |             << Vector3D(-3.0f, -3.0f, -3.0f) | 
| 180 |             << Vector3D(-1.2f, -1.8f, -2.4f) | 
| 181 |             << Vector3D(0.5f, 5.0f, 0.5f) | 
| 182 |             << Vector3D(1.241379261016846f, 1.862068772315979f, 2.48275852203369f); | 
| 183 | } | 
| 184 |  | 
| 185 | void tst_QRay3D::projection() | 
| 186 | { | 
| 187 |     QFETCH(Vector3D, point); | 
| 188 |     QFETCH(Vector3D, direction); | 
| 189 |     QFETCH(Vector3D, vector); | 
| 190 |     QFETCH(Vector3D, expected); | 
| 191 |     Qt3DRender::RayCasting::QRay3D line(point, direction); | 
| 192 |     Vector3D result = line.project(vector); | 
| 193 |     QVERIFY(fuzzyCompare(result, expected)); | 
| 194 | } | 
| 195 |  | 
| 196 | void tst_QRay3D::point_data() | 
| 197 | { | 
| 198 |     QTest::addColumn<Vector3D>(name: "point" ); | 
| 199 |     QTest::addColumn<Vector3D>(name: "direction" ); | 
| 200 |     QTest::addColumn<Vector3D>(name: "point_on_line_pos_0_6" ); | 
| 201 |     QTest::addColumn<Vector3D>(name: "point_on_line_neg_7_2" ); | 
| 202 |  | 
| 203 |     QTest::newRow(dataTag: "line on x-axis from origin" ) | 
| 204 |             << Vector3D() | 
| 205 |             << Vector3D(2.0f, 0.0f, 0.0f) | 
| 206 |             << Vector3D(0.6f, 0.0f, 0.0f) | 
| 207 |             << Vector3D(-7.2f, 0.0f, 0.0f); | 
| 208 |  | 
| 209 |     QTest::newRow(dataTag: "line parallel -z-axis from 3,3,3" ) | 
| 210 |             << Vector3D(3.0f, 3.0f, 3.0f) | 
| 211 |             << Vector3D(0.0f, 0.0f, -0.7f) | 
| 212 |             << Vector3D(3.0f, 3.0f, 2.4f) | 
| 213 |             << Vector3D(3.0f, 3.0f, 10.2f); | 
| 214 |  | 
| 215 |     QTest::newRow(dataTag: "vertical line (parallel to y-axis)" ) | 
| 216 |             << Vector3D(0.5f, 0.0f, 0.5f) | 
| 217 |             << Vector3D(0.0f, 5.3f, 0.0f) | 
| 218 |             << Vector3D(0.5f, 0.6f, 0.5f) | 
| 219 |             << Vector3D(0.5f, -7.2f, 0.5f); | 
| 220 |  | 
| 221 |     QTest::newRow(dataTag: "equidistant from all 3 axes" ) | 
| 222 |             << Vector3D(0.5f, 0.0f, 0.5f) | 
| 223 |             << Vector3D(1.0f, 1.0f, 1.0f) | 
| 224 |             << Vector3D(0.84641f, 0.34641f, 0.84641f) | 
| 225 |             << Vector3D(-3.65692f, -4.15692f, -3.65692f); | 
| 226 |  | 
| 227 |     QTest::newRow(dataTag: "negative direction" ) | 
| 228 |             << Vector3D(-3.0f, -3.0f, -3.0f) | 
| 229 |             << Vector3D(-1.2f, -1.8f, -2.4f) | 
| 230 |             << Vector3D(-3.22283f, -3.33425f, -3.44567f) | 
| 231 |             << Vector3D(-0.325987f, 1.01102f, 2.34803f); | 
| 232 | } | 
| 233 |  | 
| 234 | void tst_QRay3D::point() | 
| 235 | { | 
| 236 |     QFETCH(Vector3D, point); | 
| 237 |     QFETCH(Vector3D, direction); | 
| 238 |     QFETCH(Vector3D, point_on_line_pos_0_6); | 
| 239 |     QFETCH(Vector3D, point_on_line_neg_7_2); | 
| 240 |     Qt3DRender::RayCasting::QRay3D line(point, direction); | 
| 241 |     QVERIFY(fuzzyCompare(line.point(0.6f), point_on_line_pos_0_6)); | 
| 242 |     QVERIFY(fuzzyCompare(line.point(-7.2f), point_on_line_neg_7_2)); | 
| 243 |     QVERIFY(fuzzyCompare(line.projectedDistance(point_on_line_pos_0_6), 0.6f)); | 
| 244 |     QVERIFY(fuzzyCompare(line.projectedDistance(point_on_line_neg_7_2), -7.2f)); | 
| 245 | } | 
| 246 |  | 
| 247 | void tst_QRay3D::contains_point_data() | 
| 248 | { | 
| 249 |     QTest::addColumn<Vector3D>(name: "origin" ); | 
| 250 |     QTest::addColumn<Vector3D>(name: "direction" ); | 
| 251 |     QTest::addColumn<Vector3D>(name: "point" ); | 
| 252 |     QTest::addColumn<bool>(name: "contains" ); | 
| 253 |  | 
| 254 |     QTest::newRow(dataTag: "bogus this line with null direction" ) | 
| 255 |             << Vector3D(1.0, 3.0, 3.0) | 
| 256 |             << Vector3D(0.0, 0.0, 0.0) | 
| 257 |             << Vector3D(1.0, 2.0, 4.0) | 
| 258 |             << false; | 
| 259 |  | 
| 260 |     QTest::newRow(dataTag: "point at the origin" ) | 
| 261 |             << Vector3D(0.0, 0.0, 0.0) | 
| 262 |             << Vector3D(1.0, 3.0, 3.0) | 
| 263 |             << Vector3D(0.0, 0.0, 0.0) | 
| 264 |             << true; | 
| 265 |  | 
| 266 |     QTest::newRow(dataTag: "close to the origin" ) | 
| 267 |             << Vector3D(1.0, 1.0, 1.0) | 
| 268 |             << Vector3D(1.0, 3.0, 3.0) | 
| 269 |             << Vector3D(1.0005f, 1.0005f, 1.0) | 
| 270 |             << false; | 
| 271 |  | 
| 272 |     QTest::newRow(dataTag: "45 line line in plane x=1" ) | 
| 273 |             << Vector3D(1.0, 3.0, 3.0) | 
| 274 |             << Vector3D(0.0, -1.0, -1.0) | 
| 275 |             << Vector3D(1.0, 4.0, 4.0) | 
| 276 |             << true; | 
| 277 |     { | 
| 278 |         // This is to prove that the constructed approach give the | 
| 279 |         // same results | 
| 280 |         Vector3D p(1.0, 3.0, 3.0); | 
| 281 |         Vector3D v(0.0, -1.0, -1.0); | 
| 282 |  | 
| 283 |         QTest::newRow(dataTag: "constructed 45 line line in plane x=1" ) | 
| 284 |                 << p | 
| 285 |                 << v | 
| 286 |                 << p + v | 
| 287 |                 << true; | 
| 288 |     } | 
| 289 |  | 
| 290 |     QTest::newRow(dataTag: "intersection with negative s in plane z=-1" ) | 
| 291 |         << Vector3D(1.0f, 2.0f, -1.0f) | 
| 292 |         << Vector3D(1.0f, 1.0f, 0.0f) | 
| 293 |         << Vector3D(2.0f, 1.0f, 0.0f) | 
| 294 |         << false; | 
| 295 |  | 
| 296 |     QTest::newRow(dataTag: "45 angled line" ) | 
| 297 |         << Vector3D(3.0f, 0.0f, -1.0f) | 
| 298 |         << Vector3D(1.0f, -1.0f, 1.0f) | 
| 299 |         << Vector3D(6.0f, -3.0f, 2.0f) | 
| 300 |         << true; | 
| 301 |  | 
| 302 |     { | 
| 303 |         Vector3D p(-10.0, 3.0, 3.0); | 
| 304 |         Vector3D v(0.0, 20.0, -1.0); | 
| 305 |         QTest::newRow(dataTag: "constructed vector close to axis" ) | 
| 306 |                 << p | 
| 307 |                 << v | 
| 308 |                 << p + v * 3.0 | 
| 309 |                 << true; | 
| 310 |     } | 
| 311 |  | 
| 312 |     { | 
| 313 |         Vector3D p(1.0, 3.0, 3.0); | 
| 314 |         Vector3D v(40.0, 500.0, -1.0); | 
| 315 |         QTest::newRow(dataTag: "constructed larger values close to axis" ) | 
| 316 |                 << p | 
| 317 |                 << v | 
| 318 |                 << p + v | 
| 319 |                 << true; | 
| 320 |     } | 
| 321 | } | 
| 322 |  | 
| 323 | void tst_QRay3D::contains_point() | 
| 324 | { | 
| 325 |     QFETCH(Vector3D, origin); | 
| 326 |     QFETCH(Vector3D, direction); | 
| 327 |     QFETCH(Vector3D, point); | 
| 328 |     QFETCH(bool, contains); | 
| 329 |  | 
| 330 |     Qt3DRender::RayCasting::QRay3D line(origin, direction); | 
| 331 |     QCOMPARE(line.contains(point), contains); | 
| 332 | } | 
| 333 |  | 
| 334 | void tst_QRay3D::contains_ray_data() | 
| 335 | { | 
| 336 |     contains_point_data(); | 
| 337 | } | 
| 338 |  | 
| 339 | void tst_QRay3D::contains_ray() | 
| 340 | { | 
| 341 |     QFETCH(Vector3D, origin); | 
| 342 |     QFETCH(Vector3D, direction); | 
| 343 |     QFETCH(Vector3D, point); | 
| 344 |     QFETCH(bool, contains); | 
| 345 |  | 
| 346 |     Qt3DRender::RayCasting::QRay3D line(origin, direction); | 
| 347 |     if (contains) { | 
| 348 |         Qt3DRender::RayCasting::QRay3D line2(point, direction); | 
| 349 |         QVERIFY(line.contains(line2)); | 
| 350 |         QVERIFY(line2.contains(line)); | 
| 351 |  | 
| 352 |         // Reversed direction is also contained. | 
| 353 |         Qt3DRender::RayCasting::QRay3D line3(point, -direction); | 
| 354 |         QVERIFY(line.contains(line2)); | 
| 355 |         QVERIFY(line2.contains(line)); | 
| 356 |  | 
| 357 |         // Different direction. | 
| 358 |         Qt3DRender::RayCasting::QRay3D line4(point, Vector3D(direction.y(), direction.x(), direction.z())); | 
| 359 |         QVERIFY(!line.contains(line4)); | 
| 360 |         QVERIFY(!line4.contains(line)); | 
| 361 |     } else { | 
| 362 |         Qt3DRender::RayCasting::QRay3D line2(point, direction); | 
| 363 |         QVERIFY(!line.contains(line2)); | 
| 364 |         QVERIFY(!line2.contains(line)); | 
| 365 |     } | 
| 366 | } | 
| 367 |  | 
| 368 | void tst_QRay3D::distance_data() | 
| 369 | { | 
| 370 |     QTest::addColumn<Vector3D>(name: "origin" ); | 
| 371 |     QTest::addColumn<Vector3D>(name: "direction" ); | 
| 372 |     QTest::addColumn<Vector3D>(name: "point" ); | 
| 373 |     QTest::addColumn<float>(name: "distance" ); | 
| 374 |  | 
| 375 |     QTest::newRow(dataTag: "axis-x" ) | 
| 376 |         << Vector3D(6.0f, 0.0f, 0.0f) | 
| 377 |         << Vector3D(1.0f, 0.0f, 0.0f) | 
| 378 |         << Vector3D(0.0f, 0.0f, 0.0f) | 
| 379 |         << 0.0f; | 
| 380 |  | 
| 381 |     QTest::newRow(dataTag: "axis-x to 1" ) | 
| 382 |         << Vector3D(6.0f, 0.0f, 0.0f) | 
| 383 |         << Vector3D(1.0f, 0.0f, 0.0f) | 
| 384 |         << Vector3D(0.0f, 1.0f, 0.0f) | 
| 385 |         << 1.0f; | 
| 386 |  | 
| 387 |     QTest::newRow(dataTag: "neg-axis-y" ) | 
| 388 |         << Vector3D(0.0f, 6.0f, 0.0f) | 
| 389 |         << Vector3D(0.0f, -1.5f, 0.0f) | 
| 390 |         << Vector3D(0.0f, 100.0f, 0.0f) | 
| 391 |         << 0.0f; | 
| 392 |  | 
| 393 |     QTest::newRow(dataTag: "neg-axis-y to 2" ) | 
| 394 |         << Vector3D(0.0f, 6.0f, 0.0f) | 
| 395 |         << Vector3D(0.0f, -1.5f, 0.0f) | 
| 396 |         << Vector3D(2.0f, 0.0f, 0.0f) | 
| 397 |         << 2.0f; | 
| 398 | } | 
| 399 |  | 
| 400 | void tst_QRay3D::distance() | 
| 401 | { | 
| 402 |     QFETCH(Vector3D, origin); | 
| 403 |     QFETCH(Vector3D, direction); | 
| 404 |     QFETCH(Vector3D, point); | 
| 405 |     QFETCH(float, distance); | 
| 406 |  | 
| 407 |     Qt3DRender::RayCasting::QRay3D line(origin, direction); | 
| 408 |     QCOMPARE(line.distance(point), distance); | 
| 409 | } | 
| 410 |  | 
| 411 | void tst_QRay3D::compare() | 
| 412 | { | 
| 413 |     Qt3DRender::RayCasting::QRay3D ray1(Vector3D(10, 20, 30), Vector3D(-3, -4, -5)); | 
| 414 |     Qt3DRender::RayCasting::QRay3D ray2(Vector3D(10, 20, 30), Vector3D(1.5f, 2.0f, 2.5f)); | 
| 415 |     Qt3DRender::RayCasting::QRay3D ray3(Vector3D(0, 20, 30), Vector3D(-3, -4, -5)); | 
| 416 |     QVERIFY(ray1 == ray1); | 
| 417 |     QVERIFY(!(ray1 != ray1)); | 
| 418 |     QVERIFY(qFuzzyCompare(ray1, ray1)); | 
| 419 |     QVERIFY(ray1 != ray2); | 
| 420 |     QVERIFY(!(ray1 == ray2)); | 
| 421 |     QVERIFY(!qFuzzyCompare(ray1, ray2)); | 
| 422 |     QVERIFY(ray1 != ray3); | 
| 423 |     QVERIFY(!(ray1 == ray3)); | 
| 424 |     QVERIFY(!qFuzzyCompare(ray1, ray3)); | 
| 425 | } | 
| 426 |  | 
| 427 | void tst_QRay3D::dataStream() | 
| 428 | { | 
| 429 | #ifndef QT_NO_DATASTREAM | 
| 430 |     Qt3DRender::RayCasting::QRay3D ray(Vector3D(1.0f, 2.0f, 3.0f), Vector3D(4.0f, 5.0f, 6.0f)); | 
| 431 |  | 
| 432 |     QByteArray data; | 
| 433 |     { | 
| 434 |         QDataStream stream(&data, QIODevice::WriteOnly); | 
| 435 |         stream << ray; | 
| 436 |     } | 
| 437 |  | 
| 438 |     Qt3DRender::RayCasting::QRay3D ray2; | 
| 439 |     { | 
| 440 |         QDataStream stream2(data); | 
| 441 |         stream2 >> ray2; | 
| 442 |     } | 
| 443 |  | 
| 444 |     QVERIFY(ray == ray2); | 
| 445 | #endif | 
| 446 | } | 
| 447 |  | 
| 448 | void tst_QRay3D::transform_data() | 
| 449 | { | 
| 450 |     create_data(); | 
| 451 | } | 
| 452 |  | 
| 453 | void tst_QRay3D::transform() | 
| 454 | { | 
| 455 |     QFETCH(Vector3D, point); | 
| 456 |     QFETCH(Vector3D, direction); | 
| 457 |  | 
| 458 |     Matrix4x4 m; | 
| 459 |     { | 
| 460 |         QMatrix4x4 c; | 
| 461 |         c.translate(x: -1.0f, y: 2.5f, z: 5.0f); | 
| 462 |         c.rotate(angle: 45.0f, x: 1.0f, y: 1.0f, z: 1.0f); | 
| 463 |         c.scale(factor: 23.5f); | 
| 464 |         m = Matrix4x4(c); | 
| 465 |     } | 
| 466 |  | 
| 467 |     Qt3DRender::RayCasting::QRay3D ray1(point, direction); | 
| 468 |     Qt3DRender::RayCasting::QRay3D ray2(ray1); | 
| 469 |     Qt3DRender::RayCasting::QRay3D ray3; | 
| 470 |  | 
| 471 |     ray1.transform(matrix: m); | 
| 472 |     ray3 = ray2.transformed(matrix: m); | 
| 473 |  | 
| 474 |     QVERIFY(fuzzyCompare(ray1.origin(), ray3.origin())); | 
| 475 |     QVERIFY(fuzzyCompare(ray1.direction(), ray3.direction())); | 
| 476 |  | 
| 477 |     QVERIFY(fuzzyCompare(ray1.origin(), m * point)); | 
| 478 |     QVERIFY(fuzzyCompare(ray1.direction(), m.mapVector(direction).normalized())); | 
| 479 | } | 
| 480 |  | 
| 481 | class tst_QRay3DProperties : public QObject | 
| 482 | { | 
| 483 |     Q_OBJECT | 
| 484 |     Q_PROPERTY(Qt3DRender::RayCasting::QRay3D ray READ ray WRITE setRay) | 
| 485 | public: | 
| 486 |     tst_QRay3DProperties(QObject *parent = 0) : QObject(parent) {} | 
| 487 |  | 
| 488 |     Qt3DRender::RayCasting::QRay3D ray() const { return r; } | 
| 489 |     void setRay(const Qt3DRender::RayCasting::QRay3D& value) { r = value; } | 
| 490 |  | 
| 491 | private: | 
| 492 |     Qt3DRender::RayCasting::QRay3D r; | 
| 493 | }; | 
| 494 |  | 
| 495 | // Test getting and setting properties via the metaobject system. | 
| 496 | void tst_QRay3D::properties() | 
| 497 | { | 
| 498 |     tst_QRay3DProperties obj; | 
| 499 |  | 
| 500 |     qRegisterMetaType<Qt3DRender::RayCasting::QRay3D>(); | 
| 501 |  | 
| 502 |     obj.setRay(Qt3DRender::RayCasting::QRay3D(Vector3D(1, 2, 3), Vector3D(4, 5, 6))); | 
| 503 |  | 
| 504 |     Qt3DRender::RayCasting::QRay3D r = qvariant_cast<Qt3DRender::RayCasting::QRay3D>(v: obj.property(name: "ray" )); | 
| 505 |     QCOMPARE(r.origin(), Vector3D(1, 2, 3)); | 
| 506 |     QCOMPARE(r.direction(), Vector3D(4, 5, 6).normalized()); | 
| 507 |  | 
| 508 |     obj.setProperty(name: "ray" , | 
| 509 |                     value: QVariant::fromValue | 
| 510 |                         (value: Qt3DRender::RayCasting::QRay3D(Vector3D(-1, -2, -3), Vector3D(-4, -5, -6)))); | 
| 511 |  | 
| 512 |     r = qvariant_cast<Qt3DRender::RayCasting::QRay3D>(v: obj.property(name: "ray" )); | 
| 513 |     QCOMPARE(r.origin(), Vector3D(-1, -2, -3)); | 
| 514 |     QCOMPARE(r.direction(), Vector3D(-4, -5, -6).normalized()); | 
| 515 | } | 
| 516 |  | 
| 517 | void tst_QRay3D::metaTypes() | 
| 518 | { | 
| 519 |     int id = qMetaTypeId<Qt3DRender::RayCasting::QRay3D>(); | 
| 520 |     QVERIFY(QMetaType::type("Qt3DRender::RayCasting::QRay3D" ) == id); | 
| 521 |     QCOMPARE(QByteArray(QMetaType::typeName(id)), QByteArray("Qt3DRender::RayCasting::QRay3D" )); | 
| 522 |     QVERIFY(QMetaType::isRegistered(id)); | 
| 523 | } | 
| 524 |  | 
| 525 | void tst_QRay3D::shouldNotAllowNullDirection() | 
| 526 | { | 
| 527 |     // GIVEN | 
| 528 |     Qt3DRender::RayCasting::QRay3D ray; | 
| 529 |  | 
| 530 |     QCOMPARE(ray.origin(), Vector3D(0, 0, 0)); | 
| 531 |     QCOMPARE(ray.direction(), Vector3D(0, 0, 1)); | 
| 532 |  | 
| 533 |     // WHEN | 
| 534 |     ray.setDirection(Vector3D(0, 0, 0)); | 
| 535 |  | 
| 536 |     // THEN | 
| 537 |     QCOMPARE(ray.direction(), Vector3D(0, 0, 1)); | 
| 538 | } | 
| 539 |  | 
| 540 | QTEST_APPLESS_MAIN(tst_QRay3D) | 
| 541 |  | 
| 542 | #include "tst_qray3d.moc" | 
| 543 |  |