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}