spirv_std/
matrix.rs

1//! a set of common SPIR-V Matrices, used for intrinsics
2
3use core::fmt::{Debug, Display, Formatter};
4use glam::{Affine3A, Mat3, Mat3A, Mat4, Vec3, Vec3A};
5
6/// A Matrix with 4 columns of [`Vec3`], very similar to glam's [`Affine3A`].
7///
8/// Primarily used in ray tracing extensions to represent object rotation, scale and translation.
9///
10/// # Limitations
11/// These Limitations apply to all structs marked with `#[spirv(matrix)]`, which `Matrix4x3` is the only one in
12/// `spirv-std`:
13/// * Cannot be used within buffers, push constants or anything that requires an "explicit layout". Use [`Affine3A`],
14/// [`Mat4`] or the combination of [`Mat3`] with [`Vec3`] instead and convert them to `Matrix4x3` in the shader.
15/// * There may be other situations where this type may surprisingly fail!
16#[derive(Clone, Copy, Default, PartialEq)]
17#[repr(C)]
18#[spirv(matrix)]
19#[allow(missing_docs)]
20pub struct Matrix4x3 {
21    pub x_axis: Vec3A,
22    pub y_axis: Vec3A,
23    pub z_axis: Vec3A,
24    pub w_axis: Vec3A,
25}
26
27/// The `from_*` fn signatures should match [`Affine3A`], to make it easier to switch to [`Affine3A`] later.
28/// The `to_*` fn signatures are custom.
29impl Matrix4x3 {
30    /// Convert from glam's [`Affine3A`]
31    pub fn from_affine3a(affine: Affine3A) -> Self {
32        Self {
33            x_axis: affine.x_axis,
34            y_axis: affine.y_axis,
35            z_axis: affine.z_axis,
36            w_axis: affine.w_axis,
37        }
38    }
39
40    /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and
41    /// rotation)
42    pub fn from_mat3(mat3: Mat3) -> Self {
43        Self::from_affine3a(Affine3A::from_mat3(mat3))
44    }
45
46    /// Creates an affine transform from a 3x3 matrix (expressing scale, shear and rotation)
47    /// and a translation vector.
48    ///
49    /// Equivalent to `Affine3A::from_translation(translation) * Affine3A::from_mat3(mat3)`
50    pub fn from_mat3_translation(mat3: Mat3, translation: Vec3) -> Self {
51        Self::from_affine3a(Affine3A::from_mat3_translation(mat3, translation))
52    }
53
54    /// The given `Mat4` must be an affine transform,
55    /// i.e. contain no perspective transform.
56    pub fn from_mat4(m: Mat4) -> Self {
57        Self::from_affine3a(Affine3A::from_mat4(m))
58    }
59
60    /// Convert to glam's [`Affine3A`]
61    pub fn to_affine3a(self) -> Affine3A {
62        Affine3A {
63            matrix3: Mat3A {
64                x_axis: self.x_axis,
65                y_axis: self.y_axis,
66                z_axis: self.z_axis,
67            },
68            translation: self.w_axis,
69        }
70    }
71
72    /// Creates a 3x3 matrix representing the rotation and scale, cutting off the translation
73    pub fn to_mat3a(self) -> Mat3A {
74        self.to_affine3a().matrix3
75    }
76
77    /// Creates a 3x3 matrix representing the rotation and scale, cutting off the translation
78    pub fn to_mat3(self) -> Mat3 {
79        Mat3::from(self.to_mat3a())
80    }
81
82    /// Creates a 4x4 matrix from this affine transform
83    pub fn to_mat4(self) -> Mat4 {
84        Mat4::from(self.to_affine3a())
85    }
86}
87
88impl Debug for Matrix4x3 {
89    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
90        Debug::fmt(&self.to_mat4(), f)
91    }
92}
93
94impl Display for Matrix4x3 {
95    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
96        Display::fmt(&self.to_mat4(), f)
97    }
98}