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 #ifndef CORE_UTIL_PICKING_H
16 #define CORE_UTIL_PICKING_H
17 
18 #include <3d/util/intf_picking.h>
19 #include <base/containers/string_view.h>
20 #include <core/namespace.h>
21 
22 CORE_BEGIN_NAMESPACE()
23 class IEcs;
24 class IEngine;
25 CORE_END_NAMESPACE()
26 
27 CORE3D_BEGIN_NAMESPACE()
28 class IJointMatricesComponentManager;
29 class IMeshComponentManager;
30 class ITransformComponentManager;
31 class IRenderMeshComponentManager;
32 class IWorldMatrixComponentManager;
33 struct CameraComponent;
34 struct MeshComponent;
35 
36 class Picking : public IPicking {
37 public:
38     Picking() = default;
39     ~Picking() override = default;
40     BASE_NS::Math::Vec3 ScreenToWorld(
41         CORE_NS::IEcs const& ecs, CORE_NS::Entity cameraEntity, BASE_NS::Math::Vec3 screenCoordinate) const override;
42 
43     BASE_NS::Math::Vec3 WorldToScreen(
44         CORE_NS::IEcs const& ecs, CORE_NS::Entity cameraEntity, BASE_NS::Math::Vec3 worldCoordinate) const override;
45 
46     BASE_NS::vector<RayCastResult> RayCast(CORE_NS::IEcs const& ecs, const BASE_NS::Math::Vec3& start,
47         const BASE_NS::Math::Vec3& direction) const override;
48     BASE_NS::vector<RayCastResult> RayCast(CORE_NS::IEcs const& ecs, const BASE_NS::Math::Vec3& start,
49         const BASE_NS::Math::Vec3& direction, uint64_t layerMask) const override;
50     BASE_NS::vector<RayTriangleCastResult> RayCast(const BASE_NS::Math::Vec3& start,
51         const BASE_NS::Math::Vec3& direction, BASE_NS::array_view<const BASE_NS::Math::Vec3> triangles) const override;
52 
53     BASE_NS::vector<RayCastResult> RayCastFromCamera(
54         CORE_NS::IEcs const& ecs, CORE_NS::Entity camera, const BASE_NS::Math::Vec2& screenPos) const override;
55     BASE_NS::vector<RayCastResult> RayCastFromCamera(CORE_NS::IEcs const& ecs, CORE_NS::Entity camera,
56         const BASE_NS::Math::Vec2& screenPos, uint64_t layerMask) const override;
57     BASE_NS::vector<RayTriangleCastResult> RayCastFromCamera(CORE_NS::IEcs const& ecs, CORE_NS::Entity camera,
58         const BASE_NS::Math::Vec2& screenPos, BASE_NS::array_view<const BASE_NS::Math::Vec3> triangles) const override;
59 
60     MinAndMax GetWorldAABB(const BASE_NS::Math::Mat4X4& world, const BASE_NS::Math::Vec3& aabbMin,
61         const BASE_NS::Math::Vec3& aabbMax) const override;
62 
63     MinAndMax GetWorldMatrixComponentAABB(CORE_NS::Entity entity, bool isRecursive, CORE_NS::IEcs& ecs) const override;
64 
65     MinAndMax GetTransformComponentAABB(CORE_NS::Entity entity, bool isRecursive, CORE_NS::IEcs& ecs) const override;
66 
67     // IInterface
68     const IInterface* GetInterface(const BASE_NS::Uid& uid) const override;
69     IInterface* GetInterface(const BASE_NS::Uid& uid) override;
70 
71     void Ref() override;
72     void Unref() override;
73 
74 protected:
75     /** Safely compute the inverse of a direction 1/direction with zero checking. */
DirectionVectorInverse(const BASE_NS::Math::Vec3 & direction)76     inline BASE_NS::Math::Vec3 DirectionVectorInverse(const BASE_NS::Math::Vec3& direction) const
77     {
78         BASE_NS::Math::Vec3 invDir { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(),
79             std::numeric_limits<float>::max() };
80         if (direction.x != 0.f) {
81             invDir.x = 1.f / direction.x;
82         }
83         if (direction.y != 0.f) {
84             invDir.y = 1.f / direction.y;
85         }
86         if (direction.z != 0.f) {
87             invDir.z = 1.f / direction.z;
88         }
89         return invDir;
90     }
91 };
92 
GetName(const IPicking *)93 inline constexpr BASE_NS::string_view GetName(const IPicking*)
94 {
95     return "IPicking";
96 }
97 
98 CORE3D_END_NAMESPACE()
99 
100 #endif // CORE_UTIL_PICKING_H