dae_parser/core/
scene.rs

1use crate::*;
2
3#[cfg(feature = "nalgebra")]
4use nalgebra::Matrix4;
5
6/// Embodies the entire set of information that can be visualized
7/// from the contents of a COLLADA resource.
8#[derive(Clone, Default, Debug)]
9pub struct Scene {
10    /// The instantiated [`PhysicsScene`] elements describe
11    /// any physics being applied to the scene.
12    pub instance_physics_scene: Vec<Instance<PhysicsScene>>,
13    /// The scene graph is built from the [`VisualScene`] elements instantiated under [`Scene`].
14    pub instance_visual_scene: Option<Instance<VisualScene>>,
15    /// Provides arbitrary additional information about this element.
16    pub extra: Vec<Extra>,
17}
18
19impl Scene {
20    /// Construct a new `Scene` from a [`VisualScene`] instance.
21    pub fn new(instance_visual_scene: Instance<VisualScene>) -> Self {
22        Self {
23            instance_physics_scene: vec![],
24            instance_visual_scene: Some(instance_visual_scene),
25            extra: vec![],
26        }
27    }
28}
29
30impl XNode for Scene {
31    const NAME: &'static str = "scene";
32    fn parse(element: &Element) -> Result<Self> {
33        debug_assert_eq!(element.name(), Self::NAME);
34        let mut it = element.children().peekable();
35        Ok(Scene {
36            instance_physics_scene: Instance::parse_list(&mut it)?,
37            instance_visual_scene: Instance::parse_opt(&mut it)?,
38            extra: Extra::parse_many(it)?,
39        })
40    }
41}
42
43impl XNodeWrite for Scene {
44    fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
45        let e = Self::elem().start(w)?;
46        self.instance_physics_scene.write_to(w)?;
47        self.instance_visual_scene.write_to(w)?;
48        self.extra.write_to(w)?;
49        e.end(w)
50    }
51}
52
53/// Embodies the entire set of information that can be visualized
54/// from the contents of a COLLADA resource.
55#[derive(Clone, Debug)]
56pub struct VisualScene {
57    /// A text string containing the unique identifier of the element.
58    pub id: Option<String>,
59    /// The text string name of this element.
60    pub name: Option<String>,
61    /// Asset management information about this element.
62    pub asset: Option<Box<Asset>>,
63    /// The scene graph subtrees.
64    pub nodes: Vec<Node>,
65    /// The [`EvaluateScene`] element declares information
66    /// specifying how to evaluate this [`VisualScene`].
67    pub evaluate_scene: Vec<EvaluateScene>,
68    /// Provides arbitrary additional information about this element.
69    pub extra: Vec<Extra>,
70}
71
72impl VisualScene {
73    /// Create a new empty `VisualScene`.
74    pub fn new(id: impl Into<String>, name: Option<String>) -> Self {
75        Self {
76            id: Some(id.into()),
77            name,
78            asset: None,
79            nodes: vec![],
80            evaluate_scene: vec![],
81            extra: vec![],
82        }
83    }
84}
85
86impl XNode for VisualScene {
87    const NAME: &'static str = "visual_scene";
88    fn parse(element: &Element) -> Result<Self> {
89        debug_assert_eq!(element.name(), Self::NAME);
90        let mut it = element.children().peekable();
91        Ok(VisualScene {
92            id: element.attr("id").map(Into::into),
93            name: element.attr("name").map(Into::into),
94            asset: Asset::parse_opt_box(&mut it)?,
95            nodes: Node::parse_list(&mut it)?,
96            evaluate_scene: EvaluateScene::parse_list(&mut it)?,
97            extra: Extra::parse_many(it)?,
98        })
99    }
100}
101
102impl XNodeWrite for VisualScene {
103    fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
104        let mut e = Self::elem();
105        e.opt_attr("id", &self.id);
106        e.opt_attr("name", &self.name);
107        let e = e.start(w)?;
108        self.asset.write_to(w)?;
109        self.nodes.write_to(w)?;
110        self.evaluate_scene.write_to(w)?;
111        self.extra.write_to(w)?;
112        e.end(w)
113    }
114}
115
116/// Embodies the hierarchical relationship of elements in a scene.
117///
118/// The [`Node`] element declares a point of interest in a scene.
119/// A node denotes one point on a branch of the scene graph.
120/// The [`Node`] element is essentially the root of a subgraph of the entire scene graph.
121#[derive(Clone, Debug)]
122pub struct Node {
123    /// A text string containing the unique identifier of the element.
124    pub id: Option<String>,
125    /// The text string name of this element.
126    pub name: Option<String>,
127    /// A text string value containing the subidentifier of this element.
128    /// This value must be unique within the scope of the parent element.
129    pub sid: Option<String>,
130    /// The type of the [`Node`] element.
131    pub ty: NodeType,
132    /// The layers to which this node belongs.
133    pub layer: Vec<String>,
134    /// Asset management information about this element.
135    pub asset: Option<Box<Asset>>,
136    /// Any combination of geometric transforms.
137    pub transforms: Vec<Transform>,
138    /// Allows the node to instantiate a camera object.
139    pub instance_camera: Vec<Instance<Camera>>,
140    /// Allows the node to instantiate a controller object.
141    pub instance_controller: Vec<Instance<Controller>>,
142    /// Allows the node to instantiate a geometry object.
143    pub instance_geometry: Vec<Instance<Geometry>>,
144    /// Allows the node to instantiate a light object.
145    pub instance_light: Vec<Instance<Light>>,
146    /// Allows the node to instantiate a hierarchy of other nodes.
147    pub instance_node: Vec<Instance<Node>>,
148    /// Allows the node to recursively define hierarchy.
149    pub children: Vec<Node>,
150    /// Provides arbitrary additional information about this element.
151    pub extra: Vec<Extra>,
152}
153
154impl XNode for Node {
155    const NAME: &'static str = "node";
156    fn parse(element: &Element) -> Result<Self> {
157        debug_assert_eq!(element.name(), Self::NAME);
158        let mut it = element.children().peekable();
159        let extra;
160        Ok(Node {
161            id: element.attr("id").map(Into::into),
162            name: element.attr("name").map(Into::into),
163            sid: element.attr("sid").map(Into::into),
164            ty: parse_attr(element.attr("type"))?.unwrap_or_default(),
165            layer: element.attr("layer").map_or_else(Vec::new, |s| {
166                s.split_ascii_whitespace().map(|s| s.to_owned()).collect()
167            }),
168            asset: Asset::parse_opt_box(&mut it)?,
169            transforms: parse_list_many(&mut it, Transform::parse)?,
170            instance_camera: Instance::parse_list(&mut it)?,
171            instance_controller: Instance::parse_list(&mut it)?,
172            instance_geometry: Instance::parse_list(&mut it)?,
173            instance_light: Instance::parse_list(&mut it)?,
174            instance_node: Instance::parse_list(&mut it)?,
175            children: {
176                // Note: this is nonconforming, COLLADA spec says `extra` should come
177                // after `children`.
178                // However FBX Collada exporter has been witnessed producing such files
179                extra = Extra::parse_list(&mut it)?;
180                Node::parse_list(&mut it)?
181            },
182            extra: Extra::parse_append_many(extra, it)?,
183        })
184    }
185}
186
187impl XNodeWrite for Node {
188    fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
189        let mut e = Self::elem();
190        e.opt_attr("id", &self.id);
191        e.opt_attr("name", &self.name);
192        e.opt_attr("sid", &self.sid);
193        e.def_print_attr("type", self.ty, Default::default());
194        if let Some(s) = arr_to_string(&self.layer) {
195            e.attr("layer", &s)
196        }
197        if self.is_empty() {
198            e.end(w)
199        } else {
200            let e = e.start(w)?;
201            self.asset.write_to(w)?;
202            self.transforms.write_to(w)?;
203            self.instance_camera.write_to(w)?;
204            self.instance_controller.write_to(w)?;
205            self.instance_geometry.write_to(w)?;
206            self.instance_light.write_to(w)?;
207            self.instance_node.write_to(w)?;
208            self.children.write_to(w)?;
209            self.extra.write_to(w)?;
210            e.end(w)
211        }
212    }
213}
214
215impl CollectLocalMaps for Node {
216    fn collect_local_maps<'a>(&'a self, maps: &mut LocalMaps<'a>) {
217        maps.insert(self);
218        self.children.collect_local_maps(maps);
219    }
220}
221
222impl Node {
223    /// Construct a new default node with the given `id` and `name`.
224    pub fn new(id: impl Into<String>, name: Option<String>) -> Self {
225        Self {
226            id: Some(id.into()),
227            name,
228            sid: Default::default(),
229            ty: Default::default(),
230            layer: Default::default(),
231            asset: Default::default(),
232            transforms: Default::default(),
233            instance_camera: Default::default(),
234            instance_controller: Default::default(),
235            instance_geometry: Default::default(),
236            instance_light: Default::default(),
237            instance_node: Default::default(),
238            children: Default::default(),
239            extra: Default::default(),
240        }
241    }
242
243    /// Add a transform to this node's transformation stack.
244    pub fn push_transform(&mut self, transform: impl Into<Transform>) {
245        self.transforms.push(transform.into())
246    }
247
248    fn on_children<'a, E>(
249        &'a self,
250        f: &mut impl FnMut(&'a Self) -> Result<(), E>,
251    ) -> Result<(), E> {
252        f(self)?;
253        for child in &self.children {
254            child.on_children(f)?
255        }
256        Ok(())
257    }
258
259    /// Returns true if this node has no sub-elements.
260    pub fn is_empty(&self) -> bool {
261        self.asset.is_none()
262            && self.transforms.is_empty()
263            && self.instance_camera.is_empty()
264            && self.instance_controller.is_empty()
265            && self.instance_geometry.is_empty()
266            && self.instance_light.is_empty()
267            && self.instance_node.is_empty()
268            && self.children.is_empty()
269            && self.extra.is_empty()
270    }
271}
272
273impl Traversable for Node {
274    fn traverse<'a, E>(
275        doc: &'a Document,
276        mut f: impl FnMut(&'a Node) -> Result<(), E>,
277    ) -> Result<(), E> {
278        doc.library.iter().try_for_each(|elem| match elem {
279            LibraryElement::Nodes(lib) => lib.items.iter().try_for_each(|e| e.on_children(&mut f)),
280            LibraryElement::VisualScenes(lib) => lib
281                .items
282                .iter()
283                .try_for_each(|e| e.nodes.iter().try_for_each(|e| e.on_children(&mut f))),
284            _ => Ok(()),
285        })
286    }
287}
288
289#[cfg(feature = "nalgebra")]
290impl Node {
291    /// Apply the transformation stack on this node to a [`Matrix4`].
292    /// If `mat` beforehand is the transformation applying at the parent of the
293    /// current node, then `mat` after this call is the transformation that
294    /// applies to everything in this node and in the children.
295    pub fn prepend_transforms(&self, mat: &mut Matrix4<f32>) {
296        for t in &self.transforms {
297            t.prepend_to_matrix(mat)
298        }
299    }
300
301    /// Apply the transformation stack on this node to a [`Matrix4`].
302    /// If `mat` before this call is a transformation applying to a child of this node,
303    /// then `mat` afterward is the transformation situating the child in the parent frame.
304    pub fn append_transforms(&self, mat: &mut Matrix4<f32>) {
305        for t in self.transforms.iter().rev() {
306            t.append_to_matrix(mat)
307        }
308    }
309
310    /// Convert this node's transformation stack to a [`Matrix4`].
311    pub fn transform_as_matrix(&self) -> Matrix4<f32> {
312        let mut mat = Matrix4::identity();
313        self.prepend_transforms(&mut mat);
314        mat
315    }
316}
317
318/// The type of a [`Node`] element.
319#[derive(Clone, Copy, Debug, PartialEq, Eq)]
320pub enum NodeType {
321    /// A regular node.
322    Node,
323    /// A joint. See [`Joints`].
324    Joint,
325}
326
327impl Default for NodeType {
328    fn default() -> Self {
329        Self::Node
330    }
331}
332
333impl FromStr for NodeType {
334    type Err = ();
335
336    fn from_str(s: &str) -> Result<Self, Self::Err> {
337        match s {
338            "NODE" => Ok(Self::Node),
339            "JOINT" => Ok(Self::Joint),
340            _ => Err(()),
341        }
342    }
343}
344
345impl NodeType {
346    /// The XML name of a value in this enumeration.
347    pub fn to_str(self) -> &'static str {
348        match self {
349            Self::Node => "NODE",
350            Self::Joint => "JOINT",
351        }
352    }
353}
354
355impl Display for NodeType {
356    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
357        Display::fmt(self.to_str(), f)
358    }
359}
360
361/// Declares information specifying how to evaluate a [`VisualScene`].
362#[derive(Clone, Debug)]
363pub struct EvaluateScene {
364    /// The text string name of this element.
365    pub name: Option<String>,
366    /// Describes the effect passes to evaluate a scene.
367    pub render: Vec<Render>,
368}
369
370impl EvaluateScene {
371    /// Construct a new `EvaluateScene` with the given effect passes.
372    pub fn new(render: Vec<Render>) -> Self {
373        assert!(!render.is_empty());
374        Self { name: None, render }
375    }
376}
377
378impl XNode for EvaluateScene {
379    const NAME: &'static str = "evaluate_scene";
380    fn parse(element: &Element) -> Result<Self> {
381        debug_assert_eq!(element.name(), Self::NAME);
382        let mut it = element.children().peekable();
383        let res = EvaluateScene {
384            name: element.attr("name").map(Into::into),
385            render: Render::parse_list_n::<1>(&mut it)?,
386        };
387        finish(res, it)
388    }
389}
390
391impl XNodeWrite for EvaluateScene {
392    fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
393        let mut e = Self::elem();
394        e.opt_attr("name", &self.name);
395        let e = e.start(w)?;
396        self.render.write_to(w)?;
397        e.end(w)
398    }
399}