block_mesh/geometry/
axis.rs

1use ilattice::glam::{IVec3, UVec3};
2
3/// Either the X, Y, or Z axis.
4#[derive(Clone, Copy, Debug, Eq, PartialEq)]
5#[repr(u8)]
6pub enum Axis {
7    X = 0,
8    Y = 1,
9    Z = 2,
10}
11
12impl Axis {
13    /// The index for a point's component on this axis.
14    #[inline]
15    pub fn index(&self) -> usize {
16        *self as usize
17    }
18
19    #[inline]
20    pub const fn get_unit_vector(&self) -> UVec3 {
21        match self {
22            Axis::X => UVec3::X,
23            Axis::Y => UVec3::Y,
24            Axis::Z => UVec3::Z,
25        }
26    }
27}
28
29/// One of the six possible `{N, U, V}` --> `{X, Y, Z}` mappings.
30///
31/// This can be combined with a `-1` or `+1` sign for the **N**ormal axis to
32/// make an [`OrientedBlockFace`][crate::OrientedBlockFace].
33///
34/// See the [`geometry` module documentation][crate::geometry] for more
35/// information on `{N, U, V}` space.
36///
37/// # Even and Odd
38///
39/// Even permutations:
40/// - [AxisPermutation::Xyz]
41/// - [AxisPermutation::Zxy]
42/// - [AxisPermutation::Yzx]
43///
44/// Odd permutations:
45/// - [AxisPermutation::Zyx]
46/// - [AxisPermutation::Xzy]
47/// - [AxisPermutation::Yxz]
48#[derive(Clone, Copy, Debug, Eq, PartialEq)]
49pub enum AxisPermutation {
50    // Even permutations
51    Xyz,
52    Zxy,
53    Yzx,
54    // Odd permutations
55    Zyx,
56    Xzy,
57    Yxz,
58}
59
60impl AxisPermutation {
61    #[inline]
62    pub const fn even_with_normal_axis(axis: Axis) -> Self {
63        match axis {
64            Axis::X => AxisPermutation::Xyz,
65            Axis::Y => AxisPermutation::Yzx,
66            Axis::Z => AxisPermutation::Zxy,
67        }
68    }
69
70    #[inline]
71    pub const fn odd_with_normal_axis(axis: Axis) -> Self {
72        match axis {
73            Axis::X => AxisPermutation::Xzy,
74            Axis::Y => AxisPermutation::Yxz,
75            Axis::Z => AxisPermutation::Zyx,
76        }
77    }
78
79    #[inline]
80    pub const fn sign(&self) -> i32 {
81        match self {
82            AxisPermutation::Xyz => 1,
83            AxisPermutation::Zxy => 1,
84            AxisPermutation::Yzx => 1,
85            AxisPermutation::Zyx => -1,
86            AxisPermutation::Xzy => -1,
87            AxisPermutation::Yxz => -1,
88        }
89    }
90
91    /// Returns the [`Axes`] in the order specified by the permutation.
92    ///
93    /// # Example
94    ///
95    /// ```
96    /// # use block_mesh::*;
97    /// let xyz = AxisPermutation::Xyz;
98    /// assert_eq!(xyz.axes(), [Axis::X, Axis::Y, Axis::Z]);
99    /// ```
100    ///
101    /// [`Axes`]: Axis
102    #[inline]
103    pub const fn axes(&self) -> [Axis; 3] {
104        match self {
105            AxisPermutation::Xyz => [Axis::X, Axis::Y, Axis::Z],
106            AxisPermutation::Zxy => [Axis::Z, Axis::X, Axis::Y],
107            AxisPermutation::Yzx => [Axis::Y, Axis::Z, Axis::X],
108            AxisPermutation::Zyx => [Axis::Z, Axis::Y, Axis::X],
109            AxisPermutation::Xzy => [Axis::X, Axis::Z, Axis::Y],
110            AxisPermutation::Yxz => [Axis::Y, Axis::X, Axis::Z],
111        }
112    }
113}
114
115/// Either the -X, +X, -Y, +Y, -Z, or +Z axis.
116#[derive(Clone, Copy, Debug, Eq, PartialEq)]
117#[repr(u8)]
118pub enum SignedAxis {
119    NegX = 0,
120    PosX = 1,
121    NegY = 2,
122    PosY = 3,
123    NegZ = 4,
124    PosZ = 5,
125}
126
127impl SignedAxis {
128    #[inline]
129    pub fn new(sign: i32, axis: Axis) -> Self {
130        assert!(sign != 0);
131
132        match (sign > 0, axis) {
133            (false, Axis::X) => Self::NegX,
134            (false, Axis::Y) => Self::NegY,
135            (false, Axis::Z) => Self::NegZ,
136            (true, Axis::X) => Self::PosX,
137            (true, Axis::Y) => Self::PosY,
138            (true, Axis::Z) => Self::PosZ,
139        }
140    }
141
142    #[inline]
143    pub fn unsigned_axis(&self) -> Axis {
144        match self {
145            Self::NegX => Axis::X,
146            Self::NegY => Axis::Y,
147            Self::NegZ => Axis::Z,
148            Self::PosX => Axis::X,
149            Self::PosY => Axis::Y,
150            Self::PosZ => Axis::Z,
151        }
152    }
153
154    #[inline]
155    pub fn signum(&self) -> i32 {
156        match self {
157            Self::NegX => -1,
158            Self::NegY => -1,
159            Self::NegZ => -1,
160            Self::PosX => 1,
161            Self::PosY => 1,
162            Self::PosZ => 1,
163        }
164    }
165
166    #[inline]
167    pub fn get_unit_vector(&self) -> IVec3 {
168        match self {
169            Self::NegX => -IVec3::X,
170            Self::NegY => -IVec3::Y,
171            Self::NegZ => -IVec3::Z,
172            Self::PosX => IVec3::X,
173            Self::PosY => IVec3::Y,
174            Self::PosZ => IVec3::Z,
175        }
176    }
177
178    #[inline]
179    pub fn from_vector(v: IVec3) -> Option<Self> {
180        match v.to_array() {
181            [x, 0, 0] => Some(SignedAxis::new(x, Axis::X)),
182            [0, y, 0] => Some(SignedAxis::new(y, Axis::Y)),
183            [0, 0, z] => Some(SignedAxis::new(z, Axis::Z)),
184            _ => None,
185        }
186    }
187}