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

1//! Common stuff for layer elements.
2
3use std::convert::{TryFrom, TryInto};
4
5use anyhow::{bail, format_err, Error};
6
7use crate::{
8    fbxcel::tree::v7400::NodeHandle,
9    v7400::data::mesh::{layer::LayerElementIndex, TriangleVertexIndex, TriangleVertices},
10};
11
12/// Layer element node handle.
13#[derive(Debug, Clone, Copy)]
14pub struct LayerElementHandle<'a> {
15    /// `LayerElement*` node under `Geometry`.
16    node: NodeHandle<'a>,
17}
18
19impl<'a> LayerElementHandle<'a> {
20    /// Creates a new `LayerElementHandle`.
21    pub(crate) fn new(node: NodeHandle<'a>) -> Self {
22        Self { node }
23    }
24
25    /// Returns a reference to the node handle.
26    pub fn node(&self) -> &NodeHandle<'a> {
27        &self.node
28    }
29
30    /// Returns type-local layer element index.
31    pub fn typed_index(&self) -> Result<LayerElementIndex, Error> {
32        let raw = self
33            .node()
34            .attributes()
35            .get(0)
36            .ok_or_else(|| format_err!("No attributes found for `{}` node", self.node().name()))?
37            .get_i32_or_type()
38            .map_err(|ty| format_err!("Expected `i32` as layer element index, but got {:?}", ty))?;
39        if raw < 0 {
40            bail!(
41                "Expected non-negative integer as layer element index, but got {:?}",
42                raw
43            );
44        }
45
46        Ok(LayerElementIndex::new(raw as u32))
47    }
48
49    /// Retuns layer element name.
50    ///
51    /// This conflicts with `fbxcel::tree::v7400::NodeHandle::name()`.
52    /// If you want to get node name, do `obj.node().name()` instead of
53    /// `obj.name()`.
54    pub fn name(&self) -> Result<&'a str, Error> {
55        self.children_by_name("Name")
56            .next()
57            .ok_or_else(|| {
58                format_err!(
59                    "Child node `Name` not found for `{}` node",
60                    self.node().name()
61                )
62            })?
63            .attributes()
64            .get(0)
65            .ok_or_else(|| format_err!("No attributes found for `{}` node", self.node().name()))?
66            .get_string_or_type()
67            .map_err(|ty| format_err!("Expected string as layer element name, but got {:?}", ty))
68    }
69
70    /// Returns mapping mode.
71    pub fn mapping_mode(&self) -> Result<MappingMode, Error> {
72        self.children_by_name("MappingInformationType")
73            .next()
74            .ok_or_else(|| {
75                format_err!(
76                    "Child node `MappingInformationType` not found for `{}` node",
77                    self.node().name()
78                )
79            })?
80            .attributes()
81            .get(0)
82            .ok_or_else(|| format_err!("No attributes found for `{}` node", self.node().name()))?
83            .get_string_or_type()
84            .map_err(|ty| format_err!("Expected string as layer element name, but got {:?}", ty))
85            .and_then(str::parse)
86    }
87
88    /// Returns reference mode.
89    pub fn reference_mode(&self) -> Result<ReferenceMode, Error> {
90        self.children_by_name("ReferenceInformationType")
91            .next()
92            .ok_or_else(|| {
93                format_err!(
94                    "Child node `ReferenceInformationType` not found for `{}` node",
95                    self.node().name()
96                )
97            })?
98            .attributes()
99            .get(0)
100            .ok_or_else(|| format_err!("No attributes found for `{}` node", self.node().name()))?
101            .get_string_or_type()
102            .map_err(|ty| format_err!("Expected string as layer element name, but got {:?}", ty))
103            .and_then(str::parse)
104    }
105}
106
107impl<'a> std::ops::Deref for LayerElementHandle<'a> {
108    type Target = NodeHandle<'a>;
109
110    fn deref(&self) -> &Self::Target {
111        &self.node
112    }
113}
114
115/// Mapping mode.
116#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
117pub enum MappingMode {
118    /// Undetermined.
119    None,
120    /// By ontrol point.
121    ByControlPoint,
122    /// By polygon vertex.
123    ByPolygonVertex,
124    /// By polygon.
125    ByPolygon,
126    /// By edge.
127    ByEdge,
128    /// Single value for all.
129    AllSame,
130}
131
132impl TryFrom<&str> for MappingMode {
133    type Error = Error;
134
135    fn try_from(s: &str) -> Result<Self, Self::Error> {
136        match s {
137            "ByControlPoint" | "ByVertex" | "ByVertice" => Ok(MappingMode::ByControlPoint),
138            "ByPolygonVertex" => Ok(MappingMode::ByPolygonVertex),
139            "ByPolygon" => Ok(MappingMode::ByPolygon),
140            "ByEdge" => Ok(MappingMode::ByEdge),
141            "AllSame" => Ok(MappingMode::AllSame),
142            s => Err(format_err!("Failed to parse mapping mode: got {:?}", s)),
143        }
144    }
145}
146
147impl std::str::FromStr for MappingMode {
148    type Err = Error;
149
150    fn from_str(s: &str) -> Result<Self, Self::Err> {
151        s.try_into()
152    }
153}
154
155/// Reference mode.
156#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
157pub enum ReferenceMode {
158    /// Direct.
159    Direct,
160    /// Index to direct.
161    IndexToDirect,
162}
163
164impl TryFrom<&str> for ReferenceMode {
165    type Error = Error;
166
167    fn try_from(s: &str) -> Result<Self, Self::Error> {
168        match s {
169            "Direct" => Ok(ReferenceMode::Direct),
170            "IndexToDirect" => Ok(ReferenceMode::IndexToDirect),
171            s => Err(format_err!("Failed to parse reference mode: got {:?}", s)),
172        }
173    }
174}
175
176impl std::str::FromStr for ReferenceMode {
177    type Err = Error;
178
179    fn from_str(s: &str) -> Result<Self, Self::Err> {
180        s.try_into()
181    }
182}
183
184/// Reference information.
185#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
186pub enum ReferenceInformation<'a> {
187    /// Direct.
188    Direct,
189    /// Index to direct.
190    IndexToDirect(&'a [i32]),
191}
192
193impl ReferenceInformation<'_> {
194    /// Returns direct index.
195    pub(crate) fn get_direct(&self, i: usize) -> Result<LayerContentIndex, Error> {
196        match self {
197            ReferenceInformation::Direct => Ok(LayerContentIndex::new(i)),
198            ReferenceInformation::IndexToDirect(indices) => {
199                let direct = indices.get(i).cloned().ok_or_else(|| {
200                    format_err!(
201                        "Index out of range: indices.len()={:?}, i={:?}",
202                        indices.len(),
203                        i
204                    )
205                })?;
206                let direct = if direct < 0 {
207                    // Negative direct index will be the last vertex index of a polygon.
208                    // Get the true index value by bitwise negation.
209                    !direct as usize
210                } else {
211                    direct as usize
212                };
213                Ok(LayerContentIndex::new(direct))
214            }
215        }
216    }
217}
218
219impl From<ReferenceInformation<'_>> for ReferenceMode {
220    fn from(v: ReferenceInformation<'_>) -> Self {
221        match v {
222            ReferenceInformation::Direct => ReferenceMode::Direct,
223            ReferenceInformation::IndexToDirect(_) => ReferenceMode::IndexToDirect,
224        }
225    }
226}
227
228/// Index of value in a layer element.
229#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
230pub(crate) struct LayerContentIndex(usize);
231
232impl LayerContentIndex {
233    /// Creates a new `LayerContentIndex`.
234    pub(crate) fn new(i: usize) -> Self {
235        Self(i)
236    }
237
238    /// Returns the index.
239    pub(crate) fn get(self) -> usize {
240        self.0
241    }
242
243    /// Returns the layer content index for the corresponding control point.
244    pub(crate) fn control_point_data_from_triangle_vertices(
245        reference_info: ReferenceInformation<'_>,
246        mapping_mode: MappingMode,
247        triangle_vertices: &TriangleVertices<'_>,
248        layer_element_array_len: usize,
249        tri_vi: TriangleVertexIndex,
250    ) -> Result<LayerContentIndex, Error> {
251        let index = match mapping_mode {
252            MappingMode::None | MappingMode::ByEdge => {
253                bail!("Unsupported mapping mode: {:?}", mapping_mode)
254            }
255            MappingMode::ByControlPoint => {
256                let cpi = triangle_vertices
257                    .control_point_index(tri_vi)
258                    .ok_or_else(|| {
259                        format_err!("Failed to get control point index: tri_vi={:?}", tri_vi)
260                    })?;
261                reference_info.get_direct(cpi.to_u32() as usize)?
262            }
263            MappingMode::ByPolygonVertex => {
264                let pvi = triangle_vertices
265                    .polygon_vertex_index(tri_vi)
266                    .ok_or_else(|| {
267                        format_err!("Failed to get polygon vertex index: tri_vi={:?}", tri_vi)
268                    })?;
269                reference_info.get_direct(pvi.to_usize())?
270            }
271            MappingMode::ByPolygon => {
272                let poly_i = triangle_vertices
273                    .polygon_index(tri_vi.triangle_index())
274                    .ok_or_else(|| {
275                        format_err!("Failed to get polygon vertex index: tri_vi={:?}", tri_vi)
276                    })?;
277                reference_info.get_direct(poly_i.to_usize())?
278            }
279            MappingMode::AllSame => reference_info.get_direct(0)?,
280        };
281        if index.get() >= layer_element_array_len {
282            bail!(
283                "Calculated index out of range: index={:?}, array_len={:?}",
284                index,
285                layer_element_array_len
286            );
287        }
288
289        Ok(index)
290    }
291}