1use gltf_v1_derive::Validate;
2use serde_derive::{Deserialize, Serialize};
3
4use super::{accessor::Accessor, common::StringIndex, node::Node};
5
6#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
7pub struct Skin {
8 #[serde(
9 rename = "bindShapeMatrix",
10 skip_serializing_if = "matrix_is_default",
11 default = "default_matrix"
12 )]
13 pub bind_shape_matrix: [f32; 16],
14 #[serde(rename = "inverseBindMatrices")]
15 pub inverse_bind_matrices: StringIndex<Accessor>,
16 #[serde(default)]
17 #[serde(rename = "jointNames")]
18 pub joint_names: Vec<StringIndex<Node>>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub name: Option<String>,
21}
22
23fn matrix_is_default(value: &[f32; 16]) -> bool {
24 value[0] == 1.0
25 && value[1] == 0.0
26 && value[2] == 0.0
27 && value[3] == 0.0
28 && value[4] == 0.0
29 && value[5] == 1.0
30 && value[6] == 0.0
31 && value[7] == 0.0
32 && value[8] == 0.0
33 && value[9] == 0.0
34 && value[10] == 1.0
35 && value[11] == 0.0
36 && value[12] == 0.0
37 && value[13] == 0.0
38 && value[14] == 0.0
39 && value[15] == 1.0
40}
41
42fn default_matrix() -> [f32; 16] {
43 [
44 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
45 ]
46}
47
48#[test]
49fn test_skin_deserialize() {
50 let data = r#"{
51 "bindShapeMatrix": [
52 1,
53 0,
54 0,
55 0,
56 0,
57 1,
58 0,
59 0,
60 0,
61 0,
62 1,
63 0,
64 0,
65 0,
66 0,
67 1
68 ],
69 "inverseBindMatrices": "accessor_id",
70 "jointNames": [
71 "joint_name",
72 "another_joint_name"
73 ],
74 "name": "user-defined skin name",
75 "extensions" : {
76 "extension_name" : {
77 "extension specific" : "value"
78 }
79 },
80 "extras" : {
81 "Application specific" : "The extra object can contain any properties."
82 }
83 }"#;
84 let skin: Result<Skin, _> = serde_json::from_str(data);
85 let skin_unwrap = skin.unwrap();
86 println!("{}", serde_json::to_string(&skin_unwrap).unwrap());
87 assert_eq!(Some("user-defined skin name".to_string()), skin_unwrap.name);
88}