mod3d_gltf/
node.rs

1// A GLTF node is effectively a 'thing' in the hierarchy of 'thing's in the
2// scenes of the gltf
3//
4// A GLTF node can be a camera; this is the placement and orientation
5// of a reference to one of the GltfCamera of the file. A camera should
6// not have children.
7//
8// A GLTF node can be a skin, which is an index into the GltfSkin of the file.
9// That skin is only permitted to reference nodes (through its 'skeleton' and
10// 'joints' fields) which are referenced by the same scenes as this node is
11// (through its hierarchy) referenced from. If this
12//
13#[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//a GltfNode
27//tp GltfNode
28#[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    /// The children of the node; if there are none then this is a root node
35    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    // optional: extensions, extras
49}
50
51//ip Named for GltfNode
52impl Named for GltfNode {
53    type Index = NodeIndex;
54    fn is_name(&self, name: &str) -> bool {
55        self.name == name
56    }
57}
58
59//ip GltfNode
60impl 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}