nova_math/vector/
vector3.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    CrossProduct, DotProduct, IntoDegrees, IntoRadians, Length, LengthSquared, Lerp, Normalize,
32    NormalizeAssign, Real,
33};
34use crate::vector::TVec2;
35use crate::vector::TVec4;
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 3 component vector
44///
45#[repr(align(16))]
46#[derive(Copy, Clone, Debug)]
47pub struct TVec3<T: Real> {
48    pub(crate) data: [T; 4],
49}
50
51///
52/// Const fn for constructing a TVec3 in a const context
53///
54pub const fn vector_3_f32(x: f32, y: f32, z: f32) -> TVec3<f32> {
55    TVec3::<f32> {
56        data: [x, y, z, 0.0],
57    }
58}
59
60///
61/// Const fn for constructing a TVec3 in a const context
62///
63pub const fn vector_3_f64(x: f64, y: f64, z: f64) -> TVec3<f64> {
64    TVec3::<f64> {
65        data: [x, y, z, 0.0],
66    }
67}
68
69impl<T: Real> TVec3<T> {
70    ///
71    /// Constructs a new Vec3
72    ///
73    #[inline]
74    pub fn new(x: T, y: T, z: T) -> Self {
75        TVec3 {
76            data: [x, y, z, T::zero()],
77        }
78    }
79
80    ///
81    /// Return a vector with all zeroes
82    ///
83    #[inline]
84    pub fn zero() -> Self {
85        Self::new(T::zero(), T::zero(), T::zero())
86    }
87
88    ///
89    /// Return a vector with all ones
90    ///
91    #[inline]
92    pub fn one() -> Self {
93        Self::new(T::one(), T::one(), T::one())
94    }
95
96    ///
97    /// Return a unit vector that points in the up direction
98    ///
99    #[inline]
100    pub fn up() -> Self {
101        Self::new(T::zero(), T::one(), T::zero())
102    }
103
104    ///
105    /// Return a unit vector that points in the down direction
106    ///
107    #[inline]
108    pub fn down() -> Self {
109        Self::new(T::zero(), -T::one(), T::zero())
110    }
111
112    ///
113    /// Return a unit vector that points in the right direction
114    ///
115    #[inline]
116    pub fn right() -> Self {
117        Self::new(T::one(), T::zero(), T::zero())
118    }
119
120    ///
121    /// Return a unit vector that points in the left direction
122    ///
123    #[inline]
124    pub fn left() -> Self {
125        Self::new(-T::one(), T::zero(), T::zero())
126    }
127
128    ///
129    /// Return a unit vector that points in the forward direction
130    ///
131    #[inline]
132    pub fn forward() -> Self {
133        Self::new(T::zero(), T::zero(), T::one())
134    }
135
136    ///
137    /// Return a unit vector that points in the back direction
138    ///
139    #[inline]
140    pub fn back() -> Self {
141        Self::new(T::zero(), T::zero(), -T::one())
142    }
143}
144
145impl<T: Real> Display for TVec3<T> {
146    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
147        write!(
148            f,
149            "[ {:precision$} {:precision$} {:precision$} ]",
150            self.data[0],
151            self.data[1],
152            self.data[2],
153            precision = f.precision().unwrap_or(f.width().unwrap_or(4)),
154        )
155    }
156}
157
158impl<T: Real> From<T> for TVec3<T> {
159    #[inline]
160    fn from(other: T) -> Self {
161        Self::new(other, T::zero(), T::zero())
162    }
163}
164
165impl<T: Real> From<TVec2<T>> for TVec3<T> {
166    #[inline]
167    fn from(other: TVec2<T>) -> Self {
168        Self::new(other.data[0], other.data[1], T::zero())
169    }
170}
171
172impl<T: Real> From<TVec4<T>> for TVec3<T> {
173    #[inline]
174    fn from(other: TVec4<T>) -> Self {
175        Self::new(other.data[0], other.data[1], other.data[2])
176    }
177}
178
179impl<T: Real> From<[T; 3]> for TVec3<T> {
180    ///
181    /// Take the array as a vector
182    ///
183    #[inline]
184    fn from(other: [T; 3]) -> Self {
185        Self {
186            data: [other[0], other[1], other[2], T::zero()],
187        }
188    }
189}
190
191impl<T: Real> Into<[T; 3]> for TVec3<T> {
192    #[inline]
193    fn into(self) -> [T; 3] {
194        [self.data[0], self.data[1], self.data[2]]
195    }
196}
197
198impl<T: Real> From<(T, T, T)> for TVec3<T> {
199    ///
200    /// Take the array as a vector
201    ///
202    #[inline]
203    fn from(other: (T, T, T)) -> Self {
204        Self {
205            data: [other.0, other.1, other.2, T::zero()],
206        }
207    }
208}
209
210impl<T: Real> Into<(T, T, T)> for TVec3<T> {
211    #[inline]
212    fn into(self) -> (T, T, T) {
213        (self.data[0], self.data[1], self.data[2])
214    }
215}
216
217impl<T: Real> Index<usize> for TVec3<T> {
218    type Output = T;
219
220    #[inline]
221    fn index(&self, index: usize) -> &Self::Output {
222        &self.data[index]
223    }
224}
225
226impl<T: Real> IndexMut<usize> for TVec3<T> {
227    #[inline]
228    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
229        &mut self.data[index]
230    }
231}
232
233//
234// VEC3 <-> VEC3 MATH TRAIT IMPLS
235//
236
237impl<T: Real> Add<TVec3<T>> for TVec3<T> {
238    type Output = TVec3<T>;
239
240    #[inline]
241    fn add(mut self, rhs: TVec3<T>) -> Self::Output {
242        self.data[0] += rhs.data[0];
243        self.data[1] += rhs.data[1];
244        self.data[2] += rhs.data[2];
245        self
246    }
247}
248
249impl<T: Real> AddAssign<TVec3<T>> for TVec3<T> {
250    #[inline]
251    fn add_assign(&mut self, rhs: TVec3<T>) {
252        self.data[0] += rhs.data[0];
253        self.data[1] += rhs.data[1];
254        self.data[2] += rhs.data[2];
255    }
256}
257
258impl<T: Real> Sub<TVec3<T>> for TVec3<T> {
259    type Output = TVec3<T>;
260
261    #[inline]
262    fn sub(mut self, rhs: TVec3<T>) -> Self::Output {
263        self.data[0] -= rhs.data[0];
264        self.data[1] -= rhs.data[1];
265        self.data[2] -= rhs.data[2];
266        self
267    }
268}
269
270impl<T: Real> SubAssign<TVec3<T>> for TVec3<T> {
271    #[inline]
272    fn sub_assign(&mut self, rhs: TVec3<T>) {
273        self.data[0] -= rhs.data[0];
274        self.data[1] -= rhs.data[1];
275        self.data[2] -= rhs.data[2];
276    }
277}
278
279impl<T: Real> Mul<TVec3<T>> for TVec3<T> {
280    type Output = TVec3<T>;
281
282    #[inline]
283    fn mul(mut self, rhs: TVec3<T>) -> Self::Output {
284        self.data[0] *= rhs.data[0];
285        self.data[1] *= rhs.data[1];
286        self.data[2] *= rhs.data[2];
287        self
288    }
289}
290
291impl<T: Real> MulAssign<TVec3<T>> for TVec3<T> {
292    #[inline]
293    fn mul_assign(&mut self, rhs: TVec3<T>) {
294        self.data[0] *= rhs.data[0];
295        self.data[1] *= rhs.data[1];
296        self.data[2] *= rhs.data[2];
297    }
298}
299
300impl<T: Real> Div<TVec3<T>> for TVec3<T> {
301    type Output = TVec3<T>;
302
303    #[inline]
304    fn div(mut self, rhs: TVec3<T>) -> Self::Output {
305        self.data[0] /= rhs.data[0];
306        self.data[1] /= rhs.data[1];
307        self.data[2] /= rhs.data[2];
308        self
309    }
310}
311
312impl<T: Real> DivAssign<TVec3<T>> for TVec3<T> {
313    #[inline]
314    fn div_assign(&mut self, rhs: TVec3<T>) {
315        self.data[0] /= rhs.data[0];
316        self.data[1] /= rhs.data[1];
317        self.data[2] /= rhs.data[2];
318    }
319}
320
321//
322// VEC3 <-> FLOAT MATH TRAITS IMPLS
323//
324
325impl<T: Real> Add<T> for TVec3<T> {
326    type Output = TVec3<T>;
327
328    #[inline]
329    fn add(mut self, rhs: T) -> Self::Output {
330        self.data[0] += rhs;
331        self.data[1] += rhs;
332        self.data[2] += rhs;
333        self
334    }
335}
336
337impl<T: Real> AddAssign<T> for TVec3<T> {
338    #[inline]
339    fn add_assign(&mut self, rhs: T) {
340        self.data[0] += rhs;
341        self.data[1] += rhs;
342        self.data[2] += rhs;
343    }
344}
345
346impl<T: Real> Sub<T> for TVec3<T> {
347    type Output = TVec3<T>;
348
349    #[inline]
350    fn sub(mut self, rhs: T) -> Self::Output {
351        self.data[0] -= rhs;
352        self.data[1] -= rhs;
353        self.data[2] -= rhs;
354        self
355    }
356}
357
358impl<T: Real> SubAssign<T> for TVec3<T> {
359    #[inline]
360    fn sub_assign(&mut self, rhs: T) {
361        self.data[0] -= rhs;
362        self.data[1] -= rhs;
363        self.data[2] -= rhs;
364    }
365}
366
367impl<T: Real> Mul<T> for TVec3<T> {
368    type Output = TVec3<T>;
369
370    #[inline]
371    fn mul(mut self, rhs: T) -> Self::Output {
372        self.data[0] *= rhs;
373        self.data[1] *= rhs;
374        self.data[2] *= rhs;
375        self
376    }
377}
378
379impl<T: Real> MulAssign<T> for TVec3<T> {
380    #[inline]
381    fn mul_assign(&mut self, rhs: T) {
382        self.data[0] *= rhs;
383        self.data[1] *= rhs;
384        self.data[2] *= rhs;
385    }
386}
387
388impl<T: Real> Div<T> for TVec3<T> {
389    type Output = TVec3<T>;
390
391    #[inline]
392    fn div(mut self, rhs: T) -> Self::Output {
393        self.data[0] /= rhs;
394        self.data[1] /= rhs;
395        self.data[2] /= rhs;
396        self
397    }
398}
399
400impl<T: Real> DivAssign<T> for TVec3<T> {
401    #[inline]
402    fn div_assign(&mut self, rhs: T) {
403        self.data[0] /= rhs;
404        self.data[1] /= rhs;
405        self.data[2] /= rhs;
406    }
407}
408
409impl<T: Real> Neg for TVec3<T> {
410    type Output = Self;
411
412    #[inline]
413    fn neg(mut self) -> Self::Output {
414        self.data[0] = -self.data[0];
415        self.data[1] = -self.data[1];
416        self.data[2] = -self.data[2];
417        self
418    }
419}
420
421impl<T: Real> Lerp<T> for TVec3<T> {
422    #[inline]
423    fn lerp(&self, b: &Self, factor: T) -> Self {
424        *self + ((*self - *b) * factor)
425    }
426}
427
428impl<T: Real> Length for TVec3<T> {
429    type Output = T;
430
431    #[inline]
432    fn length(&self) -> Self::Output {
433        self.length_squared().sqrt()
434    }
435}
436
437impl<T: Real> LengthSquared for TVec3<T> {
438    type Output = T;
439
440    #[inline]
441    fn length_squared(&self) -> Self::Output {
442        self.dot(self)
443    }
444}
445
446impl<T: Real> Normalize for TVec3<T> {
447    #[inline]
448    fn normalize(mut self) -> Self {
449        self.normalize_assign();
450        self
451    }
452}
453
454impl<T: Real> NormalizeAssign for TVec3<T> {
455    #[inline]
456    fn normalize_assign(&mut self) {
457        let len = self.length();
458        *self *= T::one() / len;
459    }
460}
461
462impl<T: Real> DotProduct<T> for TVec3<T> {
463    #[inline]
464    fn dot(&self, rhs: &Self) -> T {
465        (self.data[0] * rhs.data[0]) + (self.data[1] * rhs.data[1]) + (self.data[2] * rhs.data[2])
466    }
467}
468
469impl<T: Real> IntoDegrees for TVec3<T> {
470    #[inline]
471    fn into_degrees(mut self) -> Self {
472        self.data[0] = self.data[0].into_degrees();
473        self.data[1] = self.data[1].into_degrees();
474        self.data[2] = self.data[2].into_degrees();
475        self
476    }
477}
478
479impl<T: Real> IntoRadians for TVec3<T> {
480    #[inline]
481    fn into_radians(mut self) -> Self {
482        self.data[0] = self.data[0].into_radians();
483        self.data[1] = self.data[1].into_radians();
484        self.data[2] = self.data[2].into_radians();
485        self
486    }
487}
488
489impl<T: Real> CrossProduct for TVec3<T> {
490    #[inline]
491    fn cross(&self, rhs: &Self) -> Self {
492        let x = (self.data[1] * rhs.data[2]) - (self.data[2] * rhs.data[1]);
493        let y = (self.data[2] * rhs.data[0]) - (self.data[0] * rhs.data[2]);
494        let z = (self.data[0] * rhs.data[1]) - (self.data[1] * rhs.data[0]);
495        Self::new(x, y, z)
496    }
497}
498
499impl<T: Real> PartialEq<TVec3<T>> for TVec3<T> {
500    #[inline]
501    fn eq(&self, other: &TVec3<T>) -> bool {
502        self.data[0] == other.data[0]
503            && self.data[1] == other.data[1]
504            && self.data[2] == other.data[2]
505    }
506
507    #[inline]
508    fn ne(&self, other: &TVec3<T>) -> bool {
509        self.data[0] != other.data[0]
510            || self.data[1] != other.data[1]
511            || self.data[2] != other.data[2]
512    }
513}