• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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/vector.h>
23 #include <base/math/vector.h>
24 #include <core/ecs/entity.h>
25 #include <core/plugin/intf_interface.h>
26 
27 CORE_BEGIN_NAMESPACE()
28 class IEcs;
29 CORE_END_NAMESPACE()
30 
31 CORE3D_BEGIN_NAMESPACE()
32 class ISceneNode;
33 
34 /** \addtogroup group_util_picking
35  *  @{
36  */
37 struct MinAndMax {
38 #define CORE_FMAX std::numeric_limits<float>::max()
39     BASE_NS::Math::Vec3 minAABB { CORE_FMAX, CORE_FMAX, CORE_FMAX };
40     BASE_NS::Math::Vec3 maxAABB { -CORE_FMAX, -CORE_FMAX, -CORE_FMAX };
41 #undef CORE_FMAX
42 };
43 
44 /** Raycast result */
45 struct RayCastResult {
46     /** Node that was hit. */
47     ISceneNode* node { nullptr };
48 
49     /** Distance to intersection. */
50     float distance { 0.0f };
51 };
52 
53 class IPicking : public CORE_NS::IInterface {
54 public:
55     static constexpr auto UID = BASE_NS::Uid { "9a4791d7-19e2-4dc0-a4fd-b0804d153d70" };
56 
57     using Ptr = BASE_NS::refcnt_ptr<IPicking>;
58 
59     /** Projects normalized screen coordinates to world coordinates. Origin is at the top left corner. Z-value of the
60      * screen coordinate is interpreted so that 0.0 maps to the near plane and 1.0 to the far plane.
61      * @param ecs Entity component system where cameraEntity lives.
62      * @param cameraEntity Camera entity to be used for projection.
63      * @param screenCoordinate Normalized screen coordinates.
64      * @return Projected world coordinates.
65      */
66     virtual BASE_NS::Math::Vec3 ScreenToWorld(
67         CORE_NS::IEcs const& ecs, CORE_NS::Entity cameraEntity, BASE_NS::Math::Vec3 screenCoordinate) const = 0;
68 
69     /** Projects world coordinates to normalized screen coordinates.
70      * @param ecs Entity component system where cameraEntity lives.
71      * @param cameraEntity Camera entity to be used for projection.
72      * @param worldCoordinate World coordinates to be projected.
73      * @return Projected screen coordinates.
74      */
75     virtual BASE_NS::Math::Vec3 WorldToScreen(
76         CORE_NS::IEcs const& ecs, CORE_NS::Entity cameraEntity, BASE_NS::Math::Vec3 worldCoordinate) const = 0;
77 
78     /** Calculates a world space AABB from local min max values. */
79     virtual MinAndMax GetWorldAABB(const BASE_NS::Math::Mat4X4& world, const BASE_NS::Math::Vec3& aabbMin,
80         const BASE_NS::Math::Vec3& aabbMax) const = 0;
81 
82     /**
83      * Calculates a world space AABB for an entity and optionally all of it's children recursively. Uses the world
84      * matrix component for the calculations i.e. the values are only valid after the ECS has updated all the systems
85      * that manipulate the world matrix.
86      */
87     virtual MinAndMax GetWorldMatrixComponentAABB(
88         CORE_NS::Entity entity, bool isRecursive, CORE_NS::IEcs& ecs) const = 0;
89 
90     /**
91      * Calculates a world space AABB for an entity and optionally all of it's children recursively. Uses only the
92      * transform component for the calculations. This way the call will also give valid results even when the ECS has
93      * not been updated. Does not take skinning or animations into account.
94      */
95     virtual MinAndMax GetTransformComponentAABB(CORE_NS::Entity entity, bool isRecursive, CORE_NS::IEcs& ecs) const = 0;
96 
97     /**
98      * Get all nodes node hit by ray.
99      * @param ecs Entity component system where hit test is done.
100      * @param start Starting point of the ray.
101      * @param direction Direction of the ray.
102      * @return Array of raycast results that describe node that was hit and distance to intersection (ordered by
103      * distance).
104      */
105     virtual BASE_NS::vector<RayCastResult> RayCast(
106         CORE_NS::IEcs const& ecs, const BASE_NS::Math::Vec3& start, const BASE_NS::Math::Vec3& direction) const = 0;
107 
108     /**
109      * Get all nodes node hit by ray using a camera and 2D screen coordinates as input.
110      * @param ecs EntityComponentSystem where hit test is done.
111      * @param camera Camera entity to be used for the hit test.
112      * @param screenPos screen coordinates for hit test. Where (0, 0) is the upper left corner of the screen and (1, 1)
113      * the lower left corner.
114      * @return Array of raycast results that describe node that was hit and distance to intersection (ordered by
115      * distance).
116      */
117     virtual BASE_NS::vector<RayCastResult> RayCastFromCamera(
118         CORE_NS::IEcs const& ecs, CORE_NS::Entity camera, const BASE_NS::Math::Vec2& screenPos) const = 0;
119 
120 protected:
121     IPicking() = default;
122     virtual ~IPicking() = default;
123 };
124 
GetName(const IPicking *)125 inline constexpr BASE_NS::string_view GetName(const IPicking*)
126 {
127     return "IPicking";
128 }
129 
130 /** @} */
131 CORE3D_END_NAMESPACE()
132 
133 #endif // API_3D_UTIL_IPICKING_H
134