nova_math/vector/
vector4.rs

1/*
2 *
3 * This file is a part of NovaEngine
4 * https://gitlab.com/MindSpunk/NovaEngine
5 *
6 *
7 * MIT License
8 *
9 * Copyright (c) 2018 Nathan Voglsam
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a copy
12 * of this software and associated documentation files (the "Software"), to deal
13 * in the Software without restriction, including without limitation the rights
14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 * copies of the Software, and to permit persons to whom the Software is
16 * furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included in all
19 * copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
30use crate::traits::{
31    DotProduct, IntoDegrees, IntoRadians, Length, LengthSquared, Lerp, Normalize, NormalizeAssign,
32    Real,
33};
34use crate::vector::TVec2;
35use crate::vector::TVec3;
36use core::fmt::{Display, Error, Formatter};
37use core::ops::{
38    Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
39};
40
41//==================================================================================================
42///
43/// A generic 4 component vector
44///
45#[repr(align(16))]
46#[derive(Copy, Clone, Debug)]
47pub struct TVec4<T: Real> {
48    pub(crate) data: [T; 4],
49}
50
51///
52/// Const fn for constructing a TVec2 in a const context
53///
54pub const fn vector_4_f32(x: f32, y: f32, z: f32, w: f32) -> TVec4<f32> {
55    TVec4::<f32> { data: [x, y, z, w] }
56}
57
58///
59/// Const fn for constructing a TVec2 in a const context
60///
61pub const fn vector_4_f64(x: f64, y: f64, z: f64, w: f64) -> TVec4<f64> {
62    TVec4::<f64> { data: [x, y, z, w] }
63}
64
65impl<T: Real> TVec4<T> {
66    ///
67    /// Constructs a new Vec4
68    ///
69    #[inline]
70    pub fn new(x: T, y: T, z: T, w: T) -> Self {
71        TVec4 { data: [x, y, z, w] }
72    }
73
74    ///
75    ///
76    ///
77    #[inline]
78    pub fn zero() -> Self {
79        Self::new(T::zero(), T::zero(), T::zero(), T::zero())
80    }
81}
82
83impl<T: Real> Display for TVec4<T> {
84    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
85        write!(
86            f,
87            "[ {:precision$} {:precision$} {:precision$} {:precision$} ]",
88            self.data[0],
89            self.data[1],
90            self.data[2],
91            self.data[3],
92            precision = f.precision().unwrap_or(f.width().unwrap_or(4)),
93        )
94    }
95}
96
97impl<T: Real> From<T> for TVec4<T> {
98    #[inline]
99    fn from(other: T) -> Self {
100        Self::new(other, T::zero(), T::zero(), T::zero())
101    }
102}
103
104impl<T: Real> From<TVec2<T>> for TVec4<T> {
105    #[inline]
106    fn from(other: TVec2<T>) -> Self {
107        Self::new(other.data[0], other.data[1], T::zero(), T::zero())
108    }
109}
110
111impl<T: Real> From<TVec3<T>> for TVec4<T> {
112    #[inline]
113    fn from(other: TVec3<T>) -> Self {
114        Self::new(other.data[0], other.data[1], other.data[2], T::zero())
115    }
116}
117
118impl<T: Real> From<[T; 4]> for TVec4<T> {
119    ///
120    /// Take the array as a vector
121    ///
122    #[inline]
123    fn from(other: [T; 4]) -> Self {
124        Self { data: other }
125    }
126}
127
128impl<T: Real> Into<[T; 4]> for TVec4<T> {
129    #[inline]
130    fn into(self) -> [T; 4] {
131        self.data
132    }
133}
134
135impl<T: Real> Index<usize> for TVec4<T> {
136    type Output = T;
137
138    #[inline]
139    fn index(&self, index: usize) -> &Self::Output {
140        &self.data[index]
141    }
142}
143
144impl<T: Real> IndexMut<usize> for TVec4<T> {
145    #[inline]
146    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
147        &mut self.data[index]
148    }
149}
150
151//
152// VEC4 <-> VEC4 MATH TRAIT IMPLS
153//
154
155impl<T: Real> Add<TVec4<T>> for TVec4<T> {
156    type Output = TVec4<T>;
157
158    #[inline]
159    fn add(mut self, rhs: TVec4<T>) -> Self::Output {
160        self.data[0] += rhs.data[0];
161        self.data[1] += rhs.data[1];
162        self.data[2] += rhs.data[2];
163        self.data[3] += rhs.data[3];
164        self
165    }
166}
167
168impl<T: Real> AddAssign<TVec4<T>> for TVec4<T> {
169    #[inline]
170    fn add_assign(&mut self, rhs: TVec4<T>) {
171        self.data[0] += rhs.data[0];
172        self.data[1] += rhs.data[1];
173        self.data[2] += rhs.data[2];
174        self.data[3] += rhs.data[3];
175    }
176}
177
178impl<T: Real> Sub<TVec4<T>> for TVec4<T> {
179    type Output = TVec4<T>;
180
181    #[inline]
182    fn sub(mut self, rhs: TVec4<T>) -> Self::Output {
183        self.data[0] -= rhs.data[0];
184        self.data[1] -= rhs.data[1];
185        self.data[2] -= rhs.data[2];
186        self.data[3] -= rhs.data[3];
187        self
188    }
189}
190
191impl<T: Real> SubAssign<TVec4<T>> for TVec4<T> {
192    #[inline]
193    fn sub_assign(&mut self, rhs: TVec4<T>) {
194        self.data[0] -= rhs.data[0];
195        self.data[1] -= rhs.data[1];
196        self.data[2] -= rhs.data[2];
197        self.data[3] -= rhs.data[3];
198    }
199}
200
201impl<T: Real> Mul<TVec4<T>> for TVec4<T> {
202    type Output = TVec4<T>;
203
204    #[inline]
205    fn mul(mut self, rhs: TVec4<T>) -> Self::Output {
206        self.data[0] *= rhs.data[0];
207        self.data[1] *= rhs.data[1];
208        self.data[2] *= rhs.data[2];
209        self.data[3] *= rhs.data[3];
210        self
211    }
212}
213
214impl<T: Real> MulAssign<TVec4<T>> for TVec4<T> {
215    #[inline]
216    fn mul_assign(&mut self, rhs: TVec4<T>) {
217        self.data[0] *= rhs.data[0];
218        self.data[1] *= rhs.data[1];
219        self.data[2] *= rhs.data[2];
220        self.data[3] *= rhs.data[3];
221    }
222}
223
224impl<T: Real> Div<TVec4<T>> for TVec4<T> {
225    type Output = TVec4<T>;
226
227    #[inline]
228    fn div(mut self, rhs: TVec4<T>) -> Self::Output {
229        self.data[0] /= rhs.data[0];
230        self.data[1] /= rhs.data[1];
231        self.data[2] /= rhs.data[2];
232        self.data[3] /= rhs.data[3];
233        self
234    }
235}
236
237impl<T: Real> DivAssign<TVec4<T>> for TVec4<T> {
238    #[inline]
239    fn div_assign(&mut self, rhs: TVec4<T>) {
240        self.data[0] /= rhs.data[0];
241        self.data[1] /= rhs.data[1];
242        self.data[2] /= rhs.data[2];
243        self.data[3] /= rhs.data[3];
244    }
245}
246
247//
248// VEC4 <-> FLOAT MATH TRAITS IMPLS
249//
250
251impl<T: Real> Add<T> for TVec4<T> {
252    type Output = TVec4<T>;
253
254    #[inline]
255    fn add(mut self, rhs: T) -> Self::Output {
256        self.data[0] += rhs;
257        self.data[1] += rhs;
258        self.data[2] += rhs;
259        self.data[3] += rhs;
260        self
261    }
262}
263
264impl<T: Real> AddAssign<T> for TVec4<T> {
265    #[inline]
266    fn add_assign(&mut self, rhs: T) {
267        self.data[0] += rhs;
268        self.data[1] += rhs;
269        self.data[2] += rhs;
270        self.data[3] += rhs;
271    }
272}
273
274impl<T: Real> Sub<T> for TVec4<T> {
275    type Output = TVec4<T>;
276
277    #[inline]
278    fn sub(mut self, rhs: T) -> Self::Output {
279        self.data[0] -= rhs;
280        self.data[1] -= rhs;
281        self.data[2] -= rhs;
282        self.data[3] -= rhs;
283        self
284    }
285}
286
287impl<T: Real> SubAssign<T> for TVec4<T> {
288    #[inline]
289    fn sub_assign(&mut self, rhs: T) {
290        self.data[0] -= rhs;
291        self.data[1] -= rhs;
292        self.data[2] -= rhs;
293        self.data[3] -= rhs;
294    }
295}
296
297impl<T: Real> Mul<T> for TVec4<T> {
298    type Output = TVec4<T>;
299
300    #[inline]
301    fn mul(mut self, rhs: T) -> Self::Output {
302        self.data[0] *= rhs;
303        self.data[1] *= rhs;
304        self.data[2] *= rhs;
305        self.data[3] *= rhs;
306        self
307    }
308}
309
310impl<T: Real> MulAssign<T> for TVec4<T> {
311    #[inline]
312    fn mul_assign(&mut self, rhs: T) {
313        self.data[0] *= rhs;
314        self.data[1] *= rhs;
315        self.data[2] *= rhs;
316        self.data[3] *= rhs;
317    }
318}
319
320impl<T: Real> Div<T> for TVec4<T> {
321    type Output = TVec4<T>;
322
323    #[inline]
324    fn div(mut self, rhs: T) -> Self::Output {
325        self.data[0] /= rhs;
326        self.data[1] /= rhs;
327        self.data[2] /= rhs;
328        self.data[3] /= rhs;
329        self
330    }
331}
332
333impl<T: Real> DivAssign<T> for TVec4<T> {
334    #[inline]
335    fn div_assign(&mut self, rhs: T) {
336        self.data[0] /= rhs;
337        self.data[1] /= rhs;
338        self.data[2] /= rhs;
339        self.data[3] /= rhs;
340    }
341}
342
343impl<T: Real> Neg for TVec4<T> {
344    type Output = Self;
345
346    #[inline]
347    fn neg(mut self) -> Self::Output {
348        self.data[0] = -self.data[0];
349        self.data[1] = -self.data[1];
350        self.data[2] = -self.data[2];
351        self.data[3] = -self.data[3];
352        self
353    }
354}
355
356impl<T: Real> Lerp<T> for TVec4<T> {
357    #[inline]
358    fn lerp(&self, b: &Self, factor: T) -> Self {
359        *self + ((*self - *b) * factor)
360    }
361}
362
363impl<T: Real> Length for TVec4<T> {
364    type Output = T;
365
366    fn length(&self) -> Self::Output {
367        self.length_squared().sqrt()
368    }
369}
370
371impl<T: Real> LengthSquared for TVec4<T> {
372    type Output = T;
373
374    fn length_squared(&self) -> Self::Output {
375        self.dot(self)
376    }
377}
378
379impl<T: Real> Normalize for TVec4<T> {
380    fn normalize(mut self) -> Self {
381        self.normalize_assign();
382        self
383    }
384}
385
386impl<T: Real> NormalizeAssign for TVec4<T> {
387    fn normalize_assign(&mut self) {
388        let len = self.length();
389        *self *= T::one() / len;
390    }
391}
392
393impl<T: Real> IntoDegrees for TVec4<T> {
394    #[inline]
395    fn into_degrees(mut self) -> Self {
396        self.data[0] = self.data[0].into_degrees();
397        self.data[1] = self.data[1].into_degrees();
398        self.data[2] = self.data[2].into_degrees();
399        self.data[3] = self.data[3].into_degrees();
400        self
401    }
402}
403
404impl<T: Real> IntoRadians for TVec4<T> {
405    #[inline]
406    fn into_radians(mut self) -> Self {
407        self.data[0] = self.data[0].into_radians();
408        self.data[1] = self.data[1].into_radians();
409        self.data[2] = self.data[2].into_radians();
410        self.data[3] = self.data[3].into_radians();
411        self
412    }
413}
414
415impl<T: Real> DotProduct<T> for TVec4<T> {
416    #[inline]
417    fn dot(&self, rhs: &Self) -> T {
418        (self.data[0] * rhs.data[0])
419            + (self.data[1] * rhs.data[1])
420            + (self.data[2] * rhs.data[2])
421            + (self.data[3] * rhs.data[3])
422    }
423}
424
425impl<T: Real> PartialEq<TVec4<T>> for TVec4<T> {
426    #[inline]
427    fn eq(&self, other: &TVec4<T>) -> bool {
428        self.data[0] == other.data[0]
429            && self.data[1] == other.data[1]
430            && self.data[2] == other.data[2]
431            && self.data[3] == other.data[3]
432    }
433
434    #[inline]
435    fn ne(&self, other: &TVec4<T>) -> bool {
436        self.data[0] != other.data[0]
437            || self.data[1] != other.data[1]
438            || self.data[2] != other.data[2]
439            || self.data[3] != other.data[3]
440    }
441}