Move Vectormath main
C++20 game and graphics mathematics
Loading...
Searching...
No Matches
Vec2.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <cassert>
5#include <cmath>
6#include <cstddef>
7#include <cstdint>
8#include <type_traits>
9
10#include <mv/math/Tolerance.hpp>
11#include <mv/math/detail/VectorOps.hpp>
12
13namespace mv::math
14{
15 template <typename T>
16 requires std::is_arithmetic_v<T>
17 class alignas(sizeof(T) * 2U) Vec2
18 {
19 public:
20 using Component = T;
21
22 constexpr Vec2() noexcept = default;
23
24 constexpr Vec2(T x, T y) noexcept : Components_{x, y}
25 {
26 }
27
28 template <typename U>
29 requires(std::is_arithmetic_v<U> && !std::is_same_v<T, U>)
30 explicit constexpr Vec2(const Vec2<U>& other) noexcept :
31 Components_{static_cast<T>(other.X()), static_cast<T>(other.Y())}
32 {
33 }
34
35 [[nodiscard]] static constexpr Vec2 Zero() noexcept
36 {
37 return Vec2(T(0), T(0));
38 }
39
40 [[nodiscard]] static constexpr Vec2 One() noexcept
41 {
42 return Vec2(T(1), T(1));
43 }
44
45 [[nodiscard]] static constexpr Vec2 Filled(T value) noexcept
46 {
47 return Vec2(value, value);
48 }
49
50 [[nodiscard]] static constexpr Vec2 AxisX() noexcept
51 {
52 return Vec2(T(1), T(0));
53 }
54
55 [[nodiscard]] static constexpr Vec2 AxisY() noexcept
56 {
57 return Vec2(T(0), T(1));
58 }
59
60 [[nodiscard]] constexpr T X() const noexcept
61 {
62 return Components_[0];
63 }
64
65 [[nodiscard]] constexpr T Y() const noexcept
66 {
67 return Components_[1];
68 }
69
70 [[nodiscard]] constexpr T operator[](std::size_t index) const noexcept
71 {
72 assert(index < 2U);
73 return Components_[index];
74 }
75
76 template <std::size_t Index>
77 [[nodiscard]] constexpr T Get() const noexcept
78 {
79 static_assert(Index < 2U);
80 return Components_[Index];
81 }
82
83 constexpr void SetX(T value) noexcept
84 {
85 Components_[0] = value;
86 }
87
88 constexpr void SetY(T value) noexcept
89 {
90 Components_[1] = value;
91 }
92
93 [[nodiscard]] constexpr bool SetComponent(std::size_t index,
94 T value) noexcept
95 {
96 if (index >= 2U)
97 {
98 return false;
99 }
100 Components_[index] = value;
101 return true;
102 }
103
104 template <std::size_t Index>
105 constexpr void Set(T value) noexcept
106 {
107 static_assert(Index < 2U);
108 Components_[Index] = value;
109 }
110
111 [[nodiscard]] Vec2 operator+(const Vec2& other) const noexcept
112 {
113 return FromNative(Ops::Add(Ops::Load2(Components_),
114 Ops::Load2(other.Components_)));
115 }
116
117 [[nodiscard]] Vec2 operator-(const Vec2& other) const noexcept
118 {
119 return FromNative(Ops::Subtract(Ops::Load2(Components_),
120 Ops::Load2(other.Components_)));
121 }
122
123 [[nodiscard]] Vec2 operator*(const Vec2& other) const noexcept
124 {
125 return FromNative(Ops::Multiply(Ops::Load2(Components_),
126 Ops::Load2(other.Components_)));
127 }
128
129 [[nodiscard]] Vec2 operator/(const Vec2& other) const noexcept
130 {
131 return FromNative(Ops::Divide2(Ops::Load2(Components_),
132 Ops::Load2(other.Components_)));
133 }
134
135 [[nodiscard]] Vec2 operator+(T scalar) const noexcept
136 {
137 return FromNative(Ops::Add(Ops::Load2(Components_), scalar));
138 }
139
140 [[nodiscard]] Vec2 operator-(T scalar) const noexcept
141 {
142 return FromNative(Ops::Subtract(Ops::Load2(Components_), scalar));
143 }
144
145 [[nodiscard]] Vec2 operator*(T scalar) const noexcept
146 {
147 return FromNative(Ops::Multiply(Ops::Load2(Components_), scalar));
148 }
149
150 [[nodiscard]] Vec2 operator/(T scalar) const noexcept
151 {
152 return FromNative(Ops::Divide(Ops::Load2(Components_), scalar));
153 }
154
156 {
157 return FromNative(Ops::Negate(Ops::Load2(Components_)));
158 }
159
160 Vec2& operator+=(const Vec2& other) noexcept
161 {
162 *this = *this + other;
163 return *this;
164 }
165
166 Vec2& operator-=(const Vec2& other) noexcept
167 {
168 *this = *this - other;
169 return *this;
170 }
171
172 Vec2& operator*=(const Vec2& other) noexcept
173 {
174 *this = *this * other;
175 return *this;
176 }
177
178 Vec2& operator/=(const Vec2& other) noexcept
179 {
180 *this = *this / other;
181 return *this;
182 }
183
185 {
186 *this = *this + scalar;
187 return *this;
188 }
189
191 {
192 *this = *this - scalar;
193 return *this;
194 }
195
197 {
198 *this = *this * scalar;
199 return *this;
200 }
201
203 {
204 *this = *this / scalar;
205 return *this;
206 }
207
209 const Vec2& vector) noexcept
210 {
211 return vector * scalar;
212 }
213
214 [[nodiscard]] friend constexpr bool operator==(
215 const Vec2&, const Vec2&) noexcept = default;
216
217 private:
218 // A compact two-lane value is intentionally scalar-backed. Expanding
219 // every Vec2f into a four-lane SIMD register inhibits the compiler's
220 // more effective loop-level vectorization for arrays of 8-byte values.
221 using Ops = detail::ScalarVectorOps<T>;
222
223 [[nodiscard]] static Vec2 FromNative(
224 typename Ops::Native value) noexcept
225 {
226 Vec2 result;
227 Ops::Store2(value, result.Components_);
228 return result;
229 }
230
231 T Components_[2]{};
232 };
233
244 using Vec2i = Vec2i32;
245 using Vec2u = Vec2u32;
246
247 template <typename T>
248 [[nodiscard]] T Dot(const Vec2<T>& left, const Vec2<T>& right) noexcept
249 {
250 using Ops = detail::ScalarVectorOps<T>;
251 const T leftValues[2] = {left.X(), left.Y()};
252 const T rightValues[2] = {right.X(), right.Y()};
253 return Ops::Dot2(Ops::Load2(leftValues), Ops::Load2(rightValues));
254 }
255
256 template <typename T>
257 [[nodiscard]] T LengthSquared(const Vec2<T>& value) noexcept
258 {
259 return Dot(value, value);
260 }
261
262 template <typename T>
263 requires std::is_floating_point_v<T>
265 const Vec2<T>& left,
266 const Vec2<T>& right,
268 {
269 return IsNearlyEqual(left.X(), right.X(), tolerance) &&
271 }
272
273 template <typename T>
274 requires std::is_floating_point_v<T>
276 const Vec2<T>& value,
277 T absoluteTolerance = Tolerance<T>::Default().Absolute) noexcept
278 {
279 return IsNearlyZero(value.X(), absoluteTolerance) &&
281 }
282
283 template <typename T>
284 requires std::is_floating_point_v<T>
285 [[nodiscard]] T Length(const Vec2<T>& value) noexcept
286 {
287 // Semantics follow GLSL 4.60 section 8.5's length operation.
288 return std::sqrt(LengthSquared(value));
289 }
290
291 template <typename T>
293 const Vec2<T>& right) noexcept
294 {
295 return LengthSquared(left - right);
296 }
297
298 template <typename T>
299 requires std::is_floating_point_v<T>
300 [[nodiscard]] T Distance(const Vec2<T>& left, const Vec2<T>& right) noexcept
301 {
302 // Semantics follow GLSL 4.60 section 8.5's distance operation.
303 return Length(left - right);
304 }
305
306 template <typename T>
308 const Vec2<T>& right) noexcept
309 {
310 return Vec2<T>(std::min(left.X(), right.X()),
311 std::min(left.Y(), right.Y()));
312 }
313
314 template <typename T>
316 const Vec2<T>& right) noexcept
317 {
318 return Vec2<T>(std::max(left.X(), right.X()),
319 std::max(left.Y(), right.Y()));
320 }
321
322 template <typename T>
324 const Vec2<T>& minimum,
325 const Vec2<T>& maximum) noexcept
326 {
327 // Component semantics follow GLSL 4.60 section 8.3's clamp operation.
328 return Min(Max(value, minimum), maximum);
329 }
330
331 template <typename T>
333 T minimum,
334 T maximum) noexcept
335 {
337 }
338
339 template <typename T>
340 requires(std::is_signed_v<T> || std::is_floating_point_v<T>)
341 [[nodiscard]] Vec2<T> Abs(const Vec2<T>& value) noexcept
342 {
343 return Vec2<T>(static_cast<T>(std::abs(value.X())),
344 static_cast<T>(std::abs(value.Y())));
345 }
346
347 template <typename T>
348 requires(std::is_signed_v<T> || std::is_floating_point_v<T>)
349 [[nodiscard]] Vec2<T> Sign(const Vec2<T>& value) noexcept
350 {
351 // Component semantics follow GLSL 4.60 section 8.3's sign operation.
352 const auto sign = [](T component)
353 {
354 return static_cast<T>((T(0) < component) - (component < T(0)));
355 };
356 return Vec2<T>(sign(value.X()), sign(value.Y()));
357 }
358
359 template <typename T>
360 requires std::is_floating_point_v<T>
362 const Vec2<T>& to,
363 T amount) noexcept
364 {
365 // Algebra follows GLSL 4.60 section 8.3's mix operation.
366 return from + (to - from) * amount;
367 }
368
369 template <typename T>
370 requires std::is_floating_point_v<T>
372 const Vec2<T>& to,
373 T amount) noexcept
374 {
375 return LerpUnclamped(from, to, std::clamp(amount, T(0), T(1)));
376 }
377} // namespace mv::math
378
379static_assert(sizeof(mv::math::Vec2f) == 8);
380static_assert(alignof(mv::math::Vec2f) == 8);
381static_assert(std::is_trivially_copyable_v<mv::math::Vec2f>);
382static_assert(std::is_standard_layout_v<mv::math::Vec2f>);
Vec2 operator-() const noexcept
Definition Vec2.hpp:155
constexpr void SetY(T value) noexcept
Definition Vec2.hpp:88
Vec2 operator*(T scalar) const noexcept
Definition Vec2.hpp:145
Vec2 operator+(const Vec2 &other) const noexcept
Definition Vec2.hpp:111
Vec2 & operator/=(T scalar) noexcept
Definition Vec2.hpp:202
constexpr T operator[](std::size_t index) const noexcept
Definition Vec2.hpp:70
Vec2 & operator*=(T scalar) noexcept
Definition Vec2.hpp:196
constexpr T X() const noexcept
Definition Vec2.hpp:60
constexpr T Y() const noexcept
Definition Vec2.hpp:65
constexpr T Get() const noexcept
Definition Vec2.hpp:77
static constexpr Vec2 Zero() noexcept
Definition Vec2.hpp:35
Vec2 operator-(const Vec2 &other) const noexcept
Definition Vec2.hpp:117
constexpr void SetX(T value) noexcept
Definition Vec2.hpp:83
static constexpr Vec2 One() noexcept
Definition Vec2.hpp:40
static constexpr Vec2 Filled(T value) noexcept
Definition Vec2.hpp:45
constexpr void Set(T value) noexcept
Definition Vec2.hpp:105
Vec2 operator-(T scalar) const noexcept
Definition Vec2.hpp:140
Vec2 operator/(const Vec2 &other) const noexcept
Definition Vec2.hpp:129
Vec2 & operator-=(T scalar) noexcept
Definition Vec2.hpp:190
friend Vec2 operator*(T scalar, const Vec2 &vector) noexcept
Definition Vec2.hpp:208
Vec2 & operator*=(const Vec2 &other) noexcept
Definition Vec2.hpp:172
constexpr Vec2(const Vec2< U > &other) noexcept
Definition Vec2.hpp:30
Vec2 operator*(const Vec2 &other) const noexcept
Definition Vec2.hpp:123
constexpr bool SetComponent(std::size_t index, T value) noexcept
Definition Vec2.hpp:93
Vec2 & operator-=(const Vec2 &other) noexcept
Definition Vec2.hpp:166
Vec2 & operator/=(const Vec2 &other) noexcept
Definition Vec2.hpp:178
Vec2 & operator+=(const Vec2 &other) noexcept
Definition Vec2.hpp:160
constexpr Vec2() noexcept=default
friend constexpr bool operator==(const Vec2 &, const Vec2 &) noexcept=default
Vec2 operator+(T scalar) const noexcept
Definition Vec2.hpp:135
Vec2 & operator+=(T scalar) noexcept
Definition Vec2.hpp:184
Vec2 operator/(T scalar) const noexcept
Definition Vec2.hpp:150
static constexpr Vec2 AxisX() noexcept
Definition Vec2.hpp:50
static constexpr Vec2 AxisY() noexcept
Definition Vec2.hpp:55
Vec2< T > Sign(const Vec2< T > &value) noexcept
Definition Vec2.hpp:349
Vec2< std::int32_t > Vec2i32
Definition Vec2.hpp:240
constexpr T Dot(const Quat< T > &left, const Quat< T > &right) noexcept
Definition Quat.hpp:102
Vec2< T > LerpUnclamped(const Vec2< T > &from, const Vec2< T > &to, T amount) noexcept
Definition Vec2.hpp:361
Vec2< float > Vec2f
Definition Vec2.hpp:234
Vec2< std::uint32_t > Vec2u32
Definition Vec2.hpp:241
T Distance(const Point3< T > &point, const Line3< T > &line) noexcept
bool IsNearlyEqual(const Quat< T > &left, const Quat< T > &right, Tolerance< T > tolerance=Tolerance< T >::Default()) noexcept
Definition Quat.hpp:176
constexpr T LengthSquared(const Quat< T > &value) noexcept
Definition Quat.hpp:110
Vec2< T > Min(const Vec2< T > &left, const Vec2< T > &right) noexcept
Definition Vec2.hpp:307
Vec2< T > Clamp(const Vec2< T > &value, const Vec2< T > &minimum, const Vec2< T > &maximum) noexcept
Definition Vec2.hpp:323
T Length(const Quat< T > &value) noexcept
Definition Quat.hpp:116
constexpr bool IsNearlyZero(T value, T absoluteTolerance=Tolerance< T >::Default().Absolute) noexcept
Definition Tolerance.hpp:54
Vec2< T > Max(const Vec2< T > &left, const Vec2< T > &right) noexcept
Definition Vec2.hpp:315
Vec2< T > Lerp(const Vec2< T > &from, const Vec2< T > &to, T amount) noexcept
Definition Vec2.hpp:371
Vec2< T > Abs(const Vec2< T > &value) noexcept
Definition Vec2.hpp:341
T DistanceSquared(const Point3< T > &point, const Line3< T > &line) noexcept