• 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_BASE_MATH_VECTOR_UTIL_H
17 #define API_BASE_MATH_VECTOR_UTIL_H
18 
19 #include <base/math/mathf.h>
20 #include <base/math/vector.h>
21 #include <base/namespace.h>
22 
BASE_BEGIN_NAMESPACE()23 BASE_BEGIN_NAMESPACE()
24 namespace Math {
25 /** \addtogroup group_math_vectorutil
26  *  @{
27  */
28 // Vector2
29 /** Dot product of two vector2's */
30 static inline constexpr float Dot(const Vec2& lhs, const Vec2& rhs)
31 {
32     return (lhs.x * rhs.x) + (lhs.y * rhs.y);
33 }
34 
35 /** Cross product of two vector2's */
36 static inline constexpr float Cross(const Vec2& lhs, const Vec2& rhs)
37 {
38     return lhs.x * rhs.y - lhs.y * rhs.x;
39 }
40 
41 /** Linearly interpolate between two vector2's */
42 static inline constexpr Vec2 Lerp(Vec2 v1, Vec2 v2, float t)
43 {
44     t = Math::clamp01(t);
45     return Vec2(v1.x + (v2.x - v1.x) * t, v1.y + (v2.y - v1.y) * t);
46 }
47 
48 /** Return squared magnitude of two vector2's */
49 static inline constexpr float SqrMagnitude(const Vec2& vec)
50 {
51     return vec.x * vec.x + vec.y * vec.y;
52 }
53 
54 /** Return magnitude of two vector2's */
55 static inline float Magnitude(const Vec2& vec)
56 {
57     return Math::sqrt(vec.x * vec.x + vec.y * vec.y);
58 }
59 
60 /** Return distance between vector2's */
61 static inline float distance(const Vec2& v0, const Vec2& v1)
62 {
63     return Magnitude(v1 - v0);
64 }
65 
66 /** Return two component min of vector2's */
67 static constexpr inline Vec2 min(const Vec2& lhs, const Vec2& rhs)
68 {
69     return Vec2(min(lhs.x, rhs.x), min(lhs.y, rhs.y));
70 }
71 
72 /** Return two component max of vector2's */
73 static constexpr inline Vec2 max(const Vec2& lhs, const Vec2& rhs)
74 {
75     return Vec2(max(lhs.x, rhs.x), max(lhs.y, rhs.y));
76 }
77 
78 /** Return normalized vector2 (if magnitude is not larger than epsilon, returns zero vector) */
79 static inline Vec2 Normalize(const Vec2& value)
80 {
81     const float mag = Magnitude(value);
82     if (mag > Math::EPSILON)
83         return value / mag;
84     else
85         return Vec2(0.0f, 0.0f);
86 }
87 
88 /** Return vector2 perpendicular to input in clock-wise direction */
89 static inline Vec2 PerpendicularCW(const Vec2& value)
90 {
91     return Vec2(-value.y, value.x);
92 }
93 
94 /** Return vector2 perpendicular to input in counter clock-wise direction */
95 static inline Vec2 PerpendicularCCW(const Vec2& value)
96 {
97     return Vec2(value.y, -value.x);
98 }
99 
100 /** Return vector2 rotated clock wise by angle radians */
101 static inline Vec2 RotateCW(const Vec2& value, float angle)
102 {
103     const float s = Math::sin(angle);
104     const float c = Math::cos(angle);
105     return Vec2(value.x * c - value.y * s, value.y * c + value.x * s);
106 }
107 
108 /** Return intersection of two Vec2 start points and direction vectors. Returns boolean flag indicating if the vectors
109  * intersect. */
110 static inline Vec2 Intersect(
111     const Vec2& aStart, const Vec2& aDir, const Vec2& bStart, const Vec2& bDir, bool infinite, bool& intersected)
112 {
113     const auto denominator = Cross(aDir, bDir);
114 
115     if (Math::abs(denominator) < BASE_EPSILON) {
116         // The lines are parallel
117         intersected = false;
118         return {};
119     }
120 
121     // Solve the intersection positions
122     const auto originDist = bStart - aStart;
123     const auto uNumerator = Cross(originDist, aDir);
124     const auto u = uNumerator / denominator;
125     const auto t = Cross(originDist, bDir) / denominator;
126 
127     if (!infinite && (t < 0 || t > 1 || u < 0 || u > 1)) {
128         // The intersection lies outside of the line segments
129         intersected = false;
130         return {};
131     }
132 
133     intersected = true;
134 
135     // Calculate the intersection point
136     return aStart + aDir * t;
137 }
138 
139 // Vector3
140 /** Dot product of two vector3's */
141 static inline constexpr float Dot(const Vec3& lhs, const Vec3& rhs)
142 {
143     return (lhs.x * rhs.x) + (lhs.y * rhs.y) + (lhs.z * rhs.z);
144 }
145 
146 /** Cross product of two vector3's */
147 static inline constexpr Vec3 Cross(const Vec3& lhs, const Vec3& rhs)
148 {
149     return Vec3(lhs.y * rhs.z - lhs.z * rhs.y, lhs.z * rhs.x - lhs.x * rhs.z, lhs.x * rhs.y - lhs.y * rhs.x);
150 }
151 
152 /** Linearly interpolate between v1 and v2 vector3's by value t */
153 static inline constexpr Vec3 Lerp(const Vec3& v1, const Vec3& v2, float t)
154 {
155     t = Math::clamp01(t);
156     return Vec3(v1.x + (v2.x - v1.x) * t, v1.y + (v2.y - v1.y) * t, v1.z + (v2.z - v1.z) * t);
157 }
158 
159 /** Return squared magnitude of vector3's */
160 static inline constexpr float SqrMagnitude(const Vec3& vec)
161 {
162     return vec.x * vec.x + vec.y * vec.y + vec.z * vec.z;
163 }
164 
165 /** Return magnitude of vector3's */
166 static inline float Magnitude(const Vec3& vec)
167 {
168     return Math::sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
169 }
170 
171 /** Return squared distance of two vector3's */
172 static inline float Distance2(const Vec3& v0, const Vec3& v1)
173 {
174     return SqrMagnitude(v1 - v0);
175 }
176 
177 /** Return normalized vector3 (if magnitude is not larger than epsilon, returns zero vector) */
178 static inline Vec3 Normalize(const Vec3& value)
179 {
180     const float mag = Magnitude(value);
181     if (mag > Math::EPSILON) {
182         return value / mag;
183     } else {
184         return Vec3(0.0f, 0.0f, 0.0f);
185     }
186 }
187 
188 /** Return three component min of vector3's */
189 static constexpr inline Vec3 min(const Vec3& lhs, const Vec3& rhs)
190 {
191     return Vec3(min(lhs.x, rhs.x), min(lhs.y, rhs.y), min(lhs.z, rhs.z));
192 }
193 
194 /** Return three component max of vector3's */
195 static constexpr inline Vec3 max(const Vec3& lhs, const Vec3& rhs)
196 {
197     return Vec3(max(lhs.x, rhs.x), max(lhs.y, rhs.y), max(lhs.z, rhs.z));
198 }
199 
200 /** Return scaled value of vector3 */
201 static inline Vec3 Scale(Vec3 const& v, float desiredLength)
202 {
203     return v * desiredLength / Magnitude(v);
204 }
205 
206 /** Combine vector3's which have been multiplied with scalar (a * ascl) + (b * bscl) */
207 static inline constexpr Vec3 Combine(Vec3 const& a, Vec3 const& b, float ascl, float bscl)
208 {
209     return (a * ascl) + (b * bscl);
210 }
211 
212 // Vector4
213 /** Return squared magnitude of vector4 */
214 static inline constexpr float SqrMagnitude(const Vec4& vec)
215 {
216     return vec.x * vec.x + vec.y * vec.y + vec.z * vec.z + vec.w * vec.w;
217 }
218 
219 /** Linearly interpolate between v1 and v2 vector4's by value t */
220 static inline constexpr Vec4 Lerp(const Vec4& v1, const Vec4& v2, float t)
221 {
222     t = Math::clamp01(t);
223     return Vec4(v1.x + (v2.x - v1.x) * t, v1.y + (v2.y - v1.y) * t, v1.z + (v2.z - v1.z) * t, v1.w + (v2.w - v1.w) * t);
224 }
225 
226 /** @} */
227 } // namespace Math
228 BASE_END_NAMESPACE()
229 
230 #endif // API_BASE_MATH_VECTOR_UTIL_H
231