1 #ifndef DALI_SCENE3D_NAVIGATION_MESH_H
2 #define DALI_SCENE3D_NAVIGATION_MESH_H
5 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
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>
31 #include <dali-scene3d/public-api/api.h>
33 namespace Dali::Scene3D::Internal::Algorithm
38 namespace Dali::Scene3D::Loader
40 class NavigationMeshFactory;
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;
48 namespace Dali::Scene3D::Algorithm
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;
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;
59 * @class NavigationMesh
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).
65 * NavigationMesh uses any coordinate system that it has been exported with.
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.
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()).
77 class DALI_SCENE3D_API NavigationMesh
83 * Describes a single polygon's face
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
96 * Describes a single edge
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
107 * Describes a single Vertex
114 float coordinates[NAVIGATION_MESH_MAX_COMPONENTS_3D]; ///< Coordinates of vertex
122 NavigationMesh() = delete;
131 * @brief Returns total number of faces
133 * @return number of faces
135 [[nodiscard]] uint32_t GetFaceCount() const;
138 * @brief Returns total number of edges
140 * @return number of edges
142 [[nodiscard]] uint32_t GetEdgeCount() const;
145 * @brief Returns total number of vertices
147 * @return number of vertices
149 [[nodiscard]] uint32_t GetVertexCount() const;
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
157 * @return True if floor has been found, False otherwise
159 bool FindFloor(const Dali::Vector3& position, Dali::Vector3& outPosition, FaceIndex& faceIndex);
162 * @brief Looks for a floor starting from specified face
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.
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
173 * @return True on success, false otherwise
175 bool FindFloorForFace(const Dali::Vector3& position, FaceIndex faceIndex, bool dontCheckNeighbours, Dali::Vector3& outPosition);
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
182 [[nodiscard]] const Face* GetFace(FaceIndex index) const;
185 * @brief Returns edge structure
186 * @param[in] index Index of edge to retrieve
187 * @return Pointer to valid Edge structure or nullptr
189 [[nodiscard]] const Edge* GetEdge(EdgeIndex index) const;
192 * @brief Returns vertex structure
193 * @param[in] index Index of vertex to retrieve
194 * @return Pointer to valid Vertex structure or nullptr
196 [[nodiscard]] const Vertex* GetVertex(VertexIndex index) const;
199 * @brief Sets static transform for the navigation mesh object
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).
206 * The scene transform matrix can be set in the DALi event thread using
207 * Dali::DevelActor::GetWorldTransform(sceneActor)
211 * Actor parentActorOfNavigationMesh; // non-null object
212 * Dali::DevelActor::GetWorldTransform(parentActorOfNavigationMesh);
213 * navigationMesh->SetSceneTransform(parentActorOfNavigationMesh);
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.
220 * @param[in] transform Valid transform 4x4 matrix
222 void SetSceneTransform(const Dali::Matrix& transform);
225 * @brief transforms point into the NavigationMesh local space
227 * Transforms a 3D point into navigation mesh space (space used when
228 * NavigationMesh has been created, most likely 3D editor space).
230 * @param[in] point Point to transform
231 * @return Point transformed to the local space
233 Dali::Vector3 PointSceneToLocal(const Dali::Vector3& point) const;
236 * @brief Transforms point into the parent transform space
238 * Transforms the given point into the parent space (set with SetSceneTransform()).
240 * @param[in] point Point to transform
241 * @return Point transformed into the parent space
243 Dali::Vector3 PointLocalToScene(const Dali::Vector3& point) const;
246 * @brief Returns direction of the gravity vector
248 * Gravity vector points down.
250 * @return Gravity vector 3D
252 Dali::Vector3 GetGravityVector() const;
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
258 DALI_INTERNAL explicit NavigationMesh(NavigationMeshImpl* impl);
260 std::unique_ptr<NavigationMeshImpl> mImpl;
262 } // namespace Dali::Scene3D::Algorithm
263 #endif // DALI_SCENE3D_NAVIGATION_MESH_H