Skip to main content

russimp_ng/
node.rs

1use crate::{metadata::MetaData, sys::aiNode, *};
2use derivative::Derivative;
3use std::{
4    cell::RefCell,
5    rc::{Rc, Weak},
6};
7
8#[derive(Default, Derivative)]
9#[derivative(Debug)]
10pub struct Node {
11    pub name: String,
12    pub children: RefCell<Vec<Rc<Node>>>,
13    pub meshes: Vec<u32>,
14    pub metadata: Option<MetaData>,
15    pub transformation: Matrix4x4,
16    #[derivative(Debug = "ignore")]
17    pub parent: Weak<Node>,
18}
19
20impl Node {
21    pub(crate) fn new(node: &aiNode) -> Rc<Node> {
22        Self::allocate(node, None)
23    }
24
25    fn allocate(node: &aiNode, parent: Option<&Rc<Node>>) -> Rc<Node> {
26        // current simple node
27        let res_node = Rc::new(Self::create_simple_node(node, parent));
28
29        *res_node.children.borrow_mut() =
30            utils::get_base_type_vec_from_raw(node.mChildren, node.mNumChildren)
31                .into_iter()
32                .map(|child| Self::allocate(child, Some(&res_node)))
33                .collect::<Vec<_>>();
34
35        res_node
36    }
37
38    fn create_simple_node(node: &aiNode, parent: Option<&Rc<Node>>) -> Node {
39        Node {
40            name: node.mName.into(),
41            children: RefCell::new(Vec::new()),
42            meshes: utils::get_raw_vec(node.mMeshes, node.mNumMeshes),
43            metadata: utils::get_raw(node.mMetaData),
44            transformation: (&node.mTransformation).into(),
45            parent: parent.map(Rc::downgrade).unwrap_or_default(),
46        }
47    }
48}
49
50#[cfg(test)]
51mod test {
52    use crate::utils;
53
54    #[test]
55    fn checking_nodes() {
56        use crate::scene::{PostProcess, Scene};
57
58        let current_directory_buf = utils::get_model("models/BLEND/box.blend");
59
60        let scene = Scene::from_file(
61            current_directory_buf.as_str(),
62            vec![
63                PostProcess::CalculateTangentSpace,
64                PostProcess::Triangulate,
65                PostProcess::JoinIdenticalVertices,
66                PostProcess::SortByPrimitiveType,
67            ],
68        )
69        .unwrap();
70
71        let root = scene.root.as_ref().unwrap();
72        let children = root.children.borrow();
73
74        assert_eq!("<BlenderRoot>".to_string(), root.name);
75        assert_eq!(3, children.len());
76
77        let first_son = &children[0];
78        assert_eq!("Cube".to_string(), first_son.name);
79
80        let second_son = &children[1];
81        assert_eq!("Lamp".to_string(), second_son.name);
82
83        assert_eq!(0, root.meshes.len());
84
85        assert!(root.metadata.is_none());
86
87        assert_eq!(1.0, root.transformation.a1);
88        assert_eq!(1.0, root.transformation.b2);
89        assert_eq!(1.0, root.transformation.c3);
90        assert_eq!(1.0, root.transformation.d4);
91    }
92
93    #[test]
94    fn childs_parent_name_matches() {
95        use crate::scene::{PostProcess, Scene};
96
97        let current_directory_buf = utils::get_model("models/BLEND/box.blend");
98
99        let scene = Scene::from_file(
100            current_directory_buf.as_str(),
101            vec![
102                PostProcess::CalculateTangentSpace,
103                PostProcess::Triangulate,
104                PostProcess::JoinIdenticalVertices,
105                PostProcess::SortByPrimitiveType,
106            ],
107        )
108        .unwrap();
109
110        let root = scene.root.as_ref().unwrap();
111        let children = root.children.borrow();
112
113        let first_son = &children[0];
114        let dad = first_son.parent.upgrade().unwrap();
115
116        assert_eq!(root.name, dad.name);
117    }
118
119    #[test]
120    fn debug_root() {
121        use crate::scene::{PostProcess, Scene};
122
123        let current_directory_buf = utils::get_model("models/BLEND/box.blend");
124
125        let scene = Scene::from_file(
126            current_directory_buf.as_str(),
127            vec![
128                PostProcess::CalculateTangentSpace,
129                PostProcess::Triangulate,
130                PostProcess::JoinIdenticalVertices,
131                PostProcess::SortByPrimitiveType,
132            ],
133        )
134        .unwrap();
135
136        dbg!(&scene.root);
137    }
138}