vector_traits/
vector3.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 crate::prelude::*;
7
8/// A basic three-dimensional vector trait, designed for flexibility in precision.
9///
10/// The `HasXYZ` trait abstracts over three-dimensional vectors, allowing for easy
11/// transition between different precisions (e.g., `f32` and `f64`) without necessitating
12/// significant codebase modifications. It only provides the most basic vector interface.
13/// It is intended to be used in situations where you need a custom storage type of vectors.
14/// For example an FFI type.
15///
16/// Implementors of this trait can benefit from the ability to switch between different
17/// precision representations seamlessly, making it ideal for applications where varying
18/// precision levels might be desirable at different stages or configurations.
19///
20pub trait HasXYZ: HasXY {
21    fn new_3d(x: Self::Scalar, y: Self::Scalar, z: Self::Scalar) -> Self;
22    fn z(self) -> Self::Scalar;
23    fn z_mut(&mut self) -> &mut Self::Scalar;
24    fn set_z(&mut self, val: Self::Scalar);
25}
26
27/// A generic three-dimensional vector trait.
28///
29/// The `GenericVector3` trait abstracts over three-dimensional vectors, allowing for easy
30/// transition between different precisions (e.g., `f32` and `f64`) without necessitating
31/// significant codebase modifications. It provides the common operations one would expect
32/// for 3D vectors, such as dot products, cross products, and normalization.
33///
34/// Implementors of this trait can benefit from the ability to switch between different
35/// precision representations seamlessly, making it ideal for applications where varying
36/// precision levels might be desirable at different stages or configurations.
37///
38/// The associated `Scalar` type represents the scalar type (e.g., `f32` or `f64`) used
39/// by the vector, and `Vector2` is the corresponding two-dimensional vector type.
40///
41/// Note: The actual trait functionality might vary based on the concrete implementations.
42pub trait GenericVector3:
43    HasXYZ
44    + Copy
45    + Approx
46    + PartialEq
47    + std::ops::AddAssign
48    + std::ops::SubAssign
49    + std::ops::Index<usize, Output = Self::Scalar>
50    + std::ops::IndexMut<usize, Output = Self::Scalar>
51    + std::ops::Neg<Output = Self>
52    + std::ops::Add<Self, Output = Self>
53    + std::ops::Sub<Self, Output = Self>
54    + std::ops::Mul<Self::Scalar, Output = Self>
55    + std::ops::Div<Self::Scalar, Output = Self>
56    + Into<[Self::Scalar; 3]>
57    + From<[Self::Scalar; 3]>
58{
59    // Associated constants
60    const ZERO: Self;
61    const ONE: Self;
62
63    type Affine: Affine3D<Vector3 = Self>;
64    type Aabb: Aabb3<Vector = Self>;
65    type Vector2: GenericVector2<Scalar = Self::Scalar, Vector3 = Self>;
66    fn new(x: Self::Scalar, y: Self::Scalar, z: Self::Scalar) -> Self;
67    fn splat(value: Self::Scalar) -> Self;
68    fn to_2d(self) -> Self::Vector2;
69    fn magnitude(self) -> Self::Scalar;
70    fn magnitude_sq(self) -> Self::Scalar;
71    fn dot(self, other: Self) -> Self::Scalar;
72    fn cross(self, rhs: Self) -> Self;
73    fn normalize(self) -> Self;
74    fn try_normalize(self, epsilon: Self::Scalar) -> Option<Self>;
75    fn distance(self, other: Self) -> Self::Scalar;
76    fn distance_sq(self, rhs: Self) -> Self::Scalar;
77    fn min(self, rhs: Self) -> Self;
78    fn max(self, rhs: Self) -> Self;
79    /// Clamps the vector's components to be within the range defined by `min` and `max`.
80    ///
81    /// # Note
82    /// This implementation does **not** follow `nalgebra`'s convention for `clamp`.
83    /// In `nalgebra`, `clamp` is symmetric around zero.
84    /// In this implementation, `clamp` ensures that `self` is bounded by `min` and `max`
85    /// in a non-symmetric way: `self.min(max).max(min)`.
86    fn clamp(self, min: Self, max: Self) -> Self;
87    /// returns false on all inf or NaN values
88    fn is_finite(self) -> bool;
89}
90
91/// Trait for vector types that can be upgraded to a SIMD-optimized variant
92/// for computation, then downgraded back.
93pub trait SimdUpgradable: GenericVector3
94where
95    Self::Simd: GenericVector3<Scalar = Self::Scalar>,
96{
97    /// The SIMD-optimized version of this vector type.
98    /// For glam::Vec3, this is glam::Vec3A. For glam::DVec3, this is glam::DVec3 itself (no-op).
99    type Simd;
100
101    /// Convert to the SIMD-optimized variant
102    fn to_simd(self) -> Self::Simd;
103
104    /// Convert from the SIMD-optimized variant
105    fn from_simd(simd: Self::Simd) -> Self;
106}