2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include "dali-scene3d/public-api/algorithm/navigation-mesh.h"
19 #include "dali-scene3d/public-api/loader/navigation-mesh-factory.h"
20 #include <dali-test-suite-utils.h>
23 using namespace Dali::Scene3D::Algorithm;
24 using namespace Dali::Scene3D::Loader;
26 int UtcDaliNavigationMeshCreateFromFileFail1(void)
28 tet_infoline("UtcDaliNavigationMeshCreateFromFileFail1: Fails to create navigation mesh from file");
30 // No such file, misspelled name
31 auto result = NavigationMeshFactory::CreateFromFile("notexisting.bin");
33 DALI_TEST_CHECK(result == nullptr);
38 int UtcDaliNavigationMeshCreateFromFileOk1(void)
40 tet_infoline("UtcDaliNavigationMeshCreateFromFileOk1: Creates navigation mesh using file");
42 auto result = NavigationMeshFactory::CreateFromFile("resources/navmesh-test.bin");
44 DALI_TEST_CHECK(result != nullptr);
49 int UtcDaliNavigationMeshCreateFromBufferP(void)
51 tet_infoline("UtcDaliNavigationMeshCreateFromBufferP: Creates navigation mesh using binary buffer");
53 auto fin = fopen("resources/navmesh-test.bin", "rb");
54 [[maybe_unused]] auto err = fseek(fin, 0, SEEK_END);
55 auto length = ftell(fin);
56 fseek( fin, 0, SEEK_SET);
57 std::vector<uint8_t> buffer;
58 buffer.resize(length);
59 fread( buffer.data(), 1, length, fin );
61 auto result = NavigationMeshFactory::CreateFromBuffer( buffer );
62 DALI_TEST_CHECK(result != nullptr);
67 int UtcDaliNavigationMeshCountersP(void)
69 tet_infoline("UtcDaliNavigationMeshCountersP: Test vertex, edge and face counts");
71 auto result = NavigationMeshFactory::CreateFromFile("resources/navmesh-test.bin");
73 DALI_TEST_CHECK(result != nullptr);
75 auto vertexCount = result->GetVertexCount();
76 auto edgeCount = result->GetEdgeCount();
77 auto faceCount = result->GetFaceCount();
79 DALI_TEST_EQUALS( vertexCount, 132, TEST_LOCATION );
80 DALI_TEST_EQUALS( edgeCount, 300, TEST_LOCATION );
81 DALI_TEST_EQUALS( faceCount, 165, TEST_LOCATION );
86 int UtcDaliNavigationMeshGetVertexP(void)
88 tet_infoline("UtcDaliNavigationMeshGetVertexP: Test vertex getters");
90 auto navmesh = NavigationMeshFactory::CreateFromFile("resources/navmesh-test.bin");
92 DALI_TEST_CHECK(navmesh != nullptr);
94 auto vertexCount = navmesh->GetVertexCount();
96 DALI_TEST_EQUALS( vertexCount, 132, TEST_LOCATION );
98 // List of coords, must be verified with Blender exporter
100 std::vector<float> vertexData = {
101 -7.000000f, -3.000000f, 0.000000f, -4.018748f, 3.000000f, 0.000000f,
102 1.943754f, -1.500000f, 0.000000f, -2.541295f, -0.756627f, 0.000000f,
103 -0.277504f, -1.593252f, 0.000000f, 0.682341f, 2.316388f, 3.349901f,
104 1.912569f, 1.240314f, 2.549901f, 2.215021f, -0.365898f, 1.749901f,
105 1.460422f, -1.815717f, 0.949901f, -0.336699f, -2.992929f, 3.829999f,
106 -3.179410f, 0.153939f, 3.829999f, -3.664814f, 2.992929f, 3.829999f,
107 -1.384417f, 0.876845f, 3.829999f, -1.571236f, 1.101834f, 3.829999f
112 for( auto i = 0u; i < 132; i+= 10, j+= 3)
114 const auto* vertex = navmesh->GetVertex(i);
115 Vector3 v0(vertex->co);
116 Vector3 v1(vertexData[j], vertexData[j+1], vertexData[j+2]);
117 DALI_TEST_EQUALS( v0, v1, TEST_LOCATION);
123 int UtcDaliNavigationMeshGetEdgeP(void)
125 tet_infoline("UtcDaliNavigationMeshGetEdgeP: Test edge getters");
127 auto navmesh = NavigationMeshFactory::CreateFromFile("resources/navmesh-test.bin");
129 DALI_TEST_CHECK(navmesh != nullptr);
131 auto edgeCount = navmesh->GetEdgeCount();
133 DALI_TEST_EQUALS( edgeCount, 300, TEST_LOCATION );
135 // List of coords, must be verified with Blender exporter
137 std::vector<uint16_t> edgeData = {
151 for( auto i = 0u; i < 300; i+= 30, j+= 4)
153 const auto* edge = navmesh->GetEdge(i);
154 auto e0 = edge->face[0];
155 auto e1 = edge->face[1];
156 auto v0 = edge->vertex[0];
157 auto v1 = edge->vertex[1];
159 DALI_TEST_EQUALS(e0, edgeData[j+0], TEST_LOCATION);
160 DALI_TEST_EQUALS(e1, edgeData[j+1], TEST_LOCATION);
161 DALI_TEST_EQUALS(v0, edgeData[j+2], TEST_LOCATION);
162 DALI_TEST_EQUALS(v1, edgeData[j+3], TEST_LOCATION);
168 int UtcDaliNavigationMeshGetFaceP(void)
170 tet_infoline("UtcDaliNavigationMeshGetFaceP: Test face getters");
172 auto navmesh = NavigationMeshFactory::CreateFromFile("resources/navmesh-test.bin");
174 DALI_TEST_CHECK(navmesh != nullptr);
176 auto faceCount = navmesh->GetFaceCount();
178 DALI_TEST_EQUALS( faceCount, 165, TEST_LOCATION );
180 // List of coords, must be verified with Blender exporter
183 std::vector<NavigationMesh::Face> faceData = {
184 {{6, 10, 17}, {14, 32, 8}, {0.000000f, 0.000000f, 1.000000f}, {-3.024998f, 2.500000f, 0.000000f}},
185 {{130, 120, 44}, {228, 215, 33}, {0.000000f, 0.000000f, 1.000000f}, {-1.097451f, 1.192811f, 3.829999f}},
186 {{30, 9, 38}, {13, 291, 289}, {0.000000f, -0.000000f, 1.000000f}, {-3.029388f, -1.252209f, 0.000000f}},
187 {{55, 52, 53}, {140, 95, 96}, {0.522345f, -0.298279f, 0.798865f}, {0.743287f, 1.610713f, 3.136567f}},
188 {{69, 66, 67}, {91, 121, 122}, {0.071722f, -0.597219f, 0.798865f}, {1.632142f, 0.155658f, 2.016567f}},
189 {{41, 86, 87}, {81, 160, 80}, {-0.563316f, -0.210929f, 0.798864f}, {0.340215f, -1.799765f, 0.416567f}},
190 {{28, 19, 27}, {55, 74, 47}, {0.000000f, -0.000000f, 1.000000f}, {-0.640862f, -1.037395f, 0.000000f}},
191 {{118, 96, 111}, {213, 241, 240}, {0.000000f, 0.000000f, 1.000000f}, {-6.577459f, -0.586560f, 3.829999f}},
192 {{91, 107, 103}, {170, 258, 257}, {-0.021129f, 0.023143f, 0.999509f}, {-2.551766f, 1.007552f, 3.829145f}},
193 {{97, 120, 130}, {191, 228, 271}, {0.000000f, 0.000000f, 1.000000f}, {-1.795930f, 0.710873f, 3.829999f}},
194 {{30, 39, 31}, {290, 296, 295}, {0.000000f, 0.000000f, 1.000000f}, {-2.291577f, -0.509718f, 0.000000f}},
198 for( auto i = 0u; i < 165; i+= 16, j++)
200 const auto* face = navmesh->GetFace(i);
201 Vector3 n0(face->normal);
202 Vector3 c0(face->center);
204 Vector3 n1(faceData[j].normal);
205 Vector3 c1(faceData[j].center);
207 DALI_TEST_EQUALS( n0, n1, TEST_LOCATION);
208 DALI_TEST_EQUALS( c0, c1, TEST_LOCATION);
210 DALI_TEST_EQUALS( faceData[j].vertex[0], face->vertex[0], TEST_LOCATION);
211 DALI_TEST_EQUALS( faceData[j].vertex[1], face->vertex[1], TEST_LOCATION);
212 DALI_TEST_EQUALS( faceData[j].vertex[2], face->vertex[2], TEST_LOCATION);
214 DALI_TEST_EQUALS( faceData[j].edge[0], face->edge[0], TEST_LOCATION);
215 DALI_TEST_EQUALS( faceData[j].edge[1], face->edge[1], TEST_LOCATION);
216 DALI_TEST_EQUALS( faceData[j].edge[2], face->edge[2], TEST_LOCATION);
223 int UtcDaliNavigationGetGravityP(void)
225 tet_infoline("UtcDaliNavigationGetGravityP: Tests gravity vector");
226 auto navmesh = NavigationMeshFactory::CreateFromFile("resources/navmesh-test.bin");
227 auto gravity = navmesh->GetGravityVector();
229 // navmesh-test.bin is exported in Blender and the default gravity is Z = -1
230 Dali::Vector3 expectedGravity( 0.0f, 0.0f, -1.0f );
232 DALI_TEST_EQUALS( gravity, expectedGravity, TEST_LOCATION);
237 int UtcDaliNavigationSetTransformP(void)
239 tet_infoline("UtcDaliNavigationSetTransformP: Test setting transform");
241 auto navmesh = NavigationMeshFactory::CreateFromFile("resources/navmesh-test.bin");
244 matrix.SetIdentity();
245 Quaternion q = Quaternion( Radian(Degree(-90)), Vector3(1.0, 0.0, 0.0));
247 matrix.Multiply( newMatrix, matrix, q); // Rotate matrix along X-axis
249 navmesh->SetSceneTransform(newMatrix);
251 auto point = Vector3(0, 1, 0);
253 [[maybe_unused]] Vector3 navMeshLocalSpace;
254 [[maybe_unused]] Vector3 navMeshParentSpace;
255 navMeshLocalSpace = navmesh->PointSceneToLocal(point);
257 // Should match gravity vector
258 auto gravityVector = navmesh->GetGravityVector();
260 // 'point' should be turned into the gravity vector after transforming into the local space
261 DALI_TEST_EQUALS( navMeshLocalSpace, gravityVector, TEST_LOCATION);
263 navMeshParentSpace = navmesh->PointLocalToScene(gravityVector);
265 // The gravity should be transformed back into point
266 DALI_TEST_EQUALS( navMeshParentSpace, point, TEST_LOCATION);
271 int UtcDaliNavigationFindFloor0P(void)
273 tet_infoline("UtcDaliNavigationFindFloor0P: Finds floor with result");
275 auto navmesh = NavigationMeshFactory::CreateFromFile("resources/navmesh-test.bin");
277 // All calculations in the navmesh local space
278 navmesh->SetSceneTransform(Matrix(Matrix::IDENTITY));
280 std::vector<Vector3> inPositions;
281 std::vector<Vector3> expectedPositions;
282 std::vector<uint32_t> expectedFaceIndex;
283 std::vector<bool> expectedResult;
285 // Lift slightly over the floor level
286 auto upFromGravity = navmesh->GetGravityVector() * (0.05f);
288 auto size = navmesh->GetFaceCount();
289 for( auto i = 0u; i < size; ++i)
291 const auto* face = navmesh->GetFace(i);
292 Vector3(face->center);
293 inPositions.emplace_back(Vector3(face->center));
294 inPositions.back() -= Vector3( upFromGravity );
295 expectedResult.emplace_back(true);
297 expectedPositions.emplace_back(face->center);
298 expectedFaceIndex.emplace_back(i);
301 // Add negative results
302 // Middle 'circle' of scene
303 inPositions.emplace_back(Vector3(-0.048838f, 0.039285f, 0.013085f));
304 expectedPositions.emplace_back();
305 expectedFaceIndex.emplace_back( NavigationMesh::NULL_FACE );
306 expectedResult.emplace_back(false);
308 // Triangle under stairs
309 inPositions.emplace_back(Vector3(0.44365f, -1.787f, 0.13085f));
310 expectedPositions.emplace_back();
311 expectedFaceIndex.emplace_back( NavigationMesh::NULL_FACE );
312 expectedResult.emplace_back(false);
315 inPositions.emplace_back(Vector3(0.77197f, -3.8596f, 0.13085f));
316 expectedPositions.emplace_back();
317 expectedFaceIndex.emplace_back( NavigationMesh::NULL_FACE );
318 expectedResult.emplace_back(false);
320 for( auto i = 0u; i < inPositions.size(); ++i )
323 uint32_t faceIndex {NavigationMesh::NULL_FACE};
324 auto result = navmesh->FindFloor(inPositions[i], outPosition, faceIndex);
325 DALI_TEST_EQUALS( bool(result), bool(expectedResult[i]), TEST_LOCATION);
326 DALI_TEST_EQUALS( faceIndex, expectedFaceIndex[i], TEST_LOCATION);
327 DALI_TEST_EQUALS( outPosition, expectedPositions[i], TEST_LOCATION);
333 int UtcDaliNavigationFindFloorForFace1P(void)
335 tet_infoline("UtcDaliNavigationFindFloorForFace1P: Finds floor for selected face");
337 auto navmesh = NavigationMeshFactory::CreateFromFile("resources/navmesh-test.bin");
339 // All calculations in the navmesh local space
340 navmesh->SetSceneTransform(Matrix(Matrix::IDENTITY));
344 auto position = Vector3( 0, 0, 0);
345 auto dontCheckNeighbours = true;
346 auto outPosition = Vector3();
347 auto expectedPosition = Vector3();
351 // test 1. position lies within selected triangle
353 position = Vector3(-6.0767f, -1.7268f, 4.287f);
354 expectedPosition = Vector3(-6.0767f, -1.7268f, 3.83f);
355 dontCheckNeighbours = true;
356 result = navmesh->FindFloorForFace(position, faceIndex, dontCheckNeighbours, outPosition);
358 DALI_TEST_EQUALS( result, true, TEST_LOCATION);
359 DALI_TEST_EQUALS( outPosition, expectedPosition, TEST_LOCATION);
363 // test 2. position lies outside selected triangle, not checking neighbours
365 position = Vector3(-5.3073f, -0.6023f, 4.287f);
366 expectedPosition = Vector3::ZERO;
367 outPosition = Vector3::ZERO;
368 dontCheckNeighbours = true;
369 result = navmesh->FindFloorForFace(position, faceIndex, dontCheckNeighbours, outPosition);
371 DALI_TEST_EQUALS( result, false, TEST_LOCATION);
372 DALI_TEST_EQUALS( outPosition, expectedPosition, TEST_LOCATION);
376 // test 3. position lies outside selected triangle but this time checking neighbours
378 position = Vector3(-5.3073f, -0.6023f, 4.287f);
379 expectedPosition = Vector3(-5.3073, -0.6023, 3.83);
380 outPosition = Vector3::ZERO;
381 dontCheckNeighbours = false;
382 result = navmesh->FindFloorForFace(position, faceIndex, dontCheckNeighbours, outPosition);
384 DALI_TEST_EQUALS( result, true, TEST_LOCATION);
385 DALI_TEST_EQUALS( outPosition, expectedPosition, TEST_LOCATION);
392 int UtcDaliNavigationFindFloorForFace2P(void)
394 tet_infoline("UtcDaliNavigationFindFloorForFace2P: Finds floor for selected face");
396 auto navmesh = NavigationMeshFactory::CreateFromFile("resources/navmesh-test.bin");
398 // All calculations in the navmesh local space
399 navmesh->SetSceneTransform(Matrix(Matrix::IDENTITY));
402 [[maybe_unused]] auto faceIndex = 0u;
403 auto position = Vector3( 0, 0, 0);
404 auto dontCheckNeighbours = true;
405 auto outPosition = Vector3();
406 auto expectedPosition = Vector3();
410 // test 4. position lies within a triangle but this time full search forced,
411 // the navmesh must have no previous searches (mCurrentFace shouldn't be set)
413 position = Vector3(-6.0767f, -1.7268f, 4.287f);
414 expectedPosition = Vector3(-6.0767f, -1.7268f, 3.83f);
415 dontCheckNeighbours = true;
416 result = navmesh->FindFloorForFace(position, NavigationMesh::NULL_FACE, dontCheckNeighbours, outPosition);
418 DALI_TEST_EQUALS( result, true, TEST_LOCATION);
419 DALI_TEST_EQUALS( outPosition, expectedPosition, TEST_LOCATION);