1use super::{Vec2, Vec3, Vector, VectorConst};
2use num_traits::Float;
3use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
4
5pub type Vec4f = Vec3<f32>;
6pub type Vec4d = Vec3<f64>;
7
8#[derive(Debug, PartialEq, Default, Clone, Copy, PartialOrd)]
10#[repr(C)]
11pub struct Vec4<F>
12where
13 F: Float,
14{
15 pub x: F,
16 pub y: F,
17 pub z: F,
18 pub w: F,
19}
20
21impl<F> Vec4<F>
22where
23 F: Float,
24{
25 #[inline(always)]
27 pub fn new(x: F, y: F, z: F, w: F) -> Self {
28 Self { x, y, z, w }
29 }
30
31 #[inline]
33 pub fn from_vec3(v: Vec3<F>, w: F) -> Self {
34 Self {
35 x: v.x,
36 y: v.y,
37 z: v.z,
38 w,
39 }
40 }
41
42 #[inline]
44 pub fn from_vec2(xy: Vec2<F>, zw: Vec2<F>) -> Self {
45 Self {
46 x: xy.x,
47 y: xy.y,
48 z: zw.x,
49 w: zw.y,
50 }
51 }
52
53 #[inline]
55 pub fn split(&self) -> (F, F, F, F) {
56 (self.x, self.y, self.z, self.w)
57 }
58
59 #[inline]
61 pub fn combine(xyzw: (F, F, F, F)) -> Self {
62 Self {
63 x: xyzw.0,
64 y: xyzw.1,
65 z: xyzw.2,
66 w: xyzw.3,
67 }
68 }
69
70 #[inline]
72 pub fn into_basis(self) -> (Self, Self, Self, Self) {
73 (
74 Self {
75 x: self.x,
76 y: F::zero(),
77 z: F::zero(),
78 w: F::zero(),
79 },
80 Self {
81 x: F::zero(),
82 y: self.y,
83 z: F::zero(),
84 w: F::zero(),
85 },
86 Self {
87 x: F::zero(),
88 y: F::zero(),
89 z: self.z,
90 w: F::zero(),
91 },
92 Self {
93 x: F::zero(),
94 y: F::zero(),
95 z: F::zero(),
96 w: self.w,
97 },
98 )
99 }
100
101 #[inline]
103 pub fn distance_to(&self, other: Self) -> F {
104 (other - *self).magnitude()
105 }
106
107 #[inline]
109 pub fn dot(&self, other: Self) -> F {
110 self.x * other.x + self.y * other.y + self.z * other.z + self.w * other.w
111 }
112
113 #[inline]
115 pub fn dot_normalized(&self, other: Self) -> F {
116 self.normalized().dot(other.normalized())
117 }
118
119 #[inline]
121 pub fn scale(&mut self, factor: F) {
122 self.x = self.x * factor;
123 self.y = self.y * factor;
124 self.z = self.z * factor;
125 self.w = self.w * factor;
126 }
127
128 #[inline]
130 pub fn magnitude(&self) -> F {
131 F::sqrt(self.sqrt_magnitude())
132 }
133
134 #[inline]
136 pub fn sqrt_magnitude(&self) -> F {
137 self.x * self.x + self.y * self.y + self.z * self.z + self.w * self.w
138 }
139
140 #[inline]
142 pub fn normalized(&self) -> Self {
143 let l = self.magnitude();
144 Self {
145 x: self.x / l,
146 y: self.y / l,
147 z: self.z / l,
148 w: self.w / l,
149 }
150 }
151
152 #[inline]
154 pub fn normalize(&mut self) {
155 let l = self.magnitude();
156 self.x = self.x / l;
157 self.y = self.y / l;
158 self.z = self.z / l;
159 self.w = self.w / l;
160 }
161}
162
163impl<F> VectorConst<F> for Vec4<F>
164where
165 F: Float,
166{
167 const SIZE: usize = 3;
168
169 fn get<const I: usize>(&self) -> F {
170 match I {
171 0 => self.x,
172 1 => self.y,
173 2 => self.z,
174 3 => self.w,
175 _ => panic!("Index out of range. Expected 0..=2"),
176 }
177 }
178
179 fn set<const I: usize>(&mut self, v: F) {
180 match I {
181 0 => self.x = v,
182 1 => self.y = v,
183 2 => self.z = v,
184 3 => self.w = v,
185 _ => panic!("Index out of range. Expected 0..=2"),
186 }
187 }
188}
189
190impl<F> Vector<F> for Vec4<F>
191where
192 F: Float,
193{
194 const SIZE: usize = 3;
195
196 fn get(&self, i: usize) -> F {
197 match i {
198 0 => self.x,
199 1 => self.y,
200 2 => self.z,
201 3 => self.w,
202 _ => panic!("Index out of range. Expected 0..=2"),
203 }
204 }
205
206 fn set(&mut self, i: usize, v: F) {
207 match i {
208 0 => self.x = v,
209 1 => self.y = v,
210 2 => self.z = v,
211 3 => self.w = v,
212 _ => panic!("Index out of range. Expected 0..=2"),
213 }
214 }
215}
216
217impl<F> Add for Vec4<F>
218where
219 F: Float,
220{
221 type Output = Self;
222
223 #[inline]
224 fn add(self, rhs: Self) -> Self::Output {
225 Self {
226 x: self.x + rhs.x,
227 y: self.y + rhs.y,
228 z: self.z + rhs.z,
229 w: self.w + rhs.w,
230 }
231 }
232}
233
234impl<F> AddAssign for Vec4<F>
235where
236 F: Float,
237{
238 #[inline]
239 fn add_assign(&mut self, rhs: Self) {
240 self.x = self.x + rhs.x;
241 self.y = self.y + rhs.y;
242 self.z = self.z + rhs.z;
243 self.w = self.w + rhs.w;
244 }
245}
246
247impl<F> Sub for Vec4<F>
248where
249 F: Float,
250{
251 type Output = Self;
252
253 #[inline]
254 fn sub(self, rhs: Self) -> Self::Output {
255 Self {
256 x: self.x - rhs.x,
257 y: self.y - rhs.y,
258 z: self.z - rhs.z,
259 w: self.w - rhs.w,
260 }
261 }
262}
263
264impl<F> SubAssign for Vec4<F>
265where
266 F: Float,
267{
268 #[inline]
269 fn sub_assign(&mut self, rhs: Self) {
270 self.x = self.x - rhs.x;
271 self.y = self.y - rhs.y;
272 self.z = self.z - rhs.z;
273 self.w = self.w - rhs.w;
274 }
275}
276
277impl<F> Mul<F> for Vec4<F>
278where
279 F: Float,
280{
281 type Output = Self;
282
283 #[inline]
284 fn mul(self, rhs: F) -> Self::Output {
285 Self {
286 x: self.x * rhs,
287 y: self.y * rhs,
288 z: self.z * rhs,
289 w: self.w * rhs,
290 }
291 }
292}
293
294impl<F> MulAssign<F> for Vec4<F>
295where
296 F: Float,
297{
298 #[inline]
299 fn mul_assign(&mut self, rhs: F) {
300 self.x = self.x * rhs;
301 self.y = self.y * rhs;
302 self.z = self.z * rhs;
303 self.w = self.w * rhs;
304 }
305}
306
307impl<F> Div<F> for Vec4<F>
308where
309 F: Float,
310{
311 type Output = Self;
312
313 #[inline]
314 fn div(self, rhs: F) -> Self::Output {
315 Self {
316 x: self.x / rhs,
317 y: self.y / rhs,
318 z: self.z / rhs,
319 w: self.w / rhs,
320 }
321 }
322}
323
324impl<F> DivAssign<F> for Vec4<F>
325where
326 F: Float,
327{
328 #[inline]
329 fn div_assign(&mut self, rhs: F) {
330 self.x = self.x / rhs;
331 self.y = self.y / rhs;
332 self.z = self.z / rhs;
333 self.w = self.w / rhs;
334 }
335}
336
337impl<F> Neg for Vec4<F>
338where
339 F: Float,
340{
341 type Output = Self;
342
343 #[inline]
344 fn neg(self) -> Self::Output {
345 Self {
346 x: -self.x,
347 y: -self.y,
348 z: -self.z,
349 w: -self.w,
350 }
351 }
352}