Skip to main content

russimp_ng/
animation.rs

1use crate::{sys::*, *};
2use derivative::Derivative;
3
4#[derive(Derivative)]
5#[derivative(Debug)]
6pub struct MeshMorphKey {
7    pub time: f64,
8    pub values: Vec<u32>,
9    pub weights: Vec<f64>,
10}
11
12impl From<&aiMeshMorphKey> for MeshMorphKey {
13    fn from(mesh_morph_key: &aiMeshMorphKey) -> Self {
14        Self {
15            time: mesh_morph_key.mTime,
16            values: utils::get_raw_vec(mesh_morph_key.mValues, mesh_morph_key.mNumValuesAndWeights),
17            weights: utils::get_raw_vec(
18                mesh_morph_key.mWeights,
19                mesh_morph_key.mNumValuesAndWeights,
20            ),
21        }
22    }
23}
24
25#[derive(Derivative)]
26#[derivative(Debug)]
27pub struct MeshMorphAnim {
28    pub keys: Vec<MeshMorphKey>,
29    pub name: String,
30}
31
32impl From<&aiMeshMorphAnim> for MeshMorphAnim {
33    fn from(mesh: &aiMeshMorphAnim) -> Self {
34        Self {
35            keys: utils::get_vec(mesh.mKeys, mesh.mNumKeys),
36            name: mesh.mName.into(),
37        }
38    }
39}
40
41#[derive(Derivative)]
42#[derivative(Debug)]
43pub struct VectorKey {
44    pub time: f64,
45    pub value: Vector3D,
46}
47
48impl From<&aiVectorKey> for VectorKey {
49    fn from(vec: &aiVectorKey) -> Self {
50        Self {
51            time: vec.mTime,
52            value: (&vec.mValue).into(),
53        }
54    }
55}
56
57#[repr(C)]
58#[derive(Copy, Clone, Derivative)]
59#[derivative(Debug)]
60pub struct QuatKey {
61    pub time: f64,
62    pub value: Quaternion,
63}
64
65impl From<&aiQuatKey> for QuatKey {
66    fn from(quat_key: &aiQuatKey) -> Self {
67        Self {
68            time: quat_key.mTime,
69            value: (&quat_key.mValue).into(),
70        }
71    }
72}
73
74#[repr(C)]
75#[derive(Debug, Copy, Clone)]
76pub struct Quaternion {
77    pub w: f32,
78    pub x: f32,
79    pub y: f32,
80    pub z: f32,
81}
82
83impl From<&aiQuaternion> for Quaternion {
84    fn from(quaternion: &aiQuaternion) -> Self {
85        Self {
86            w: quaternion.w,
87            x: quaternion.x,
88            y: quaternion.y,
89            z: quaternion.z,
90        }
91    }
92}
93
94#[derive(Derivative)]
95#[derivative(Debug)]
96pub struct NodeAnim {
97    pub name: String,
98    pub position_keys: Vec<VectorKey>,
99    pub rotation_keys: Vec<QuatKey>,
100    pub scaling_keys: Vec<VectorKey>,
101    pub post_state: u32,
102    pub pre_state: u32,
103}
104
105impl From<&aiNodeAnim> for NodeAnim {
106    fn from(node_anim: &aiNodeAnim) -> NodeAnim {
107        NodeAnim {
108            name: node_anim.mNodeName.into(),
109            position_keys: utils::get_vec(node_anim.mPositionKeys, node_anim.mNumPositionKeys),
110            rotation_keys: utils::get_vec(node_anim.mRotationKeys, node_anim.mNumRotationKeys),
111            scaling_keys: utils::get_vec(node_anim.mScalingKeys, node_anim.mNumScalingKeys),
112            post_state: node_anim.mPostState as _,
113            pre_state: node_anim.mPreState as _,
114        }
115    }
116}
117
118#[derive(Derivative)]
119#[derivative(Debug)]
120pub struct MeshAnim {
121    pub name: String,
122    pub keys: Vec<MeshKey>,
123}
124
125impl From<&aiMeshAnim> for MeshAnim {
126    fn from(mesh: &aiMeshAnim) -> MeshAnim {
127        MeshAnim {
128            name: mesh.mName.into(),
129            keys: utils::get_vec(mesh.mKeys, mesh.mNumKeys),
130        }
131    }
132}
133
134#[derive(Derivative)]
135#[derivative(Debug)]
136pub struct MeshKey {
137    pub time: f64,
138    pub value: u32,
139}
140
141impl From<&aiMeshKey> for MeshKey {
142    fn from(mesh_key: &aiMeshKey) -> MeshKey {
143        MeshKey {
144            time: mesh_key.mTime,
145            value: mesh_key.mValue,
146        }
147    }
148}
149
150#[derive(Default, Derivative)]
151#[derivative(Debug)]
152pub struct Animation {
153    pub name: String,
154    pub channels: Vec<NodeAnim>,
155    pub duration: f64,
156    pub morph_mesh_channels: Vec<MeshMorphAnim>,
157    pub mesh_channels: Vec<MeshAnim>,
158    pub ticks_per_second: f64,
159}
160
161impl From<&aiAnimation> for Animation {
162    fn from(animation: &aiAnimation) -> Self {
163        Self {
164            name: animation.mName.into(),
165            channels: utils::get_vec_from_raw(animation.mChannels, animation.mNumChannels),
166            duration: animation.mDuration,
167            morph_mesh_channels: utils::get_vec_from_raw(
168                animation.mMorphMeshChannels,
169                animation.mNumMorphMeshChannels,
170            ),
171            mesh_channels: utils::get_vec_from_raw(
172                animation.mMeshChannels,
173                animation.mNumMeshChannels,
174            ),
175            ticks_per_second: animation.mTicksPerSecond,
176        }
177    }
178}
179
180#[cfg(test)]
181mod test {
182    use crate::utils;
183
184    #[test]
185    fn camera_roll_animation_read() {
186        use crate::scene::{PostProcess, Scene};
187
188        let current_directory_buf = utils::get_model("models/3DS/CameraRollAnim.3ds");
189
190        let scene = Scene::from_file(
191            current_directory_buf.as_str(),
192            vec![
193                PostProcess::CalculateTangentSpace,
194                PostProcess::Triangulate,
195                PostProcess::JoinIdenticalVertices,
196                PostProcess::SortByPrimitiveType,
197            ],
198        )
199        .unwrap();
200
201        assert_eq!(1, scene.animations.len());
202        assert_eq!("3DSMasterAnim".to_string(), scene.animations[0].name);
203        assert_eq!(1, scene.animations[0].channels.len());
204        assert_eq!("Camera01".to_string(), scene.animations[0].channels[0].name);
205
206        assert_eq!(0, scene.animations[0].channels[0].pre_state);
207        assert_eq!(0, scene.animations[0].channels[0].post_state);
208        assert_eq!(0.0, scene.animations[0].channels[0].rotation_keys[0].time);
209        assert_eq!(
210            0.9999999,
211            scene.animations[0].channels[0].rotation_keys[0].value.w
212        );
213        assert_eq!(
214            -0.00046456736,
215            scene.animations[0].channels[0].rotation_keys[0].value.x
216        );
217        assert_eq!(
218            0.0,
219            scene.animations[0].channels[0].rotation_keys[0].value.y
220        );
221        assert_eq!(
222            0.0,
223            scene.animations[0].channels[0].rotation_keys[0].value.z
224        );
225
226        assert_eq!(120.0, scene.animations[0].channels[0].rotation_keys[1].time);
227        assert_eq!(
228            0.7806558,
229            scene.animations[0].channels[0].rotation_keys[1].value.w
230        );
231        assert_eq!(
232            -0.6249612,
233            scene.animations[0].channels[0].rotation_keys[1].value.x
234        );
235        assert_eq!(
236            0.0,
237            scene.animations[0].channels[0].rotation_keys[1].value.y
238        );
239        assert_eq!(
240            0.0,
241            scene.animations[0].channels[0].rotation_keys[1].value.z
242        );
243
244        assert_eq!(0.0, scene.animations[0].channels[0].scaling_keys[0].time);
245        assert_eq!(1.0, scene.animations[0].channels[0].scaling_keys[0].value.x);
246        assert_eq!(1.0, scene.animations[0].channels[0].scaling_keys[0].value.y);
247        assert_eq!(1.0, scene.animations[0].channels[0].scaling_keys[0].value.z);
248
249        // position keys
250        assert_eq!(1, scene.animations[0].channels[0].position_keys.len());
251        assert_eq!(0.0, scene.animations[0].channels[0].position_keys[0].time);
252        assert_eq!(
253            -153.0771,
254            scene.animations[0].channels[0].position_keys[0].value.x
255        );
256        assert_eq!(
257            3.272005,
258            scene.animations[0].channels[0].position_keys[0].value.y
259        );
260        assert_eq!(
261            22.777624,
262            scene.animations[0].channels[0].position_keys[0].value.z
263        );
264
265        assert_eq!(120.0, scene.animations[0].duration);
266        assert_eq!(0, scene.animations[0].morph_mesh_channels.len());
267    }
268
269    #[test]
270    fn debug_animations() {
271        use crate::scene::{PostProcess, Scene};
272
273        let current_directory_buf = utils::get_model("models/3DS/CameraRollAnim.3ds");
274
275        let scene = Scene::from_file(
276            current_directory_buf.as_str(),
277            vec![
278                PostProcess::CalculateTangentSpace,
279                PostProcess::Triangulate,
280                PostProcess::JoinIdenticalVertices,
281                PostProcess::SortByPrimitiveType,
282            ],
283        )
284        .unwrap();
285
286        dbg!(&scene.animations);
287    }
288}