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_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 (Y down)*/
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 vector2 rotated counter clock wise by angle radians (Y down) */
109 static inline Vec2 RotateCCW(const Vec2& value, float angle)
110 {
111 const float s = Math::sin(angle);
112 const float c = Math::cos(angle);
113 return Vec2(value.x * c + value.y * s, value.y * c - value.x * s);
114 }
115
116 /** Return intersection of two Vec2 start points and direction vectors. Returns boolean flag indicating if the vectors
117 * intersect. */
118 static inline Vec2 Intersect(
119 const Vec2& aStart, const Vec2& aDir, const Vec2& bStart, const Vec2& bDir, bool infinite, bool& intersected)
120 {
121 const auto denominator = Cross(aDir, bDir);
122
123 if (Math::abs(denominator) < BASE_EPSILON) {
124 // The lines are parallel
125 intersected = false;
126 return {};
127 }
128
129 // Solve the intersection positions
130 const auto originDist = bStart - aStart;
131 const auto uNumerator = Cross(originDist, aDir);
132 const auto u = uNumerator / denominator;
133 const auto t = Cross(originDist, bDir) / denominator;
134
135 if (!infinite && (t < 0 || t > 1 || u < 0 || u > 1)) {
136 // The intersection lies outside of the line segments
137 intersected = false;
138 return {};
139 }
140
141 intersected = true;
142
143 // Calculate the intersection point
144 return aStart + aDir * t;
145 }
146
147 // Vector3
148 /** Dot product of two vector3's */
149 static inline constexpr float Dot(const Vec3& lhs, const Vec3& rhs)
150 {
151 return (lhs.x * rhs.x) + (lhs.y * rhs.y) + (lhs.z * rhs.z);
152 }
153
154 /** Cross product of two vector3's */
155 static inline constexpr Vec3 Cross(const Vec3& lhs, const Vec3& rhs)
156 {
157 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);
158 }
159
160 /** Linearly interpolate between v1 and v2 vector3's by value t */
161 static inline constexpr Vec3 Lerp(const Vec3& v1, const Vec3& v2, float t)
162 {
163 t = Math::clamp01(t);
164 return Vec3(v1.x + (v2.x - v1.x) * t, v1.y + (v2.y - v1.y) * t, v1.z + (v2.z - v1.z) * t);
165 }
166
167 /** Return squared magnitude of vector3's */
168 static inline constexpr float SqrMagnitude(const Vec3& vec)
169 {
170 return vec.x * vec.x + vec.y * vec.y + vec.z * vec.z;
171 }
172
173 /** Return magnitude of vector3's */
174 static inline float Magnitude(const Vec3& vec)
175 {
176 return Math::sqrt(vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
177 }
178
179 /** Return squared distance of two vector3's */
180 static inline float Distance2(const Vec3& v0, const Vec3& v1)
181 {
182 return SqrMagnitude(v1 - v0);
183 }
184
185 /** Return normalized vector3 (if magnitude is not larger than epsilon, returns zero vector) */
186 static inline Vec3 Normalize(const Vec3& value)
187 {
188 const float mag = Magnitude(value);
189 if (mag > Math::EPSILON) {
190 return value / mag;
191 } else {
192 return Vec3(0.0f, 0.0f, 0.0f);
193 }
194 }
195
196 /** Return three component min of vector3's */
197 static constexpr inline Vec3 min(const Vec3& lhs, const Vec3& rhs)
198 {
199 return Vec3(min(lhs.x, rhs.x), min(lhs.y, rhs.y), min(lhs.z, rhs.z));
200 }
201
202 /** Return three component max of vector3's */
203 static constexpr inline Vec3 max(const Vec3& lhs, const Vec3& rhs)
204 {
205 return Vec3(max(lhs.x, rhs.x), max(lhs.y, rhs.y), max(lhs.z, rhs.z));
206 }
207
208 /** Return scaled value of vector3 */
209 static inline Vec3 Scale(Vec3 const& v, float desiredLength)
210 {
211 return v * desiredLength / Magnitude(v);
212 }
213
214 /** Combine vector3's which have been multiplied with scalar (a * ascl) + (b * bscl) */
215 static inline constexpr Vec3 Combine(Vec3 const& a, Vec3 const& b, float ascl, float bscl)
216 {
217 return (a * ascl) + (b * bscl);
218 }
219
220 // Vector4
221 /** Return squared magnitude of vector4 */
222 static inline constexpr float SqrMagnitude(const Vec4& vec)
223 {
224 return vec.x * vec.x + vec.y * vec.y + vec.z * vec.z + vec.w * vec.w;
225 }
226
227 /** Linearly interpolate between v1 and v2 vector4's by value t */
228 static inline constexpr Vec4 Lerp(const Vec4& v1, const Vec4& v2, float t)
229 {
230 t = Math::clamp01(t);
231 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);
232 }
233
234 /** @} */
235 } // namespace Math
236 BASE_END_NAMESPACE()
237
238 #endif // API_BASE_MATH_VECTOR_UTIL_H
239