pub mod iter;
#[cfg(feature = "utils")]
pub mod util;
use json;
use {Accessor, Buffer, Document, Material};
#[cfg(feature = "utils")]
use accessor;
pub use json::mesh::{Mode, Semantic};
use json::validation::Checked;
pub type Attribute<'a> = (Semantic, Accessor<'a>);
pub type BoundingBox = Bounds<[f32; 3]>;
#[derive(Clone, Debug, PartialEq)]
pub struct Bounds<T> {
pub min: T,
pub max: T,
}
#[derive(Clone, Debug)]
pub struct Mesh<'a> {
document: &'a Document,
index: usize,
json: &'a json::mesh::Mesh,
}
#[derive(Clone, Debug)]
pub struct MorphTarget<'a> {
positions: Option<Accessor<'a>>,
normals: Option<Accessor<'a>>,
tangents: Option<Accessor<'a>>,
}
#[derive(Clone, Debug)]
pub struct Primitive<'a> {
mesh: &'a Mesh<'a>,
index: usize,
json: &'a json::mesh::Primitive,
}
#[derive(Clone, Debug)]
pub struct Reader<'a, 's, F>
where
F: Clone + Fn(Buffer<'a>) -> Option<&'s [u8]>,
{
pub(crate) primitive: &'a Primitive<'a>,
pub(crate) get_buffer_data: F,
}
impl<'a> Mesh<'a> {
pub(crate) fn new(
document: &'a Document,
index: usize,
json: &'a json::mesh::Mesh,
) -> Self {
Self {
document: document,
index: index,
json: json,
}
}
pub fn index(&self) -> usize {
self.index
}
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) -> iter::Primitives<'a> {
iter::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,
}
}
pub fn bounding_box(&self) -> BoundingBox {
let pos_accessor_index = self.json.attributes.get(&Checked::Valid(Semantic::Positions)).unwrap();
let pos_accessor = self.mesh.document.accessors().nth(pos_accessor_index.value()).unwrap();
let min: [f32; 3] = json::deserialize::from_value(pos_accessor.min().unwrap()).unwrap();
let max: [f32; 3] = json::deserialize::from_value(pos_accessor.max().unwrap()).unwrap();
Bounds { min, max }
}
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.document.accessors().nth(index.value()).unwrap())
}
pub fn index(&self) -> usize {
self.index
}
pub fn indices(&self) -> Option<Accessor> {
self.json.indices
.as_ref()
.map(|index| self.mesh.document.accessors().nth(index.value()).unwrap())
}
pub fn attributes(&self) -> iter::Attributes {
iter::Attributes {
document: self.mesh.document,
prim: self,
iter: self.json.attributes.iter(),
}
}
pub fn material(&self) -> Material {
self.json.material
.as_ref()
.map(|index| self.mesh.document.materials().nth(index.value()).unwrap())
.unwrap_or_else(|| Material::default(self.mesh.document))
}
pub fn mode(&self) -> Mode {
self.json.mode.unwrap()
}
pub fn morph_targets(&self) -> iter::MorphTargets {
if let Some(slice) = self.json.targets.as_ref() {
iter::MorphTargets {
document: self.mesh.document,
iter: slice.iter(),
}
} else {
iter::MorphTargets {
document: self.mesh.document,
iter: (&[]).iter(),
}
}
}
#[cfg(feature = "utils")]
pub fn reader<'s, F>(
&'a self,
get_buffer_data: F,
) -> Reader<'a, 's, F>
where
F: Clone + Fn(Buffer<'a>) -> Option<&'s [u8]>,
{
Reader { primitive: self, get_buffer_data }
}
}
#[cfg(feature = "utils")]
impl<'a, 's, F> Reader<'a, 's, F>
where F: Clone + Fn(Buffer<'a>) -> Option<&'s [u8]>,
{
pub fn read_positions(&self) -> Option<util::ReadPositions<'s>> {
if let Some(accessor) = self.primitive.get(&Semantic::Positions) {
if let Some(slice) = (self.get_buffer_data)(accessor.clone().view().buffer()) {
return Some(accessor::Iter::new(accessor, slice))
}
}
None
}
pub fn read_normals(&self) -> Option<util::ReadNormals<'s>> {
if let Some(accessor) = self.primitive.get(&Semantic::Normals) {
if let Some(slice) = (self.get_buffer_data)(accessor.clone().view().buffer()) {
return Some(accessor::Iter::new(accessor, slice))
}
}
None
}
pub fn read_tangents(&self) -> Option<util::ReadTangents<'s>> {
if let Some(accessor) = self.primitive.get(&Semantic::Tangents) {
if let Some(slice) = (self.get_buffer_data)(accessor.clone().view().buffer()) {
return Some(accessor::Iter::new(accessor, slice))
}
}
None
}
pub fn read_colors(&self, set: u32) -> Option<util::ReadColors<'s>> {
use accessor::DataType::{U8, U16, F32};
use accessor::Dimensions::{Vec3, Vec4};
use self::util::ReadColors;
if let Some(accessor) = self.primitive.get(&Semantic::Colors(set)) {
if let Some(slice) = (self.get_buffer_data)(accessor.clone().view().buffer()) {
return Some(
match (accessor.data_type(), accessor.dimensions()) {
(U8, Vec3) => ReadColors::RgbU8(accessor::Iter::new(accessor, slice)),
(U16, Vec3) => ReadColors::RgbU16(accessor::Iter::new(accessor, slice)),
(F32, Vec3) => ReadColors::RgbF32(accessor::Iter::new(accessor, slice)),
(U8, Vec4) => ReadColors::RgbaU8(accessor::Iter::new(accessor, slice)),
(U16, Vec4) => ReadColors::RgbaU16(accessor::Iter::new(accessor, slice)),
(F32, Vec4) => ReadColors::RgbaF32(accessor::Iter::new(accessor, slice)),
_ => unreachable!(),
}
)
}
}
None
}
pub fn read_indices(&self) -> Option<util::ReadIndices<'s>> {
use accessor::DataType;
use self::util::ReadIndices;
if let Some(accessor) = self.primitive.indices() {
if let Some(slice) = (self.get_buffer_data)(accessor.clone().view().buffer()) {
return Some(
match accessor.data_type() {
DataType::U8 => ReadIndices::U8(accessor::Iter::new(accessor, slice)),
DataType::U16 => ReadIndices::U16(accessor::Iter::new(accessor, slice)),
DataType::U32 => ReadIndices::U32(accessor::Iter::new(accessor, slice)),
_ => unreachable!(),
}
)
}
}
None
}
pub fn read_joints(&self, set: u32) -> Option<util::ReadJoints<'s>> {
use accessor::DataType;
use self::util::ReadJoints;
if let Some(accessor) = self.primitive.get(&Semantic::Joints(set)) {
if let Some(slice) = (self.get_buffer_data)(accessor.view().buffer()) {
return Some(
match accessor.data_type() {
DataType::U8 => ReadJoints::U8(accessor::Iter::new(accessor, slice)),
DataType::U16 => ReadJoints::U16(accessor::Iter::new(accessor, slice)),
_ => unreachable!(),
}
)
}
}
None
}
pub fn read_tex_coords(&self, set: u32) -> Option<util::ReadTexCoords<'s>> {
use accessor::DataType;
use self::util::ReadTexCoords;
if let Some(accessor) = self.primitive.get(&Semantic::TexCoords(set)) {
if let Some(slice) = (self.get_buffer_data)(accessor.view().buffer()) {
return Some(
match accessor.data_type() {
DataType::U8 => ReadTexCoords::U8(accessor::Iter::new(accessor, slice)),
DataType::U16 => ReadTexCoords::U16(accessor::Iter::new(accessor, slice)),
DataType::F32 => ReadTexCoords::F32(accessor::Iter::new(accessor, slice)),
_ => unreachable!(),
}
)
}
}
None
}
pub fn read_weights(&self, set: u32) -> Option<util::ReadWeights<'s>> {
use self::accessor::DataType;
use self::util::ReadWeights;
if let Some(accessor) = self.primitive.get(&Semantic::Weights(set)) {
if let Some(slice) = (self.get_buffer_data)(accessor.view().buffer()) {
return Some(
match accessor.data_type() {
DataType::U8 => ReadWeights::U8(accessor::Iter::new(accessor, slice)),
DataType::U16 => ReadWeights::U16(accessor::Iter::new(accessor, slice)),
DataType::F32 => ReadWeights::F32(accessor::Iter::new(accessor, slice)),
_ => unreachable!(),
}
)
}
}
None
}
pub fn read_morph_targets(&self) -> util::ReadMorphTargets<'a, 's, F> {
util::ReadMorphTargets {
index: 0,
reader: self.clone(),
}
}
}
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()
}
}