305 lines
8.9 KiB
Rust
305 lines
8.9 KiB
Rust
use crate::{image, Document};
|
|
|
|
pub use json::texture::{MagFilter, MinFilter, WrappingMode};
|
|
#[cfg(feature = "extensions")]
|
|
use serde_json::{Map, Value};
|
|
|
|
lazy_static! {
|
|
static ref DEFAULT_SAMPLER: json::texture::Sampler = Default::default();
|
|
}
|
|
|
|
/// A reference to a `Texture`.
|
|
#[derive(Clone, Debug)]
|
|
pub struct Info<'a> {
|
|
/// The parent `Texture` struct.
|
|
texture: Texture<'a>,
|
|
|
|
/// The corresponding JSON struct.
|
|
json: &'a json::texture::Info,
|
|
}
|
|
|
|
/// Texture sampler properties for filtering and wrapping modes.
|
|
#[derive(Clone, Debug)]
|
|
pub struct Sampler<'a> {
|
|
/// The parent `Document` struct.
|
|
#[allow(dead_code)]
|
|
document: &'a Document,
|
|
|
|
/// The corresponding JSON index - `None` when the default sampler.
|
|
index: Option<usize>,
|
|
|
|
/// The corresponding JSON struct.
|
|
json: &'a json::texture::Sampler,
|
|
}
|
|
|
|
/// A texture and its sampler.
|
|
#[derive(Clone, Debug)]
|
|
pub struct Texture<'a> {
|
|
/// The parent `Document` struct.
|
|
document: &'a Document,
|
|
|
|
/// The corresponding JSON index.
|
|
index: usize,
|
|
|
|
/// The corresponding JSON struct.
|
|
json: &'a json::texture::Texture,
|
|
}
|
|
|
|
impl<'a> Sampler<'a> {
|
|
/// Constructs a `Sampler`.
|
|
pub(crate) fn new(
|
|
document: &'a Document,
|
|
index: usize,
|
|
json: &'a json::texture::Sampler,
|
|
) -> Self {
|
|
Self {
|
|
document,
|
|
index: Some(index),
|
|
json,
|
|
}
|
|
}
|
|
|
|
/// Constructs the default `Sampler`.
|
|
pub(crate) fn default(document: &'a Document) -> Self {
|
|
Self {
|
|
document,
|
|
index: None,
|
|
json: &DEFAULT_SAMPLER,
|
|
}
|
|
}
|
|
|
|
/// Returns the internal JSON index if this `Sampler` was explicity defined.
|
|
///
|
|
/// This function returns `None` if the `Sampler` is the default sampler.
|
|
pub fn index(&self) -> Option<usize> {
|
|
self.index
|
|
}
|
|
|
|
/// Magnification filter.
|
|
pub fn mag_filter(&self) -> Option<MagFilter> {
|
|
self.json.mag_filter.map(|filter| filter.unwrap())
|
|
}
|
|
|
|
/// Minification filter.
|
|
pub fn min_filter(&self) -> Option<MinFilter> {
|
|
self.json.min_filter.map(|filter| filter.unwrap())
|
|
}
|
|
|
|
/// Optional user-defined name for this object.
|
|
#[cfg(feature = "names")]
|
|
pub fn name(&self) -> Option<&str> {
|
|
self.json.name.as_deref()
|
|
}
|
|
|
|
/// `s` wrapping mode.
|
|
pub fn wrap_s(&self) -> WrappingMode {
|
|
self.json.wrap_s.unwrap()
|
|
}
|
|
|
|
/// `t` wrapping mode.
|
|
pub fn wrap_t(&self) -> WrappingMode {
|
|
self.json.wrap_t.unwrap()
|
|
}
|
|
|
|
/// Returns extension data unknown to this crate version.
|
|
#[cfg(feature = "extensions")]
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
|
|
pub fn extensions(&self) -> Option<&Map<String, Value>> {
|
|
let ext = self.json.extensions.as_ref()?;
|
|
Some(&ext.others)
|
|
}
|
|
|
|
/// Queries extension data unknown to this crate version.
|
|
#[cfg(feature = "extensions")]
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
|
|
pub fn extension_value(&self, ext_name: &str) -> Option<&Value> {
|
|
let ext = self.json.extensions.as_ref()?;
|
|
ext.others.get(ext_name)
|
|
}
|
|
|
|
/// Optional application specific data.
|
|
pub fn extras(&self) -> &json::Extras {
|
|
&self.json.extras
|
|
}
|
|
}
|
|
|
|
impl<'a> Texture<'a> {
|
|
/// Constructs a `Texture`.
|
|
pub(crate) fn new(
|
|
document: &'a Document,
|
|
index: usize,
|
|
json: &'a json::texture::Texture,
|
|
) -> Self {
|
|
Self {
|
|
document,
|
|
index,
|
|
json,
|
|
}
|
|
}
|
|
|
|
/// Returns the internal JSON index.
|
|
pub fn index(&self) -> usize {
|
|
self.index
|
|
}
|
|
|
|
/// Optional user-defined name for this object.
|
|
#[cfg(feature = "names")]
|
|
pub fn name(&self) -> Option<&str> {
|
|
self.json.name.as_deref()
|
|
}
|
|
|
|
/// Returns the sampler used by this texture.
|
|
pub fn sampler(&self) -> Sampler<'a> {
|
|
self.json
|
|
.sampler
|
|
.as_ref()
|
|
.map(|index| self.document.samplers().nth(index.value()).unwrap())
|
|
.unwrap_or_else(|| Sampler::default(self.document))
|
|
}
|
|
|
|
/// Returns the image used by this texture.
|
|
#[cfg(feature = "allow_empty_texture")]
|
|
pub fn source(&self) -> Option<image::Image<'a>> {
|
|
let index = self.json.source.value();
|
|
if index == u32::MAX as usize {
|
|
None
|
|
} else {
|
|
Some(self.document.images().nth(index).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.value())
|
|
.unwrap()
|
|
}
|
|
|
|
/// Returns extension data unknown to this crate version.
|
|
#[cfg(feature = "extensions")]
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
|
|
pub fn extensions(&self) -> Option<&Map<String, Value>> {
|
|
let ext = self.json.extensions.as_ref()?;
|
|
Some(&ext.others)
|
|
}
|
|
|
|
/// Queries extension data unknown to this crate version.
|
|
#[cfg(feature = "extensions")]
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
|
|
pub fn extension_value(&self, ext_name: &str) -> Option<&Value> {
|
|
let ext = self.json.extensions.as_ref()?;
|
|
ext.others.get(ext_name)
|
|
}
|
|
|
|
/// Optional application specific data.
|
|
pub fn extras(&self) -> &json::Extras {
|
|
&self.json.extras
|
|
}
|
|
}
|
|
|
|
impl<'a> Info<'a> {
|
|
/// Constructs a reference to a `Texture`.
|
|
pub(crate) fn new(texture: Texture<'a>, json: &'a json::texture::Info) -> Self {
|
|
Self { texture, json }
|
|
}
|
|
|
|
/// The set index of the texture's `TEXCOORD` attribute.
|
|
pub fn tex_coord(&self) -> u32 {
|
|
self.json.tex_coord
|
|
}
|
|
|
|
/// Returns the referenced `Texture`.
|
|
pub fn texture(&self) -> Texture<'a> {
|
|
self.texture.clone()
|
|
}
|
|
|
|
/// Returns texture transform information
|
|
#[cfg(feature = "KHR_texture_transform")]
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "KHR_texture_transform")))]
|
|
pub fn texture_transform(&self) -> Option<TextureTransform<'a>> {
|
|
self.json
|
|
.extensions
|
|
.as_ref()?
|
|
.texture_transform
|
|
.as_ref()
|
|
.map(TextureTransform::new)
|
|
}
|
|
|
|
/// Returns extension data unknown to this crate version.
|
|
#[cfg(feature = "extensions")]
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
|
|
pub fn extensions(&self) -> Option<&Map<String, Value>> {
|
|
let ext = self.json.extensions.as_ref()?;
|
|
Some(&ext.others)
|
|
}
|
|
|
|
/// Queries extension data unknown to this crate version.
|
|
#[cfg(feature = "extensions")]
|
|
#[cfg_attr(docsrs, doc(cfg(feature = "extensions")))]
|
|
pub fn extension_value(&self, ext_name: &str) -> Option<&Value> {
|
|
let ext = self.json.extensions.as_ref()?;
|
|
ext.others.get(ext_name)
|
|
}
|
|
|
|
/// Optional application specific data.
|
|
pub fn extras(&self) -> &json::Extras {
|
|
&self.json.extras
|
|
}
|
|
}
|
|
|
|
impl<'a> AsRef<Texture<'a>> for Info<'a> {
|
|
fn as_ref(&self) -> &Texture<'a> {
|
|
&self.texture
|
|
}
|
|
}
|
|
|
|
/// Many techniques can be used to optimize resource usage for a 3d scene.
|
|
/// Chief among them is the ability to minimize the number of textures the GPU must load.
|
|
/// To achieve this, many engines encourage packing many objects' low-resolution textures into a single large texture atlas.
|
|
/// The region of the resulting atlas that corresponds with each object is then defined by vertical and horizontal offsets,
|
|
/// and the width and height of the region.
|
|
///
|
|
/// To support this use case, this extension adds `offset`, `rotation`, and `scale` properties to textureInfo structures.
|
|
/// These properties would typically be implemented as an affine transform on the UV coordinates.
|
|
#[cfg(feature = "KHR_texture_transform")]
|
|
pub struct TextureTransform<'a> {
|
|
/// The corresponding JSON struct.
|
|
json: &'a json::extensions::texture::TextureTransform,
|
|
}
|
|
|
|
#[cfg(feature = "KHR_texture_transform")]
|
|
impl<'a> TextureTransform<'a> {
|
|
/// Constructs `TextureTransform`
|
|
pub(crate) fn new(json: &'a json::extensions::texture::TextureTransform) -> Self {
|
|
Self { json }
|
|
}
|
|
|
|
/// The offset of the UV coordinate origin as a factor of the texture dimensions.
|
|
pub fn offset(&self) -> [f32; 2] {
|
|
self.json.offset.0
|
|
}
|
|
|
|
/// Rotate the UVs by this many radians counter-clockwise around the origin.
|
|
/// This is equivalent to a similar rotation of the image clockwise.
|
|
pub fn rotation(&self) -> f32 {
|
|
self.json.rotation.0
|
|
}
|
|
|
|
/// The scale factor applied to the components of the UV coordinates.
|
|
pub fn scale(&self) -> [f32; 2] {
|
|
self.json.scale.0
|
|
}
|
|
|
|
/// Overrides the textureInfo texCoord value if supplied, and if this extension is supported.
|
|
pub fn tex_coord(&self) -> Option<u32> {
|
|
self.json.tex_coord
|
|
}
|
|
|
|
/// Optional application specific data.
|
|
pub fn extras(&self) -> &json::Extras {
|
|
&self.json.extras
|
|
}
|
|
}
|