[dali_2.3.21] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / algorithm / navigation-mesh.h
1 #ifndef DALI_SCENE3D_NAVIGATION_MESH_H
2 #define DALI_SCENE3D_NAVIGATION_MESH_H
3
4 /*
5  * Copyright (c) 2024 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 // EXTERNAL INCLUDES
21 #include <dali/public-api/common/vector-wrapper.h>
22 #include <dali/public-api/math/matrix.h>
23 #include <dali/public-api/math/vector3.h>
24 #include <dali/public-api/math/vector4.h>
25
26 #include <cinttypes>
27 #include <cstdio>
28 #include <limits>
29 #include <memory>
30
31 // INTERNAL INCLUDES
32 #include <dali-scene3d/public-api/api.h>
33
34 namespace Dali::Scene3D::Internal::Algorithm
35 {
36 class NavigationMesh;
37 }
38
39 namespace Dali::Scene3D::Loader
40 {
41 class NavigationMeshFactory;
42 }
43
44 constexpr auto NAVIGATION_MESH_MAX_VERTICES_PER_FACE = 3u;
45 constexpr auto NAVIGATION_MESH_MAX_EDGES_PER_FACE    = 3u;
46 constexpr auto NAVIGATION_MESH_MAX_COMPONENTS_3D     = 3u;
47 constexpr auto NAVIGATION_MESH_MAX_COMPONENTS_2D     = 2u;
48
49 namespace Dali::Scene3D::Algorithm
50 {
51 // Using PImpling but not usual DALi handles as this object isn't supposed to be refcounted
52 using NavigationMeshImpl = Dali::Scene3D::Internal::Algorithm::NavigationMesh;
53
54 // Make each to change each index value's type here.
55 using VertexIndex = uint16_t;
56 using EdgeIndex   = uint16_t;
57 using FaceIndex   = uint16_t;
58
59 /**
60  * @class NavigationMesh
61  *
62  * NavigationMesh is a set of connected faces. The data contains
63  * Polygons (Polys), Edges and Vertices and describes relations
64  * between (for example, edge knows which polys are on each side).
65  *
66  * NavigationMesh uses any coordinate system that it has been exported with.
67  *
68  * The mesh is exported with gravity direction. This is because various editors
69  * may define UP vector differently. Note, the Gravity vector points DOWN.
70  *
71  * - All calculation take place in the navigation mesh local space
72  * - The NavigationMesh should use a correct transformation matrix (SetSceneTransform())
73  * - Without transform, the NavigationMesh space stays local (compatible with exporter tool)
74  * - The NavigationMesh defines Gravity vector (down)
75  * - The finding floor results are returned back into the scene space (set with SetSceneTransform()).
76  *
77  */
78 class DALI_SCENE3D_API NavigationMesh
79 {
80 public:
81   /**
82    * @struct Face
83    *
84    * Describes a single polygon's face
85    */
86   struct Face
87   {
88     VertexIndex vertex[NAVIGATION_MESH_MAX_VERTICES_PER_FACE]; ///< Vertices per face
89     EdgeIndex   edge[NAVIGATION_MESH_MAX_EDGES_PER_FACE];      ///< Edges per face
90     float       normal[NAVIGATION_MESH_MAX_COMPONENTS_3D];     ///< Normal vector
91     float       center[NAVIGATION_MESH_MAX_COMPONENTS_3D];     ///< Barycentric coordinates
92   };
93
94   /**
95    * @struct Edge
96    *
97    * Describes a single edge
98    */
99   struct Edge
100   {
101     VertexIndex vertex[NAVIGATION_MESH_MAX_COMPONENTS_2D]; ///< Vertices making the edge
102     FaceIndex   face[NAVIGATION_MESH_MAX_COMPONENTS_2D];   ///< Faces on both sides of edge
103   };
104
105   /**
106    * @struct Vertex
107    *
108    * Describes a single Vertex
109    *
110    */
111   struct Vertex
112   {
113     union
114     {
115       float coordinates[NAVIGATION_MESH_MAX_COMPONENTS_3D]; ///< Coordinates of vertex
116       struct
117       {
118         float x, y, z;
119       };
120     };
121   };
122
123   NavigationMesh() = delete;
124
125 public:
126   /**
127    * @brief Destructor
128    */
129   ~NavigationMesh();
130
131   /**
132    * @brief Returns total number of faces
133    *
134    * @return number of faces
135    */
136   [[nodiscard]] uint32_t GetFaceCount() const;
137
138   /**
139    * @brief Returns total number of edges
140    *
141    * @return number of edges
142    */
143   [[nodiscard]] uint32_t GetEdgeCount() const;
144
145   /**
146    * @brief Returns total number of vertices
147    *
148    * @return number of vertices
149    */
150   [[nodiscard]] uint32_t GetVertexCount() const;
151
152   /**
153    * @brief Looks for the floor under specified position
154    * @param[in] position Position to investigate
155    * @param[out] outPosition Position on the floor in found
156    * @param[out] outFaceIndex Index of NavigationMesh face associated with floor
157    *
158    * @return True if floor has been found, False otherwise
159    */
160   bool FindFloor(const Dali::Vector3& position, Dali::Vector3& outPosition, FaceIndex& outFaceIndex);
161
162   /**
163    * @brief Looks for a floor starting from specified face
164    *
165    * The function performs lookup starting from the specified face. If 'dontCheckNeighbours' is 'true'
166    * then function will fail if 'position' falls outside boundries of face. If 'dontCheckNeighbours'
167    * is 'false' the function will continue search expanding onto neighbouring faces.
168    *
169    * @param[in] position Position to investigate
170    * @param[in] faceIndex Face index to start lookup
171    * @param[in] dontCheckNeighbours If true, the neighbouring faces won't be tested
172    * @param[out] outPosition Result of lookup
173    *
174    * @return True on success, false otherwise
175    */
176   bool FindFloorForFace(const Dali::Vector3& position, FaceIndex faceIndex, bool dontCheckNeighbours, Dali::Vector3& outPosition);
177
178   /**
179    * @brief Returns pointer to Face structure
180    * @param[in] index Index of face to retrieve
181    * @return Pointer to valid Face structure or nullptr
182    */
183   [[nodiscard]] const Face* GetFace(FaceIndex index) const;
184
185   /**
186    * @brief Returns edge structure
187    * @param[in] index Index of edge to retrieve
188    * @return Pointer to valid Edge structure or nullptr
189    */
190   [[nodiscard]] const Edge* GetEdge(EdgeIndex index) const;
191
192   /**
193    * @brief Returns vertex structure
194    * @param[in] index Index of vertex to retrieve
195    * @return Pointer to valid Vertex structure or nullptr
196    */
197   [[nodiscard]] const Vertex* GetVertex(VertexIndex index) const;
198
199   /**
200    * @brief Sets static transform for the navigation mesh object
201    *
202    * The NavigationMesh may require to be transformed into the coordinates
203    * of the scene object. The exporter exports navigation geometry in a local
204    * space. The transform must be set in order to use the navigation mesh
205    * in the scene space (most likely DALi coordinate space).
206    *
207    * The scene transform matrix can be set in the DALi event thread using
208    * Dali::DevelActor::GetWorldTransform(sceneActor)
209    *
210    * For example:
211    * @code
212    * Actor parentActorOfNavigationMesh; // non-null object
213    * Dali::DevelActor::GetWorldTransform(parentActorOfNavigationMesh);
214    * navigationMesh->SetSceneTransform(parentActorOfNavigationMesh);
215    * @endcode
216    *
217    * The transform remains static until changed by calling SetSceneTransform() again.
218    * It means that if the matrix is obtained from the actor and actor transform will
219    * change the navigation mesh won't be aligned anymore.
220    *
221    * @param[in] transform Valid transform 4x4 matrix
222    */
223   void SetSceneTransform(const Dali::Matrix& transform);
224
225   /**
226    * @brief transforms point into the NavigationMesh local space
227    *
228    * Transforms a 3D point into navigation mesh space (space used when
229    * NavigationMesh has been created, most likely 3D editor space).
230    *
231    * @param[in] point Point to transform
232    * @return Point transformed to the local space
233    */
234   Dali::Vector3 PointSceneToLocal(const Dali::Vector3& point) const;
235
236   /**
237    * @brief Transforms point into the parent transform space
238    *
239    * Transforms the given point into the parent space (set with SetSceneTransform()).
240    *
241    * @param[in] point Point to transform
242    * @return Point transformed into the parent space
243    */
244   Dali::Vector3 PointLocalToScene(const Dali::Vector3& point) const;
245
246   /**
247    * @brief Returns direction of the gravity vector
248    *
249    * Gravity vector points down.
250    *
251    * @return Gravity vector 3D
252    */
253   Dali::Vector3 GetGravityVector() const;
254
255   /**
256    * @brief Performs ray/face intersect test
257    * @param[in] origin Origin of ray
258    * @param[in] direction Direction of ray
259    *
260    * @SINCE_2_2.53
261    * @return Valid FaceIndex on hit or NULL_FACE on miss
262    */
263   [[nodiscard]] FaceIndex RayFaceIntersect(const Vector3& origin, const Vector3& direction) const;
264
265   static constexpr FaceIndex NULL_FACE{std::numeric_limits<FaceIndex>::max()}; ///< Represents null face
266   static constexpr EdgeIndex NULL_EDGE{std::numeric_limits<EdgeIndex>::max()}; ///< Represents null edge
267
268 public:
269   DALI_INTERNAL explicit NavigationMesh(NavigationMeshImpl* impl);
270
271   std::unique_ptr<NavigationMeshImpl> mImpl;
272 };
273
274 // Alias name for collider mesh
275 // TODO: currently ColliderMesh is NavigationMesh however
276 //       there should be separation from data and algorithms.
277 //       Both, NavigationMesh and ColliderMesh use the same
278 //       data structures but differ in the way they use data.
279 using ColliderMesh = NavigationMesh;
280
281 } // namespace Dali::Scene3D::Algorithm
282 #endif // DALI_SCENE3D_NAVIGATION_MESH_H