threecrate_core/
transform.rs1use nalgebra::{Point3, Vector3, Matrix4, Isometry3, Transform3, UnitQuaternion};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
8pub struct Transform3D {
9 pub matrix: Matrix4<f32>,
10}
11
12impl Transform3D {
13 pub fn identity() -> Self {
15 Self {
16 matrix: Matrix4::identity(),
17 }
18 }
19
20 pub fn translation(translation: Vector3<f32>) -> Self {
22 Self {
23 matrix: Matrix4::new_translation(&translation),
24 }
25 }
26
27 pub fn rotation(rotation: UnitQuaternion<f32>) -> Self {
29 Self {
30 matrix: rotation.to_homogeneous(),
31 }
32 }
33
34 pub fn scaling(scale: Vector3<f32>) -> Self {
36 Self {
37 matrix: Matrix4::new_nonuniform_scaling(&scale),
38 }
39 }
40
41 pub fn uniform_scaling(scale: f32) -> Self {
43 Self {
44 matrix: Matrix4::new_scaling(scale),
45 }
46 }
47
48 pub fn from_translation_rotation(
50 translation: Vector3<f32>,
51 rotation: UnitQuaternion<f32>,
52 ) -> Self {
53 let isometry = Isometry3::from_parts(translation.into(), rotation);
54 Self {
55 matrix: isometry.to_homogeneous(),
56 }
57 }
58
59 pub fn transform_point(&self, point: &Point3<f32>) -> Point3<f32> {
61 let homogeneous = self.matrix * point.to_homogeneous();
62 Point3::from_homogeneous(homogeneous).unwrap_or(*point)
63 }
64
65 pub fn transform_vector(&self, vector: &Vector3<f32>) -> Vector3<f32> {
67 let homogeneous = self.matrix.fixed_view::<3, 3>(0, 0) * vector;
68 homogeneous
69 }
70
71 pub fn compose(self, other: Self) -> Self {
73 Self {
74 matrix: self.matrix * other.matrix,
75 }
76 }
77
78 pub fn inverse(self) -> Option<Self> {
80 self.matrix.try_inverse().map(|inv_matrix| Self {
81 matrix: inv_matrix,
82 })
83 }
84
85 pub fn is_identity(&self, epsilon: f32) -> bool {
87 let identity = Matrix4::identity();
88 (self.matrix - identity).norm() < epsilon
89 }
90}
91
92impl Default for Transform3D {
93 fn default() -> Self {
94 Self::identity()
95 }
96}
97
98impl std::ops::Mul for Transform3D {
99 type Output = Self;
100
101 fn mul(self, rhs: Self) -> Self::Output {
102 self.compose(rhs)
103 }
104}
105
106impl From<Matrix4<f32>> for Transform3D {
107 fn from(matrix: Matrix4<f32>) -> Self {
108 Self { matrix }
109 }
110}
111
112impl From<Isometry3<f32>> for Transform3D {
113 fn from(isometry: Isometry3<f32>) -> Self {
114 Self {
115 matrix: isometry.to_homogeneous(),
116 }
117 }
118}
119
120impl From<Transform3<f32>> for Transform3D {
121 fn from(transform: Transform3<f32>) -> Self {
122 Self {
123 matrix: transform.into_inner(),
124 }
125 }
126}