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 #include "frustum_util.h"
17 
18 #include <cstdint>
19 
20 #include <base/containers/string_view.h>
21 #include <base/math/matrix.h>
22 #include <base/math/vector.h>
23 #include <base/math/vector_util.h>
24 #include <base/namespace.h>
25 #include <base/util/uid.h>
26 #include <core/namespace.h>
27 
28 CORE_BEGIN_NAMESPACE()
29 using BASE_NS::string_view;
30 using BASE_NS::Uid;
31 using BASE_NS::Math::Mat4X4;
32 using BASE_NS::Math::Vec3;
33 
CreateFrustum(const Mat4X4 & matrix) const34 Frustum FrustumUtil::CreateFrustum(const Mat4X4& matrix) const
35 {
36     Frustum frustum;
37 
38     auto& planes = frustum.planes;
39     planes[Frustum::PLANE_LEFT].x = matrix[0].w + matrix[0].x;
40     planes[Frustum::PLANE_LEFT].y = matrix[1].w + matrix[1].x;
41     planes[Frustum::PLANE_LEFT].z = matrix[2].w + matrix[2].x;
42     planes[Frustum::PLANE_LEFT].w = matrix[3].w + matrix[3].x;
43 
44     planes[Frustum::PLANE_RIGHT].x = matrix[0].w - matrix[0].x;
45     planes[Frustum::PLANE_RIGHT].y = matrix[1].w - matrix[1].x;
46     planes[Frustum::PLANE_RIGHT].z = matrix[2].w - matrix[2].x;
47     planes[Frustum::PLANE_RIGHT].w = matrix[3].w - matrix[3].x;
48 
49     planes[Frustum::PLANE_BOTTOM].x = matrix[0].w - matrix[0].y;
50     planes[Frustum::PLANE_BOTTOM].y = matrix[1].w - matrix[1].y;
51     planes[Frustum::PLANE_BOTTOM].z = matrix[2].w - matrix[2].y;
52     planes[Frustum::PLANE_BOTTOM].w = matrix[3].w - matrix[3].y;
53 
54     planes[Frustum::PLANE_TOP].x = matrix[0].w + matrix[0].y;
55     planes[Frustum::PLANE_TOP].y = matrix[1].w + matrix[1].y;
56     planes[Frustum::PLANE_TOP].z = matrix[2].w + matrix[2].y;
57     planes[Frustum::PLANE_TOP].w = matrix[3].w + matrix[3].y;
58 
59     planes[Frustum::PLANE_NEAR].x = matrix[0].w + matrix[0].z;
60     planes[Frustum::PLANE_NEAR].y = matrix[1].w + matrix[1].z;
61     planes[Frustum::PLANE_NEAR].z = matrix[2].w + matrix[2].z;
62     planes[Frustum::PLANE_NEAR].w = matrix[3].w + matrix[3].z;
63 
64     planes[Frustum::PLANE_FAR].x = matrix[0].w - matrix[0].z;
65     planes[Frustum::PLANE_FAR].y = matrix[1].w - matrix[1].z;
66     planes[Frustum::PLANE_FAR].z = matrix[2].w - matrix[2].z;
67     planes[Frustum::PLANE_FAR].w = matrix[3].w - matrix[3].z;
68 
69     for (uint32_t idx = 0; idx < Frustum::PLANE_COUNT; ++idx) {
70         const float rcpLength = 1.0f / Magnitude(Vec3(planes[idx]));
71         planes[idx] *= rcpLength;
72     }
73     return frustum;
74 }
75 
SphereFrustumCollision(const Frustum & frustum,const Vec3 pos,const float radius) const76 bool FrustumUtil::SphereFrustumCollision(const Frustum& frustum, const Vec3 pos, const float radius) const
77 {
78     for (auto const& plane : frustum.planes) {
79         const float d = (plane.x * pos.x) + (plane.y * pos.y) + (plane.z * pos.z) + plane.w;
80         if (d <= -radius) {
81             return false;
82         }
83     }
84     return true;
85 }
86 
GetInterface(const Uid & uid) const87 const IInterface* FrustumUtil::GetInterface(const Uid& uid) const
88 {
89     if ((uid == IFrustumUtil::UID) || (uid == IInterface::UID)) {
90         return this;
91     }
92     return nullptr;
93 }
94 
GetInterface(const Uid & uid)95 IInterface* FrustumUtil::GetInterface(const Uid& uid)
96 {
97     if ((uid == IFrustumUtil::UID) || (uid == IInterface::UID)) {
98         return this;
99     }
100     return nullptr;
101 }
102 
Ref()103 void FrustumUtil::Ref() {}
104 
Unref()105 void FrustumUtil::Unref() {}
106 CORE_END_NAMESPACE()
107