solstice_2d/d3/
transform.rs

1use crate::Rad;
2use nalgebra::{Isometry3, Translation3, UnitQuaternion, Vector3};
3
4#[derive(Debug, Copy, Clone, PartialEq)]
5pub struct Transform3D {
6    isometry: Isometry3<f32>,
7    scale: Vector3<f32>,
8}
9
10impl Default for Transform3D {
11    fn default() -> Self {
12        Self {
13            isometry: Isometry3::translation(0., 0., 0.),
14            scale: Vector3::new(1., 1., 1.),
15        }
16    }
17}
18
19impl Transform3D {
20    pub fn translation(x: f32, y: f32, z: f32) -> Self {
21        Self {
22            isometry: Isometry3::translation(x, y, z),
23            scale: Vector3::new(1., 1., 1.),
24        }
25    }
26
27    pub fn rotation<R, P, Y>(roll: R, pitch: P, yaw: Y) -> Self
28    where
29        R: Into<Rad>,
30        P: Into<Rad>,
31        Y: Into<Rad>,
32    {
33        Self {
34            isometry: Isometry3::from_parts(
35                Translation3::new(0., 0., 0.),
36                UnitQuaternion::from_euler_angles(roll.into().0, pitch.into().0, yaw.into().0),
37            ),
38            ..Default::default()
39        }
40    }
41
42    pub fn scale(x: f32, y: f32, z: f32) -> Self {
43        Self {
44            scale: Vector3::new(x, y, z),
45            ..Default::default()
46        }
47    }
48
49    pub fn lerp_slerp(&self, other: &Self, t: f32) -> Self {
50        let isometry = self.isometry.lerp_slerp(&other.isometry, t);
51        let scale = self.scale.lerp(&other.scale, t);
52        Self { isometry, scale }
53    }
54
55    pub fn transform_point(&self, x: f32, y: f32, z: f32) -> [f32; 3] {
56        let p = nalgebra::Point3::new(x * self.scale.x, y * self.scale.y, z * self.scale.z);
57        let p = self.isometry.transform_point(&p);
58        [p.x, p.y, p.z]
59    }
60
61    pub fn inverse_transform_point(&self, x: f32, y: f32, z: f32) -> [f32; 3] {
62        let p = nalgebra::Point3::new(x * self.scale.x, y * self.scale.y, z * self.scale.z);
63        let p = self.isometry.inverse_transform_point(&p);
64        [p.x, p.y, p.z]
65    }
66
67    pub fn look_at(x: f32, y: f32, z: f32) -> Self {
68        let eye = nalgebra::Point3::new(0., 0., 0.);
69        let target = nalgebra::Point3::new(x, y, z);
70        let up = nalgebra::Vector3::y();
71        Self {
72            isometry: Isometry3::look_at_lh(&eye, &target, &up),
73            ..Default::default()
74        }
75    }
76}
77
78impl std::ops::Mul for Transform3D {
79    type Output = Transform3D;
80
81    fn mul(self, rhs: Self) -> Self::Output {
82        let t = self
83            .isometry
84            .rotation
85            .transform_vector(&rhs.isometry.translation.vector.component_mul(&self.scale))
86            + self.isometry.translation.vector;
87        Self {
88            isometry: Isometry3::from_parts(
89                t.into(),
90                self.isometry.rotation * rhs.isometry.rotation,
91            ),
92            scale: self.scale.component_mul(&rhs.scale),
93        }
94    }
95}
96
97impl std::ops::MulAssign for Transform3D {
98    fn mul_assign(&mut self, rhs: Self) {
99        *self = *self * rhs;
100    }
101}
102
103impl From<Transform3D> for mint::ColumnMatrix4<f32> {
104    fn from(inner: Transform3D) -> Self {
105        inner
106            .isometry
107            .to_homogeneous()
108            .prepend_nonuniform_scaling(&inner.scale)
109            .into()
110    }
111}
112
113impl From<&Transform3D> for mint::ColumnMatrix4<f32> {
114    fn from(inner: &Transform3D) -> Self {
115        inner
116            .isometry
117            .to_homogeneous()
118            .prepend_nonuniform_scaling(&inner.scale)
119            .into()
120    }
121}