use anyhow::{bail, format_err, Error};
use mint::Vector3;
use crate::v7400::data::mesh::{
layer::{
LayerContentIndex, LayerElementHandle, MappingMode, ReferenceInformation, ReferenceMode,
},
TriangleVertexIndex, TriangleVertices,
};
#[derive(Debug, Clone, Copy)]
pub struct LayerElementNormalHandle<'a> {
node: LayerElementHandle<'a>,
}
impl<'a> LayerElementNormalHandle<'a> {
pub fn new(node: LayerElementHandle<'a>) -> Self {
Self { node }
}
pub fn normals(&self) -> Result<Normals<'a>, Error> {
Normals::new(self)
}
fn normals_vec3_slice(&self) -> Result<&'a [f64], Error> {
self.children_by_name("Normals")
.next()
.ok_or_else(|| format_err!("No `Normals` found for `LayerElementNormal` node"))?
.attributes()
.get(0)
.ok_or_else(|| format_err!("No attributes found for `Normals` node"))?
.get_arr_f64_or_type()
.map_err(|ty| format_err!("Expected `[f64]` as normals, but got {:?}", ty))
}
fn normals_norm_slice(&self) -> Result<Option<&'a [f64]>, Error> {
let normals_w_node = match self.children_by_name("NormalsW").next() {
Some(v) => v,
None => return Ok(None),
};
normals_w_node
.attributes()
.get(0)
.ok_or_else(|| format_err!("No attributes found for `NormalsW` node"))?
.get_arr_f64_or_type()
.map(Some)
.map_err(|ty| format_err!("Expected `[f64]` as normals W, but got {:?}", ty))
}
}
impl<'a> std::ops::Deref for LayerElementNormalHandle<'a> {
type Target = LayerElementHandle<'a>;
fn deref(&self) -> &Self::Target {
&self.node
}
}
#[derive(Debug, Clone, Copy)]
pub struct Normals<'a> {
normals: &'a [f64],
#[allow(dead_code)] normals_w: Option<&'a [f64]>,
mapping_mode: MappingMode,
}
impl<'a> Normals<'a> {
fn new(handle: &LayerElementNormalHandle<'a>) -> Result<Self, Error> {
let normals = handle.normals_vec3_slice()?;
let normals_w = handle.normals_norm_slice()?;
let mapping_mode = handle.mapping_mode()?;
let reference_mode = handle.reference_mode()?;
if reference_mode != ReferenceMode::Direct {
bail!(
"Unsupported reference mode for normals: {:?}",
reference_mode
);
}
Ok(Self {
normals,
normals_w,
mapping_mode,
})
}
pub fn normal(
&self,
tris: &TriangleVertices<'a>,
tri_vi: TriangleVertexIndex,
) -> Result<Vector3<f64>, Error> {
let i = LayerContentIndex::control_point_data_from_triangle_vertices(
ReferenceInformation::Direct,
self.mapping_mode,
tris,
self.normals.len() / 3,
tri_vi,
)?;
Ok(Vector3::from_slice(&self.normals[(i.get() * 3)..]))
}
}