glam_det 2.0.0

A simple and fast 3D math library for games and graphics.
Documentation
// Copyright (C) 2020-2025 glam-det authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/// Euler rotation sequences.
///
/// The angles are applied starting from the right.
/// E.g. XYZ will first apply the z-axis rotation.
///
/// YXZ can be used for yaw (y-axis), pitch (x-axis), roll (z-axis).
#[derive(Debug, Clone, Copy)]
pub enum EulerRot {
    /// Tait-Bryan rotation ZYX
    ZYX,
    /// Tait-Bryan rotation ZXY
    ZXY,
    /// Tait-Bryan rotation YXZ
    YXZ,
    /// Tait-Bryan rotation YZX
    YZX,
    /// Tait-Bryan rotation XYZ
    XYZ,
    /// Tait-Bryan rotation XZY
    XZY,
    /// Proper Euler rotation ZYZ
    ZYZ,
    /// Proper Euler rotation ZXZ
    ZXZ,
    /// Proper Euler rotation YXY
    YXY,
    /// Proper Euler rotation YZY
    YZY,
    /// Proper Eulerrotation XYX
    XYX,
    /// Proper Euler rotation XZX
    XZX,
}

impl EulerRot {
    pub(crate) const fn levi_civita_sig(self) -> f32 {
        let (i, j, k) = self.map_sequence();
        let (i, j, k) = (i as i32, j as i32, k as i32);
        ((i - j) * (j - k) * (k - i) / 2) as f32
    }

    pub(crate) const fn map_sequence(self) -> (usize, usize, usize) {
        use EulerRot::*;
        match self {
            XYZ | ZYZ => (3, 2, 1),
            YXZ | ZXZ => (3, 1, 2),
            ZXY | YXY => (2, 1, 3),
            XZY | YZY => (2, 3, 1),
            ZYX | XYX => (1, 2, 3),
            YZX | XZX => (1, 3, 2),
        }
    }

    pub(crate) const fn not_proper(self) -> bool {
        use EulerRot::*;
        match self {
            ZYX | ZXY | YXZ | YZX | XYZ | XZY => true,
            ZYZ | ZXZ | YXY | YZY | XYX | XZX => false,
        }
    }
}

impl Default for EulerRot {
    /// Default `XYZ` as pitch (x-axis), yaw (y-axis), roll (z-axis).
    fn default() -> Self {
        Self::XYZ
    }
}