vector_traits/glam_impl/
vec2a.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Copyright (c) 2023, 2025 lacklustr@protonmail.com https://github.com/eadf
3
4// This file is part of vector-traits.
5
6use super::Aabb2A;
7use crate::{glam, prelude::*};
8use std::{
9    fmt,
10    fmt::Debug,
11    ops::{Add, AddAssign, Div, Index, IndexMut, Mul, Neg, Sub},
12};
13
14/// A wrapper around `Vec2` with zero runtime cost. Created to facilitate the implementation of the trait
15/// `GenericVector3` for `Vec3A`. While not an ideal solution, it is the most suitable one identified.
16/// Note that this type is only as aligned as `glam::Vec2` is.
17#[repr(transparent)]
18#[derive(Copy, Clone, PartialEq)]
19pub struct Vec2A(pub glam::Vec2);
20
21// Implement necessary traits and delegate to inner glam::Vec2
22impl std::ops::Deref for Vec2A {
23    type Target = glam::Vec2;
24
25    #[inline(always)]
26    fn deref(&self) -> &Self::Target {
27        &self.0
28    }
29}
30
31impl std::ops::DerefMut for Vec2A {
32    #[inline(always)]
33    fn deref_mut(&mut self) -> &mut Self::Target {
34        &mut self.0
35    }
36}
37impl std::ops::SubAssign for Vec2A {
38    fn sub_assign(&mut self, rhs: Self) {
39        self.0 -= rhs.0;
40    }
41}
42
43impl AddAssign for Vec2A {
44    #[inline(always)]
45    fn add_assign(&mut self, rhs: Self) {
46        self.0 += rhs.0;
47    }
48}
49
50impl std::ops::MulAssign<f32> for Vec2A {
51    #[inline(always)]
52    fn mul_assign(&mut self, rhs: f32) {
53        self.0 *= rhs;
54    }
55}
56
57impl std::ops::DivAssign<f32> for Vec2A {
58    #[inline(always)]
59    fn div_assign(&mut self, rhs: f32) {
60        self.0 /= rhs;
61    }
62}
63
64impl std::ops::MulAssign for Vec2A {
65    #[inline(always)]
66    fn mul_assign(&mut self, rhs: Self) {
67        self.0 *= rhs.0;
68    }
69}
70
71impl std::ops::DivAssign for Vec2A {
72    #[inline(always)]
73    fn div_assign(&mut self, rhs: Self) {
74        self.0 /= rhs.0;
75    }
76}
77
78impl Add for Vec2A {
79    type Output = Self;
80
81    #[inline(always)]
82    fn add(self, rhs: Self) -> Self::Output {
83        Vec2A(self.0 + rhs.0)
84    }
85}
86
87impl Sub for Vec2A {
88    type Output = Self;
89
90    #[inline(always)]
91    fn sub(self, rhs: Self) -> Self::Output {
92        Vec2A(self.0 - rhs.0)
93    }
94}
95
96impl Neg for Vec2A {
97    type Output = Self;
98
99    #[inline(always)]
100    fn neg(self) -> Self::Output {
101        Vec2A(-self.0)
102    }
103}
104
105// Scalar multiplication (Vec2A * f32 and f32 * Vec2A)
106impl Mul<f32> for Vec2A {
107    type Output = Self;
108
109    #[inline(always)]
110    fn mul(self, rhs: f32) -> Self::Output {
111        Vec2A(self.0 * rhs)
112    }
113}
114
115impl Mul<Vec2A> for f32 {
116    type Output = Vec2A;
117
118    #[inline(always)]
119    fn mul(self, rhs: Vec2A) -> Self::Output {
120        Vec2A(self * rhs.0)
121    }
122}
123
124// Scalar division (Vec2A / f32)
125impl Div<f32> for Vec2A {
126    type Output = Self;
127
128    #[inline(always)]
129    fn div(self, rhs: f32) -> Self::Output {
130        Vec2A(self.0 / rhs)
131    }
132}
133
134impl Vec2A {
135    pub const fn new(x: f32, y: f32) -> Self {
136        Self(glam::Vec2::new(x, y))
137    }
138}
139
140impl From<glam::Vec2> for Vec2A {
141    fn from(v: glam::Vec2) -> Self {
142        Self(v)
143    }
144}
145
146impl From<Vec2A> for glam::Vec2 {
147    #[inline(always)]
148    fn from(v: Vec2A) -> Self {
149        v.0
150    }
151}
152
153impl From<(f32, f32)> for Vec2A {
154    #[inline(always)]
155    fn from(tuple: (f32, f32)) -> Self {
156        Vec2A(glam::Vec2::new(tuple.0, tuple.1))
157    }
158}
159
160impl From<[f32; 2]> for Vec2A {
161    #[inline(always)]
162    fn from(array: [f32; 2]) -> Self {
163        Self(glam::Vec2::from(array))
164    }
165}
166
167impl From<Vec2A> for [f32; 2] {
168    #[inline(always)]
169    fn from(val: Vec2A) -> Self {
170        val.0.into()
171    }
172}
173
174impl Debug for Vec2A {
175    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176        write!(f, "Vec2A({},{})", self.0.x, self.0.y)
177    }
178}
179
180impl Index<usize> for Vec2A {
181    type Output = f32;
182
183    #[inline(always)]
184    fn index(&self, index: usize) -> &Self::Output {
185        &self.0[index]
186    }
187}
188
189impl IndexMut<usize> for Vec2A {
190    #[inline(always)]
191    fn index_mut(&mut self, index: usize) -> &mut f32 {
192        &mut self.0[index]
193    }
194}
195
196impl HasXY for Vec2A {
197    type Scalar = f32;
198    #[inline(always)]
199    fn new_2d(x: Self::Scalar, y: Self::Scalar) -> Self {
200        Self(glam::Vec2::new(x, y))
201    }
202
203    #[inline(always)]
204    fn x(self) -> Self::Scalar {
205        self.0.x
206    }
207
208    #[inline(always)]
209    fn x_mut(&mut self) -> &mut Self::Scalar {
210        &mut self.0.x
211    }
212
213    #[inline(always)]
214    fn set_x(&mut self, val: Self::Scalar) {
215        self.0.x = val;
216    }
217
218    #[inline(always)]
219    fn y(self) -> Self::Scalar {
220        self.0.y
221    }
222
223    #[inline(always)]
224    fn y_mut(&mut self) -> &mut Self::Scalar {
225        &mut self.0.y
226    }
227
228    #[inline(always)]
229    fn set_y(&mut self, val: Self::Scalar) {
230        self.0.y = val
231    }
232}
233
234impl GenericVector2 for Vec2A {
235    const ZERO: Self = Self(glam::Vec2::ZERO);
236    const ONE: Self = Self(glam::Vec2::ONE);
237
238    type Vector3 = glam::Vec3A;
239    type Affine = glam::Mat3A;
240    type Aabb = Aabb2A;
241    #[inline(always)]
242    fn new(x: Self::Scalar, y: Self::Scalar) -> Self {
243        Vec2A::new(x, y)
244    }
245    #[inline(always)]
246    fn splat(value: Self::Scalar) -> Self {
247        Self::new(value, value)
248    }
249    #[inline(always)]
250    fn to_3d(self, z: Self::Scalar) -> Self::Vector3 {
251        glam::vec3a(self.0.x, self.0.y, z)
252    }
253
254    #[inline(always)]
255    fn magnitude(self) -> Self::Scalar {
256        self.0.length()
257    }
258
259    #[inline(always)]
260    fn magnitude_sq(self) -> Self::Scalar {
261        self.0.length_squared()
262    }
263
264    #[inline(always)]
265    fn dot(self, other: Self) -> Self::Scalar {
266        self.0.dot(other.0)
267    }
268
269    #[inline(always)]
270    fn perp_dot(self, rhs: Self) -> Self::Scalar {
271        self.0.perp_dot(rhs.0)
272    }
273
274    #[inline(always)]
275    fn distance(self, rhs: Self) -> Self::Scalar {
276        self.0.distance(rhs.0)
277    }
278
279    #[inline(always)]
280    fn distance_sq(self, rhs: Self) -> Self::Scalar {
281        self.0.distance_squared(rhs.0)
282    }
283
284    #[inline(always)]
285    fn normalize(self) -> Self {
286        Vec2A(self.0.normalize())
287    }
288
289    #[inline(always)]
290    fn try_normalize(self, epsilon: Self::Scalar) -> Option<Self> {
291        let l_sq = self.0.length_squared();
292        (l_sq > epsilon * epsilon).then(|| self / l_sq.sqrt())
293    }
294    #[inline(always)]
295    fn min(self, rhs: Self) -> Self {
296        self.0.min(rhs.0).into()
297    }
298    #[inline(always)]
299    fn max(self, rhs: Self) -> Self {
300        self.0.max(rhs.0).into()
301    }
302    #[inline(always)]
303    fn clamp(self, min: Self, max: Self) -> Self {
304        self.0.clamp(min.0, max.0).into()
305    }
306    #[inline(always)]
307    fn is_finite(self) -> bool {
308        self.0.x.is_finite() && self.0.y.is_finite()
309    }
310}
311
312#[allow(dead_code)] // it is used, promise
313#[cfg(feature = "glam")]
314#[inline(always)]
315#[must_use]
316pub const fn vec2a(x: f32, y: f32) -> Vec2A {
317    Vec2A::new(x, y)
318}