diff --git a/Cargo.toml b/Cargo.toml index e58ce283..a84d8dfe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ version = "0.25" [features] default = ["import", "utils", "names"] +allow-empty-texture = ["gltf-json/allow-empty-texture"] extensions = ["gltf-json/extensions"] extras = ["gltf-json/extras"] names = ["gltf-json/names"] diff --git a/gltf-json/Cargo.toml b/gltf-json/Cargo.toml index 2511ac3d..14fa1295 100644 --- a/gltf-json/Cargo.toml +++ b/gltf-json/Cargo.toml @@ -16,6 +16,7 @@ serde_json = { features = ["raw_value"], version = "1.0" } [features] default = [] +allow-empty-texture = [] names = [] extensions = [] extras = [] diff --git a/gltf-json/src/extensions/mod.rs b/gltf-json/src/extensions/mod.rs index 8119fb2b..09711a45 100644 --- a/gltf-json/src/extensions/mod.rs +++ b/gltf-json/src/extensions/mod.rs @@ -52,6 +52,13 @@ pub const ENABLED_EXTENSIONS: &[&str] = &[ "KHR_materials_ior", #[cfg(feature = "KHR_materials_emissive_strength")] "KHR_materials_emissive_strength", + // Allowlisted texture extensions. Processing is delegated to the user. + #[cfg(feature = "allow-empty-texture")] + "KHR_texture_basisu", + #[cfg(feature = "allow-empty-texture")] + "EXT_texture_webp", + #[cfg(feature = "allow-empty-texture")] + "MSFT_texture_dds", ]; /// Names of glTF 2.0 extensions supported by the library. diff --git a/gltf-json/src/texture.rs b/gltf-json/src/texture.rs index 4ad3236a..5d6c2b71 100644 --- a/gltf-json/src/texture.rs +++ b/gltf-json/src/texture.rs @@ -1,5 +1,5 @@ -use crate::validation::{Checked, Error, Validate}; -use crate::{extensions, image, Extras, Index, Path, Root}; +use crate::validation::Checked; +use crate::{extensions, image, Extras, Index}; use gltf_derive::Validate; use serde::{de, ser}; use serde_derive::{Deserialize, Serialize}; @@ -166,9 +166,14 @@ pub struct Sampler { pub extras: Extras, } +#[cfg(feature = "allow-empty-texture")] +pub type Source = Option>; + +#[cfg(not(feature = "allow-empty-texture"))] +pub type Source = Index; + /// A texture and its sampler. #[derive(Clone, Debug, Deserialize, Serialize, Validate)] -#[gltf(validate_hook = "texture_validate_hook")] pub struct Texture { /// Optional user-defined name for this object. #[cfg(feature = "names")] @@ -180,8 +185,11 @@ pub struct Texture { pub sampler: Option>, /// The index of the image used by this texture. - #[serde(skip_serializing_if = "Option::is_none")] - pub source: Option>, + #[cfg_attr( + feature = "allow-empty-texture", + serde(skip_serializing_if = "Option::is_none") + )] + pub source: Source, /// Extension specific data. #[serde(default, skip_serializing_if = "Option::is_none")] @@ -194,19 +202,6 @@ pub struct Texture { pub extras: Extras, } -fn texture_validate_hook(texture: &Texture, root: &Root, path: P, report: &mut R) -where - P: Fn() -> Path, - R: FnMut(&dyn Fn() -> Path, Error), -{ - let source_path = || path().field("source"); - if let Some(index) = texture.source.as_ref() { - index.validate(root, source_path, report); - } else { - report(&source_path, Error::Missing); - } -} - #[derive(Clone, Debug, Deserialize, Serialize, Validate)] /// Reference to a `Texture`. pub struct Info { diff --git a/src/accessor/mod.rs b/src/accessor/mod.rs index a932658f..f4d3fc67 100644 --- a/src/accessor/mod.rs +++ b/src/accessor/mod.rs @@ -40,9 +40,10 @@ //! for accessor in gltf.accessors() { //! match (accessor.data_type(), accessor.dimensions()) { //! (DataType::F32, Dimensions::Vec3) => { -//! let iter = Iter::<[f32; 3]>::new(accessor, get_buffer_data); -//! for item in iter { -//! println!("{:?}", item); +//! if let Some(iter) = Iter::<[f32; 3]>::new(accessor, get_buffer_data) { +//! for item in iter { +//! println!("{:?}", item); +//! } //! } //! } //! _ => {}, diff --git a/src/texture.rs b/src/texture.rs index a6a56fe8..a08373ac 100644 --- a/src/texture.rs +++ b/src/texture.rs @@ -1,6 +1,6 @@ use crate::{image, Document}; -pub use json::texture::{MagFilter, MinFilter, WrappingMode}; +pub use json::texture::{MagFilter, MinFilter, Source, WrappingMode}; #[cfg(feature = "extensions")] use serde_json::{Map, Value}; @@ -158,10 +158,20 @@ impl<'a> Texture<'a> { } /// Returns the image used by this texture. + #[cfg(feature = "allow-empty-texture")] + pub fn source(&self) -> Option> { + self.json + .source + .as_ref() + .map(|index| self.document.images().nth(index.value()).unwrap()) + } + + /// Returns the image used by this texture. + #[cfg(not(feature = "allow-empty-texture"))] pub fn source(&self) -> image::Image<'a> { self.document .images() - .nth(self.json.source.unwrap().value()) + .nth(self.json.source.value()) .unwrap() }