unity_mirror_rs/unity_engine/
transform.rs

1#![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    /// 将弧度转换为角度,并限制到 [0, 360) 范围
62    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    /// 四元数转欧拉角 (ZYX 顺序)
71    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        // 计算 Roll (X-axis rotation)
75        let t0 = 2.0 * (w * x + y * z);
76        let t1 = 1.0 - 2.0 * (x * x + ysqr);
77        let roll = t0.atan2(t1); // 绕 X 轴的旋转
78        // 计算 Pitch (Y-axis rotation)
79        let t2 = 2.0 * (w * y - z * x);
80        let t2 = t2.clamp(-1.0, 1.0); // 限制在 [-1, 1] 范围
81        let pitch = t2.asin(); // 绕 Y 轴的旋转
82        // 计算 Yaw (Z-axis rotation)
83        let t3 = 2.0 * (w * z + x * y);
84        let t4 = 1.0 - 2.0 * (ysqr + z * z);
85        let yaw = t3.atan2(t4); // 绕 Z 轴的旋转
86        // 转换为角度并限制到 [0, 360)
87        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    // 辅助函数:将角度转换为弧度
95    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        // 将欧拉角从角度转换为弧度
100        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        // 计算半角
104        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        // 按公式计算四元数分量
111        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    /// 计算全局变换矩阵
121    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    /// 从变换矩阵中提取位置、旋转和缩放
129    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    /// 计算相对变换
152    pub fn relative_transform(parent: &Transform, child: &Transform) -> Transform {
153        // 父级和子级的全局变换矩阵
154        let parent_global_matrix = parent.to_global_matrix();
155        let child_global_matrix = child.to_global_matrix();
156
157        // 计算相对矩阵
158        let relative_matrix = parent_global_matrix
159            .try_inverse()
160            .expect("Parent matrix is not invertible")
161            * child_global_matrix;
162
163        // 从相对矩阵提取新的 Transform
164        Transform::from_matrix(&relative_matrix)
165    }
166}