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 101 102 103 104
use crate::Rad; use nalgebra::{Isometry3, Translation3, UnitQuaternion, Vector3}; #[derive(Debug, Copy, Clone, PartialEq)] pub struct Transform3D { isometry: Isometry3<f32>, scale: Vector3<f32>, } impl Default for Transform3D { fn default() -> Self { Self { isometry: Isometry3::translation(0., 0., 0.), scale: Vector3::new(1., 1., 1.), } } } impl Transform3D { pub fn translation(x: f32, y: f32, z: f32) -> Self { Self { isometry: Isometry3::translation(x, y, z), scale: Vector3::new(1., 1., 1.), } } pub fn rotation<R: Into<Rad>>(roll: R, pitch: R, yaw: R) -> Self { Self { isometry: Isometry3::from_parts( Translation3::new(0., 0., 0.), UnitQuaternion::from_euler_angles(roll.into().0, pitch.into().0, yaw.into().0), ), ..Default::default() } } pub fn scale(x: f32, y: f32, z: f32) -> Self { Self { scale: Vector3::new(x, y, z), ..Default::default() } } pub fn transform_point(&self, x: f32, y: f32, z: f32) -> [f32; 3] { let p = nalgebra::Point3::new(x * self.scale.x, y * self.scale.y, z * self.scale.z); let p = self.isometry.transform_point(&p); [p.x, p.y, p.z] } pub fn look_at(x: f32, y: f32, z: f32) -> Self { let eye = nalgebra::Point3::new(0., 0., 0.); let target = nalgebra::Point3::new(x, y, z); let up = nalgebra::Vector3::y(); Self { isometry: Isometry3::look_at_lh(&eye, &target, &up), ..Default::default() } } } impl std::ops::Mul for Transform3D { type Output = Transform3D; fn mul(self, rhs: Self) -> Self::Output { let t = self .isometry .rotation .transform_vector(&rhs.isometry.translation.vector.component_mul(&self.scale)) + self.isometry.translation.vector; Self { isometry: Isometry3::from_parts( t.into(), self.isometry.rotation * rhs.isometry.rotation, ), scale: self.scale.component_mul(&rhs.scale), } } } impl std::ops::MulAssign for Transform3D { fn mul_assign(&mut self, rhs: Self) { *self = *self * rhs; } } impl From<Transform3D> for mint::ColumnMatrix4<f32> { fn from(inner: Transform3D) -> Self { inner .isometry .to_homogeneous() .prepend_nonuniform_scaling(&inner.scale) .into() } } impl From<&Transform3D> for mint::ColumnMatrix4<f32> { fn from(inner: &Transform3D) -> Self { inner .isometry .to_homogeneous() .prepend_nonuniform_scaling(&inner.scale) .into() } }