solstice_2d/d3/
transform.rs1use 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}