1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use glam::{Affine3A, Mat3, Vec3, Vec3Swizzles, Vec4};

#[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect;

/// Reduced-size version of `glam::Affine3A` for use when storage has
/// significant performance impact. Convert to `glam::Affine3A` to do
/// non-trivial calculations.
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
pub struct Affine3 {
    /// Scaling, rotation, shears, and other non-translation affine transforms
    pub matrix3: Mat3,
    /// Translation
    pub translation: Vec3,
}

impl Affine3 {
    /// Calculates the transpose of the affine 4x3 matrix to a 3x4 and formats it for packing into GPU buffers
    #[inline]
    pub fn to_transpose(&self) -> [Vec4; 3] {
        let transpose_3x3 = self.matrix3.transpose();
        [
            transpose_3x3.x_axis.extend(self.translation.x),
            transpose_3x3.y_axis.extend(self.translation.y),
            transpose_3x3.z_axis.extend(self.translation.z),
        ]
    }

    /// Calculates the inverse transpose of the 3x3 matrix and formats it for packing into GPU buffers
    #[inline]
    pub fn inverse_transpose_3x3(&self) -> ([Vec4; 2], f32) {
        let inverse_transpose_3x3 = Affine3A::from(self).inverse().matrix3.transpose();
        (
            [
                (inverse_transpose_3x3.x_axis, inverse_transpose_3x3.y_axis.x).into(),
                (
                    inverse_transpose_3x3.y_axis.yz(),
                    inverse_transpose_3x3.z_axis.xy(),
                )
                    .into(),
            ],
            inverse_transpose_3x3.z_axis.z,
        )
    }
}

impl From<&Affine3A> for Affine3 {
    fn from(affine: &Affine3A) -> Self {
        Self {
            matrix3: affine.matrix3.into(),
            translation: affine.translation.into(),
        }
    }
}

impl From<&Affine3> for Affine3A {
    fn from(affine3: &Affine3) -> Self {
        Self {
            matrix3: affine3.matrix3.into(),
            translation: affine3.translation.into(),
        }
    }
}