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}