fbxcel_dom/v7400/data/mesh/layer/
normal.rs

1//! Normal.
2
3use anyhow::{bail, format_err, Error};
4use mint::Vector3;
5
6use crate::v7400::data::mesh::{
7    layer::{
8        LayerContentIndex, LayerElementHandle, MappingMode, ReferenceInformation, ReferenceMode,
9    },
10    TriangleVertexIndex, TriangleVertices,
11};
12
13/// Layer element node handle.
14#[derive(Debug, Clone, Copy)]
15pub struct LayerElementNormalHandle<'a> {
16    /// `LayerElementNormal` node.
17    node: LayerElementHandle<'a>,
18}
19
20impl<'a> LayerElementNormalHandle<'a> {
21    /// Creates a new `LayerElementNormalHandle`.
22    pub fn new(node: LayerElementHandle<'a>) -> Self {
23        Self { node }
24    }
25
26    /// Returns `Normals` data.
27    pub fn normals(&self) -> Result<Normals<'a>, Error> {
28        Normals::new(self)
29    }
30
31    /// Returns reference to the normals (xyz) slice.
32    fn normals_vec3_slice(&self) -> Result<&'a [f64], Error> {
33        self.children_by_name("Normals")
34            .next()
35            .ok_or_else(|| format_err!("No `Normals` found for `LayerElementNormal` node"))?
36            .attributes()
37            .get(0)
38            .ok_or_else(|| format_err!("No attributes found for `Normals` node"))?
39            .get_arr_f64_or_type()
40            .map_err(|ty| format_err!("Expected `[f64]` as normals, but got {:?}", ty))
41    }
42
43    /// Returns reference to the normals norms (w = `sqrt(x*x + y*y + z*z)`)
44    /// slice.
45    ///
46    /// It is not guaranteed to be correct value.
47    /// Use with care, especially if you are using untrusted data.
48    fn normals_norm_slice(&self) -> Result<Option<&'a [f64]>, Error> {
49        let normals_w_node = match self.children_by_name("NormalsW").next() {
50            Some(v) => v,
51            None => return Ok(None),
52        };
53        normals_w_node
54            .attributes()
55            .get(0)
56            .ok_or_else(|| format_err!("No attributes found for `NormalsW` node"))?
57            .get_arr_f64_or_type()
58            .map(Some)
59            .map_err(|ty| format_err!("Expected `[f64]` as normals W, but got {:?}", ty))
60    }
61}
62
63impl<'a> std::ops::Deref for LayerElementNormalHandle<'a> {
64    type Target = LayerElementHandle<'a>;
65
66    fn deref(&self) -> &Self::Target {
67        &self.node
68    }
69}
70
71/// Normals.
72#[derive(Debug, Clone, Copy)]
73pub struct Normals<'a> {
74    /// Normals.
75    normals: &'a [f64],
76    /// Normals W.
77    #[allow(dead_code)] // Useful for debugging using `Debug`.
78    normals_w: Option<&'a [f64]>,
79    /// Mapping mode.
80    mapping_mode: MappingMode,
81}
82
83impl<'a> Normals<'a> {
84    /// Creates a new `Normals`.
85    fn new(handle: &LayerElementNormalHandle<'a>) -> Result<Self, Error> {
86        let normals = handle.normals_vec3_slice()?;
87        let normals_w = handle.normals_norm_slice()?;
88        let mapping_mode = handle.mapping_mode()?;
89        let reference_mode = handle.reference_mode()?;
90        if reference_mode != ReferenceMode::Direct {
91            bail!(
92                "Unsupported reference mode for normals: {:?}",
93                reference_mode
94            );
95        }
96        Ok(Self {
97            normals,
98            normals_w,
99            mapping_mode,
100        })
101    }
102
103    /// Returns `[f64; 3]` normal corresponding to the given triangle vertex
104    /// index.
105    pub fn normal(
106        &self,
107        tris: &TriangleVertices<'a>,
108        tri_vi: TriangleVertexIndex,
109    ) -> Result<Vector3<f64>, Error> {
110        let i = LayerContentIndex::control_point_data_from_triangle_vertices(
111            ReferenceInformation::Direct,
112            self.mapping_mode,
113            tris,
114            self.normals.len() / 3,
115            tri_vi,
116        )?;
117        Ok(Vector3::from_slice(&self.normals[(i.get() * 3)..]))
118    }
119}