renderling/transform/
cpu.rs

1//! CPU side of transform.
2
3use std::sync::{Arc, RwLock};
4
5use craballoc::{runtime::IsRuntime, slab::SlabAllocator, value::Hybrid};
6use crabslab::Id;
7use glam::{Mat4, Quat, Vec3};
8
9use super::shader::TransformDescriptor;
10
11/// A decomposed 3d transformation.
12#[derive(Clone, Debug)]
13pub struct Transform {
14    pub(crate) descriptor: Hybrid<TransformDescriptor>,
15}
16
17impl From<&Transform> for Transform {
18    fn from(value: &Transform) -> Self {
19        value.clone()
20    }
21}
22
23impl Transform {
24    /// Stage a new transform on the GPU.
25    pub(crate) fn new(slab: &SlabAllocator<impl IsRuntime>) -> Self {
26        let descriptor = slab.new_value(TransformDescriptor::default());
27        Self { descriptor }
28    }
29
30    /// Return a pointer to the underlying descriptor data on the GPU.
31    pub fn id(&self) -> Id<TransformDescriptor> {
32        self.descriptor.id()
33    }
34
35    /// Return the a copy of the underlying descriptor.
36    pub fn descriptor(&self) -> TransformDescriptor {
37        self.descriptor.get()
38    }
39
40    /// Set the descriptor.
41    pub fn set_descriptor(&self, descriptor: TransformDescriptor) -> &Self {
42        self.descriptor.set(descriptor);
43        self
44    }
45
46    /// Set the descriptor and return the `Transform`.
47    pub fn with_descriptor(self, descriptor: TransformDescriptor) -> Self {
48        self.set_descriptor(descriptor);
49        self
50    }
51
52    /// Return the transform in combined matrix format;
53    pub fn as_mat4(&self) -> Mat4 {
54        self.descriptor().into()
55    }
56
57    /// Get the translation of the transform.
58    pub fn translation(&self) -> Vec3 {
59        self.descriptor.get().translation
60    }
61
62    /// Modify the translation of the transform.
63    ///
64    /// # Arguments
65    ///
66    /// - `f`: A closure that takes a mutable reference to the translation vector and returns a value of type `T`.
67    pub fn modify_translation<T: 'static>(&self, f: impl FnOnce(&mut Vec3) -> T) -> T {
68        self.descriptor.modify(|t| f(&mut t.translation))
69    }
70
71    /// Set the translation of the transform.
72    ///
73    /// # Arguments
74    ///
75    /// - `translation`: A 3d translation vector `Vec3`.
76    pub fn set_translation(&self, translation: impl Into<Vec3>) -> &Self {
77        self.descriptor
78            .modify(|t| t.translation = translation.into());
79        self
80    }
81
82    /// Set the translation of the transform.
83    ///
84    /// # Arguments
85    ///
86    /// - `translation`: A 3d translation vector `Vec3`.
87    pub fn with_translation(self, translation: impl Into<Vec3>) -> Self {
88        self.set_translation(translation);
89        self
90    }
91
92    /// Get the rotation of the transform.
93    pub fn rotation(&self) -> Quat {
94        self.descriptor.get().rotation
95    }
96
97    /// Modify the rotation of the transform.
98    ///
99    /// # Arguments
100    ///
101    /// - `f`: A closure that takes a mutable reference to the rotation quaternion and returns a value of type `T`.
102    pub fn modify_rotation<T: 'static>(&self, f: impl FnOnce(&mut Quat) -> T) -> T {
103        self.descriptor.modify(|t| f(&mut t.rotation))
104    }
105
106    /// Set the rotation of the transform.
107    ///
108    /// # Arguments
109    ///
110    /// - `rotation`: A quaternion representing the rotation.
111    pub fn set_rotation(&self, rotation: impl Into<Quat>) -> &Self {
112        self.descriptor.modify(|t| t.rotation = rotation.into());
113        self
114    }
115
116    /// Set the rotation of the transform.
117    ///
118    /// # Arguments
119    ///
120    /// - `rotation`: A quaternion representing the rotation.
121    pub fn with_rotation(self, rotation: impl Into<Quat>) -> Self {
122        self.set_rotation(rotation);
123        self
124    }
125
126    /// Get the scale of the transform.
127    pub fn scale(&self) -> Vec3 {
128        self.descriptor.get().scale
129    }
130
131    /// Modify the scale of the transform.
132    ///
133    /// # Arguments
134    ///
135    /// - `f`: A closure that takes a mutable reference to the scale vector and returns a value of type `T`.
136    pub fn modify_scale<T: 'static>(&self, f: impl FnOnce(&mut Vec3) -> T) -> T {
137        self.descriptor.modify(|t| f(&mut t.scale))
138    }
139
140    /// Set the scale of the transform.
141    ///
142    /// # Arguments
143    ///
144    /// - `scale`: A 3d scale vector `Vec3`.
145    pub fn set_scale(&self, scale: impl Into<Vec3>) -> &Self {
146        self.descriptor.modify(|t| t.scale = scale.into());
147        self
148    }
149
150    /// Set the scale of the transform.
151    ///
152    /// # Arguments
153    ///
154    /// - `scale`: A 3d scale vector `Vec3`.
155    pub fn with_scale(self, scale: impl Into<Vec3>) -> Self {
156        self.set_scale(scale);
157        self
158    }
159}
160
161/// Manages scene heirarchy on the [`Stage`](crate::stage::Stage).
162///
163/// Can be created with
164/// [`Stage::new_nested_transform`](crate::stage::Stage::new_nested_transform).
165///
166/// Clones all reference the same nested transform.
167#[derive(Clone)]
168pub struct NestedTransform {
169    pub(crate) global_transform: Transform,
170    local_transform: Arc<RwLock<TransformDescriptor>>,
171    children: Arc<RwLock<Vec<NestedTransform>>>,
172    parent: Arc<RwLock<Option<NestedTransform>>>,
173}
174
175impl core::fmt::Debug for NestedTransform {
176    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
177        let children = self
178            .children
179            .read()
180            .unwrap()
181            .iter()
182            .map(|nt| nt.global_transform.id())
183            .collect::<Vec<_>>();
184        let parent = self
185            .parent
186            .read()
187            .unwrap()
188            .as_ref()
189            .map(|nt| nt.global_transform.id());
190        f.debug_struct("NestedTransform")
191            .field("local_transform", &self.local_transform)
192            .field("children", &children)
193            .field("parent", &parent)
194            .finish()
195    }
196}
197
198impl From<&NestedTransform> for Transform {
199    fn from(value: &NestedTransform) -> Self {
200        value.global_transform.clone()
201    }
202}
203
204impl From<NestedTransform> for Transform {
205    fn from(value: NestedTransform) -> Self {
206        value.global_transform
207    }
208}
209
210impl NestedTransform {
211    /// Stage a new hierarchical transform on the GPU.
212    pub(crate) fn new(slab: &SlabAllocator<impl IsRuntime>) -> Self {
213        let nested = NestedTransform {
214            local_transform: Arc::new(RwLock::new(TransformDescriptor::default())),
215            global_transform: Transform::new(slab),
216            children: Default::default(),
217            parent: Default::default(),
218        };
219        nested.mark_dirty();
220        nested
221    }
222
223    /// Get the _local_ translation of the transform.
224    pub fn local_translation(&self) -> Vec3 {
225        self.local_transform.read().unwrap().translation
226    }
227
228    /// Modify the _local_ translation of the transform.
229    ///
230    /// # Arguments
231    ///
232    /// - `f`: A closure that takes a mutable reference to the translation vector and returns a value of type `T`.
233    pub fn modify_local_translation<T>(&self, f: impl FnOnce(&mut Vec3) -> T) -> T {
234        let t = {
235            let mut local_transform = self.local_transform.write().unwrap();
236            f(&mut local_transform.translation)
237        };
238        self.mark_dirty();
239        t
240    }
241
242    /// Set the _local_ translation of the transform.
243    ///
244    /// # Arguments
245    ///
246    /// - `translation`: A 3d translation vector `Vec3`.
247    pub fn set_local_translation(&self, translation: impl Into<Vec3>) -> &Self {
248        self.local_transform.write().unwrap().translation = translation.into();
249        self.mark_dirty();
250        self
251    }
252
253    /// Set the _local_ translation of the transform.
254    ///
255    /// # Arguments
256    ///
257    /// - `translation`: A 3d translation vector `Vec3`.
258    pub fn with_local_translation(self, translation: impl Into<Vec3>) -> Self {
259        self.set_local_translation(translation);
260        self
261    }
262
263    /// Get the _local_ rotation of the transform.
264    pub fn local_rotation(&self) -> Quat {
265        self.local_transform.read().unwrap().rotation
266    }
267
268    /// Modify the _local_ rotation of the transform.
269    ///
270    /// # Arguments
271    ///
272    /// - `f`: A closure that takes a mutable reference to the rotation quaternion and returns a value of type `T`.
273    pub fn modify_local_rotation<T>(&self, f: impl FnOnce(&mut Quat) -> T) -> T {
274        let t = {
275            let mut local_transform = self.local_transform.write().unwrap();
276            f(&mut local_transform.rotation)
277        };
278        self.mark_dirty();
279        t
280    }
281
282    /// Set the _local_ rotation of the transform.
283    ///
284    /// # Arguments
285    ///
286    /// - `rotation`: A quaternion representing the rotation.
287    pub fn set_local_rotation(&self, rotation: impl Into<Quat>) -> &Self {
288        self.local_transform.write().unwrap().rotation = rotation.into();
289        self.mark_dirty();
290        self
291    }
292
293    /// Set the _local_ rotation of the transform.
294    ///
295    /// # Arguments
296    ///
297    /// - `rotation`: A quaternion representing the rotation.
298    pub fn with_local_rotation(self, rotation: impl Into<Quat>) -> Self {
299        self.set_local_rotation(rotation);
300        self
301    }
302
303    /// Get the _local_ scale of the transform.
304    pub fn local_scale(&self) -> Vec3 {
305        self.local_transform.read().unwrap().scale
306    }
307
308    /// Modify the _local_ scale of the transform.
309    ///
310    /// # Arguments
311    ///
312    /// - `f`: A closure that takes a mutable reference to the scale vector and returns a value of type `T`.
313    pub fn modify_local_scale<T>(&self, f: impl FnOnce(&mut Vec3) -> T) -> T {
314        let t = {
315            let mut local_transform = self.local_transform.write().unwrap();
316            f(&mut local_transform.scale)
317        };
318        self.mark_dirty();
319        t
320    }
321
322    /// Set the _local_ scale of the transform.
323    ///
324    /// # Arguments
325    ///
326    /// - `scale`: A 3d scale vector `Vec3`.
327    pub fn set_local_scale(&self, scale: impl Into<Vec3>) -> &Self {
328        self.local_transform.write().unwrap().scale = scale.into();
329        self.mark_dirty();
330        self
331    }
332
333    /// Set the _local_ scale of the transform.
334    ///
335    /// # Arguments
336    ///
337    /// - `scale`: A 3d scale vector `Vec3`.
338    pub fn with_local_scale(self, scale: impl Into<Vec3>) -> Self {
339        self.set_local_scale(scale);
340        self
341    }
342
343    /// Return a pointer to the underlying descriptor data on the GPU.
344    ///
345    /// The descriptor is the descriptor that describes the _global_ transform.
346    pub fn global_id(&self) -> Id<TransformDescriptor> {
347        self.global_transform.id()
348    }
349
350    /// Return the descriptor of the _global_ transform.
351    ///
352    /// This traverses the heirarchy and computes the result.
353    pub fn global_descriptor(&self) -> TransformDescriptor {
354        let maybe_parent_guard = self.parent.read().unwrap();
355        let transform = self.local_descriptor();
356        let parent_transform = maybe_parent_guard
357            .as_ref()
358            .map(|parent| parent.global_descriptor())
359            .unwrap_or_default();
360        TransformDescriptor::from(Mat4::from(parent_transform) * Mat4::from(transform))
361    }
362
363    /// Return the descriptor of the _local_ tarnsform.
364    pub fn local_descriptor(&self) -> TransformDescriptor {
365        *self.local_transform.read().unwrap()
366    }
367
368    fn mark_dirty(&self) {
369        self.global_transform
370            .descriptor
371            .set(self.global_descriptor());
372        for child in self.children.read().unwrap().iter() {
373            child.mark_dirty();
374        }
375    }
376
377    /// Get a vector containing all the hierarchy's transforms.
378    ///
379    /// Starts with the root transform and ends with the local transform.
380    pub fn hierarchy(&self) -> Vec<TransformDescriptor> {
381        let mut transforms = vec![];
382        if let Some(parent) = self.parent() {
383            transforms.extend(parent.hierarchy());
384        }
385        transforms.push(self.local_descriptor());
386        transforms
387    }
388
389    pub fn add_child(&self, node: &NestedTransform) {
390        *node.parent.write().unwrap() = Some(self.clone());
391        node.mark_dirty();
392        self.children.write().unwrap().push(node.clone());
393    }
394
395    pub fn remove_child(&self, node: &NestedTransform) {
396        self.children.write().unwrap().retain_mut(|child| {
397            if child.global_transform.id() == node.global_transform.id() {
398                node.mark_dirty();
399                let _ = node.parent.write().unwrap().take();
400                false
401            } else {
402                true
403            }
404        });
405    }
406
407    /// Return a clone of the parent `NestedTransform`, if any.
408    pub fn parent(&self) -> Option<NestedTransform> {
409        self.parent.read().unwrap().clone()
410    }
411}