1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt3D module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include <QtTest/QtTest> |
30 | #include <Qt3DRender/private/entity_p.h> |
31 | #include <Qt3DRender/private/triangleboundingvolume_p.h> |
32 | #include <Qt3DRender/private/qraycastingservice_p.h> |
33 | #include <Qt3DRender/private/qray3d_p.h> |
34 | #include <Qt3DRender/qcameralens.h> |
35 | #include <Qt3DRender/qcamera.h> |
36 | #include <Qt3DRender/private/qboundingvolume_p.h> |
37 | |
38 | class tst_TriangleBoundingVolume : public QObject |
39 | { |
40 | Q_OBJECT |
41 | public: |
42 | tst_TriangleBoundingVolume() {} |
43 | ~tst_TriangleBoundingVolume() {} |
44 | |
45 | private Q_SLOTS: |
46 | void checkInitialState() |
47 | { |
48 | // GIVEN |
49 | Qt3DRender::Render::TriangleBoundingVolume volume = Qt3DRender::Render::TriangleBoundingVolume(Qt3DCore::QNodeId(), |
50 | Vector3D(), |
51 | Vector3D(), |
52 | Vector3D()); |
53 | |
54 | // THEN |
55 | QCOMPARE(volume.id(), Qt3DCore::QNodeId()); |
56 | QCOMPARE(volume.a(), Vector3D()); |
57 | QCOMPARE(volume.b(), Vector3D()); |
58 | QCOMPARE(volume.c(), Vector3D()); |
59 | QCOMPARE(volume.type(), Qt3DRender::RayCasting::QBoundingVolume::Triangle); |
60 | } |
61 | |
62 | void transformed_data() |
63 | { |
64 | QTest::addColumn<Vector3D>(name: "a" ); |
65 | QTest::addColumn<Vector3D>(name: "b" ); |
66 | QTest::addColumn<Vector3D>(name: "c" ); |
67 | |
68 | QTest::addColumn<Vector3D>(name: "transformedA" ); |
69 | QTest::addColumn<Vector3D>(name: "transformedB" ); |
70 | QTest::addColumn<Vector3D>(name: "transformedC" ); |
71 | |
72 | QTest::newRow(dataTag: "onFarPlane" ) |
73 | << Vector3D(-1.0, 1.0, 0.0) |
74 | << Vector3D(0.0, -1.0, 0.0) |
75 | << Vector3D(1.0, 1.0, 0.0) |
76 | << Vector3D(-1.0, 1.0, -40.0) |
77 | << Vector3D(0.0, -1.0, -40.0) |
78 | << Vector3D(1.0, 1.0, -40.0); |
79 | |
80 | QTest::newRow(dataTag: "onNearPlane" ) |
81 | << Vector3D(-1.0, 1.0, 40.0) |
82 | << Vector3D(0.0, -1.0, 40.0) |
83 | << Vector3D(1.0, 1.0, 40.0) |
84 | << Vector3D(-1.0, 1.0, 0.0) |
85 | << Vector3D(0.0, -1.0, 0.0) |
86 | << Vector3D(1.0, 1.0, 0.0); |
87 | |
88 | |
89 | } |
90 | |
91 | void transformed() |
92 | { |
93 | // GIVEN |
94 | QFETCH(Vector3D, a); |
95 | QFETCH(Vector3D, b); |
96 | QFETCH(Vector3D, c); |
97 | QFETCH(Vector3D, transformedA); |
98 | QFETCH(Vector3D, transformedB); |
99 | QFETCH(Vector3D, transformedC); |
100 | Qt3DRender::Render::TriangleBoundingVolume volume(Qt3DCore::QNodeId(), |
101 | a, |
102 | b, |
103 | c); |
104 | Qt3DRender::QCamera camera; |
105 | camera.setProjectionType(Qt3DRender::QCameraLens::PerspectiveProjection); |
106 | camera.setFieldOfView(45.0f); |
107 | camera.setAspectRatio(800.0f/600.0f); |
108 | camera.setNearPlane(0.1f); |
109 | camera.setFarPlane(1000.0f); |
110 | camera.setPosition(QVector3D(0.0f, 0.0f, 40.0f)); |
111 | camera.setUpVector(QVector3D(0.0f, 1.0f, 0.0f)); |
112 | camera.setViewCenter(QVector3D(0.0f, 0.0f, 0.0f)); |
113 | |
114 | const Matrix4x4 viewMatrix(camera.viewMatrix()); |
115 | |
116 | // WHEN |
117 | volume.transform(mat: viewMatrix); |
118 | |
119 | // THEN |
120 | QCOMPARE(transformedA, volume.a()); |
121 | QCOMPARE(transformedB, volume.b()); |
122 | QCOMPARE(transformedC, volume.c()); |
123 | } |
124 | |
125 | void intersects_data() |
126 | { |
127 | QTest::addColumn<Qt3DRender::RayCasting::QRay3D>(name: "ray" ); |
128 | QTest::addColumn<Vector3D>(name: "a" ); |
129 | QTest::addColumn<Vector3D>(name: "b" ); |
130 | QTest::addColumn<Vector3D>(name: "c" ); |
131 | QTest::addColumn<Vector3D>(name: "uvw" ); |
132 | QTest::addColumn<float>(name: "t" ); |
133 | QTest::addColumn<bool>(name: "isIntersecting" ); |
134 | |
135 | const float farPlaneDistance = 40.0; |
136 | |
137 | QTest::newRow(dataTag: "halfway_center" ) |
138 | << Qt3DRender::RayCasting::QRay3D(Vector3D(), Vector3D(0.0, 0.0, 1.0), farPlaneDistance) |
139 | << Vector3D(3.0, 1.5, 20.0) |
140 | << Vector3D(0.0, -1.5, 20.0) |
141 | << Vector3D(-3, 1.5, 20.0) |
142 | << Vector3D(0.25, 0.5, 0.25) |
143 | << 0.5f |
144 | << true; |
145 | QTest::newRow(dataTag: "miss_halfway_center_too_short" ) |
146 | << Qt3DRender::RayCasting::QRay3D(Vector3D(), Vector3D(0.0, 0.0, 1.0), farPlaneDistance * 0.25f) |
147 | << Vector3D(3.0, 1.5, 20.0) |
148 | << Vector3D(0.0, -1.5, 20.0) |
149 | << Vector3D(-3, 1.5, 20.0) |
150 | << Vector3D() |
151 | << 0.0f |
152 | << false; |
153 | QTest::newRow(dataTag: "far_center" ) |
154 | << Qt3DRender::RayCasting::QRay3D(Vector3D(), Vector3D(0.0, 0.0, 1.0), farPlaneDistance) |
155 | << Vector3D(3.0, 1.5, 40.0) |
156 | << Vector3D(0.0, -1.5, 40.0) |
157 | << Vector3D(-3, 1.5, 40.0) |
158 | << Vector3D(0.25, 0.5, 0.25) |
159 | << 1.0f |
160 | << true; |
161 | QTest::newRow(dataTag: "near_center" ) |
162 | << Qt3DRender::RayCasting::QRay3D(Vector3D(), Vector3D(0.0, 0.0, 1.0), 1.0f) |
163 | << Vector3D(3.0, 1.5, 0.0) |
164 | << Vector3D(0.0, -1.5, 0.0) |
165 | << Vector3D(-3, 1.5, 0.0) |
166 | << Vector3D(0.25, 0.5, 0.25) |
167 | << 0.0f |
168 | << true; |
169 | QTest::newRow(dataTag: "above_miss_center" ) |
170 | << Qt3DRender::RayCasting::QRay3D(Vector3D(0.0, 2.0, 0.0), Vector3D(0.0, 2.0, 1.0), 1.0f) |
171 | << Vector3D(3.0, 1.5, 0.0) |
172 | << Vector3D(0.0, -1.5, 0.0) |
173 | << Vector3D(-3, 1.5, 0.0) |
174 | << Vector3D() |
175 | << 0.0f |
176 | << false; |
177 | QTest::newRow(dataTag: "below_miss_center" ) |
178 | << Qt3DRender::RayCasting::QRay3D(Vector3D(0.0, -2.0, 0.0), Vector3D(0.0, -2.0, 1.0), 1.0f) |
179 | << Vector3D(3.0, 1.5, 0.0) |
180 | << Vector3D(0.0, -1.5, 0.0) |
181 | << Vector3D(-3, 1.5, 0.0) |
182 | << Vector3D() |
183 | << 0.0f |
184 | << false; |
185 | } |
186 | |
187 | void intersects() |
188 | { |
189 | // GIVEN |
190 | QFETCH(Qt3DRender::RayCasting::QRay3D, ray); |
191 | QFETCH(Vector3D, a); |
192 | QFETCH(Vector3D, b); |
193 | QFETCH(Vector3D, c); |
194 | QFETCH(Vector3D, uvw); |
195 | QFETCH(float, t); |
196 | QFETCH(bool, isIntersecting); |
197 | |
198 | // WHEN |
199 | Vector3D tmp_uvw; |
200 | float tmp_t; |
201 | const bool shouldBeIntersecting = Qt3DRender::Render::intersectsSegmentTriangle(ray, |
202 | a, b, c, |
203 | uvw&: tmp_uvw, |
204 | t&: tmp_t); |
205 | |
206 | // THEN |
207 | QCOMPARE(shouldBeIntersecting, isIntersecting); |
208 | if (isIntersecting) { |
209 | QVERIFY(qFuzzyCompare(uvw, tmp_uvw)); |
210 | QVERIFY(qFuzzyCompare(t, tmp_t)); |
211 | } |
212 | } |
213 | }; |
214 | |
215 | QTEST_APPLESS_MAIN(tst_TriangleBoundingVolume) |
216 | |
217 | #include "tst_triangleboundingvolume.moc" |
218 | |