1 /* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef API_3D_UTIL_IPICKING_H 17 #define API_3D_UTIL_IPICKING_H 18 19 #include <limits> 20 21 #include <3d/namespace.h> 22 #include <base/containers/array_view.h> 23 #include <base/containers/refcnt_ptr.h> 24 #include <base/containers/vector.h> 25 #include <base/math/matrix.h> 26 #include <base/namespace.h> 27 #include <base/util/uid.h> 28 #include <core/namespace.h> 29 #include <core/plugin/intf_interface.h> 30 31 BASE_BEGIN_NAMESPACE() 32 namespace Math { 33 class Mat4X4; 34 } // namespace Math 35 BASE_END_NAMESPACE() 36 37 CORE_BEGIN_NAMESPACE() 38 class IEcs; 39 struct Entity; 40 CORE_END_NAMESPACE() 41 42 CORE3D_BEGIN_NAMESPACE() 43 class ISceneNode; 44 45 /** \addtogroup group_util_picking 46 * @{ 47 */ 48 struct MinAndMax { 49 #define CORE_FMAX std::numeric_limits<float>::max() 50 BASE_NS::Math::Vec3 minAABB { CORE_FMAX, CORE_FMAX, CORE_FMAX }; 51 BASE_NS::Math::Vec3 maxAABB { -CORE_FMAX, -CORE_FMAX, -CORE_FMAX }; 52 #undef CORE_FMAX 53 }; 54 55 /** Raycast result. */ 56 struct RayCastResult { 57 /** Node that was hit. */ 58 ISceneNode* node { nullptr }; 59 60 /** Distance to AABB center. */ 61 float centerDistance { 0.0f }; 62 63 /** Distance to the hit position. */ 64 float distance { 0.0f }; 65 66 /** Position of the hit. */ 67 BASE_NS::Math::Vec3 worldPosition { 0.0f, 0.0f, 0.0f }; 68 }; 69 70 /** Raycast result for ray-triangle intersection. */ 71 struct RayTriangleCastResult { 72 /** Distance to the hit position. */ 73 float distance { 0.0f }; 74 75 /** Position of the hit. */ 76 BASE_NS::Math::Vec3 worldPosition { 0.0f, 0.0f, 0.0f }; 77 78 /** Ray hit UV for ray-triangle intersection. */ 79 BASE_NS::Math::Vec2 hitUv { 0.0f, 0.0f }; 80 81 /** The index of the triangle hit. */ 82 uint64_t triangleIndex { 0 }; 83 }; 84 85 class IPicking : public CORE_NS::IInterface { 86 public: 87 static constexpr auto UID = BASE_NS::Uid { "9a4791d7-19e2-4dc0-a4fd-b0804d153d70" }; 88 89 using Ptr = BASE_NS::refcnt_ptr<IPicking>; 90 91 /** Projects normalized screen coordinates to world coordinates. Origin is at the top left corner. Z-value of the 92 * screen coordinate is interpreted so that 0.0 maps to the near plane and 1.0 to the far plane. 93 * @param ecs Entity component system where cameraEntity lives. 94 * @param cameraEntity Camera entity to be used for projection. 95 * @param screenCoordinate Normalized screen coordinates. 96 * @return Projected world coordinates. 97 */ 98 virtual BASE_NS::Math::Vec3 ScreenToWorld( 99 CORE_NS::IEcs const& ecs, CORE_NS::Entity cameraEntity, BASE_NS::Math::Vec3 screenCoordinate) const = 0; 100 101 /** Projects world coordinates to normalized screen coordinates. 102 * @param ecs Entity component system where cameraEntity lives. 103 * @param cameraEntity Camera entity to be used for projection. 104 * @param worldCoordinate World coordinates to be projected. 105 * @return Projected screen coordinates. 106 */ 107 virtual BASE_NS::Math::Vec3 WorldToScreen( 108 CORE_NS::IEcs const& ecs, CORE_NS::Entity cameraEntity, BASE_NS::Math::Vec3 worldCoordinate) const = 0; 109 110 /** Calculates a world space AABB from local min max values. */ 111 virtual MinAndMax GetWorldAABB(const BASE_NS::Math::Mat4X4& world, const BASE_NS::Math::Vec3& aabbMin, 112 const BASE_NS::Math::Vec3& aabbMax) const = 0; 113 114 /** 115 * Calculates a world space AABB for an entity and optionally all of it's children recursively. Uses the world 116 * matrix component for the calculations i.e. the values are only valid after the ECS has updated all the systems 117 * that manipulate the world matrix. 118 */ 119 virtual MinAndMax GetWorldMatrixComponentAABB( 120 CORE_NS::Entity entity, bool isRecursive, CORE_NS::IEcs& ecs) const = 0; 121 122 /** 123 * Calculates a world space AABB for an entity and optionally all of it's children recursively. Uses only the 124 * transform component for the calculations. This way the call will also give valid results even when the ECS has 125 * not been updated. Does not take skinning or animations into account. 126 */ 127 virtual MinAndMax GetTransformComponentAABB(CORE_NS::Entity entity, bool isRecursive, CORE_NS::IEcs& ecs) const = 0; 128 129 /** 130 * Get all nodes hit by ray. 131 * @param ecs Entity component system where hit test is done. 132 * @param start Starting point of the ray. 133 * @param direction Direction of the ray. 134 * @return Array of raycast results that describe node that was hit and distance to intersection (ordered by 135 * distance). 136 */ 137 virtual BASE_NS::vector<RayCastResult> RayCast( 138 CORE_NS::IEcs const& ecs, const BASE_NS::Math::Vec3& start, const BASE_NS::Math::Vec3& direction) const = 0; 139 140 /** 141 * Get nodes hit by ray. Only entities included in the given layer mask are in the result. Entities without 142 * LayerComponent default to LayerConstants::DEFAULT_LAYER_MASK. 143 * @param ecs Entity component system where hit test is done. 144 * @param start Starting point of the ray. 145 * @param direction Direction of the ray. 146 * @param layerMask Layer mask for limiting the returned result. 147 * @return Array of raycast results that describe node that was hit and distance to intersection (ordered by 148 * distance). 149 */ 150 virtual BASE_NS::vector<RayCastResult> RayCast(CORE_NS::IEcs const& ecs, const BASE_NS::Math::Vec3& start, 151 const BASE_NS::Math::Vec3& direction, uint64_t layerMask) const = 0; 152 153 /** 154 * Raycast against a triangle. 155 * @param start Starting point of the ray. 156 * @param direction Direction of the ray. 157 * @param triangles A list of triangles defined by 3 corner vertices. Must be TRIANGLE_LIST. 158 * @return Array of ray-triangle cast results that describe the intersection against triangles. 159 */ 160 virtual BASE_NS::vector<RayTriangleCastResult> RayCast(const BASE_NS::Math::Vec3& start, 161 const BASE_NS::Math::Vec3& direction, BASE_NS::array_view<const BASE_NS::Math::Vec3> triangles) const = 0; 162 163 /** 164 * Get all nodes hit by ray using a camera and 2D screen coordinates as input. 165 * @param ecs EntityComponentSystem where hit test is done. 166 * @param camera Camera entity to be used for the hit test. 167 * @param screenPos screen coordinates for hit test. Where (0, 0) is the upper left corner of the screen and (1, 1) 168 * the lower left corner. 169 * @return Array of raycast results that describe node that was hit and distance to intersection (ordered by 170 * distance). 171 */ 172 virtual BASE_NS::vector<RayCastResult> RayCastFromCamera( 173 CORE_NS::IEcs const& ecs, CORE_NS::Entity camera, const BASE_NS::Math::Vec2& screenPos) const = 0; 174 175 /** 176 * Get nodes hit by ray using a camera and 2D screen coordinates as input. Only entities included in the given layer 177 * mask are in the result. Entities without LayerComponent default to LayerConstants::DEFAULT_LAYER_MASK. 178 * @param ecs EntityComponentSystem where hit test is done. 179 * @param camera Camera entity to be used for the hit test. 180 * @param screenPos screen coordinates for hit test. Where (0, 0) is the upper left corner of the screen and (1, 1) 181 * the lower left corner. 182 * @param layerMask Layer mask for limiting the returned result. 183 * @return Array of raycast results that describe node that was hit and distance to intersection (ordered by 184 * distance). 185 */ 186 virtual BASE_NS::vector<RayCastResult> RayCastFromCamera(CORE_NS::IEcs const& ecs, CORE_NS::Entity camera, 187 const BASE_NS::Math::Vec2& screenPos, uint64_t layerMask) const = 0; 188 189 /** 190 * Calculates the ray-triangle intersection between a ray and a triangle. 191 * @param ecs EntityComponentSystem where hit test is done. 192 * @param camera Camera entity to be used for the hit test. 193 * @param screenPos screen coordinates for hit test. Where (0, 0) is the upper left corner of the screen and (1, 1) 194 * the lower left corner. 195 * @param triangles Triangle list where every triangle is defined by 3 corner vertices. Must be TRIANGLE_LIST. 196 * @return Array of ray-triangle cast results. 197 */ 198 virtual BASE_NS::vector<RayTriangleCastResult> RayCastFromCamera(CORE_NS::IEcs const& ecs, CORE_NS::Entity camera, 199 const BASE_NS::Math::Vec2& screenPos, BASE_NS::array_view<const BASE_NS::Math::Vec3> triangles) const = 0; 200 201 protected: 202 IPicking() = default; 203 virtual ~IPicking() = default; 204 }; 205 206 /** @} */ 207 CORE3D_END_NAMESPACE() 208 209 #endif // API_3D_UTIL_IPICKING_H 210