fromsoftware_shared/dl_math/
special.rs

1use std::mem;
2
3use glam::{Mat3A, Mat4, Vec3A, Vec4};
4
5use crate::{F32Matrix4x4, F32Vector4};
6
7/// Row-major 4x4 float model matrix.
8#[repr(C, align(16))]
9#[derive(Debug, Clone, Copy, PartialEq)]
10pub struct F32ModelMatrix(
11    pub F32Vector4,
12    pub F32Vector4,
13    pub F32Vector4,
14    pub F32Vector4,
15);
16
17/// Row-major 4x4 float view matrix.
18pub type F32ViewMatrix = F32ModelMatrix;
19
20/// Row-major 4x4 float model matrix packed as a column major 4x3.
21///
22/// The 4x4 is packed by discarding the 4th component of each row.
23#[repr(C, align(16))]
24#[derive(Debug, Clone, Copy, PartialEq)]
25pub struct F32PackedModelMatrix(pub F32Vector4, pub F32Vector4, pub F32Vector4);
26
27impl F32ModelMatrix {
28    /// Construct from an array of row vectors.
29    #[inline]
30    pub fn new(r0: F32Vector4, r1: F32Vector4, r2: F32Vector4, r3: F32Vector4) -> Self {
31        Self(r0, r1, r2, r3)
32    }
33
34    /// Extract the rotation matrix.
35    #[inline]
36    pub fn rotation<T: From<Mat3A>>(&self) -> T {
37        let m =
38            Mat4::from_cols(self.0.into(), self.1.into(), self.2.into(), self.3.into()).transpose();
39        Mat3A::from_mat4(m).into()
40    }
41
42    /// Extract the translation vector.
43    #[inline]
44    pub fn translation<T: From<Vec3A>>(&self) -> T {
45        Vec3A::from_vec4(self.3.into()).into()
46    }
47}
48
49impl F32PackedModelMatrix {
50    /// Pack from an array of row vectors.
51    #[inline]
52    pub fn new(r0: F32Vector4, r1: F32Vector4, r2: F32Vector4, r3: F32Vector4) -> Self {
53        let t = Mat4::from_cols(r0.into(), r1.into(), r2.into(), r3.into()).transpose();
54        Self(t.x_axis.into(), t.y_axis.into(), t.z_axis.into())
55    }
56
57    /// Extract the rotation matrix.
58    #[inline]
59    pub fn rotation<T: From<glam::Mat3A>>(&self) -> T {
60        let m = Mat4::from_cols(self.0.into(), self.1.into(), self.2.into(), Vec4::ZERO);
61        Mat3A::from_mat4(m).into()
62    }
63
64    /// Extract the translation vector.
65    #[inline]
66    pub fn translation<T: From<glam::Vec3A>>(&self) -> T {
67        Vec3A::from_vec4(self.w_axis().into()).into()
68    }
69
70    /// Extract the x axis.
71    #[inline]
72    pub fn x_axis(&self) -> F32Vector4 {
73        F32Vector4(self.0.0, self.1.0, self.2.0, 0.0)
74    }
75
76    /// Extract the y axis.
77    #[inline]
78    pub fn y_axis(&self) -> F32Vector4 {
79        F32Vector4(self.0.1, self.1.1, self.2.1, 0.0)
80    }
81
82    /// Extract the z axis.
83    #[inline]
84    pub fn z_axis(&self) -> F32Vector4 {
85        F32Vector4(self.0.2, self.1.2, self.2.2, 0.0)
86    }
87
88    /// Extract the w axis.
89    #[inline]
90    pub fn w_axis(&self) -> F32Vector4 {
91        F32Vector4(self.0.3, self.1.3, self.2.3, 1.0)
92    }
93}
94
95impl From<F32ModelMatrix> for F32PackedModelMatrix {
96    #[inline]
97    fn from(F32ModelMatrix(r0, r1, r2, r3): F32ModelMatrix) -> Self {
98        Self::new(r0, r1, r2, r3)
99    }
100}
101
102impl From<F32ModelMatrix> for F32Matrix4x4 {
103    #[inline]
104    fn from(F32ModelMatrix(r0, r1, r2, r3): F32ModelMatrix) -> Self {
105        Self(r0, r1, r2, r3)
106    }
107}
108
109impl From<F32ModelMatrix> for Mat4 {
110    #[inline]
111    fn from(F32ModelMatrix(r0, r1, r2, r3): F32ModelMatrix) -> Self {
112        let mut m = Self::from_cols(r0.into(), r1.into(), r2.into(), r3.into());
113        let w_axis = mem::replace(&mut m.w_axis, Vec4::W);
114
115        Self {
116            w_axis,
117            ..m.transpose()
118        }
119    }
120}
121
122impl From<F32PackedModelMatrix> for F32ModelMatrix {
123    #[inline]
124    fn from(F32PackedModelMatrix(c0, c1, c2): F32PackedModelMatrix) -> Self {
125        let t = Mat4::from_cols(c0.into(), c1.into(), c2.into(), Vec4::W).transpose();
126
127        Self(
128            t.x_axis.into(),
129            t.y_axis.into(),
130            t.z_axis.into(),
131            t.w_axis.into(),
132        )
133    }
134}
135
136impl From<F32PackedModelMatrix> for F32Matrix4x4 {
137    #[inline]
138    fn from(m: F32PackedModelMatrix) -> Self {
139        F32ModelMatrix::from(m).into()
140    }
141}
142
143impl From<F32PackedModelMatrix> for Mat4 {
144    #[inline]
145    fn from(F32PackedModelMatrix(c0, c1, c2): F32PackedModelMatrix) -> Self {
146        let x_axis = Vec4::from(c0).with_w(0.0);
147        let y_axis = Vec4::from(c1).with_w(0.0);
148        let z_axis = Vec4::from(c2).with_w(0.0);
149        let w_axis = Vec4::new(c0.3, c1.3, c2.3, 1.0);
150
151        Self {
152            x_axis,
153            y_axis,
154            z_axis,
155            w_axis,
156        }
157    }
158}
159
160impl From<F32Matrix4x4> for F32ModelMatrix {
161    #[inline]
162    fn from(F32Matrix4x4(r0, r1, r2, r3): F32Matrix4x4) -> Self {
163        Self(r0, r1, r2, r3)
164    }
165}
166
167impl From<F32Matrix4x4> for F32PackedModelMatrix {
168    #[inline]
169    fn from(m: F32Matrix4x4) -> Self {
170        F32ModelMatrix::from(m).into()
171    }
172}
173
174impl From<Mat4> for F32ModelMatrix {
175    #[inline]
176    fn from(mut m: Mat4) -> Self {
177        let w_axis = mem::replace(&mut m.w_axis, Vec4::W);
178        let t = m.transpose();
179
180        Self(
181            t.x_axis.into(),
182            t.y_axis.into(),
183            t.z_axis.into(),
184            w_axis.into(),
185        )
186    }
187}
188
189impl From<Mat4> for F32PackedModelMatrix {
190    #[inline]
191    fn from(m: Mat4) -> Self {
192        let x_axis = m.x_axis.with_w(m.w_axis.x).into();
193        let y_axis = m.y_axis.with_w(m.w_axis.y).into();
194        let z_axis = m.z_axis.with_w(m.w_axis.z).into();
195
196        Self(x_axis, y_axis, z_axis)
197    }
198}