dae_parser/core/
camera.rs

1use crate::*;
2
3/// Declares a view of the visual scene hierarchy or scene graph.
4/// The camera contains elements that describe the camera’s optics and imager.
5#[derive(Clone, Debug)]
6pub struct Camera {
7    /// A text string containing the unique identifier of the element.
8    pub id: Option<String>,
9    /// The text string name of this element.
10    pub name: Option<String>,
11    /// Asset management information about this element.
12    pub asset: Option<Box<Asset>>,
13    /// Describes the field of view and viewing frustum using canonical parameters.
14    pub optics: Optics,
15    /// Represents the image sensor of a camera (for example, film or CCD).
16    pub imager: Option<Imager>,
17    /// Provides arbitrary additional information about this element.
18    pub extra: Vec<Extra>,
19}
20
21impl Camera {
22    /// Construct a new `Camera` with the given projection type.
23    pub fn new(ty: ProjectionType) -> Self {
24        Self {
25            id: Default::default(),
26            name: Default::default(),
27            asset: Default::default(),
28            optics: Optics::new(ty),
29            imager: Default::default(),
30            extra: Default::default(),
31        }
32    }
33}
34
35impl XNode for Camera {
36    const NAME: &'static str = "camera";
37    fn parse(element: &Element) -> Result<Self> {
38        debug_assert_eq!(element.name(), Self::NAME);
39        let mut it = element.children().peekable();
40        Ok(Camera {
41            id: element.attr("id").map(Into::into),
42            name: element.attr("name").map(Into::into),
43            asset: Asset::parse_opt_box(&mut it)?,
44            optics: Optics::parse_one(&mut it)?,
45            imager: Imager::parse_opt(&mut it)?,
46            extra: Extra::parse_many(it)?,
47        })
48    }
49}
50
51impl XNodeWrite for Camera {
52    fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
53        let mut e = Self::elem();
54        e.opt_attr("id", &self.id);
55        e.opt_attr("name", &self.name);
56        let e = e.start(w)?;
57        self.asset.write_to(w)?;
58        self.optics.write_to(w)?;
59        self.imager.write_to(w)?;
60        self.extra.write_to(w)?;
61        e.end(w)
62    }
63}
64
65/// Represents the image sensor of a camera (for example, film or CCD).
66#[derive(Clone, Debug)]
67pub struct Imager {
68    /// Declares the information used to process some portion of the content.
69    /// This field is always nonempty, because the spec provides no common data
70    /// for `imager` elements.
71    pub technique: Vec<Technique>,
72    /// Provides arbitrary additional information about this element.
73    pub extra: Vec<Extra>,
74}
75
76impl Imager {
77    /// Construct a new `Imager` with the given technique(s).
78    pub fn new(technique: Vec<Technique>) -> Self {
79        assert!(!technique.is_empty());
80        Self {
81            technique,
82            extra: vec![],
83        }
84    }
85}
86
87impl XNode for Imager {
88    const NAME: &'static str = "imager";
89    fn parse(element: &Element) -> Result<Self> {
90        debug_assert_eq!(element.name(), Self::NAME);
91        let mut it = element.children().peekable();
92        Ok(Imager {
93            technique: Technique::parse_list_n::<1>(&mut it)?,
94            extra: Extra::parse_many(it)?,
95        })
96    }
97}
98
99impl XNodeWrite for Imager {
100    fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
101        let e = Self::elem().start(w)?;
102        self.technique.write_to(w)?;
103        self.extra.write_to(w)?;
104        e.end(w)
105    }
106}
107
108/// Represents the apparatus on a camera that projects the image onto the image sensor.
109#[derive(Clone, Debug)]
110pub struct Optics {
111    /// The projection type.
112    pub ty: ProjectionType,
113    /// Declares the information used to process some portion of the content. (optional)
114    pub technique: Vec<Technique>,
115    /// Provides arbitrary additional information about this element.
116    pub extra: Vec<Extra>,
117}
118
119impl Optics {
120    /// Construct a new `Optics` from the given projection type.
121    pub fn new(ty: ProjectionType) -> Self {
122        Self {
123            ty,
124            technique: Default::default(),
125            extra: Default::default(),
126        }
127    }
128}
129
130impl XNode for Optics {
131    const NAME: &'static str = "optics";
132    fn parse(element: &Element) -> Result<Self> {
133        debug_assert_eq!(element.name(), Self::NAME);
134        let mut it = element.children().peekable();
135        Ok(Optics {
136            ty: parse_one(Technique::COMMON, &mut it, |e| {
137                let mut it = e.children().peekable();
138                finish(parse_one_many(&mut it, ProjectionType::parse)?, it)
139            })?,
140            technique: Technique::parse_list(&mut it)?,
141            extra: Extra::parse_many(it)?,
142        })
143    }
144}
145
146impl XNodeWrite for Optics {
147    fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
148        let e = Self::elem().start(w)?;
149        let common = ElemBuilder::new(Technique::COMMON).start(w)?;
150        self.ty.write_to(w)?;
151        common.end(w)?;
152        self.technique.write_to(w)?;
153        self.extra.write_to(w)?;
154        e.end(w)
155    }
156}
157
158/// The projection type of the camera.
159#[derive(Clone, Debug)]
160pub enum ProjectionType {
161    /// An orthographic camera
162    Orthographic(Orthographic),
163    /// A perspective camera
164    Perspective(Perspective),
165}
166
167impl ProjectionType {
168    /// Parse a [`ProjectionType`] from an XML element.
169    pub fn parse(e: &Element) -> Result<Option<Self>> {
170        match e.name() {
171            Orthographic::NAME => Ok(Some(Self::Orthographic(Orthographic::parse(e)?))),
172            Perspective::NAME => Ok(Some(Self::Perspective(Perspective::parse(e)?))),
173            _ => Ok(None),
174        }
175    }
176}
177
178impl XNodeWrite for ProjectionType {
179    fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
180        match self {
181            Self::Orthographic(e) => e.write_to(w),
182            Self::Perspective(e) => e.write_to(w),
183        }
184    }
185}
186
187/// Describes the field of view of an orthographic camera.
188#[derive(Clone, Debug)]
189pub struct Orthographic {
190    /// The horizontal (X) magnification of the view.
191    pub xmag: Option<f32>,
192    /// The vertical (Y) magnification of the view.
193    pub ymag: Option<f32>,
194    /// Provides arbitrary additional information about this element.
195    pub extra: Vec<Extra>,
196    /// The aspect ratio of the field of view.
197    pub aspect_ratio: Option<f32>,
198    /// The distance to the near clipping plane.
199    pub znear: f32,
200    /// The distance to the far clipping plane.
201    pub zfar: f32,
202}
203
204impl Orthographic {
205    /// Construct a new `Orthographic` object.
206    pub fn new(xmag: Option<f32>, ymag: Option<f32>, znear: f32, zfar: f32) -> Self {
207        Self {
208            xmag,
209            ymag,
210            extra: Default::default(),
211            aspect_ratio: Default::default(),
212            znear,
213            zfar,
214        }
215    }
216}
217
218impl XNode for Orthographic {
219    const NAME: &'static str = "orthographic";
220    fn parse(element: &Element) -> Result<Self> {
221        debug_assert_eq!(element.name(), Self::NAME);
222        let mut it = element.children().peekable();
223        let res = Orthographic {
224            xmag: parse_opt("xmag", &mut it, parse_elem)?,
225            ymag: parse_opt("ymag", &mut it, parse_elem)?,
226            extra: Extra::parse_list(&mut it)?,
227            aspect_ratio: parse_opt("aspect_ratio", &mut it, parse_elem)?,
228            znear: parse_one("znear", &mut it, parse_elem)?,
229            zfar: parse_one("zfar", &mut it, parse_elem)?,
230        };
231        finish(res, it)
232    }
233}
234
235impl XNodeWrite for Orthographic {
236    fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
237        let e = Self::elem().start(w)?;
238        ElemBuilder::opt_print("xmag", &self.xmag, w)?;
239        ElemBuilder::opt_print("ymag", &self.ymag, w)?;
240        self.extra.write_to(w)?;
241        ElemBuilder::opt_print("aspect_ratio", &self.aspect_ratio, w)?;
242        ElemBuilder::print("znear", &self.znear, w)?;
243        ElemBuilder::print("zfar", &self.zfar, w)?;
244        e.end(w)
245    }
246}
247
248/// Describes the field of view of a perspective camera.
249#[derive(Clone, Copy, Debug)]
250pub struct Perspective {
251    /// The horizontal field of view in degrees.
252    pub xfov: Option<f32>,
253    /// The vertical field of view in degrees.
254    pub yfov: Option<f32>,
255    /// The aspect ratio of the field of view.
256    pub aspect_ratio: Option<f32>,
257    /// The distance to the near clipping plane.
258    pub znear: f32,
259    /// The distance to the far clipping plane.
260    pub zfar: f32,
261}
262
263impl Perspective {
264    /// Construct a new `Perspective` object.
265    pub fn new(xfov: Option<f32>, yfov: Option<f32>, znear: f32, zfar: f32) -> Self {
266        Self {
267            xfov,
268            yfov,
269            aspect_ratio: Default::default(),
270            znear,
271            zfar,
272        }
273    }
274}
275
276impl XNode for Perspective {
277    const NAME: &'static str = "perspective";
278    fn parse(element: &Element) -> Result<Self> {
279        debug_assert_eq!(element.name(), Self::NAME);
280        let mut it = element.children().peekable();
281        let res = Perspective {
282            xfov: parse_opt("xfov", &mut it, parse_elem)?,
283            yfov: parse_opt("yfov", &mut it, parse_elem)?,
284            aspect_ratio: parse_opt("aspect_ratio", &mut it, parse_elem)?,
285            znear: parse_one("znear", &mut it, parse_elem)?,
286            zfar: parse_one("zfar", &mut it, parse_elem)?,
287        };
288        finish(res, it)
289    }
290}
291
292impl XNodeWrite for Perspective {
293    fn write_to<W: Write>(&self, w: &mut XWriter<W>) -> Result<()> {
294        let e = Self::elem().start(w)?;
295        ElemBuilder::opt_print("xfov", &self.xfov, w)?;
296        ElemBuilder::opt_print("yfov", &self.yfov, w)?;
297        ElemBuilder::opt_print("aspect_ratio", &self.aspect_ratio, w)?;
298        ElemBuilder::print("znear", &self.znear, w)?;
299        ElemBuilder::print("zfar", &self.zfar, w)?;
300        e.end(w)
301    }
302}