1#[cfg(feature = "serde")]
14use serde::{Deserialize, Serialize};
15
16#[cfg(feature = "serde_json")]
17use serde_json::Value as JsonValue;
18#[cfg(not(feature = "serde_json"))]
19pub type JsonValue = ();
20
21use mod3d_base::Transformation;
22
23use crate::{CameraIndex, MeshIndex, Named, NodeIndex, SkinIndex};
24use crate::{Error, Result};
25
26#[derive(Debug, Default)]
29#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
30#[cfg_attr(feature = "serde", serde(default))]
31pub struct GltfNode {
32 #[cfg_attr(feature = "serde", serde(default))]
33 name: String,
34 children: Vec<NodeIndex>,
36 camera: Option<CameraIndex>,
37 skin: Option<SkinIndex>,
38 matrix: Option<[f32; 16]>,
39 mesh: Option<MeshIndex>,
40 rotation: Option<[f32; 4]>,
41 translation: Option<[f32; 3]>,
42 scale: Option<[f32; 3]>,
43 weights: Option<JsonValue>,
44 #[cfg_attr(feature = "serde", serde(skip))]
45 local_transformation: Transformation,
46 #[cfg_attr(feature = "serde", serde(skip))]
47 global_transformation: Transformation,
48 }
50
51impl Named for GltfNode {
53 type Index = NodeIndex;
54 fn is_name(&self, name: &str) -> bool {
55 self.name == name
56 }
57}
58
59impl GltfNode {
61 pub fn validate(&self, n: NodeIndex) -> Result<()> {
62 if self.skin.is_some() && self.mesh.is_none() {
63 return Err(Error::BadJson(format!(
64 "Node {n} has a skin but no mesh which is illegal",
65 )));
66 }
67 if self.matrix.is_some()
68 && (self.rotation.is_some() || self.translation.is_some() || self.scale.is_some())
69 {
70 return Err(Error::BadJson(format!(
71 "Node {n} has a matrix and some TRS",
72 )));
73 }
74
75 if self.weights.is_some() {
76 return Err(Error::BadJson(format!(
77 "Node {n} has morpht target weights that are not supported",
78 )));
79 }
80 Ok(())
81 }
82
83 pub fn derive(&mut self, parent_transformation: &Transformation) -> &Transformation {
84 self.local_transformation = Transformation::default();
85 if let Some(matrix) = self.matrix {
86 self.local_transformation.from_mat4(matrix);
87 } else {
88 if let Some(scale) = self.scale {
89 self.local_transformation.set_scale(scale);
90 }
91 if let Some(rotation) = self.rotation {
92 let rotation = (rotation[3], rotation[0], rotation[1], rotation[2]).into();
93 self.local_transformation.set_rotation(rotation);
94 }
95 if let Some(translation) = self.translation {
96 self.local_transformation.set_translation(translation);
97 }
98 }
99 self.global_transformation
100 .combine(parent_transformation, &self.local_transformation);
101 &self.global_transformation
102 }
103
104 pub fn is_root(&self) -> bool {
105 self.children.is_empty()
106 }
107 pub fn iter_children(&self) -> std::slice::Iter<NodeIndex> {
108 self.children.iter()
109 }
110 pub fn mesh(&self) -> Option<MeshIndex> {
111 self.mesh
112 }
113 pub fn skin(&self) -> Option<SkinIndex> {
114 self.skin
115 }
116 pub fn camera(&self) -> Option<CameraIndex> {
117 self.camera
118 }
119 pub fn global_transformation(&self) -> &Transformation {
120 &self.global_transformation
121 }
122 pub fn set_mesh(&mut self, mesh: MeshIndex) {
123 self.mesh = Some(mesh);
124 }
125 pub fn set_transformation(&mut self, transformation: &mod3d_base::Transformation) {
126 self.local_transformation = *transformation;
127 }
128 pub fn trans_mut(&mut self) -> &mut mod3d_base::Transformation {
129 &mut self.local_transformation
130 }
131 pub fn derive_gltf(&mut self) {
132 if self.local_transformation.scale() != [1., 1., 1.] {
133 self.scale = Some(self.local_transformation.scale());
134 } else {
135 self.scale = None;
136 }
137 if self.local_transformation.translation() != [0., 0., 0.] {
138 self.translation = Some(self.local_transformation.translation());
139 } else {
140 self.translation = None;
141 }
142 let (r, i, j, k) = geo_nd::quat::as_rijk(&self.local_transformation.rotation());
143 if r != 1.0 {
144 self.rotation = Some([i, j, k, r]);
145 } else {
146 self.rotation = None;
147 }
148 }
149}