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 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}