use std::{collections, iter, slice};
use json;
use {Accessor, Gltf, Material};
pub use json::mesh::{Mode, Semantic};
use json::validation::Checked;
pub type Attribute<'a> = (Semantic, Accessor<'a>);
#[derive(Clone, Debug)]
pub struct MorphTarget<'a> {
positions: Option<Accessor<'a>>,
normals: Option<Accessor<'a>>,
tangents: Option<Accessor<'a>>,
}
#[derive(Clone, Debug)]
pub struct MorphTargets<'a> {
gltf: &'a Gltf,
iter: slice::Iter<'a, json::mesh::MorphTarget>,
}
#[derive(Clone, Debug)]
pub struct Mesh<'a> {
gltf: &'a Gltf,
index: usize,
json: &'a json::mesh::Mesh,
}
#[derive(Clone, Debug)]
pub struct Primitive<'a> {
mesh: &'a Mesh<'a>,
index: usize,
json: &'a json::mesh::Primitive,
}
#[derive(Clone, Debug)]
pub struct Attributes<'a> {
gltf: &'a Gltf,
prim: &'a Primitive<'a>,
iter: collections::hash_map::Iter<
'a,
json::validation::Checked<json::mesh::Semantic>,
json::Index<json::accessor::Accessor>,
>,
}
#[derive(Clone, Debug)]
pub struct Primitives<'a> {
mesh: &'a Mesh<'a>,
iter: iter::Enumerate<slice::Iter<'a, json::mesh::Primitive>>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Bounds<T> {
pub min: T,
pub max: T,
}
impl<'a> Mesh<'a> {
pub(crate) fn new(
gltf: &'a Gltf,
index: usize,
json: &'a json::mesh::Mesh,
) -> Self {
Self {
gltf: gltf,
index: index,
json: json,
}
}
pub fn index(&self) -> usize {
self.index
}
#[doc(hidden)]
pub fn as_json(&self) -> &json::mesh::Mesh {
self.json
}
pub fn extras(&self) -> &json::Extras {
&self.json.extras
}
#[cfg(feature = "names")]
pub fn name(&self) -> Option<&str> {
self.json.name.as_ref().map(String::as_str)
}
pub fn primitives(&'a self) -> Primitives<'a> {
Primitives {
mesh: self,
iter: self.json.primitives.iter().enumerate(),
}
}
pub fn weights(&self) -> Option<&[f32]> {
self.json.weights.as_ref().map(Vec::as_slice)
}
}
impl<'a> Primitive<'a> {
pub(crate) fn new(
mesh: &'a Mesh<'a>,
index: usize,
json: &'a json::mesh::Primitive,
) -> Self {
Self {
mesh: mesh,
index: index,
json: json,
}
}
#[doc(hidden)]
pub fn as_json(&self) -> &json::mesh::Primitive {
self.json
}
pub fn position_bounds(&self) -> Option<Bounds<[f32; 3]>> {
if let Some(pos_accessor_index) = self.json.attributes.get(&Checked::Valid(Semantic::Positions)) {
let pos_accessor = self.mesh.gltf.accessors().nth(pos_accessor_index.value()).unwrap();
let min: [f32; 3] = json::from_value(pos_accessor.min().unwrap()).unwrap();
let max: [f32; 3] = json::from_value(pos_accessor.max().unwrap()).unwrap();
Some(Bounds {
min: [min[0], min[1], min[2]],
max: [max[0], max[1], max[2]]
})
} else {
None
}
}
pub fn extras(&self) -> &json::Extras {
&self.json.extras
}
pub fn get(&self, semantic: &Semantic) -> Option<Accessor> {
self.json.attributes
.get(&json::validation::Checked::Valid(semantic.clone()))
.map(|index| self.mesh.gltf.accessors().nth(index.value()).unwrap())
}
pub fn indices(&self) -> Option<Accessor> {
self.json.indices
.as_ref()
.map(|index| self.mesh.gltf.accessors().nth(index.value()).unwrap())
}
pub fn attributes(&self) -> Attributes {
Attributes {
gltf: self.mesh.gltf,
prim: self,
iter: self.json.attributes.iter(),
}
}
pub fn material(&self) -> Material {
self.json.material
.as_ref()
.map(|index| self.mesh.gltf.materials().nth(index.value()).unwrap())
.unwrap_or_else(|| Material::default(self.mesh.gltf))
}
pub fn mode(&self) -> Mode {
self.json.mode.unwrap()
}
pub fn morph_targets(&self) -> MorphTargets {
if let Some(slice) = self.json.targets.as_ref() {
MorphTargets {
gltf: self.mesh.gltf,
iter: slice.iter(),
}
} else {
MorphTargets {
gltf: self.mesh.gltf,
iter: (&[]).iter(),
}
}
}
}
impl<'a> MorphTarget<'a> {
pub fn positions(&self) -> Option<Accessor<'a>> {
self.positions.clone()
}
pub fn normals(&self) -> Option<Accessor<'a>> {
self.normals.clone()
}
pub fn tangents(&self) -> Option<Accessor<'a>> {
self.tangents.clone()
}
}
impl<'a> ExactSizeIterator for Attributes<'a> {}
impl<'a> Iterator for Attributes<'a> {
type Item = Attribute<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|(key, index)| {
let semantic = key.as_ref().unwrap().clone();
let accessor = self.gltf.accessors().nth(index.value()).unwrap();
(semantic, accessor)
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a> ExactSizeIterator for Primitives<'a> {}
impl<'a> Iterator for Primitives<'a> {
type Item = Primitive<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(index, json)| Primitive::new(self.mesh, index, json))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a> ExactSizeIterator for MorphTargets<'a> {}
impl<'a> Iterator for MorphTargets<'a> {
type Item = MorphTarget<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.iter
.next()
.map(|json| {
let positions = json.positions
.as_ref()
.map(|index| self.gltf.accessors().nth(index.value()).unwrap());
let normals = json.normals
.as_ref()
.map(|index| self.gltf.accessors().nth(index.value()).unwrap());
let tangents = json.tangents
.as_ref()
.map(|index| self.gltf.accessors().nth(index.value()).unwrap());
MorphTarget {
positions,
normals,
tangents,
}
})
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}