unity_mirror_rs/unity_engine/
transform.rs1#![allow(unused)]
2use crate::commons::RevelWeak;
3use crate::metadata_settings::metadata_transform::MetadataTransform;
4use crate::unity_engine::GameObject;
5use nalgebra::{Matrix3, Matrix4, Quaternion, Translation3, UnitQuaternion, Vector3};
6
7#[derive(Default, Clone, Debug)]
8pub struct Transform {
9 pub instance_id: i32,
10
11 pub parent: RevelWeak<Transform>,
12 pub children: Vec<RevelWeak<Transform>>,
13
14 pub game_object: RevelWeak<GameObject>,
15 pub position: Vector3<f32>,
16 pub local_position: Vector3<f32>,
17 pub rotation: Quaternion<f32>,
18 pub local_rotation: Quaternion<f32>,
19 pub local_scale: Vector3<f32>,
20}
21
22impl Transform {
23 pub fn new_with_metadata(metadata: &MetadataTransform) -> Self {
24 Transform {
25 instance_id: metadata.instance_id,
26 parent: RevelWeak::default(),
27 children: vec![],
28 game_object: RevelWeak::default(),
29 position: Vector3::new(
30 metadata.position[0],
31 metadata.position[1],
32 metadata.position[2],
33 ),
34 rotation: Quaternion::new(
35 metadata.rotation[3],
36 metadata.rotation[0],
37 metadata.rotation[1],
38 metadata.rotation[2],
39 ),
40 local_position: Vector3::new(
41 metadata.local_position[0],
42 metadata.local_position[1],
43 metadata.local_position[2],
44 ),
45 local_rotation: Quaternion::new(
46 metadata.local_rotation[3],
47 metadata.local_rotation[0],
48 metadata.local_rotation[1],
49 metadata.local_rotation[2],
50 ),
51 local_scale: Vector3::new(
52 metadata.local_scale[0],
53 metadata.local_scale[1],
54 metadata.local_scale[2],
55 ),
56 }
57 }
58}
59
60impl Transform {
61 fn radians_to_degrees_positive(radians: f32) -> f32 {
63 let degrees = radians.to_degrees();
64 if degrees < 0.0 {
65 degrees + 360.0
66 } else {
67 degrees
68 }
69 }
70 pub(crate) fn quaternion_to_euler_angles(quat: Quaternion<f32>) -> Vector3<f32> {
72 let (x, y, z, w) = (quat.w, quat.i, quat.j, quat.k);
73 let ysqr = y * y;
74 let t0 = 2.0 * (w * x + y * z);
76 let t1 = 1.0 - 2.0 * (x * x + ysqr);
77 let roll = t0.atan2(t1); let t2 = 2.0 * (w * y - z * x);
80 let t2 = t2.clamp(-1.0, 1.0); let pitch = t2.asin(); let t3 = 2.0 * (w * z + x * y);
84 let t4 = 1.0 - 2.0 * (ysqr + z * z);
85 let yaw = t3.atan2(t4); Vector3::new(
88 Self::radians_to_degrees_positive(roll),
89 Self::radians_to_degrees_positive(pitch),
90 Self::radians_to_degrees_positive(yaw),
91 )
92 }
93
94 fn degrees_to_radians(degrees: f32) -> f32 {
96 degrees * std::f32::consts::PI / 180.0
97 }
98 pub(crate) fn euler_angles_to_quaternion(euler: Vector3<f32>) -> Quaternion<f32> {
99 let roll = Self::degrees_to_radians(euler.x);
101 let pitch = Self::degrees_to_radians(euler.y);
102 let yaw = Self::degrees_to_radians(euler.z);
103 let cy = (yaw * 0.5).cos();
105 let sy = (yaw * 0.5).sin();
106 let cp = (pitch * 0.5).cos();
107 let sp = (pitch * 0.5).sin();
108 let cr = (roll * 0.5).cos();
109 let sr = (roll * 0.5).sin();
110 let w = cr * cp * cy + sr * sp * sy;
112 let x = sr * cp * cy - cr * sp * sy;
113 let y = cr * sp * cy + sr * cp * sy;
114 let z = cr * cp * sy - sr * sp * cy;
115 Quaternion::new(w, x, y, z)
116 }
117}
118
119impl Transform {
120 fn to_global_matrix(&self) -> Matrix4<f32> {
122 let translation = Translation3::from(self.position).to_homogeneous();
123 let rotation = UnitQuaternion::from_quaternion(self.rotation).to_homogeneous();
124 let scale = Matrix4::new_nonuniform_scaling(&self.local_scale);
125 translation * rotation * scale
126 }
127
128 fn from_matrix(matrix: &Matrix4<f32>) -> Self {
130 let translation = Vector3::from(matrix.fixed_view::<3, 1>(0, 3));
131 let rotation =
132 *UnitQuaternion::from_matrix(&Matrix3::from(matrix.fixed_view::<3, 3>(0, 0)));
133 let scale = Vector3::new(
134 matrix.fixed_view::<3, 1>(0, 0).norm(),
135 matrix.fixed_view::<3, 1>(0, 1).norm(),
136 matrix.fixed_view::<3, 1>(0, 2).norm(),
137 );
138 Transform {
139 instance_id: 0,
140 parent: Default::default(),
141 children: vec![],
142 game_object: Default::default(),
143 position: translation,
144 rotation,
145 local_position: Vector3::zeros(),
146 local_rotation: Quaternion::identity(),
147 local_scale: scale,
148 }
149 }
150
151 pub fn relative_transform(parent: &Transform, child: &Transform) -> Transform {
153 let parent_global_matrix = parent.to_global_matrix();
155 let child_global_matrix = child.to_global_matrix();
156
157 let relative_matrix = parent_global_matrix
159 .try_inverse()
160 .expect("Parent matrix is not invertible")
161 * child_global_matrix;
162
163 Transform::from_matrix(&relative_matrix)
165 }
166}