Let navigation mesh use same type for Index
[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) 2023 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 <memory>
29
30 // INTERNAL INCLUDES
31 #include <dali-scene3d/public-api/api.h>
32
33 namespace Dali::Scene3D::Internal::Algorithm
34 {
35 class NavigationMesh;
36 }
37
38 namespace Dali::Scene3D::Loader
39 {
40 class NavigationMeshFactory;
41 }
42
43 constexpr auto NAVIGATION_MESH_MAX_VERTICES_PER_FACE = 3u;
44 constexpr auto NAVIGATION_MESH_MAX_EDGES_PER_FACE    = 3u;
45 constexpr auto NAVIGATION_MESH_MAX_COMPONENTS_3D     = 3u;
46 constexpr auto NAVIGATION_MESH_MAX_COMPONENTS_2D     = 2u;
47
48 namespace Dali::Scene3D::Algorithm
49 {
50 // Using PImpling but not usual DALi handles as this object isn't supposed to be refcounted
51 using NavigationMeshImpl = Dali::Scene3D::Internal::Algorithm::NavigationMesh;
52
53 // Make each to change each index value's type here.
54 using VertexIndex = uint16_t;
55 using EdgeIndex   = uint16_t;
56 using FaceIndex   = uint16_t;
57
58 /**
59  * @class NavigationMesh
60  *
61  * NavigationMesh is a set of connected faces. The data contains
62  * Polygons (Polys), Edges and Vertices and describes relations
63  * between (for example, edge knows which polys are on each side).
64  *
65  * NavigationMesh uses any coordinate system that it has been exported with.
66  *
67  * The mesh is exported with gravity direction. This is because various editors
68  * may define UP vector differently. Note, the Gravity vector points DOWN.
69  *
70  * - All calculation take place in the navigation mesh local space
71  * - The NavigationMesh should use a correct transformation matrix (SetSceneTransform())
72  * - Without transform, the NavigationMesh space stays local (compatible with exporter tool)
73  * - The NavigationMesh defines Gravity vector (down)
74  * - The finding floor results are returned back into the scene space (set with SetSceneTransform()).
75  *
76  */
77 class DALI_SCENE3D_API NavigationMesh
78 {
79 public:
80   /**
81    * @struct Face
82    *
83    * Describes a single polygon's face
84    */
85   struct Face
86   {
87     VertexIndex vertex[NAVIGATION_MESH_MAX_VERTICES_PER_FACE]; ///< Vertices per face
88     EdgeIndex   edge[NAVIGATION_MESH_MAX_EDGES_PER_FACE];      ///< Edges per face
89     float       normal[NAVIGATION_MESH_MAX_COMPONENTS_3D];     ///< Normal vector
90     float       center[NAVIGATION_MESH_MAX_COMPONENTS_3D];     ///< Barycentric coordinates
91   };
92
93   /**
94    * @struct Edge
95    *
96    * Describes a single edge
97    */
98   struct Edge
99   {
100     VertexIndex vertex[NAVIGATION_MESH_MAX_COMPONENTS_2D]; ///< Vertices making the edge
101     FaceIndex   face[NAVIGATION_MESH_MAX_COMPONENTS_2D];   ///< Faces on both sides of edge
102   };
103
104   /**
105    * @struct Vertex
106    *
107    * Describes a single Vertex
108    *
109    */
110   struct Vertex
111   {
112     union
113     {
114       float coordinates[NAVIGATION_MESH_MAX_COMPONENTS_3D]; ///< Coordinates of vertex
115       struct
116       {
117         float x, y, z;
118       };
119     };
120   };
121
122   NavigationMesh() = delete;
123
124 public:
125   /**
126    * @brief Destructor
127    */
128   ~NavigationMesh();
129
130   /**
131    * @brief Returns total number of faces
132    *
133    * @return number of faces
134    */
135   [[nodiscard]] uint32_t GetFaceCount() const;
136
137   /**
138    * @brief Returns total number of edges
139    *
140    * @return number of edges
141    */
142   [[nodiscard]] uint32_t GetEdgeCount() const;
143
144   /**
145    * @brief Returns total number of vertices
146    *
147    * @return number of vertices
148    */
149   [[nodiscard]] uint32_t GetVertexCount() const;
150
151   /**
152    * @brief Looks for the floor under specified position
153    * @param[in] position Position to investigate
154    * @param[in] outPosition Position on the floor in found
155    * @param[out] faceIndex Index of NavigationMesh face associated with floor
156    *
157    * @return True if floor has been found, False otherwise
158    */
159   bool FindFloor(const Dali::Vector3& position, Dali::Vector3& outPosition, FaceIndex& faceIndex);
160
161   /**
162    * @brief Looks for a floor starting from specified face
163    *
164    * The function performs lookup starting from the specified face. If 'dontCheckNeighbours' is 'true'
165    * then function will fail if 'position' falls outside boundries of face. If 'dontCheckNeighbours'
166    * is 'false' the function will continue search expanding onto neighbouring faces.
167    *
168    * @param[in] position Position to investigate
169    * @param[in] faceIndex Face index to start lookup
170    * @param[in] dontCheckNeighbours If true, the neighbouring faces won't be tested
171    * @param[out] outPosition Result of lookup
172    *
173    * @return True on success, false otherwise
174    */
175   bool FindFloorForFace(const Dali::Vector3& position, FaceIndex faceIndex, bool dontCheckNeighbours, Dali::Vector3& outPosition);
176
177   /**
178    * @brief Returns pointer to Face structure
179    * @param[in] index Index of face to retrieve
180    * @return Pointer to valid Face structure or nullptr
181    */
182   [[nodiscard]] const Face* GetFace(FaceIndex index) const;
183
184   /**
185    * @brief Returns edge structure
186    * @param[in] index Index of edge to retrieve
187    * @return Pointer to valid Edge structure or nullptr
188    */
189   [[nodiscard]] const Edge* GetEdge(EdgeIndex index) const;
190
191   /**
192    * @brief Returns vertex structure
193    * @param[in] index Index of vertex to retrieve
194    * @return Pointer to valid Vertex structure or nullptr
195    */
196   [[nodiscard]] const Vertex* GetVertex(VertexIndex index) const;
197
198   /**
199    * @brief Sets static transform for the navigation mesh object
200    *
201    * The NavigationMesh may require to be transformed into the coordinates
202    * of the scene object. The exporter exports navigation geometry in a local
203    * space. The transform must be set in order to use the navigation mesh
204    * in the scene space (most likely DALi coordinate space).
205    *
206    * The scene transform matrix can be set in the DALi event thread using
207    * Dali::DevelActor::GetWorldTransform(sceneActor)
208    *
209    * For example:
210    * @code
211    * Actor parentActorOfNavigationMesh; // non-null object
212    * Dali::DevelActor::GetWorldTransform(parentActorOfNavigationMesh);
213    * navigationMesh->SetSceneTransform(parentActorOfNavigationMesh);
214    * @endcode
215    *
216    * The transform remains static until changed by calling SetSceneTransform() again.
217    * It means that if the matrix is obtained from the actor and actor transform will
218    * change the navigation mesh won't be aligned anymore.
219    *
220    * @param[in] transform Valid transform 4x4 matrix
221    */
222   void SetSceneTransform(const Dali::Matrix& transform);
223
224   /**
225    * @brief transforms point into the NavigationMesh local space
226    *
227    * Transforms a 3D point into navigation mesh space (space used when
228    * NavigationMesh has been created, most likely 3D editor space).
229    *
230    * @param[in] point Point to transform
231    * @return Point transformed to the local space
232    */
233   Dali::Vector3 PointSceneToLocal(const Dali::Vector3& point) const;
234
235   /**
236    * @brief Transforms point into the parent transform space
237    *
238    * Transforms the given point into the parent space (set with SetSceneTransform()).
239    *
240    * @param[in] point Point to transform
241    * @return Point transformed into the parent space
242    */
243   Dali::Vector3 PointLocalToScene(const Dali::Vector3& point) const;
244
245   /**
246    * @brief Returns direction of the gravity vector
247    *
248    * Gravity vector points down.
249    *
250    * @return Gravity vector 3D
251    */
252   Dali::Vector3 GetGravityVector() const;
253
254   static constexpr FaceIndex NULL_FACE{std::numeric_limits<FaceIndex>::max()}; ///< Represents null face
255   static constexpr EdgeIndex NULL_EDGE{std::numeric_limits<EdgeIndex>::max()}; ///< Represents null edge
256
257 public:
258   DALI_INTERNAL explicit NavigationMesh(NavigationMeshImpl* impl);
259
260   std::unique_ptr<NavigationMeshImpl> mImpl;
261 };
262 } // namespace Dali::Scene3D::Algorithm
263 #endif // DALI_SCENE3D_NAVIGATION_MESH_H