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;
54 * @class NavigationMesh
56 * NavigationMesh is a set of connected faces. The data contains
57 * Polygons (Polys), Edges and Vertices and describes relations
58 * between (for example, edge knows which polys are on each side).
60 * NavigationMesh uses any coordinate system that it has been exported with.
62 * The mesh is exported with gravity direction. This is because various editors
63 * may define UP vector differently. Note, the Gravity vector points DOWN.
65 * - All calculation take place in the navigation mesh local space
66 * - The NavigationMesh should use a correct transformation matrix (SetSceneTransform())
67 * - Without transform, the NavigationMesh space stays local (compatible with exporter tool)
68 * - The NavigationMesh defines Gravity vector (down)
69 * - The finding floor results are returned back into the scene space (set with SetSceneTransform()).
72 class DALI_SCENE3D_API NavigationMesh
78 * Describes a single polygon
82 uint16_t vertex[NAVIGATION_MESH_MAX_VERTICES_PER_FACE]; ///< Vertices per face
83 uint16_t edge[NAVIGATION_MESH_MAX_EDGES_PER_FACE]; ///< Edges per face
84 float normal[NAVIGATION_MESH_MAX_COMPONENTS_3D]; ///< Normal vector
85 float center[NAVIGATION_MESH_MAX_COMPONENTS_3D]; ///< Barycentric coordinates
91 * Describes a single edge
95 uint16_t vertex[NAVIGATION_MESH_MAX_COMPONENTS_2D]; ///< Vertices making the edge
96 uint16_t face[NAVIGATION_MESH_MAX_COMPONENTS_2D]; ///< Faces on both sides of edge
102 * Describes a single Vertex
109 float co[NAVIGATION_MESH_MAX_COMPONENTS_3D]; ///< Coordinates of vertex
117 NavigationMesh() = delete;
126 * @brief Returns total number of faces
128 * @return number of faces
130 [[nodiscard]] uint32_t GetFaceCount() const;
133 * @brief Returns total number of edges
135 * @return number of edges
137 [[nodiscard]] uint32_t GetEdgeCount() const;
140 * @brief Returns total number of vertices
142 * @return number of vertices
144 [[nodiscard]] uint32_t GetVertexCount() const;
147 * @brief Looks for the floor under specified position
148 * @param[in] position Position to investigate
149 * @param[in] outPosition Position on the floor in found
150 * @param[in] faceIndex Index of NavigationMesh face associated with floor
152 * @return True if floor has been found, False otherwise
154 bool FindFloor(const Dali::Vector3& position, Dali::Vector3& outPosition, uint32_t& faceIndex);
157 * @brief Looks for a floor starting from specified face
159 * The function performs lookup starting from the specified face. If 'dontCheckNeighbours' is 'true'
160 * then function will fail if 'position' falls outside boundries of face. If 'dontCheckNeighbours'
161 * is 'false' the function will continue search expanding onto neighbouring faces.
163 * @param[in] position Position to investigate
164 * @param[in] faceIndex Face index to start lookup
165 * @param[in] dontCheckNeighbours If true, the neighbouring faces won't be tested
166 * @param[out] outPosition Result of lookup
168 * @return True on success, false otherwise
170 bool FindFloorForFace(const Dali::Vector3& position, uint32_t faceIndex, bool dontCheckNeighbours, Dali::Vector3& outPosition);
173 * @brief Returns pointer to Face structure
174 * @param[in] index Index of face to retrieve
175 * @return Pointer to valid Face structure or nullptr
177 [[nodiscard]] const Face* GetFace(int index) const;
180 * @brief Returns edge structure
181 * @param[in] index Index of edge to retrieve
182 * @return Pointer to valid Edge structure or nullptr
184 [[nodiscard]] const Edge* GetEdge(int index) const;
187 * @brief Returns vertex structure
188 * @param[in] index Index of vertex to retrieve
189 * @return Pointer to valid Vertex structure or nullptr
191 [[nodiscard]] const Vertex* GetVertex(int index) const;
194 * @brief Sets static transform for the navigation mesh object
196 * The NavigationMesh may require to be transformed into the coordinates
197 * of the scene object. The exporter exports navigation geometry in a local
198 * space. The transform must be set in order to use the navigation mesh
199 * in the scene space (most likely DALi coordinate space).
201 * The scene transform matrix can be set in the DALi event thread using
202 * Dali::DevelActor::GetWorldTransform(sceneActor)
206 * Actor parentActorOfNavigationMesh; // non-null object
207 * Dali::DevelActor::GetWorldTransform(parentActorOfNavigationMesh);
208 * navigationMesh->SetSceneTransform(parentActorOfNavigationMesh);
211 * The transform remains static until changed by calling SetSceneTransform() again.
212 * It means that if the matrix is obtained from the actor and actor transform will
213 * change the navigation mesh won't be aligned anymore.
215 * @param[in] transform Valid transform 4x4 matrix
217 void SetSceneTransform(const Dali::Matrix& transform);
220 * @brief transforms point into the NavigationMesh local space
222 * Transforms a 3D point into navigation mesh space (space used when
223 * NavigationMesh has been created, most likely 3D editor space).
225 * @param[in] point Point to transform
226 * @return Point transformed to the local space
228 Dali::Vector3 PointSceneToLocal(const Dali::Vector3& point);
231 * @brief Transforms point into the parent transform space
233 * Transforms the given point into the parent space (set with SetSceneTransform()).
235 * @param[in] point Point to transform
236 * @return Point transformed into the parent space
238 Dali::Vector3 PointLocalToScene(const Dali::Vector3& point);
241 * @brief Returns direction of the gravity vector
243 * Gravity vector points down.
245 * @return Gravity vector 3D
247 Dali::Vector3 GetGravityVector() const;
249 static constexpr uint16_t NULL_FACE{0xffff}; ///< Represents null polygon
250 static constexpr uint16_t NULL_EDGE{0xffff}; ///< represents null edge
253 DALI_INTERNAL explicit NavigationMesh(NavigationMeshImpl* impl);
255 std::unique_ptr<NavigationMeshImpl> mImpl;
257 } // namespace Dali::Scene3D::Algorithm
258 #endif // DALI_SCENE3D_NAVIGATION_MESH_H