1use std::ops::{Mul, MulAssign};
2
3use glam::{Affine3A, Mat3, Mat3A, Mat4, Quat, Vec3, Vec3A};
4use shiv::{bundle::Bundle, world::Component};
5
6#[derive(Clone, Copy, Debug, Default, Bundle)]
7pub struct TransformBundle {
8 pub transform: Transform,
9 pub global_transform: GlobalTransform,
10}
11
12#[repr(C)]
17#[derive(Component, Clone, Copy, Debug, PartialEq)]
18pub struct Transform {
19 pub translation: Vec3,
20 pub rotation: Quat,
21 pub scale: Vec3,
22}
23
24impl Default for Transform {
25 #[inline]
26 fn default() -> Self {
27 Self::IDENTITY
28 }
29}
30
31impl Transform {
32 pub const IDENTITY: Self = Self {
33 translation: Vec3::ZERO,
34 rotation: Quat::IDENTITY,
35 scale: Vec3::ONE,
36 };
37
38 #[inline]
39 pub const fn from_xyz(x: f32, y: f32, z: f32) -> Self {
40 Self {
41 translation: Vec3::new(x, y, z),
42 rotation: Quat::IDENTITY,
43 scale: Vec3::ONE,
44 }
45 }
46
47 #[inline]
48 pub const fn from_translation(translation: Vec3) -> Self {
49 Self {
50 translation,
51 ..Self::IDENTITY
52 }
53 }
54
55 #[inline]
56 pub const fn from_rotation(rotation: Quat) -> Self {
57 Self {
58 rotation,
59 ..Self::IDENTITY
60 }
61 }
62
63 #[inline]
64 pub const fn from_scale(scale: Vec3) -> Self {
65 Self {
66 scale,
67 ..Self::IDENTITY
68 }
69 }
70
71 #[inline]
72 pub const fn with_xyz(mut self, x: f32, y: f32, z: f32) -> Self {
73 self.translation = Vec3::new(x, y, z);
74 self
75 }
76
77 #[inline]
78 pub const fn with_translation(mut self, translation: Vec3) -> Self {
79 self.translation = translation;
80 self
81 }
82
83 #[inline]
84 pub const fn with_rotation(mut self, rotation: Quat) -> Self {
85 self.rotation = rotation;
86 self
87 }
88
89 #[inline]
90 pub const fn with_scale(mut self, scale: Vec3) -> Self {
91 self.scale = scale;
92 self
93 }
94
95 #[inline]
96 pub fn local_x(&self) -> Vec3 {
97 self.rotation * Vec3::X
98 }
99
100 #[inline]
101 pub fn local_y(&self) -> Vec3 {
102 self.rotation * Vec3::Y
103 }
104
105 #[inline]
106 pub fn local_z(&self) -> Vec3 {
107 self.rotation * Vec3::Z
108 }
109
110 #[inline]
111 pub fn left(&self) -> Vec3 {
112 -self.local_x()
113 }
114
115 #[inline]
116 pub fn right(&self) -> Vec3 {
117 self.local_x()
118 }
119
120 #[inline]
121 pub fn up(&self) -> Vec3 {
122 self.local_y()
123 }
124
125 #[inline]
126 pub fn down(&self) -> Vec3 {
127 -self.local_y()
128 }
129
130 #[inline]
131 pub fn forward(&self) -> Vec3 {
132 -self.local_z()
133 }
134
135 #[inline]
136 pub fn back(&self) -> Vec3 {
137 self.local_z()
138 }
139
140 #[inline]
141 pub fn translate(&mut self, translation: Vec3) {
142 self.translation += translation;
143 }
144
145 #[inline]
146 pub fn scale(&mut self, scale: Vec3) {
147 self.scale *= scale;
148 }
149
150 #[inline]
151 pub fn rotate(&mut self, rotation: Quat) {
152 self.rotation *= rotation;
153 }
154
155 #[inline]
156 pub fn rotate_x(&mut self, angle: f32) {
157 self.rotate(Quat::from_rotation_x(angle));
158 }
159
160 #[inline]
161 pub fn rotate_y(&mut self, angle: f32) {
162 self.rotate(Quat::from_rotation_y(angle));
163 }
164
165 #[inline]
166 pub fn rotate_z(&mut self, angle: f32) {
167 self.rotate(Quat::from_rotation_z(angle));
168 }
169
170 #[inline]
171 pub fn look_at(&mut self, forward: Vec3, up: Vec3) {
172 let right = up.cross(forward).normalize();
173 let up = forward.cross(right).normalize();
174
175 self.rotation = Quat::from_mat3(&Mat3::from_cols(right, up, forward));
176 }
177
178 #[inline]
179 pub fn looking_at(mut self, forward: Vec3, up: Vec3) -> Self {
180 self.look_at(forward, up);
181 self
182 }
183
184 #[inline]
186 pub fn compute_matrix(&self) -> Mat4 {
187 Mat4::from_scale_rotation_translation(self.scale, self.rotation, self.translation)
188 }
189
190 #[inline]
192 pub fn invserse(&self) -> Self {
193 let inv_scale = self.scale.recip();
194 let inv_rotation = self.rotation.conjugate();
195
196 let mut inv_translation = -self.translation;
197 inv_translation = inv_rotation.mul_vec3(inv_translation);
198 inv_translation *= inv_scale;
199
200 Self {
201 translation: inv_translation,
202 rotation: inv_rotation,
203 scale: inv_scale,
204 }
205 }
206}
207
208impl Mul<Vec3> for Transform {
209 type Output = Vec3;
210
211 #[inline]
212 fn mul(self, rhs: Vec3) -> Self::Output {
213 let mut position = self.scale * rhs;
214 position = self.rotation * position;
215 position + self.translation
216 }
217}
218
219impl Mul for Transform {
220 type Output = Transform;
221
222 #[inline]
223 fn mul(self, rhs: Transform) -> Self::Output {
224 let mut translation = self.scale * rhs.translation;
225 translation = self.rotation * translation;
226 translation += self.translation;
227
228 Self {
229 translation,
230 rotation: self.rotation * rhs.rotation,
231 scale: self.scale * rhs.scale,
232 }
233 }
234}
235
236impl MulAssign for Transform {
237 #[inline]
238 fn mul_assign(&mut self, rhs: Transform) {
239 *self = *self * rhs;
240 }
241}
242
243#[repr(C)]
247#[derive(Component, Clone, Copy, Debug, PartialEq)]
248pub struct GlobalTransform {
249 pub translation: Vec3,
250 pub matrix: Mat3,
251}
252
253impl Default for GlobalTransform {
254 #[inline]
255 fn default() -> Self {
256 Self::IDENTITY
257 }
258}
259
260impl GlobalTransform {
261 pub const IDENTITY: Self = Self {
262 translation: Vec3::ZERO,
263 matrix: Mat3::IDENTITY,
264 };
265
266 #[inline]
267 pub const fn from_xyz(x: f32, y: f32, z: f32) -> Self {
268 Self {
269 translation: Vec3::new(x, y, z),
270 ..Self::IDENTITY
271 }
272 }
273
274 #[inline]
275 pub const fn from_translation(translation: Vec3) -> Self {
276 Self {
277 translation,
278 ..Self::IDENTITY
279 }
280 }
281
282 #[inline]
283 pub fn from_rotation(rotation: Quat) -> Self {
284 Self {
285 matrix: Mat3::from_quat(rotation),
286 ..Self::IDENTITY
287 }
288 }
289
290 #[inline]
291 pub fn from_scale(scale: Vec3) -> Self {
292 Self {
293 matrix: Mat3::from_diagonal(scale),
294 ..Self::IDENTITY
295 }
296 }
297
298 #[inline]
299 pub const fn from_matrix(matrix: Mat3) -> Self {
300 Self {
301 matrix,
302 ..Self::IDENTITY
303 }
304 }
305
306 #[inline]
307 pub const fn to_affine(self) -> Affine3A {
308 Affine3A {
309 translation: Vec3A::from_array(self.translation.to_array()),
310 matrix3: Mat3A::from_cols_array(&self.matrix.to_cols_array()),
311 }
312 }
313
314 #[inline]
315 pub fn local_x(&self) -> Vec3 {
316 Vec3::normalize(self.matrix * Vec3::X)
317 }
318
319 #[inline]
320 pub fn local_y(&self) -> Vec3 {
321 Vec3::normalize(self.matrix * Vec3::Y)
322 }
323
324 #[inline]
325 pub fn local_z(&self) -> Vec3 {
326 Vec3::normalize(self.matrix * Vec3::Z)
327 }
328
329 #[inline]
330 pub fn left(&self) -> Vec3 {
331 -self.local_x()
332 }
333
334 #[inline]
335 pub fn right(&self) -> Vec3 {
336 self.local_x()
337 }
338
339 #[inline]
340 pub fn up(&self) -> Vec3 {
341 self.local_y()
342 }
343
344 #[inline]
345 pub fn down(&self) -> Vec3 {
346 -self.local_y()
347 }
348
349 #[inline]
350 pub fn forward(&self) -> Vec3 {
351 -self.local_z()
352 }
353
354 #[inline]
355 pub fn back(&self) -> Vec3 {
356 self.local_z()
357 }
358
359 #[inline]
360 pub fn compute_matrix(&self) -> Mat4 {
361 let translation = Mat4::from_translation(self.translation);
362 let rotation_scale = Mat4::from_mat3(self.matrix);
363 translation * rotation_scale
364 }
365}
366
367impl From<Transform> for GlobalTransform {
368 #[inline]
369 fn from(value: Transform) -> Self {
370 Self {
371 translation: value.translation,
372 matrix: Mat3::from_quat(value.rotation) * Mat3::from_diagonal(value.scale),
373 }
374 }
375}
376
377impl From<&Transform> for GlobalTransform {
378 #[inline]
379 fn from(value: &Transform) -> Self {
380 Self {
381 translation: value.translation,
382 matrix: Mat3::from_quat(value.rotation) * Mat3::from_diagonal(value.scale),
383 }
384 }
385}
386
387impl Mul<Vec3> for GlobalTransform {
388 type Output = Vec3;
389
390 #[inline]
391 fn mul(self, rhs: Vec3) -> Self::Output {
392 self.matrix.mul_vec3(rhs) + self.translation
393 }
394}
395
396impl Mul<Transform> for GlobalTransform {
397 type Output = GlobalTransform;
398
399 #[inline]
400 fn mul(self, rhs: Transform) -> Self::Output {
401 self * GlobalTransform::from(rhs)
402 }
403}
404
405impl Mul for GlobalTransform {
406 type Output = GlobalTransform;
407
408 #[inline]
409 fn mul(self, rhs: GlobalTransform) -> Self::Output {
410 Self {
411 translation: self * rhs.translation,
412 matrix: self.matrix * rhs.matrix,
413 }
414 }
415}
416
417impl MulAssign for GlobalTransform {
418 #[inline]
419 fn mul_assign(&mut self, rhs: GlobalTransform) {
420 *self = *self * rhs;
421 }
422}