1use glam::{Affine3A, EulerRot, Mat3, Mat4, Quat, Vec3};
2
3#[derive(Debug, Copy, Clone)]
33pub struct Transform {
34 pub position: Vec3,
36 pub rotation: Quat,
38 pub scale: Vec3,
40
41 #[doc(hidden)]
43 pub local_matrix: Affine3A,
44 #[doc(hidden)]
46 pub world_matrix: Affine3A,
47 #[doc(hidden)]
49 pub previous_world_matrix: Affine3A,
50
51 last_position: Vec3,
53 last_rotation: Quat,
54 last_scale: Vec3,
55 force_update: bool,
56}
57
58impl Transform {
59 #[must_use]
61 pub fn new() -> Self {
62 Self {
63 position: Vec3::ZERO,
64 rotation: Quat::IDENTITY,
65 scale: Vec3::ONE,
66
67 local_matrix: Affine3A::IDENTITY,
68 world_matrix: Affine3A::IDENTITY,
69
70 previous_world_matrix: Affine3A::IDENTITY,
71
72 last_position: Vec3::ZERO,
73 last_rotation: Quat::IDENTITY,
74 last_scale: Vec3::ONE,
75 force_update: true,
76 }
77 }
78
79 pub fn update_local_matrix(&mut self) -> bool {
84 let changed = self.position != self.last_position
85 || self.rotation != self.last_rotation
86 || self.scale != self.last_scale
87 || self.force_update;
88
89 if changed {
90 self.local_matrix =
91 Affine3A::from_scale_rotation_translation(self.scale, self.rotation, self.position);
92
93 self.last_position = self.position;
94 self.last_rotation = self.rotation;
95 self.last_scale = self.scale;
96 self.force_update = false;
97 }
98
99 changed
100 }
101
102 pub fn set_rotation_euler(&mut self, x: f32, y: f32, z: f32) {
110 self.rotation = Quat::from_euler(EulerRot::XYZ, x, y, z);
111 }
112
113 #[must_use]
115 pub fn rotation_euler(&self) -> Vec3 {
116 let (x, y, z) = self.rotation.to_euler(EulerRot::XYZ);
117 Vec3::new(x, y, z)
118 }
119
120 pub fn set_rotation_euler_with_order(&mut self, x: f32, y: f32, z: f32, order: EulerRot) {
122 self.rotation = Quat::from_euler(order, x, y, z);
123 }
124
125 #[inline]
127 #[must_use]
128 pub fn local_matrix(&self) -> &Affine3A {
129 &self.local_matrix
130 }
131
132 #[inline]
134 #[must_use]
135 pub fn world_matrix(&self) -> &Affine3A {
136 &self.world_matrix
137 }
138
139 #[inline]
141 #[must_use]
142 pub fn world_matrix_as_mat4(&self) -> Mat4 {
143 Mat4::from(self.world_matrix)
144 }
145
146 pub fn set_world_matrix(&mut self, mat: Affine3A) {
148 self.world_matrix = mat;
149 }
150
151 pub fn set_position(&mut self, pos: Vec3) {
153 self.position = pos;
154 self.mark_dirty();
155 }
156
157 pub fn apply_local_matrix(&mut self, mat: Affine3A) {
160 self.local_matrix = mat;
161 let (scale, rotation, translation) = mat.to_scale_rotation_translation();
162 self.scale = scale;
163 self.rotation = rotation;
164 self.position = translation;
165 self.last_scale = scale;
166 self.last_rotation = rotation;
167 self.last_position = translation;
168 self.force_update = false;
169 }
170
171 pub fn apply_local_matrix_from_mat4(&mut self, mat: Mat4) {
173 let affine = Affine3A::from_mat4(mat);
174 self.apply_local_matrix(affine);
175 }
176
177 pub fn look_at(&mut self, target: Vec3, up: Vec3) {
179 let forward = (target - self.position).normalize();
180 if forward.cross(up).length_squared() < 1e-4 {
181 return;
182 }
183 let right = forward.cross(up).normalize();
184 let new_up = right.cross(forward).normalize();
185 let rot_mat = Mat3::from_cols(right, new_up, -forward);
186 self.rotation = Quat::from_mat3(&rot_mat);
187 }
188
189 #[inline]
191 pub fn mark_dirty(&mut self) {
192 self.force_update = true;
193 }
194
195 #[must_use]
199 pub fn rotation_basis(&self) -> (Vec3, Vec3, Vec3) {
200 let right = self.rotation * Vec3::X;
201 let up = self.rotation * Vec3::Y;
202 let forward = self.rotation * Vec3::Z;
203 (right, up, forward)
204 }
205}
206
207impl Default for Transform {
208 fn default() -> Self {
209 Self::new()
210 }
211}