Skip to main content

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