1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
use shipyard::*;
use shipyard_hierarchy::*;
use std::collections::HashSet;
use std::ops::{Mul, MulAssign};
use crate::components::*;
use crate::math::*;
pub fn trs_to_local(
mut translations:ViewMut<Translation>,
mut rotations:ViewMut<Rotation>,
mut scales:ViewMut<Scale>,
mut origins:ViewMut<Origin>,
mut local_transforms:ViewMut<LocalTransform>,
mut dirty_transforms:ViewMut<DirtyTransform>,
) {
let mut unique_ids = HashSet::<EntityId>::new();
translations.inserted_or_modified().iter_ids().for_each(|id| { unique_ids.insert(id); });
rotations.inserted_or_modified().iter_ids().for_each(|id| { unique_ids.insert(id); });
scales.inserted_or_modified().iter_ids().for_each(|id| { unique_ids.insert(id); });
origins.inserted_or_modified().iter_ids().for_each(|id| { unique_ids.insert(id); });
unique_ids
.iter()
.for_each(|id| {
let (translation, rotation, scale, origin, local_transform, dirty_transform) = (&translations, &rotations, &scales, &origins, &mut local_transforms, &mut dirty_transforms).try_get(*id).unwrap();
local_transform.0.reset_from_trs_origin(&translation.0, &rotation.0, &scale.0, &origin.0);
dirty_transform.0 = true;
});
translations.clear_inserted_and_modified();
rotations.clear_inserted_and_modified();
scales.clear_inserted_and_modified();
origins.clear_inserted_and_modified();
}
pub fn local_to_world(
root: UniqueView<TransformRoot>,
parent_storage: View<Parent>,
child_storage: View<Child>,
local_transform_storage: View<LocalTransform>,
mut dirty_transform_storage: ViewMut<DirtyTransform>,
mut world_transform_storage: ViewMut<WorldTransform>,
) {
fn update(id: EntityId, mut dirty: bool, parent: EntityId, parent_storage: &View<Parent>, child_storage: &View<Child>, local_transform_storage: &View<LocalTransform>, dirty_transform_storage: &mut ViewMut<DirtyTransform>, world_transform_storage: &mut ViewMut<WorldTransform>) {
dirty |= dirty_transform_storage[id].0;
dirty_transform_storage[id].0 = false;
if dirty {
unsafe {
let world_ptr = &mut world_transform_storage[id].0 as *mut Matrix4;
let parent_world_ptr = &world_transform_storage[parent].0 as *const Matrix4;
(&mut *world_ptr).copy_from_slice((&*parent_world_ptr).as_slice());
}
world_transform_storage[id].0 *= &local_transform_storage[id].0;
}
(parent_storage, child_storage).children(id).for_each(|child| {
update(child, dirty, id, parent_storage, child_storage, local_transform_storage, dirty_transform_storage, world_transform_storage);
});
}
let root_id = root.0;
let dirty = dirty_transform_storage[root_id].0;
dirty_transform_storage[root_id].0 = false;
if dirty {
world_transform_storage[root_id].0.copy_from_slice(local_transform_storage[root_id].0.as_slice());
}
(&parent_storage, &child_storage).children(root_id).for_each(|child| {
update(child, dirty, root_id, &parent_storage, &child_storage, &local_transform_storage, &mut dirty_transform_storage, &mut world_transform_storage);
});
}