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
use math::{Vec3, Mat4}; struct Data { parent: Option<Transform>, dirty: bool, position: Vec3, scale: Vec3, global: Mat4, } #[derive(Copy, Clone)] pub struct Transform(usize); pub struct TransformSystem { transforms: Vec<Data>, } impl TransformSystem { pub fn new() -> Self { Self { transforms: Vec::new() } } pub fn add<V1, V2>(&mut self, position: V1, scale: V2) -> Transform where Vec3: From<V1> + From<V2> { self.add_inner(None, Vec3::from(position), Vec3::from(scale)) } pub fn add_child<V1, V2>(&mut self, parent: Transform, position: V1, scale: V2) -> Transform where Vec3: From<V1> + From<V2> { self.add_inner(Some(parent), Vec3::from(position), Vec3::from(scale)) } pub fn position(&self, transform: Transform) -> Vec3 { self.transforms[transform.0].position } pub fn global(&self, transform: Transform) -> Mat4 { self.transforms[transform.0].global } pub fn set_position<V>(&mut self, transform: Transform, position: V) where Vec3: From<V> { self.transforms[transform.0].position = Vec3::from(position); } pub fn update(&mut self) { for transform in self.transforms.iter_mut() { transform.dirty = true; } for index in 0 .. self.transforms.len() { self.update_transform(index); } } fn update_transform(&mut self, index: usize) { if self.transforms[index].dirty { self.transforms[index].dirty = false; let local = Mat4::model(self.transforms[index].position, self.transforms[index].scale); if let Some(parent) = self.transforms[index].parent { self.update_transform(parent.0); self.transforms[index].global = self.transforms[parent.0].global * local; } else { self.transforms[index].global = local; } } } fn add_inner(&mut self, parent: Option<Transform>, position: Vec3, scale: Vec3) -> Transform { self.transforms.push(Data { parent, position, scale, dirty: false, global: Mat4::identity(), }); Transform(self.transforms.len() - 1) } }