#![deny(missing_docs)]
#![allow(unknown_lints)]
#[cfg(test)]
#[macro_use]
extern crate approx;
#[cfg(feature = "import")]
extern crate image as image_crate;
#[macro_use]
extern crate lazy_static;
pub extern crate gltf_json as json;
pub mod accessor;
pub mod animation;
pub mod binary;
pub mod buffer;
pub mod camera;
pub mod image;
#[cfg(feature = "import")]
mod import;
pub mod iter;
pub mod material;
pub mod mesh;
pub mod scene;
pub mod skin;
pub mod texture;
#[doc(inline)]
pub use self::animation::Animation;
#[doc(inline)]
pub use self::accessor::Accessor;
#[doc(inline)]
pub use self::buffer::Buffer;
#[doc(inline)]
pub use self::camera::Camera;
#[doc(inline)]
pub use self::image::Image;
#[cfg(feature = "import")]
#[doc(inline)]
pub use self::import::import;
#[doc(inline)]
pub use self::material::Material;
#[doc(inline)]
pub use self::mesh::{Attribute, Mesh, Primitive, Semantic};
#[doc(inline)]
pub use self::scene::{Node, Scene};
#[doc(inline)]
pub use self::skin::Skin;
#[doc(inline)]
pub use self::texture::Texture;
use std::path::Path;
use std::{fs, io, ops, result};
pub(crate) trait Normalize<T> {
fn normalize(self) -> T;
}
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
#[cfg(feature = "import")]
Base64(base64::DecodeError),
Binary(binary::Error),
#[cfg(feature = "import")]
BufferLength {
buffer: usize,
expected: usize,
actual: usize,
},
Deserialize(json::Error),
Io(std::io::Error),
#[cfg(feature = "import")]
Image(image_crate::ImageError),
#[cfg(feature = "import")]
MissingBlob,
#[cfg(feature = "import")]
UnsupportedImageEncoding,
#[cfg(feature = "import")]
UnsupportedScheme,
Validation(Vec<(json::Path, json::validation::Error)>),
}
#[derive(Clone, Debug)]
pub struct Gltf {
pub document: Document,
pub blob: Option<Vec<u8>>,
}
#[derive(Clone, Debug)]
pub struct Document(json::Root);
impl Gltf {
pub fn open<P>(path: P) -> Result<Self>
where
P: AsRef<Path>,
{
let file = fs::File::open(path)?;
let reader = io::BufReader::new(file);
let gltf = Self::from_reader(reader)?;
Ok(gltf)
}
pub fn from_reader_without_validation<R>(mut reader: R) -> Result<Self>
where
R: io::Read + io::Seek
{
let mut magic = [0u8; 4];
reader.read_exact(&mut magic)?;
reader.seek(io::SeekFrom::Start(0))?;
let (json, blob): (json::Root, Option<Vec<u8>>);
if magic.starts_with(b"glTF") {
let mut glb = binary::Glb::from_reader(reader)?;
json = json::deserialize::from_slice(&glb.json)?;
blob = glb.bin.take().map(|x| x.into_owned());
} else {
json = json::deserialize::from_reader(reader)?;
blob = None;
};
let document = Document::from_json_without_validation(json);
Ok(Gltf { document, blob })
}
pub fn from_reader<R>(reader: R) -> Result<Self>
where
R: io::Read + io::Seek,
{
let gltf = Self::from_reader_without_validation(reader)?;
let _ = gltf.document.validate()?;
Ok(gltf)
}
pub fn from_slice_without_validation(slice: &[u8]) -> Result<Self> {
let (json, blob): (json::Root, Option<Vec<u8>>);
if slice.starts_with(b"glTF") {
let mut glb = binary::Glb::from_slice(slice)?;
json = json::deserialize::from_slice(&glb.json)?;
blob = glb.bin.take().map(|x| x.into_owned());
} else {
json = json::deserialize::from_slice(slice)?;
blob = None;
};
let document = Document::from_json_without_validation(json);
Ok(Gltf { document, blob })
}
pub fn from_slice(slice: &[u8]) -> Result<Self> {
let gltf = Self::from_slice_without_validation(slice)?;
let _ = gltf.document.validate()?;
Ok(gltf)
}
}
impl ops::Deref for Gltf {
type Target = Document;
fn deref(&self) -> &Self::Target {
&self.document
}
}
impl ops::DerefMut for Gltf {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.document
}
}
impl Document {
pub fn from_json(json: json::Root) -> Result<Self> {
let document = Self::from_json_without_validation(json);
let _ = document.validate()?;
Ok(document)
}
pub fn from_json_without_validation(json: json::Root) -> Self {
Document(json)
}
pub fn into_json(self) -> json::Root {
self.0
}
pub(crate) fn validate(&self) -> Result<()> {
use json::validation::Validate;
let mut errors = Vec::new();
self.0.validate_minimally(
&self.0,
json::Path::new,
&mut |path, error| errors.push((path(), error)),
);
if errors.is_empty() {
Ok(())
} else {
Err(Error::Validation(errors))
}
}
pub fn accessors(&self) -> iter::Accessors {
iter::Accessors {
iter: self.0.accessors.iter().enumerate(),
document: self,
}
}
pub fn animations(&self) -> iter::Animations {
iter::Animations {
iter: self.0.animations.iter().enumerate(),
document: self,
}
}
pub fn buffers(&self) -> iter::Buffers {
iter::Buffers {
iter: self.0.buffers.iter().enumerate(),
document: self,
}
}
pub fn cameras(&self) -> iter::Cameras {
iter::Cameras {
iter: self.0.cameras.iter().enumerate(),
document: self,
}
}
pub fn default_scene(&self) -> Option<Scene> {
self.0
.scene
.as_ref()
.map(|index| self.scenes().nth(index.value()).unwrap())
}
pub fn extensions_used(&self) -> iter::ExtensionsUsed {
iter::ExtensionsUsed(self.0.extensions_used.iter())
}
pub fn extensions_required(&self) -> iter::ExtensionsRequired {
iter::ExtensionsRequired(self.0.extensions_required.iter())
}
pub fn images(&self) -> iter::Images {
iter::Images {
iter: self.0.images.iter().enumerate(),
document: self,
}
}
pub fn materials(&self) -> iter::Materials {
iter::Materials {
iter: self.0.materials.iter().enumerate(),
document: self,
}
}
pub fn meshes(&self) -> iter::Meshes {
iter::Meshes {
iter: self.0.meshes.iter().enumerate(),
document: self,
}
}
pub fn nodes(&self) -> iter::Nodes {
iter::Nodes {
iter: self.0.nodes.iter().enumerate(),
document: self,
}
}
pub fn samplers(&self) -> iter::Samplers {
iter::Samplers {
iter: self.0.samplers.iter().enumerate(),
document: self,
}
}
pub fn scenes(&self) -> iter::Scenes {
iter::Scenes {
iter: self.0.scenes.iter().enumerate(),
document: self,
}
}
pub fn skins(&self) -> iter::Skins {
iter::Skins {
iter: self.0.skins.iter().enumerate(),
document: self,
}
}
pub fn textures(&self) -> iter::Textures {
iter::Textures {
iter: self.0.textures.iter().enumerate(),
document: self,
}
}
pub fn views(&self) -> iter::Views {
iter::Views {
iter: self.0.buffer_views.iter().enumerate(),
document: self,
}
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match *self {
#[cfg(feature = "import")]
Error::Base64(ref e) => e.fmt(f),
Error::Binary(ref e) => e.fmt(f),
Error::Deserialize(ref e) => e.fmt(f),
Error::Io(ref e) => e.fmt(f),
#[cfg(feature = "import")]
Error::Image(ref e) => e.fmt(f),
Error::Validation(ref xs) => {
write!(f, "invalid glTF:")?;
for &(ref path, ref error) in xs {
write!(f, " {}: {};", path, error)?;
}
Ok(())
}
_ => f.write_str(std::error::Error::description(self))
}
}
}
impl std::error::Error for Error {
fn description(&self) -> &str {
match *self {
#[cfg(feature = "import")]
Error::Base64(ref e) => e.description(),
Error::Binary(ref e) => e.description(),
#[cfg(feature = "import")]
Error::BufferLength { .. } => "buffer length does not match expected length",
Error::Deserialize(ref e) => e.description(),
Error::Io(ref e) => e.description(),
#[cfg(feature = "import")]
Error::Image(ref e) => e.description(),
#[cfg(feature = "import")]
Error::MissingBlob => "missing BIN section of binary glTF",
#[cfg(feature = "import")]
Error::UnsupportedImageEncoding => "unsupported image encoding",
#[cfg(feature = "import")]
Error::UnsupportedScheme => "unsupported URI scheme",
Error::Validation(_) => "invalid glTF",
}
}
}
impl From<binary::Error> for Error {
fn from(err: binary::Error) -> Self {
Error::Binary(err)
}
}
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Self {
Error::Io(err)
}
}
#[cfg(feature = "import")]
impl From<image_crate::ImageError> for Error {
fn from(err: image_crate::ImageError) -> Self {
Error::Image(err)
}
}
impl From<json::Error> for Error {
fn from(err: json::Error) -> Self {
Error::Deserialize(err)
}
}
impl From<Vec<(json::Path, json::validation::Error)>> for Error {
fn from(errs: Vec<(json::Path, json::validation::Error)>) -> Self {
Error::Validation(errs)
}
}
impl Normalize<i8> for i8 {
fn normalize(self) -> i8 { self }
}
impl Normalize<u8> for i8 {
fn normalize(self) -> u8 { self.max(0) as u8 * 2 }
}
impl Normalize<i16> for i8 {
fn normalize(self) -> i16 { self as i16 * 0x100 }
}
impl Normalize<u16> for i8 {
fn normalize(self) -> u16 { self.max(0) as u16 * 0x200 }
}
impl Normalize<f32> for i8 {
fn normalize(self) -> f32 { (self as f32 * 127.0_f32.recip()).max(-1.0) }
}
impl Normalize<i8> for u8 {
fn normalize(self) -> i8 { (self / 2) as i8 }
}
impl Normalize<u8> for u8 {
fn normalize(self) -> u8 { self }
}
impl Normalize<i16> for u8 {
fn normalize(self) -> i16 { self as i16 * 0x80 }
}
impl Normalize<u16> for u8 {
fn normalize(self) -> u16 { self.max(0) as u16 * 2 }
}
impl Normalize<f32> for u8 {
fn normalize(self) -> f32 { (self as f32 * 32767.0_f32.recip()).max(-1.0) }
}
impl Normalize<i8> for i16 {
fn normalize(self) -> i8 { (self / 0x100) as i8 }
}
impl Normalize<u8> for i16 {
fn normalize(self) -> u8 { (self.max(0) / 0x80) as u8 }
}
impl Normalize<i16> for i16 {
fn normalize(self) -> i16 { self }
}
impl Normalize<u16> for i16 {
fn normalize(self) -> u16 { self.max(0) as u16 * 2 }
}
impl Normalize<f32> for i16 {
fn normalize(self) -> f32 { (self as f32 * 32767.0_f32.recip()).max(-1.0) }
}
impl Normalize<i8> for u16 {
fn normalize(self) -> i8 { (self / 0x200) as i8 }
}
impl Normalize<u8> for u16 {
fn normalize(self) -> u8 { (self / 0x100) as u8 }
}
impl Normalize<i16> for u16 {
fn normalize(self) -> i16 { (self / 2) as i16 }
}
impl Normalize<u16> for u16 {
fn normalize(self) -> u16 { self }
}
impl Normalize<f32> for u16 {
fn normalize(self) -> f32 { self as f32 * 65535.0_f32.recip() }
}
impl Normalize<i8> for f32 {
fn normalize(self) -> i8 { (self * 127.0) as i8 }
}
impl Normalize<u8> for f32 {
fn normalize(self) -> u8 { (self.max(0.0) * 255.0) as u8 }
}
impl Normalize<i16> for f32 {
fn normalize(self) -> i16 { (self * 32767.0) as i16 }
}
impl Normalize<u16> for f32 {
fn normalize(self) -> u16 { (self.max(0.0) * 65535.0) as u16 }
}
impl Normalize<f32> for f32 {
fn normalize(self) -> f32 { self }
}
impl<U, T> Normalize<[T; 2]> for [U; 2] where U: Normalize<T> + Copy {
fn normalize(self) -> [T; 2] {
[self[0].normalize(), self[1].normalize()]
}
}
impl<U, T> Normalize<[T; 3]> for [U; 3] where U: Normalize<T> + Copy {
fn normalize(self) -> [T; 3] {
[self[0].normalize(), self[1].normalize(), self[2].normalize()]
}
}
impl<U, T> Normalize<[T; 4]> for [U; 4] where U: Normalize<T> + Copy {
fn normalize(self) -> [T; 4] {
[self[0].normalize(), self[1].normalize(), self[2].normalize(), self[3].normalize()]
}
}