Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

423
vendor/gltf-json/src/accessor.rs vendored Normal file
View File

@@ -0,0 +1,423 @@
use crate::validation::{Checked, Error, USize64};
use crate::{buffer, extensions, Extras, Index, Path, Root};
use gltf_derive::Validate;
use serde::{de, ser};
use serde_derive::{Deserialize, Serialize};
use serde_json::Value;
use std::fmt;
/// The component data type.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)]
pub enum ComponentType {
/// Corresponds to `GL_BYTE`.
I8 = 1,
/// Corresponds to `GL_UNSIGNED_BYTE`.
U8,
/// Corresponds to `GL_SHORT`.
I16,
/// Corresponds to `GL_UNSIGNED_SHORT`.
U16,
/// Corresponds to `GL_UNSIGNED_INT`.
U32,
/// Corresponds to `GL_FLOAT`.
F32,
}
/// Specifies whether an attribute, vector, or matrix.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)]
pub enum Type {
/// Scalar quantity.
Scalar = 1,
/// 2D vector.
Vec2,
/// 3D vector.
Vec3,
/// 4D vector.
Vec4,
/// 2x2 matrix.
Mat2,
/// 3x3 matrix.
Mat3,
/// 4x4 matrix.
Mat4,
}
/// Corresponds to `GL_BYTE`.
pub const BYTE: u32 = 5120;
/// Corresponds to `GL_UNSIGNED_BYTE`.
pub const UNSIGNED_BYTE: u32 = 5121;
/// Corresponds to `GL_SHORT`.
pub const SHORT: u32 = 5122;
/// Corresponds to `GL_UNSIGNED_SHORT`.
pub const UNSIGNED_SHORT: u32 = 5123;
/// Corresponds to `GL_UNSIGNED_INT`.
pub const UNSIGNED_INT: u32 = 5125;
/// Corresponds to `GL_FLOAT`.
pub const FLOAT: u32 = 5126;
/// All valid generic vertex attribute component types.
pub const VALID_COMPONENT_TYPES: &[u32] = &[
BYTE,
UNSIGNED_BYTE,
SHORT,
UNSIGNED_SHORT,
UNSIGNED_INT,
FLOAT,
];
/// All valid index component types.
pub const VALID_INDEX_TYPES: &[u32] = &[UNSIGNED_BYTE, UNSIGNED_SHORT, UNSIGNED_INT];
/// All valid accessor types.
pub const VALID_ACCESSOR_TYPES: &[&str] =
&["SCALAR", "VEC2", "VEC3", "VEC4", "MAT2", "MAT3", "MAT4"];
/// Contains data structures for sparse storage.
pub mod sparse {
use super::*;
use crate::extensions;
/// Indices of those attributes that deviate from their initialization value.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Indices {
/// The parent buffer view containing the sparse indices.
///
/// The referenced buffer view must not have `ARRAY_BUFFER` nor
/// `ELEMENT_ARRAY_BUFFER` as its target.
#[serde(rename = "bufferView")]
pub buffer_view: Index<buffer::View>,
/// The offset relative to the start of the parent `BufferView` in bytes.
#[serde(default, rename = "byteOffset")]
pub byte_offset: USize64,
/// The data type of each index.
#[serde(rename = "componentType")]
pub component_type: Checked<IndexComponentType>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::accessor::sparse::Indices>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// Sparse storage of attributes that deviate from their initialization value.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Sparse {
/// The number of attributes encoded in this sparse accessor.
pub count: USize64,
/// Index array of size `count` that points to those accessor attributes
/// that deviate from their initialization value.
///
/// Indices must strictly increase.
pub indices: Indices,
/// Array of size `count * number_of_components` storing the displaced
/// accessor attributes pointed by `indices`.
///
/// Substituted values must have the same `component_type` and number of
/// components as the base `Accessor`.
pub values: Values,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::accessor::sparse::Sparse>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// Array of size `count * number_of_components` storing the displaced
/// accessor attributes pointed by `accessor::sparse::Indices`.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Values {
/// The parent buffer view containing the sparse indices.
///
/// The referenced buffer view must not have `ARRAY_BUFFER` nor
/// `ELEMENT_ARRAY_BUFFER` as its target.
#[serde(rename = "bufferView")]
pub buffer_view: Index<buffer::View>,
/// The offset relative to the start of the parent buffer view in bytes.
#[serde(default, rename = "byteOffset")]
pub byte_offset: USize64,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::accessor::sparse::Values>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
}
/// A typed view into a buffer view.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
#[gltf(validate_hook = "accessor_validate_hook")]
pub struct Accessor {
/// The parent buffer view this accessor reads from.
///
/// This field can be omitted in sparse accessors.
#[serde(rename = "bufferView")]
#[serde(skip_serializing_if = "Option::is_none")]
pub buffer_view: Option<Index<buffer::View>>,
/// The offset relative to the start of the parent `BufferView` in bytes.
///
/// This field can be omitted in sparse accessors.
#[serde(default, rename = "byteOffset")]
#[serde(skip_serializing_if = "Option::is_none")]
pub byte_offset: Option<USize64>,
/// The number of components within the buffer view - not to be confused
/// with the number of bytes in the buffer view.
pub count: USize64,
/// The data type of components in the attribute.
#[serde(rename = "componentType")]
pub component_type: Checked<GenericComponentType>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::accessor::Accessor>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
/// Specifies if the attribute is a scalar, vector, or matrix.
#[serde(rename = "type")]
pub type_: Checked<Type>,
/// Minimum value of each component in this attribute.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub min: Option<Value>,
/// Maximum value of each component in this attribute.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub max: Option<Value>,
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// Specifies whether integer data values should be normalized.
#[serde(default, skip_serializing_if = "is_normalized_default")]
pub normalized: bool,
/// Sparse storage of attributes that deviate from their initialization
/// value.
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
pub sparse: Option<sparse::Sparse>,
}
fn accessor_validate_hook<P, R>(accessor: &Accessor, _root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
if accessor.sparse.is_none() && accessor.buffer_view.is_none() {
// If sparse is missing, then bufferView must be present. Report that bufferView is
// missing since it is the more common one to require.
report(&|| path().field("bufferView"), Error::Missing);
}
}
// Help serde avoid serializing this glTF 2.0 default value.
fn is_normalized_default(b: &bool) -> bool {
!*b
}
/// The data type of an index.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct IndexComponentType(pub ComponentType);
/// The data type of a generic vertex attribute.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct GenericComponentType(pub ComponentType);
impl<'de> de::Deserialize<'de> for Checked<GenericComponentType> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<GenericComponentType>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_COMPONENT_TYPES)
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::ComponentType::*;
use crate::validation::Checked::*;
Ok(match value as u32 {
BYTE => Valid(GenericComponentType(I8)),
UNSIGNED_BYTE => Valid(GenericComponentType(U8)),
SHORT => Valid(GenericComponentType(I16)),
UNSIGNED_SHORT => Valid(GenericComponentType(U16)),
UNSIGNED_INT => Valid(GenericComponentType(U32)),
FLOAT => Valid(GenericComponentType(F32)),
_ => Invalid,
})
}
}
deserializer.deserialize_u64(Visitor)
}
}
impl<'de> de::Deserialize<'de> for Checked<IndexComponentType> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<IndexComponentType>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_INDEX_TYPES)
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::ComponentType::*;
use crate::validation::Checked::*;
Ok(match value as u32 {
UNSIGNED_BYTE => Valid(IndexComponentType(U8)),
UNSIGNED_SHORT => Valid(IndexComponentType(U16)),
UNSIGNED_INT => Valid(IndexComponentType(U32)),
_ => Invalid,
})
}
}
deserializer.deserialize_u64(Visitor)
}
}
impl<'de> de::Deserialize<'de> for Checked<Type> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<Type>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_ACCESSOR_TYPES)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::Type::*;
use crate::validation::Checked::*;
Ok(match value {
"SCALAR" => Valid(Scalar),
"VEC2" => Valid(Vec2),
"VEC3" => Valid(Vec3),
"VEC4" => Valid(Vec4),
"MAT2" => Valid(Mat2),
"MAT3" => Valid(Mat3),
"MAT4" => Valid(Mat4),
_ => Invalid,
})
}
}
deserializer.deserialize_str(Visitor)
}
}
impl ser::Serialize for Type {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(match *self {
Type::Scalar => "SCALAR",
Type::Vec2 => "VEC2",
Type::Vec3 => "VEC3",
Type::Vec4 => "VEC4",
Type::Mat2 => "MAT2",
Type::Mat3 => "MAT3",
Type::Mat4 => "MAT4",
})
}
}
impl ComponentType {
/// Returns the number of bytes this value represents.
pub fn size(&self) -> usize {
use self::ComponentType::*;
match *self {
I8 | U8 => 1,
I16 | U16 => 2,
F32 | U32 => 4,
}
}
/// Returns the corresponding `GLenum`.
pub fn as_gl_enum(self) -> u32 {
match self {
ComponentType::I8 => BYTE,
ComponentType::U8 => UNSIGNED_BYTE,
ComponentType::I16 => SHORT,
ComponentType::U16 => UNSIGNED_SHORT,
ComponentType::U32 => UNSIGNED_INT,
ComponentType::F32 => FLOAT,
}
}
}
impl ser::Serialize for ComponentType {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_u32(self.as_gl_enum())
}
}
impl Type {
/// Returns the equivalent number of scalar quantities this type represents.
pub fn multiplicity(&self) -> usize {
use self::Type::*;
match *self {
Scalar => 1,
Vec2 => 2,
Vec3 => 3,
Vec4 | Mat2 => 4,
Mat3 => 9,
Mat4 => 16,
}
}
}

263
vendor/gltf-json/src/animation.rs vendored Normal file
View File

@@ -0,0 +1,263 @@
use crate::validation::{Checked, Error, Validate};
use crate::{accessor, extensions, scene, Extras, Index, Path, Root};
use gltf_derive::Validate;
use serde::{de, ser};
use serde_derive::{Deserialize, Serialize};
use std::fmt;
/// All valid animation interpolation algorithms.
pub const VALID_INTERPOLATIONS: &[&str] = &["LINEAR", "STEP", "CUBICSPLINE"];
/// All valid animation property names.
pub const VALID_PROPERTIES: &[&str] = &["translation", "rotation", "scale", "weights"];
/// Specifies an interpolation algorithm.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)]
pub enum Interpolation {
/// Linear interpolation.
///
/// The animated values are linearly interpolated between keyframes.
/// When targeting a rotation, spherical linear interpolation (slerp) should be
/// used to interpolate quaternions. The number output of elements must equal
/// the number of input elements.
Linear = 1,
/// Step interpolation.
///
/// The animated values remain constant to the output of the first keyframe,
/// until the next keyframe. The number of output elements must equal the number
/// of input elements.
Step,
/// Cubic spline interpolation.
///
/// The animation's interpolation is computed using a cubic spline with specified
/// tangents. The number of output elements must equal three times the number of
/// input elements. For each input element, the output stores three elements, an
/// in-tangent, a spline vertex, and an out-tangent. There must be at least two
/// keyframes when using this interpolation
CubicSpline,
}
/// Specifies a property to animate.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Deserialize)]
pub enum Property {
/// XYZ translation vector.
Translation = 1,
/// XYZW rotation quaternion.
Rotation,
/// XYZ scale vector.
Scale,
/// Weights of morph targets.
MorphTargetWeights,
}
/// A keyframe animation.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Animation {
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::animation::Animation>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
/// An array of channels, each of which targets an animation's sampler at a
/// node's property.
///
/// Different channels of the same animation must not have equal targets.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub channels: Vec<Channel>,
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// An array of samplers that combine input and output accessors with an
/// interpolation algorithm to define a keyframe graph (but not its target).
#[serde(skip_serializing_if = "Vec::is_empty")]
pub samplers: Vec<Sampler>,
}
/// Targets an animation's sampler at a node's property.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Channel {
/// The index of a sampler in this animation used to compute the value for the
/// target.
pub sampler: Index<Sampler>,
/// The index of the node and TRS property to target.
pub target: Target,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::animation::Channel>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// The index of the node and TRS property that an animation channel targets.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Target {
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::animation::Target>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
/// The index of the node to target.
pub node: Index<scene::Node>,
/// The name of the node's property to modify or the 'weights' of the
/// morph targets it instantiates.
pub path: Checked<Property>,
}
/// Defines a keyframe graph but not its target.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Sampler {
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::animation::Sampler>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
/// The index of an accessor containing keyframe input values, e.g., time.
pub input: Index<accessor::Accessor>,
/// The interpolation algorithm.
#[serde(default)]
pub interpolation: Checked<Interpolation>,
/// The index of an accessor containing keyframe output values.
pub output: Index<accessor::Accessor>,
}
impl Validate for Animation {
fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
self.samplers
.validate(root, || path().field("samplers"), report);
for (index, channel) in self.channels.iter().enumerate() {
if channel.sampler.value() >= self.samplers.len() {
let path = || path().field("channels").index(index).field("sampler");
report(&path, Error::IndexOutOfBounds);
}
}
}
}
impl Default for Interpolation {
fn default() -> Self {
Interpolation::Linear
}
}
impl<'de> de::Deserialize<'de> for Checked<Interpolation> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<Interpolation>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_INTERPOLATIONS)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::Interpolation::*;
use crate::validation::Checked::*;
Ok(match value {
"LINEAR" => Valid(Linear),
"STEP" => Valid(Step),
"CUBICSPLINE" => Valid(CubicSpline),
_ => Invalid,
})
}
}
deserializer.deserialize_str(Visitor)
}
}
impl ser::Serialize for Interpolation {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(match *self {
Interpolation::Linear => "LINEAR",
Interpolation::Step => "STEP",
Interpolation::CubicSpline => "CUBICSPLINE",
})
}
}
impl<'de> de::Deserialize<'de> for Checked<Property> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<Property>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_PROPERTIES)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::Property::*;
use crate::validation::Checked::*;
Ok(match value {
"translation" => Valid(Translation),
"rotation" => Valid(Rotation),
"scale" => Valid(Scale),
"weights" => Valid(MorphTargetWeights),
_ => Invalid,
})
}
}
deserializer.deserialize_str(Visitor)
}
}
impl ser::Serialize for Property {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(match *self {
Property::Translation => "translation",
Property::Rotation => "rotation",
Property::Scale => "scale",
Property::MorphTargetWeights => "weights",
})
}
}

46
vendor/gltf-json/src/asset.rs vendored Normal file
View File

@@ -0,0 +1,46 @@
use crate::{extensions, Extras};
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
/// Metadata about the glTF asset.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Asset {
/// A copyright message suitable for display to credit the content creator.
#[serde(skip_serializing_if = "Option::is_none")]
pub copyright: Option<String>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::asset::Asset>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
/// Tool that generated this glTF model.
#[serde(skip_serializing_if = "Option::is_none")]
pub generator: Option<String>,
/// The minimum glTF version that this asset targets.
#[serde(rename = "minVersion")]
#[serde(skip_serializing_if = "Option::is_none")]
pub min_version: Option<String>,
/// The glTF version of this asset.
pub version: String,
}
impl Default for Asset {
fn default() -> Self {
Self {
copyright: None,
extensions: Default::default(),
extras: Default::default(),
generator: None,
min_version: None,
version: "2.0".to_string(),
}
}
}

165
vendor/gltf-json/src/buffer.rs vendored Normal file
View File

@@ -0,0 +1,165 @@
use crate::validation::{Checked, Error, USize64, Validate};
use crate::{extensions, Extras, Index, Path, Root};
use gltf_derive::Validate;
use serde::{de, ser};
use serde_derive::{Deserialize, Serialize};
use std::fmt;
/// Corresponds to `GL_ARRAY_BUFFER`.
pub const ARRAY_BUFFER: u32 = 34_962;
/// Corresponds to `GL_ELEMENT_ARRAY_BUFFER`.
pub const ELEMENT_ARRAY_BUFFER: u32 = 34_963;
/// The minimum byte stride.
pub const MIN_BYTE_STRIDE: usize = 4;
/// The maximum byte stride.
pub const MAX_BYTE_STRIDE: usize = 252;
/// All valid GPU buffer targets.
pub const VALID_TARGETS: &[u32] = &[ARRAY_BUFFER, ELEMENT_ARRAY_BUFFER];
/// Specifies the target a GPU buffer should be bound to.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Target {
/// Corresponds to `GL_ARRAY_BUFFER`.
ArrayBuffer = 1,
/// Corresponds to `GL_ELEMENT_ARRAY_BUFFER`.
ElementArrayBuffer,
}
impl ser::Serialize for Target {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
match *self {
Target::ArrayBuffer => serializer.serialize_u32(ARRAY_BUFFER),
Target::ElementArrayBuffer => serializer.serialize_u32(ELEMENT_ARRAY_BUFFER),
}
}
}
/// Distance between individual items in a buffer view, measured in bytes.
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct Stride(pub usize);
impl Validate for Stride {
fn validate<P, R>(&self, _root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
if self.0 < MIN_BYTE_STRIDE || self.0 > MAX_BYTE_STRIDE {
report(&path, Error::Invalid);
}
}
}
/// A buffer points to binary data representing geometry, animations, or skins.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Buffer {
/// The length of the buffer in bytes.
#[serde(default, rename = "byteLength")]
pub byte_length: USize64,
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// The uri of the buffer. Relative paths are relative to the .gltf file.
/// Instead of referencing an external file, the uri can also be a data-uri.
#[serde(skip_serializing_if = "Option::is_none")]
pub uri: Option<String>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::buffer::Buffer>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// A view into a buffer generally representing a subset of the buffer.
///
/// <https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#reference-bufferview>
///
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct View {
/// The parent `Buffer`.
pub buffer: Index<Buffer>,
/// The length of the `BufferView` in bytes.
#[serde(rename = "byteLength")]
pub byte_length: USize64,
/// Offset into the parent buffer in bytes.
#[serde(
default,
rename = "byteOffset",
skip_serializing_if = "Option::is_none"
)]
pub byte_offset: Option<USize64>,
/// The stride in bytes between vertex attributes or other interleavable data.
///
/// When zero, data is assumed to be tightly packed.
#[serde(rename = "byteStride")]
#[serde(skip_serializing_if = "Option::is_none")]
pub byte_stride: Option<Stride>,
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// Optional target the buffer should be bound to.
#[serde(skip_serializing_if = "Option::is_none")]
pub target: Option<Checked<Target>>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::buffer::View>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
impl<'de> de::Deserialize<'de> for Checked<Target> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<Target>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_TARGETS)
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::Target::*;
use crate::validation::Checked::*;
Ok(match value as u32 {
ARRAY_BUFFER => Valid(ArrayBuffer),
ELEMENT_ARRAY_BUFFER => Valid(ElementArrayBuffer),
_ => Invalid,
})
}
}
deserializer.deserialize_u64(Visitor)
}
}

163
vendor/gltf-json/src/camera.rs vendored Normal file
View File

@@ -0,0 +1,163 @@
use crate::validation::{Checked, Error};
use crate::{extensions, Extras, Path, Root};
use gltf_derive::Validate;
use serde::{de, ser};
use serde_derive::{Deserialize, Serialize};
use std::fmt;
/// All valid camera types.
pub const VALID_CAMERA_TYPES: &[&str] = &["perspective", "orthographic"];
/// Specifies the camera type.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Type {
/// A perspective projection.
Perspective = 1,
/// An orthographic projection.
Orthographic,
}
/// A camera's projection.
///
/// A node can reference a camera to apply a transform to place the camera in the
/// scene.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
#[gltf(validate_hook = "camera_validate_hook")]
pub struct Camera {
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// An orthographic camera containing properties to create an orthographic
/// projection matrix.
#[serde(skip_serializing_if = "Option::is_none")]
pub orthographic: Option<Orthographic>,
/// A perspective camera containing properties to create a perspective
/// projection matrix.
#[serde(skip_serializing_if = "Option::is_none")]
pub perspective: Option<Perspective>,
/// Specifies if the camera uses a perspective or orthographic projection.
#[serde(rename = "type")]
pub type_: Checked<Type>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::camera::Camera>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
fn camera_validate_hook<P, R>(camera: &Camera, _root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
if camera.orthographic.is_none() && camera.perspective.is_none() {
report(&path, Error::Missing);
}
}
/// Values for an orthographic camera.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Orthographic {
/// The horizontal magnification of the view.
pub xmag: f32,
/// The vertical magnification of the view.
pub ymag: f32,
/// The distance to the far clipping plane.
pub zfar: f32,
/// The distance to the near clipping plane.
pub znear: f32,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::camera::Orthographic>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// Values for a perspective camera.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Perspective {
/// Aspect ratio of the field of view.
#[serde(rename = "aspectRatio")]
#[serde(skip_serializing_if = "Option::is_none")]
pub aspect_ratio: Option<f32>,
/// The vertical field of view in radians.
pub yfov: f32,
/// The distance to the far clipping plane.
#[serde(skip_serializing_if = "Option::is_none")]
pub zfar: Option<f32>,
/// The distance to the near clipping plane.
pub znear: f32,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::camera::Perspective>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
impl<'de> de::Deserialize<'de> for Checked<Type> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<Type>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_CAMERA_TYPES)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::Type::*;
use crate::validation::Checked::*;
Ok(match value {
"perspective" => Valid(Perspective),
"orthographic" => Valid(Orthographic),
_ => Invalid,
})
}
}
deserializer.deserialize_str(Visitor)
}
}
impl ser::Serialize for Type {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
match *self {
Type::Perspective => serializer.serialize_str("perspective"),
Type::Orthographic => serializer.serialize_str("orthographic"),
}
}
}

View File

@@ -0,0 +1,30 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};
/// Contains data structures for sparse storage.
pub mod sparse {
use super::*;
/// Indices of those attributes that deviate from their initialization value.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Indices {}
/// Sparse storage of attributes that deviate from their initialization value.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Sparse {}
/// Array of size `count * number_of_components` storing the displaced
/// accessor attributes pointed by `accessor::sparse::Indices`.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Values {}
}
/// A typed view into a buffer view.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Accessor {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

View File

@@ -0,0 +1,24 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};
/// A keyframe animation.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Animation {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
/// Targets an animation's sampler at a node's property.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Channel {}
/// The index of the node and TRS property that an animation channel targets.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Target {}
/// Defines a keyframe graph but not its target.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Sampler {}

View File

@@ -0,0 +1,6 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
/// Metadata about the glTF asset.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Asset {}

View File

@@ -0,0 +1,20 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};
/// A buffer points to binary data representing geometry, animations, or skins.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Buffer {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
/// A view into a buffer generally representing a subset of the buffer.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct View {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

View File

@@ -0,0 +1,31 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};
/// A camera's projection.
///
/// A node can reference a camera to apply a transform to place the camera in the
/// scene.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Camera {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
/// Values for an orthographic camera.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Orthographic {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
/// Values for a perspective camera.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Perspective {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

View File

@@ -0,0 +1,12 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};
/// Image data used to create a texture.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Image {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

View File

@@ -0,0 +1,417 @@
#[allow(unused_imports)] // different features use different imports
use crate::{material::StrengthFactor, texture, validation::Validate, Extras};
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};
/// The material appearance of a primitive.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Material {
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
#[serde(
default,
rename = "KHR_materials_pbrSpecularGlossiness",
skip_serializing_if = "Option::is_none"
)]
pub pbr_specular_glossiness: Option<PbrSpecularGlossiness>,
#[cfg(feature = "KHR_materials_unlit")]
#[serde(
default,
rename = "KHR_materials_unlit",
skip_serializing_if = "Option::is_none"
)]
pub unlit: Option<Unlit>,
#[cfg(feature = "KHR_materials_transmission")]
#[serde(
default,
rename = "KHR_materials_transmission",
skip_serializing_if = "Option::is_none"
)]
pub transmission: Option<Transmission>,
#[cfg(feature = "KHR_materials_volume")]
#[serde(
default,
rename = "KHR_materials_volume",
skip_serializing_if = "Option::is_none"
)]
pub volume: Option<Volume>,
#[cfg(feature = "KHR_materials_specular")]
#[serde(
default,
rename = "KHR_materials_specular",
skip_serializing_if = "Option::is_none"
)]
pub specular: Option<Specular>,
#[cfg(feature = "KHR_materials_ior")]
#[serde(
default,
rename = "KHR_materials_ior",
skip_serializing_if = "Option::is_none"
)]
pub ior: Option<Ior>,
#[cfg(feature = "KHR_materials_emissive_strength")]
#[serde(
default,
rename = "KHR_materials_emissive_strength",
skip_serializing_if = "Option::is_none"
)]
pub emissive_strength: Option<EmissiveStrength>,
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
/// A set of parameter values that are used to define the metallic-roughness
/// material model from Physically-Based Rendering (PBR) methodology.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct PbrMetallicRoughness {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
/// A set of parameter values that are used to define the specular-glossiness
/// material model from Physically-Based Rendering (PBR) methodology.
///
/// This model supports more materials than metallic-roughness, at the cost of
/// increased memory use. When both are available, specular-glossiness should be
/// preferred.
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(default, rename_all = "camelCase")]
pub struct PbrSpecularGlossiness {
/// The material's diffuse factor.
///
/// The RGBA components of the reflected diffuse color of the
/// material. Metals have a diffuse value of `[0.0, 0.0, 0.0]`. The fourth
/// component (A) is the alpha coverage of the material. The `alphaMode`
/// property specifies how alpha is interpreted. The values are linear.
pub diffuse_factor: PbrDiffuseFactor,
/// The diffuse texture.
///
/// This texture contains RGB(A) components of the reflected diffuse color
/// of the material in sRGB color space. If the fourth component (A) is
/// present, it represents the alpha coverage of the material. Otherwise, an
/// alpha of 1.0 is assumed. The `alphaMode` property specifies how alpha is
/// interpreted. The stored texels must not be premultiplied.
#[serde(skip_serializing_if = "Option::is_none")]
pub diffuse_texture: Option<texture::Info>,
/// The material's specular factor.
pub specular_factor: PbrSpecularFactor,
/// The glossiness or smoothness of the material.
///
/// A value of 1.0 means the material has full glossiness or is perfectly
/// smooth. A value of 0.0 means the material has no glossiness or is
/// completely rough. This value is linear.
pub glossiness_factor: StrengthFactor,
/// The specular-glossiness texture.
///
/// A RGBA texture, containing the specular color of the material (RGB
/// components) and its glossiness (A component). The values are in sRGB
/// space.
#[serde(skip_serializing_if = "Option::is_none")]
pub specular_glossiness_texture: Option<texture::Info>,
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
/// Optional application specific data.
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// Defines the normal texture of a material.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct NormalTexture {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
/// Defines the occlusion texture of a material.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct OcclusionTexture {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
/// The diffuse factor of a material.
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct PbrDiffuseFactor(pub [f32; 4]);
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
impl Default for PbrDiffuseFactor {
fn default() -> Self {
PbrDiffuseFactor([1.0, 1.0, 1.0, 1.0])
}
}
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
impl Validate for PbrDiffuseFactor {}
/// The specular factor of a material.
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct PbrSpecularFactor(pub [f32; 3]);
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
impl Default for PbrSpecularFactor {
fn default() -> Self {
PbrSpecularFactor([1.0, 1.0, 1.0])
}
}
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
impl Validate for PbrSpecularFactor {}
/// Empty struct that should be present for primitives which should not be shaded with the PBR shading model.
#[cfg(feature = "KHR_materials_unlit")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Unlit {}
/// A number in the inclusive range [0.0, 1.0] with a default value of 0.0.
#[cfg(feature = "KHR_materials_transmission")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct TransmissionFactor(pub f32);
#[cfg(feature = "KHR_materials_transmission")]
impl Default for TransmissionFactor {
fn default() -> Self {
TransmissionFactor(0.0)
}
}
#[cfg(feature = "KHR_materials_transmission")]
impl Validate for TransmissionFactor {}
#[cfg(feature = "KHR_materials_transmission")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(default, rename_all = "camelCase")]
pub struct Transmission {
/// The base percentage of light that is transmitted through the surface.
///
/// The amount of light that is transmitted by the surface rather than diffusely re-emitted.
/// This is a percentage of all the light that penetrates a surface (i.e. isnt specularly reflected)
/// rather than a percentage of the total light that hits a surface.
/// A value of 1.0 means that 100% of the light that penetrates the surface is transmitted through.
pub transmission_factor: TransmissionFactor,
/// The transmission texture.
///
/// The R channel of this texture defines the amount of light that is transmitted by the surface
/// rather than diffusely re-emitted. A value of 1.0 in the red channel means that 100% of the light
/// that penetrates the surface (i.e. isnt specularly reflected) is transmitted through.
/// The value is linear and is multiplied by the transmissionFactor to determine the total transmission value.
#[serde(skip_serializing_if = "Option::is_none")]
pub transmission_texture: Option<texture::Info>,
/// Optional application specific data.
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// A positive number with default value of 1.5
#[cfg(feature = "KHR_materials_ior")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct IndexOfRefraction(pub f32);
#[cfg(feature = "KHR_materials_ior")]
impl Default for IndexOfRefraction {
fn default() -> Self {
IndexOfRefraction(1.5)
}
}
#[cfg(feature = "KHR_materials_ior")]
impl Validate for IndexOfRefraction {}
#[cfg(feature = "KHR_materials_ior")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(default, rename_all = "camelCase")]
pub struct Ior {
/// The index of refraction.
///
/// Typical values for the index of refraction range from 1 to 2.
/// In rare cases values greater than 2 are possible.
/// For example, the ior of water is 1.33, and diamond is 2.42
pub ior: IndexOfRefraction,
/// Optional application specific data.
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// A positive number with 1.0 as the default value.
#[cfg(feature = "KHR_materials_emissive_strength")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct EmissiveStrengthFactor(pub f32);
#[cfg(feature = "KHR_materials_emissive_strength")]
impl Default for EmissiveStrengthFactor {
fn default() -> Self {
EmissiveStrengthFactor(1.0)
}
}
#[cfg(feature = "KHR_materials_emissive_strength")]
impl Validate for EmissiveStrengthFactor {}
#[cfg(feature = "KHR_materials_emissive_strength")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(default, rename_all = "camelCase")]
pub struct EmissiveStrength {
/// The factor by which to scale the emissive factor or emissive texture.
pub emissive_strength: EmissiveStrengthFactor,
}
/// A number in the inclusive range [0.0, +inf] with a default value of 0.0.
#[cfg(feature = "KHR_materials_volume")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct ThicknessFactor(pub f32);
#[cfg(feature = "KHR_materials_volume")]
impl Default for ThicknessFactor {
fn default() -> Self {
ThicknessFactor(0.0)
}
}
#[cfg(feature = "KHR_materials_volume")]
impl Validate for ThicknessFactor {}
/// A number in the inclusive range [0.0, +inf] with a default value of +inf.
#[cfg(feature = "KHR_materials_volume")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct AttenuationDistance(pub f32);
#[cfg(feature = "KHR_materials_volume")]
impl Default for AttenuationDistance {
fn default() -> Self {
AttenuationDistance(f32::INFINITY)
}
}
#[cfg(feature = "KHR_materials_volume")]
impl Validate for AttenuationDistance {}
/// A colour in the inclusive range [[0.0; 3], [1.0; 3]] with a default value of [1.0; 3].
#[cfg(feature = "KHR_materials_volume")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct AttenuationColor(pub [f32; 3]);
#[cfg(feature = "KHR_materials_volume")]
impl Default for AttenuationColor {
fn default() -> Self {
AttenuationColor([1.0, 1.0, 1.0])
}
}
#[cfg(feature = "KHR_materials_volume")]
impl Validate for AttenuationColor {}
#[cfg(feature = "KHR_materials_volume")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(default, rename_all = "camelCase")]
pub struct Volume {
/// The thickness of the volume beneath the surface. The value is
/// given in the coordinate space of the mesh. If the value is 0
/// the material is thin-walled. Otherwise the material is a
/// volume boundary. The `doubleSided` property has no effect on
/// volume boundaries. Range is [0, +inf).
pub thickness_factor: ThicknessFactor,
/// A texture that defines the thickness, stored in the G channel.
/// This will be multiplied by `thickness_factor`. Range is [0, 1].
#[serde(skip_serializing_if = "Option::is_none")]
pub thickness_texture: Option<texture::Info>,
/// Density of the medium given as the average distance that light
/// travels in the medium before interacting with a particle. The
/// value is given in world space. Range is (0, +inf).
pub attenuation_distance: AttenuationDistance,
/// The color that white light turns into due to absorption when
/// reaching the attenuation distance.
pub attenuation_color: AttenuationColor,
/// Optional application specific data.
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// A number in the inclusive range [0.0, +inf] with a default value of 1.0.
#[cfg(feature = "KHR_materials_specular")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct SpecularFactor(pub f32);
#[cfg(feature = "KHR_materials_specular")]
impl Default for SpecularFactor {
fn default() -> Self {
SpecularFactor(1.0)
}
}
#[cfg(feature = "KHR_materials_specular")]
impl Validate for SpecularFactor {}
/// A colour in the inclusive range [[0.0; 3], [1.0; 3]] with a default value of [1.0; 3].
#[cfg(feature = "KHR_materials_specular")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct SpecularColorFactor(pub [f32; 3]);
#[cfg(feature = "KHR_materials_specular")]
impl Default for SpecularColorFactor {
fn default() -> Self {
SpecularColorFactor([1.0, 1.0, 1.0])
}
}
#[cfg(feature = "KHR_materials_specular")]
impl Validate for SpecularColorFactor {}
#[cfg(feature = "KHR_materials_specular")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(default, rename_all = "camelCase")]
pub struct Specular {
/// The strength of the specular reflection.
pub specular_factor: SpecularFactor,
/// A texture that defines the strength of the specular reflection,
/// stored in the alpha (`A`) channel. This will be multiplied by
/// `specular_factor`.
#[serde(skip_serializing_if = "Option::is_none")]
pub specular_texture: Option<texture::Info>,
/// The F0 color of the specular reflection (linear RGB).
pub specular_color_factor: SpecularColorFactor,
/// A texture that defines the F0 color of the specular reflection,
/// stored in the `RGB` channels and encoded in sRGB. This texture
/// will be multiplied by `specular_color_factor`.
#[serde(skip_serializing_if = "Option::is_none")]
pub specular_color_texture: Option<texture::Info>,
/// Optional application specific data.
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}

43
vendor/gltf-json/src/extensions/mesh.rs vendored Normal file
View File

@@ -0,0 +1,43 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};
/// A set of primitives to be rendered.
///
/// A node can contain one or more meshes and its transform places the meshes in
/// the scene.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Mesh {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
/// Geometry to be rendered with the given material.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Primitive {
#[cfg(feature = "KHR_materials_variants")]
#[serde(
default,
rename = "KHR_materials_variants",
skip_serializing_if = "Option::is_none"
)]
pub khr_materials_variants: Option<KhrMaterialsVariants>,
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
#[cfg(feature = "KHR_materials_variants")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct KhrMaterialsVariants {
pub mappings: Vec<Mapping>,
}
#[cfg(feature = "KHR_materials_variants")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Mapping {
pub material: u32,
pub variants: Vec<u32>,
}

73
vendor/gltf-json/src/extensions/mod.rs vendored Normal file
View File

@@ -0,0 +1,73 @@
/// Contains `Accessor` and other related data structures.
pub mod accessor;
/// Contains `Animation` and other related data structures.
pub mod animation;
/// Contains `Asset` metadata.
pub mod asset;
/// Contains `Buffer`, `View`, and other related data structures.
pub mod buffer;
/// Contains `Camera` and other related data structures.
pub mod camera;
/// Contains `Image` and other related data structures.
pub mod image;
/// Contains `Material` and other related data structures.
pub mod material;
/// Contains `Mesh` and other related data structures.
pub mod mesh;
/// Contains `Root`.
pub mod root;
/// Contains `Scene`, `Node`, and other related data structures.
pub mod scene;
/// Contains `Skin` and other related data structures.
pub mod skin;
/// Contains `Texture`, `Sampler`, and other related data structures.
pub mod texture;
pub use self::root::Root;
/// Names of glTF 2.0 extensions enabled by the user.
pub const ENABLED_EXTENSIONS: &[&str] = &[
#[cfg(feature = "KHR_lights_punctual")]
"KHR_lights_punctual",
#[cfg(feature = "KHR_materials_pbrSpecularGlossiness")]
"KHR_materials_pbrSpecularGlossiness",
#[cfg(feature = "KHR_materials_unlit")]
"KHR_materials_unlit",
#[cfg(feature = "KHR_texture_transform")]
"KHR_texture_transform",
#[cfg(feature = "KHR_materials_transmission")]
"KHR_materials_transmission",
#[cfg(feature = "KHR_materials_ior")]
"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.
pub const SUPPORTED_EXTENSIONS: &[&str] = &[
"KHR_lights_punctual",
"KHR_materials_pbrSpecularGlossiness",
"KHR_materials_unlit",
"KHR_texture_transform",
"KHR_materials_transmission",
"KHR_materials_ior",
"KHR_materials_emissive_strength",
];

118
vendor/gltf-json/src/extensions/root.rs vendored Normal file
View File

@@ -0,0 +1,118 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};
/// The root object of a glTF 2.0 asset.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Root {
#[cfg(feature = "KHR_lights_punctual")]
#[serde(
default,
rename = "KHR_lights_punctual",
skip_serializing_if = "Option::is_none"
)]
pub khr_lights_punctual: Option<KhrLightsPunctual>,
#[cfg(feature = "KHR_materials_variants")]
#[serde(
default,
rename = "KHR_materials_variants",
skip_serializing_if = "Option::is_none"
)]
pub khr_materials_variants: Option<KhrMaterialsVariants>,
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
#[cfg(feature = "KHR_lights_punctual")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct KhrLightsPunctual {
/// Lights at this node.
pub lights: Vec<crate::extensions::scene::khr_lights_punctual::Light>,
}
#[cfg(feature = "KHR_lights_punctual")]
impl crate::root::Get<crate::extensions::scene::khr_lights_punctual::Light> for crate::Root {
fn get(
&self,
id: crate::Index<crate::extensions::scene::khr_lights_punctual::Light>,
) -> Option<&crate::extensions::scene::khr_lights_punctual::Light> {
if let Some(extensions) = self.extensions.as_ref() {
if let Some(khr_lights_punctual) = extensions.khr_lights_punctual.as_ref() {
khr_lights_punctual.lights.get(id.value())
} else {
None
}
} else {
None
}
}
}
#[cfg(feature = "KHR_lights_punctual")]
impl AsRef<[crate::extensions::scene::khr_lights_punctual::Light]> for crate::Root {
fn as_ref(&self) -> &[crate::extensions::scene::khr_lights_punctual::Light] {
self.extensions
.as_ref()
.and_then(|extensions| extensions.khr_lights_punctual.as_ref())
.map(|khr_lights_punctual| khr_lights_punctual.lights.as_slice())
.unwrap_or(&[])
}
}
#[cfg(feature = "KHR_lights_punctual")]
impl AsMut<Vec<crate::extensions::scene::khr_lights_punctual::Light>> for crate::Root {
fn as_mut(&mut self) -> &mut Vec<crate::extensions::scene::khr_lights_punctual::Light> {
&mut self
.extensions
.get_or_insert_with(Default::default)
.khr_lights_punctual
.get_or_insert_with(Default::default)
.lights
}
}
#[cfg(feature = "KHR_materials_variants")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct KhrMaterialsVariants {
pub variants: Vec<crate::extensions::scene::khr_materials_variants::Variant>,
}
#[cfg(feature = "KHR_materials_variants")]
impl crate::root::Get<crate::extensions::scene::khr_materials_variants::Variant> for crate::Root {
fn get(
&self,
id: crate::Index<crate::extensions::scene::khr_materials_variants::Variant>,
) -> Option<&crate::extensions::scene::khr_materials_variants::Variant> {
self.extensions
.as_ref()?
.khr_materials_variants
.as_ref()?
.variants
.get(id.value())
}
}
#[cfg(feature = "KHR_materials_variants")]
impl AsRef<[crate::extensions::scene::khr_materials_variants::Variant]> for crate::Root {
fn as_ref(&self) -> &[crate::extensions::scene::khr_materials_variants::Variant] {
self.extensions
.as_ref()
.and_then(|extensions| extensions.khr_materials_variants.as_ref())
.map(|khr_materials_variants| khr_materials_variants.variants.as_slice())
.unwrap_or(&[])
}
}
#[cfg(feature = "KHR_materials_variants")]
impl AsMut<Vec<crate::extensions::scene::khr_materials_variants::Variant>> for crate::Root {
fn as_mut(&mut self) -> &mut Vec<crate::extensions::scene::khr_materials_variants::Variant> {
&mut self
.extensions
.get_or_insert_with(Default::default)
.khr_materials_variants
.get_or_insert_with(Default::default)
.variants
}
}

230
vendor/gltf-json/src/extensions/scene.rs vendored Normal file
View File

@@ -0,0 +1,230 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};
/// A node in the node hierarchy. When the node contains `skin`, all
/// `mesh.primitives` must contain `JOINTS_0` and `WEIGHTS_0` attributes.
/// A node can have either a `matrix` or any combination of
/// `translation`/`rotation`/`scale` (TRS) properties. TRS properties are converted
/// to matrices and postmultiplied in the `T * R * S` order to compose the
/// transformation matrix; first the scale is applied to the vertices, then the
/// rotation, and then the translation. If none are provided, the transform is the
/// identity. When a node is targeted for animation (referenced by an
/// animation.channel.target), only TRS properties may be present; `matrix` will not
/// be present.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Node {
#[cfg(feature = "KHR_lights_punctual")]
#[serde(
default,
rename = "KHR_lights_punctual",
skip_serializing_if = "Option::is_none"
)]
pub khr_lights_punctual: Option<khr_lights_punctual::KhrLightsPunctual>,
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
#[cfg(feature = "KHR_lights_punctual")]
pub mod khr_lights_punctual {
use crate::validation::{Checked, Error};
use crate::{Extras, Index, Path, Root};
use gltf_derive::Validate;
use serde::{de, ser};
use serde_derive::{Deserialize, Serialize};
use std::fmt;
/// All valid light types.
pub const VALID_TYPES: &[&str] = &["directional", "point", "spot"];
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct KhrLightsPunctual {
pub light: Index<Light>,
}
/// Specifies the light type.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Type {
/// Directional lights act as though they are infinitely far away and emit light in
/// the direction of the local -z axis. This light type inherits the orientation of
/// the node that it belongs to; position and scale are ignored except for their
/// effect on the inherited node orientation. Because it is at an infinite distance,
/// the light is not attenuated. Its intensity is defined in lumens per metre squared,
/// or lux (lm/m^2).
Directional = 1,
/// Point lights emit light in all directions from their position in space; rotation
/// and scale are ignored except for their effect on the inherited node position. The
/// brightness of the light attenuates in a physically correct manner as distance
/// increases from the light's position (i.e. brightness goes like the inverse square
/// of the distance). Point light intensity is defined in candela, which is lumens per
/// square radian (lm/sr)."
Point,
/// Spot lights emit light in a cone in the direction of the local -z axis. The angle
/// and falloff of the cone is defined using two numbers, the innerConeAngle and outer
/// ConeAngle. As with point lights, the brightness also attenuates in a physically
/// correct manner as distance increases from the light's position (i.e. brightness
/// goes like the inverse square of the distance). Spot light intensity refers to the
/// brightness inside the innerConeAngle (and at the location of the light) and is
/// defined in candela, which is lumens per square radian (lm/sr). Engines that don't
/// support two angles for spotlights should use outerConeAngle as the spotlight angle
/// (leaving innerConeAngle to implicitly be 0).
Spot,
}
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
#[gltf(validate_hook = "light_validate_hook")]
pub struct Light {
/// Color of the light source.
#[serde(default = "color_default")]
pub color: [f32; 3],
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<std::boxed::Box<serde_json::value::RawValue>>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
/// Intensity of the light source. `point` and `spot` lights use luminous intensity
/// in candela (lm/sr) while `directional` lights use illuminance in lux (lm/m^2).
#[serde(default = "intensity_default")]
pub intensity: f32,
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// A distance cutoff at which the light's intensity may be considered to have reached
/// zero.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub range: Option<f32>,
/// Spot light parameters.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub spot: Option<Spot>,
/// Specifies the light type.
#[serde(rename = "type")]
pub type_: Checked<Type>,
}
fn light_validate_hook<P, R>(light: &Light, _root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
if let Checked::Valid(ty) = light.type_.as_ref() {
if *ty == Type::Spot && light.spot.is_none() {
report(&|| path().field("spot"), Error::Missing);
}
}
}
fn color_default() -> [f32; 3] {
[1.0, 1.0, 1.0]
}
fn intensity_default() -> f32 {
1.0
}
/// Spot light parameters.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(rename_all = "camelCase")]
pub struct Spot {
/// Angle in radians from centre of spotlight where falloff begins.
#[serde(default)]
pub inner_cone_angle: f32,
/// Angle in radians from centre of spotlight where falloff ends.
#[serde(default = "outer_cone_angle_default")]
pub outer_cone_angle: f32,
}
fn outer_cone_angle_default() -> f32 {
std::f32::consts::FRAC_PI_4
}
impl<'de> de::Deserialize<'de> for Checked<Type> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<Type>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_TYPES)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::Type::*;
use crate::validation::Checked::*;
Ok(match value {
"directional" => Valid(Directional),
"point" => Valid(Point),
"spot" => Valid(Spot),
_ => Invalid,
})
}
}
deserializer.deserialize_str(Visitor)
}
}
impl ser::Serialize for Type {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(match *self {
Type::Directional => "directional",
Type::Point => "point",
Type::Spot => "spot",
})
}
}
}
#[cfg(feature = "KHR_materials_variants")]
pub mod khr_materials_variants {
use crate::validation::{Error, Validate};
use crate::{Path, Root};
use serde_derive::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Variant {
pub name: String,
}
impl Validate for Variant {
fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
self.name.validate(root, || path().field("name"), report);
}
}
}
/// The root `Node`s of a scene.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Scene {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

12
vendor/gltf-json/src/extensions/skin.rs vendored Normal file
View File

@@ -0,0 +1,12 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};
/// Joints and matrices defining a skin.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Skin {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}

View File

@@ -0,0 +1,114 @@
#[cfg(feature = "KHR_texture_transform")]
use crate::{extras::Extras, validation::Validate};
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
#[cfg(feature = "extensions")]
use serde_json::{Map, Value};
/// Texture sampler properties for filtering and wrapping modes.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Sampler {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
/// A texture and its sampler.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Texture {
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
/// Reference to a `Texture`.
pub struct Info {
#[cfg(feature = "KHR_texture_transform")]
#[serde(
default,
rename = "KHR_texture_transform",
skip_serializing_if = "Option::is_none"
)]
pub texture_transform: Option<TextureTransform>,
#[cfg(feature = "extensions")]
#[serde(default, flatten)]
pub others: Map<String, Value>,
}
/// 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")]
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(default, rename_all = "camelCase")]
pub struct TextureTransform {
// The offset of the UV coordinate origin as a factor of the texture dimensions.
pub offset: TextureTransformOffset,
/// Rotate the UVs by this many radians counter-clockwise around the origin.
/// This is equivalent to a similar rotation of the image clockwise.
pub rotation: TextureTransformRotation,
/// The scale factor applied to the components of the UV coordinates.
pub scale: TextureTransformScale,
/// Overrides the textureInfo texCoord value if supplied, and if this extension is supported.
pub tex_coord: Option<u32>,
/// Optional application specific data.
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// The offset of the UV coordinate origin as a factor of the texture dimensions.
#[cfg(feature = "KHR_texture_transform")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct TextureTransformOffset(pub [f32; 2]);
#[cfg(feature = "KHR_texture_transform")]
impl Default for TextureTransformOffset {
fn default() -> Self {
Self([0.0, 0.0])
}
}
#[cfg(feature = "KHR_texture_transform")]
impl Validate for TextureTransformOffset {}
/// Rotate the UVs by this many radians counter-clockwise around the origin.
/// This is equivalent to a similar rotation of the image clockwise.
#[cfg(feature = "KHR_texture_transform")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct TextureTransformRotation(pub f32);
#[cfg(feature = "KHR_texture_transform")]
impl Default for TextureTransformRotation {
fn default() -> Self {
Self(0.0)
}
}
#[cfg(feature = "KHR_texture_transform")]
impl Validate for TextureTransformRotation {}
/// The scale factor applied to the components of the UV coordinates.
#[cfg(feature = "KHR_texture_transform")]
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct TextureTransformScale(pub [f32; 2]);
#[cfg(feature = "KHR_texture_transform")]
impl Default for TextureTransformScale {
fn default() -> Self {
Self([1.0, 1.0])
}
}
#[cfg(feature = "KHR_texture_transform")]
impl Validate for TextureTransformScale {}

33
vendor/gltf-json/src/extras.rs vendored Normal file
View File

@@ -0,0 +1,33 @@
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
use std::fmt;
#[cfg(feature = "extras")]
pub use serde_json::value::RawValue;
/// Data type of the `extras` attribute on all glTF objects.
#[cfg(feature = "extras")]
pub type Extras = Option<::std::boxed::Box<RawValue>>;
/// Data type of the `extras` attribute on all glTF objects.
#[cfg(not(feature = "extras"))]
pub type Extras = Void;
/// Type representing no user-defined data.
#[derive(Clone, Default, Serialize, Deserialize, Validate)]
pub struct Void {
#[serde(default, skip_serializing)]
_allow_unknown_fields: (),
}
impl fmt::Debug for Void {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{{}}")
}
}
impl fmt::Display for Void {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{{}}")
}
}

49
vendor/gltf-json/src/image.rs vendored Normal file
View File

@@ -0,0 +1,49 @@
use crate::validation::Validate;
use crate::{buffer, extensions, Extras, Index};
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
/// All valid MIME types.
pub const VALID_MIME_TYPES: &[&str] = &["image/jpeg", "image/png"];
/// Image data used to create a texture.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Image {
/// The index of the buffer view that contains the image. Use this instead of
/// the image's uri property.
#[serde(rename = "bufferView")]
#[serde(skip_serializing_if = "Option::is_none")]
pub buffer_view: Option<Index<buffer::View>>,
/// The image's MIME type.
#[serde(rename = "mimeType")]
#[serde(skip_serializing_if = "Option::is_none")]
pub mime_type: Option<MimeType>,
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// The uri of the image. Relative paths are relative to the .gltf file.
/// Instead of referencing an external file, the uri can also be a data-uri.
/// The image format must be jpg or png.
#[serde(skip_serializing_if = "Option::is_none")]
pub uri: Option<String>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::image::Image>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// An image MIME type.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MimeType(pub String);
impl Validate for MimeType {}

107
vendor/gltf-json/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,107 @@
/// Contains `Accessor` and other related data structures.
pub mod accessor;
/// Contains `Animation` and other related data structures.
pub mod animation;
/// Contains `Asset` metadata.
pub mod asset;
/// Contains `Buffer`, `View`, and other related data structures.
pub mod buffer;
/// Contains `Camera` and other related data structures.
pub mod camera;
/// Contains extension specific data structures and the names of all
/// 2.0 extensions supported by the library.
pub mod extensions;
/// Contains `Extras`.
pub mod extras;
/// Contains `Image` and other related data structures.
pub mod image;
/// Contains `Material` and other related data structures.
pub mod material;
/// Contains `Mesh` and other related data structures.
pub mod mesh;
/// Contains `Path`.
pub mod path;
/// Contains `Root`.
pub mod root;
/// Contains `Scene`, `Node`, and other related data structures.
pub mod scene;
/// Contains `Skin` and other related data structures.
pub mod skin;
/// Contains `Texture`, `Sampler`, and other related data structures.
pub mod texture;
/// Contains functions that validate glTF JSON data against the specification.
pub mod validation;
#[doc(inline)]
pub use accessor::Accessor;
#[doc(inline)]
pub use animation::Animation;
#[doc(inline)]
pub use asset::Asset;
#[doc(inline)]
pub use buffer::Buffer;
#[doc(inline)]
pub use camera::Camera;
#[doc(inline)]
pub use image::Image;
#[doc(inline)]
pub use material::Material;
#[doc(inline)]
pub use mesh::Mesh;
#[doc(inline)]
pub use scene::Node;
#[doc(inline)]
pub use scene::Scene;
#[doc(inline)]
pub use skin::Skin;
#[doc(inline)]
pub use texture::Texture;
#[doc(inline)]
pub use self::extras::Extras;
#[doc(inline)]
pub use self::path::Path;
#[doc(inline)]
pub use self::root::Index;
#[doc(inline)]
pub use self::root::Root;
#[doc(inline)]
pub use serde_json::Error;
#[doc(inline)]
pub use serde_json::Value;
/// Re-exports of `serde_json` deserialization functions.
///
/// This module re-exports the generic serde deserialization functions
/// so that one can deserialize data structures other than `Root` without
/// being bound to a specific version of `serde_json`.
pub mod deserialize {
pub use serde_json::{from_reader, from_slice, from_str, from_value};
}
/// Re-exports of `serde_json` serialization functions.
///
/// This module re-exports the generic serde serialization functions
/// so that one can serialize data structures other than `Root` without
/// being bound to a specific version of `serde_json`.
pub mod serialize {
pub use serde_json::{
to_string, to_string_pretty, to_value, to_vec, to_vec_pretty, to_writer, to_writer_pretty,
};
}

311
vendor/gltf-json/src/material.rs vendored Normal file
View File

@@ -0,0 +1,311 @@
use crate::validation::{Checked, Validate};
use crate::{extensions, texture, Extras, Index};
use gltf_derive::Validate;
use serde::{de, ser};
use serde_derive::{Deserialize, Serialize};
use std::fmt;
/// All valid alpha modes.
pub const VALID_ALPHA_MODES: &[&str] = &["OPAQUE", "MASK", "BLEND"];
/// The alpha rendering mode of a material.
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
pub enum AlphaMode {
/// The alpha value is ignored and the rendered output is fully opaque.
Opaque = 1,
/// The rendered output is either fully opaque or fully transparent depending on
/// the alpha value and the specified alpha cutoff value.
Mask,
/// The alpha value is used, to determine the transparency of the rendered output.
/// The alpha cutoff value is ignored.
Blend,
}
impl ser::Serialize for AlphaMode {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
match *self {
AlphaMode::Opaque => serializer.serialize_str("OPAQUE"),
AlphaMode::Mask => serializer.serialize_str("MASK"),
AlphaMode::Blend => serializer.serialize_str("BLEND"),
}
}
}
/// The material appearance of a primitive.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(default)]
pub struct Material {
/// The alpha cutoff value of the material.
#[serde(rename = "alphaCutoff")]
//#[cfg_attr(feature = "alphaCutoff", serde(skip_serializing_if = "Option::is_none"))]
#[serde(skip_serializing_if = "Option::is_none")]
pub alpha_cutoff: Option<AlphaCutoff>,
/// The alpha rendering mode of the material.
///
/// The material's alpha rendering mode enumeration specifying the
/// interpretation of the alpha value of the main factor and texture.
///
/// * In `Opaque` mode (default) the alpha value is ignored and the rendered
/// output is fully opaque.
///
/// * In `Mask` mode, the rendered output is either fully opaque or fully
/// transparent depending on the alpha value and the specified alpha cutoff
/// value.
///
/// * In `Blend` mode, the alpha value is used to composite the source and
/// destination areas and the rendered output is combined with the
/// background using the normal painting operation (i.e. the Porter and
/// Duff over operator).
#[serde(rename = "alphaMode")]
pub alpha_mode: Checked<AlphaMode>,
/// Specifies whether the material is double-sided.
///
/// * When this value is false, back-face culling is enabled.
///
/// * When this value is true, back-face culling is disabled and double sided
/// lighting is enabled.
///
/// The back-face must have its normals reversed before the lighting
/// equation is evaluated.
#[serde(rename = "doubleSided")]
pub double_sided: bool,
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// A set of parameter values that are used to define the metallic-roughness
/// material model from Physically-Based Rendering (PBR) methodology. When not
/// specified, all the default values of `pbrMetallicRoughness` apply.
#[serde(default, rename = "pbrMetallicRoughness")]
pub pbr_metallic_roughness: PbrMetallicRoughness,
/// A tangent space normal map. The texture contains RGB components in linear
/// space. Each texel represents the XYZ components of a normal vector in
/// tangent space. Red [0 to 255] maps to X [-1 to 1]. Green [0 to 255] maps to
/// Y [-1 to 1]. Blue [128 to 255] maps to Z [1/255 to 1]. The normal vectors
/// use OpenGL conventions where +X is right and +Y is up. +Z points toward the
/// viewer.
#[serde(rename = "normalTexture")]
#[serde(skip_serializing_if = "Option::is_none")]
pub normal_texture: Option<NormalTexture>,
/// The occlusion map texture. The occlusion values are sampled from the R
/// channel. Higher values indicate areas that should receive full indirect
/// lighting and lower values indicate no indirect lighting. These values are
/// linear. If other channels are present (GBA), they are ignored for occlusion
/// calculations.
#[serde(rename = "occlusionTexture")]
#[serde(skip_serializing_if = "Option::is_none")]
pub occlusion_texture: Option<OcclusionTexture>,
/// The emissive map controls the color and intensity of the light being emitted
/// by the material. This texture contains RGB components in sRGB color space.
/// If a fourth component (A) is present, it is ignored.
#[serde(rename = "emissiveTexture")]
#[serde(skip_serializing_if = "Option::is_none")]
pub emissive_texture: Option<texture::Info>,
/// The emissive color of the material.
#[serde(rename = "emissiveFactor")]
pub emissive_factor: EmissiveFactor,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::material::Material>,
/// Optional application specific data.
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// A set of parameter values that are used to define the metallic-roughness
/// material model from Physically-Based Rendering (PBR) methodology.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(default)]
pub struct PbrMetallicRoughness {
/// The material's base color factor.
#[serde(rename = "baseColorFactor")]
pub base_color_factor: PbrBaseColorFactor,
/// The base color texture.
#[serde(rename = "baseColorTexture")]
#[serde(skip_serializing_if = "Option::is_none")]
pub base_color_texture: Option<texture::Info>,
/// The metalness of the material.
#[serde(rename = "metallicFactor")]
pub metallic_factor: StrengthFactor,
/// The roughness of the material.
///
/// * A value of 1.0 means the material is completely rough.
/// * A value of 0.0 means the material is completely smooth.
#[serde(rename = "roughnessFactor")]
pub roughness_factor: StrengthFactor,
/// The metallic-roughness texture.
///
/// This texture has two components:
///
/// The metalness values are sampled from the B channel.
/// The roughness values are sampled from the G channel.
/// These values are linear. If other channels are present (R or A),
/// they are ignored for metallic-roughness calculations.
#[serde(rename = "metallicRoughnessTexture")]
#[serde(skip_serializing_if = "Option::is_none")]
pub metallic_roughness_texture: Option<texture::Info>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::material::PbrMetallicRoughness>,
/// Optional application specific data.
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// Defines the normal texture of a material.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct NormalTexture {
/// The index of the texture.
pub index: Index<texture::Texture>,
/// The scalar multiplier applied to each normal vector of the texture.
///
/// This value is ignored if normalTexture is not specified.
#[serde(default = "material_normal_texture_scale_default")]
pub scale: f32,
/// The set index of the texture's `TEXCOORD` attribute.
#[serde(default, rename = "texCoord")]
pub tex_coord: u32,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::material::NormalTexture>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
fn material_normal_texture_scale_default() -> f32 {
1.0
}
/// Defines the occlusion texture of a material.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct OcclusionTexture {
/// The index of the texture.
pub index: Index<texture::Texture>,
/// The scalar multiplier controlling the amount of occlusion applied.
#[serde(default)]
pub strength: StrengthFactor,
/// The set index of the texture's `TEXCOORD` attribute.
#[serde(default, rename = "texCoord")]
pub tex_coord: u32,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::material::OcclusionTexture>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
/// The alpha cutoff value of a material.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct AlphaCutoff(pub f32);
/// The emissive color of a material.
#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
pub struct EmissiveFactor(pub [f32; 3]);
/// The base color factor of a material.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct PbrBaseColorFactor(pub [f32; 4]);
/// A number in the inclusive range [0.0, 1.0] with a default value of 1.0.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct StrengthFactor(pub f32);
impl Default for AlphaCutoff {
fn default() -> Self {
AlphaCutoff(0.5)
}
}
impl Validate for AlphaCutoff {}
impl Default for AlphaMode {
fn default() -> Self {
AlphaMode::Opaque
}
}
impl<'de> de::Deserialize<'de> for Checked<AlphaMode> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<AlphaMode>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_ALPHA_MODES)
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::AlphaMode::*;
use crate::validation::Checked::*;
Ok(match value {
"OPAQUE" => Valid(Opaque),
"MASK" => Valid(Mask),
"BLEND" => Valid(Blend),
_ => Invalid,
})
}
}
deserializer.deserialize_str(Visitor)
}
}
impl Validate for EmissiveFactor {}
impl Default for PbrBaseColorFactor {
fn default() -> Self {
PbrBaseColorFactor([1.0, 1.0, 1.0, 1.0])
}
}
impl Validate for PbrBaseColorFactor {}
impl Default for StrengthFactor {
fn default() -> Self {
StrengthFactor(1.0)
}
}
impl Validate for StrengthFactor {}

377
vendor/gltf-json/src/mesh.rs vendored Normal file
View File

@@ -0,0 +1,377 @@
use crate::validation::{Checked, Error};
use crate::{accessor, extensions, material, Extras, Index};
use gltf_derive::Validate;
use serde::{de, ser};
use serde_derive::{Deserialize, Serialize};
use serde_json::from_value;
use std::collections::BTreeMap;
use std::fmt;
/// Corresponds to `GL_POINTS`.
pub const POINTS: u32 = 0;
/// Corresponds to `GL_LINES`.
pub const LINES: u32 = 1;
/// Corresponds to `GL_LINE_LOOP`.
pub const LINE_LOOP: u32 = 2;
/// Corresponds to `GL_LINE_STRIP`.
pub const LINE_STRIP: u32 = 3;
/// Corresponds to `GL_TRIANGLES`.
pub const TRIANGLES: u32 = 4;
/// Corresponds to `GL_TRIANGLE_STRIP`.
pub const TRIANGLE_STRIP: u32 = 5;
/// Corresponds to `GL_TRIANGLE_FAN`.
pub const TRIANGLE_FAN: u32 = 6;
/// All valid primitive rendering modes.
pub const VALID_MODES: &[u32] = &[
POINTS,
LINES,
LINE_LOOP,
LINE_STRIP,
TRIANGLES,
TRIANGLE_STRIP,
TRIANGLE_FAN,
];
/// All valid semantic names for Morph targets.
pub const VALID_MORPH_TARGETS: &[&str] = &["POSITION", "NORMAL", "TANGENT"];
/// The type of primitives to render.
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
pub enum Mode {
/// Corresponds to `GL_POINTS`.
Points = 1,
/// Corresponds to `GL_LINES`.
Lines,
/// Corresponds to `GL_LINE_LOOP`.
LineLoop,
/// Corresponds to `GL_LINE_STRIP`.
LineStrip,
/// Corresponds to `GL_TRIANGLES`.
Triangles,
/// Corresponds to `GL_TRIANGLE_STRIP`.
TriangleStrip,
/// Corresponds to `GL_TRIANGLE_FAN`.
TriangleFan,
}
/// A set of primitives to be rendered.
///
/// A node can contain one or more meshes and its transform places the meshes in
/// the scene.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Mesh {
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::mesh::Mesh>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// Defines the geometry to be renderered with a material.
pub primitives: Vec<Primitive>,
/// Defines the weights to be applied to the morph targets.
#[serde(skip_serializing_if = "Option::is_none")]
pub weights: Option<Vec<f32>>,
}
/// Geometry to be rendered with the given material.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
#[gltf(validate_hook = "primitive_validate_hook")]
pub struct Primitive {
/// Maps attribute semantic names to the `Accessor`s containing the
/// corresponding attribute data.
pub attributes: BTreeMap<Checked<Semantic>, Index<accessor::Accessor>>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::mesh::Primitive>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
/// The index of the accessor that contains the indices.
#[serde(skip_serializing_if = "Option::is_none")]
pub indices: Option<Index<accessor::Accessor>>,
/// The index of the material to apply to this primitive when rendering
#[serde(skip_serializing_if = "Option::is_none")]
pub material: Option<Index<material::Material>>,
/// The type of primitives to render.
#[serde(default, skip_serializing_if = "is_primitive_mode_default")]
pub mode: Checked<Mode>,
/// An array of Morph Targets, each Morph Target is a dictionary mapping
/// attributes (only `POSITION`, `NORMAL`, and `TANGENT` supported) to their
/// deviations in the Morph Target.
#[serde(skip_serializing_if = "Option::is_none")]
pub targets: Option<Vec<MorphTarget>>,
}
fn is_primitive_mode_default(mode: &Checked<Mode>) -> bool {
*mode == Checked::Valid(Mode::Triangles)
}
fn primitive_validate_hook<P, R>(primitive: &Primitive, root: &crate::Root, path: P, report: &mut R)
where
P: Fn() -> crate::Path,
R: FnMut(&dyn Fn() -> crate::Path, crate::validation::Error),
{
let position_path = &|| path().field("attributes").key("POSITION");
if let Some(pos_accessor_index) = primitive
.attributes
.get(&Checked::Valid(Semantic::Positions))
{
// spec: POSITION accessor **must** have `min` and `max` properties defined.
let pos_accessor = &root.accessors[pos_accessor_index.value()];
let min_path = &|| position_path().field("min");
if let Some(ref min) = pos_accessor.min {
if from_value::<[f32; 3]>(min.clone()).is_err() {
report(min_path, Error::Invalid);
}
} else {
report(min_path, Error::Missing);
}
let max_path = &|| position_path().field("max");
if let Some(ref max) = pos_accessor.max {
if from_value::<[f32; 3]>(max.clone()).is_err() {
report(max_path, Error::Invalid);
}
} else {
report(max_path, Error::Missing);
}
} else {
report(position_path, Error::Missing);
}
}
/// A dictionary mapping attributes to their deviations in the Morph Target.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct MorphTarget {
/// XYZ vertex position displacements of type `[f32; 3]`.
#[serde(rename = "POSITION")]
#[serde(skip_serializing_if = "Option::is_none")]
pub positions: Option<Index<accessor::Accessor>>,
/// XYZ vertex normal displacements of type `[f32; 3]`.
#[serde(rename = "NORMAL")]
#[serde(skip_serializing_if = "Option::is_none")]
pub normals: Option<Index<accessor::Accessor>>,
/// XYZ vertex tangent displacements of type `[f32; 3]`.
#[serde(rename = "TANGENT")]
#[serde(skip_serializing_if = "Option::is_none")]
pub tangents: Option<Index<accessor::Accessor>>,
}
/// Vertex attribute semantic name.
#[derive(Clone, Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
pub enum Semantic {
/// Extra attribute name.
#[cfg(feature = "extras")]
Extras(String),
/// XYZ vertex positions.
Positions,
/// XYZ vertex normals.
Normals,
/// XYZW vertex tangents where the `w` component is a sign value indicating the
/// handedness of the tangent basis.
Tangents,
/// RGB or RGBA vertex color.
Colors(u32),
/// UV texture co-ordinates.
TexCoords(u32),
/// Joint indices.
Joints(u32),
/// Joint weights.
Weights(u32),
}
impl Default for Mode {
fn default() -> Mode {
Mode::Triangles
}
}
impl Mode {
/// Returns the equivalent `GLenum`.
pub fn as_gl_enum(self) -> u32 {
match self {
Mode::Points => POINTS,
Mode::Lines => LINES,
Mode::LineLoop => LINE_LOOP,
Mode::LineStrip => LINE_STRIP,
Mode::Triangles => TRIANGLES,
Mode::TriangleStrip => TRIANGLE_STRIP,
Mode::TriangleFan => TRIANGLE_FAN,
}
}
}
impl<'de> de::Deserialize<'de> for Checked<Mode> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<Mode>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_MODES)
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::Mode::*;
use crate::validation::Checked::*;
Ok(match value as u32 {
POINTS => Valid(Points),
LINES => Valid(Lines),
LINE_LOOP => Valid(LineLoop),
LINE_STRIP => Valid(LineStrip),
TRIANGLES => Valid(Triangles),
TRIANGLE_STRIP => Valid(TriangleStrip),
TRIANGLE_FAN => Valid(TriangleFan),
_ => Invalid,
})
}
}
deserializer.deserialize_u64(Visitor)
}
}
impl ser::Serialize for Mode {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_u32(self.as_gl_enum())
}
}
impl Semantic {
fn checked(s: &str) -> Checked<Self> {
use self::Semantic::*;
use crate::validation::Checked::*;
match s {
"NORMAL" => Valid(Normals),
"POSITION" => Valid(Positions),
"TANGENT" => Valid(Tangents),
#[cfg(feature = "extras")]
_ if s.starts_with('_') => Valid(Extras(s[1..].to_string())),
_ if s.starts_with("COLOR_") => match s["COLOR_".len()..].parse() {
Ok(set) => Valid(Colors(set)),
Err(_) => Invalid,
},
_ if s.starts_with("TEXCOORD_") => match s["TEXCOORD_".len()..].parse() {
Ok(set) => Valid(TexCoords(set)),
Err(_) => Invalid,
},
_ if s.starts_with("JOINTS_") => match s["JOINTS_".len()..].parse() {
Ok(set) => Valid(Joints(set)),
Err(_) => Invalid,
},
_ if s.starts_with("WEIGHTS_") => match s["WEIGHTS_".len()..].parse() {
Ok(set) => Valid(Weights(set)),
Err(_) => Invalid,
},
_ => Invalid,
}
}
}
impl ser::Serialize for Semantic {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl ToString for Semantic {
fn to_string(&self) -> String {
use self::Semantic::*;
match *self {
Positions => "POSITION".into(),
Normals => "NORMAL".into(),
Tangents => "TANGENT".into(),
Colors(set) => format!("COLOR_{}", set),
TexCoords(set) => format!("TEXCOORD_{}", set),
Joints(set) => format!("JOINTS_{}", set),
Weights(set) => format!("WEIGHTS_{}", set),
#[cfg(feature = "extras")]
Extras(ref name) => format!("_{}", name),
}
}
}
impl ToString for Checked<Semantic> {
fn to_string(&self) -> String {
match *self {
Checked::Valid(ref semantic) => semantic.to_string(),
Checked::Invalid => "<invalid semantic name>".into(),
}
}
}
impl<'de> de::Deserialize<'de> for Checked<Semantic> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<Semantic>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "semantic name")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(Semantic::checked(value))
}
}
deserializer.deserialize_str(Visitor)
}
}

98
vendor/gltf-json/src/path.rs vendored Normal file
View File

@@ -0,0 +1,98 @@
use std::fmt;
/// An immutable JSON source path.
#[derive(Default, Clone, Debug, PartialEq)]
pub struct Path(pub String);
impl Path {
/// Creates an empty JSON source path.
///
/// # Examples
///
/// Basic usage
///
/// ```rust
/// # use gltf_json::Path;
/// let path = Path::new();
/// assert_eq!("", path.as_str());
/// ```
pub fn new() -> Self {
Path(String::new())
}
/// Returns a new path ending with the given field.
///
/// # Examples
///
/// Basic usage
///
/// ```rust
/// # use gltf_json::Path;
/// let path = Path::new().field("foo");
/// assert_eq!("foo", path.as_str());
/// assert_eq!("foo.bar", path.field("bar").as_str());
/// ```
pub fn field(&self, name: &str) -> Self {
if self.0.is_empty() {
Path(name.to_string())
} else {
Path(format!("{}.{}", self.0, name))
}
}
/// Returns a new path ending with the given array index.
///
/// # Examples
///
/// Basic usage
///
/// ```rust
/// # use gltf_json::Path;
/// let path = Path::new().field("foo");
/// assert_eq!("foo[123]", path.index(123).as_str());
/// ```
pub fn index(&self, index: usize) -> Self {
Path(format!("{}[{}]", self.0, index))
}
/// Returns a new path ending with the given object key.
///
/// # Examples
///
/// Basic usage
///
/// ```rust
/// # use gltf_json::Path;
/// let path = Path::new().field("foo");
/// assert_eq!("foo[\"bar\"]", path.key("bar").as_str());
/// ```
pub fn key(&self, key: &str) -> Self {
Path(format!("{}[\"{}\"]", self.0, key))
}
/// Provides a string value for a JSON path.
///
/// # Examples
///
/// Basic usage
///
/// ```rust
/// # use gltf_json::Path;
/// let path = Path::new().field("foo").index(0).value_str("baz");
/// assert_eq!("foo[0] = \"baz\"", path.as_str());
/// ```
pub fn value_str(&self, value: &str) -> Self {
Path(format!("{} = \"{}\"", self.0, value))
}
/// Returns a view into the internal representation.
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for Path {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}

502
vendor/gltf-json/src/root.rs vendored Normal file
View File

@@ -0,0 +1,502 @@
use crate::buffer;
use crate::extensions;
use crate::texture;
use crate::validation;
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
use std::{self, fmt, io, marker};
use crate::path::Path;
use crate::{
Accessor, Animation, Asset, Buffer, Camera, Error, Extras, Image, Material, Mesh, Node, Scene,
Skin, Texture, Value,
};
use validation::Validate;
// TODO: As a breaking change, simplify by replacing uses of `Get<T>` with `AsRef<[T]>`.
/// Helper trait for retrieving top-level objects by a universal identifier.
pub trait Get<T> {
/// Retrieves a single value at the given index.
fn get(&self, id: Index<T>) -> Option<&T>;
}
/// Represents an offset into a vector of type `T` owned by the root glTF object.
///
/// This type may be used with the following functions:
///
/// * [`Root::get()`] to retrieve objects from [`Root`].
/// * [`Root::push()`] to add new objects to [`Root`].
pub struct Index<T>(u32, marker::PhantomData<fn() -> T>);
impl<T> Index<T> {
/// Given a vector of glTF objects, call [`Vec::push()`] to insert it into the vector,
/// then return an [`Index`] for it.
///
/// This allows you to easily obtain [`Index`] values with the correct index and type when
/// creating a glTF asset. Note that for [`Root`], you can call [`Root::push()`] without
/// needing to retrieve the correct vector first.
///
/// # Panics
///
/// Panics if the vector has [`u32::MAX`] or more elements, in which case an `Index` cannot be
/// created.
pub fn push(vec: &mut Vec<T>, value: T) -> Index<T> {
let len = vec.len();
let Ok(index): Result<u32, _> = len.try_into() else {
panic!(
"glTF vector of {ty} has {len} elements, which exceeds the Index limit",
ty = std::any::type_name::<T>(),
);
};
vec.push(value);
Index::new(index)
}
}
/// The root object of a glTF 2.0 asset.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[gltf(validate_hook = "root_validate_hook")]
pub struct Root {
/// An array of accessors.
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub accessors: Vec<Accessor>,
/// An array of keyframe animations.
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub animations: Vec<Animation>,
/// Metadata about the glTF asset.
pub asset: Asset,
/// An array of buffers.
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub buffers: Vec<Buffer>,
/// An array of buffer views.
#[serde(default, rename = "bufferViews")]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub buffer_views: Vec<buffer::View>,
/// The default scene.
#[serde(skip_serializing_if = "Option::is_none")]
pub scene: Option<Index<Scene>>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::root::Root>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
/// Names of glTF extensions used somewhere in this asset.
#[serde(default, rename = "extensionsUsed")]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub extensions_used: Vec<String>,
/// Names of glTF extensions required to properly load this asset.
#[serde(default, rename = "extensionsRequired")]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub extensions_required: Vec<String>,
/// An array of cameras.
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub cameras: Vec<Camera>,
/// An array of images.
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub images: Vec<Image>,
/// An array of materials.
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub materials: Vec<Material>,
/// An array of meshes.
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub meshes: Vec<Mesh>,
/// An array of nodes.
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub nodes: Vec<Node>,
/// An array of samplers.
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub samplers: Vec<texture::Sampler>,
/// An array of scenes.
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub scenes: Vec<Scene>,
/// An array of skins.
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub skins: Vec<Skin>,
/// An array of textures.
#[serde(default)]
#[serde(skip_serializing_if = "Vec::is_empty")]
pub textures: Vec<Texture>,
}
fn root_validate_hook<P, R>(root: &Root, _also_root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, crate::validation::Error),
{
for (i, ext) in root.extensions_required.iter().enumerate() {
if !crate::extensions::ENABLED_EXTENSIONS.contains(&ext.as_str()) {
report(
&|| {
path()
.field("extensionsRequired")
.index(i)
.value_str(ext.as_str())
},
crate::validation::Error::Unsupported,
);
}
}
}
impl Root {
/// Returns a single item from the root object.
pub fn get<T>(&self, index: Index<T>) -> Option<&T>
where
Self: Get<T>,
{
(self as &dyn Get<T>).get(index)
}
/// Insert the given value into this (as via [`Vec::push()`]), then return the [`Index`] to it.
///
/// This allows you to easily obtain [`Index`] values with the correct index and type when
/// creating a glTF asset.
///
/// If you have a mutable borrow conflict when using this method, consider using the more
/// explicit [`Index::push()`] method, passing it only the necessary vector.
///
/// # Panics
///
/// Panics if there are already [`u32::MAX`] or more elements of this type,
/// in which case an `Index` cannot be created.
#[track_caller]
pub fn push<T>(&mut self, value: T) -> Index<T>
where
Self: AsMut<Vec<T>>,
{
Index::push(self.as_mut(), value)
}
/// Deserialize from a JSON string slice.
#[allow(clippy::should_implement_trait)]
pub fn from_str(str_: &str) -> Result<Self, Error> {
serde_json::from_str(str_)
}
/// Deserialize from a JSON byte slice.
pub fn from_slice(slice: &[u8]) -> Result<Self, Error> {
serde_json::from_slice(slice)
}
/// Deserialize from a stream of JSON.
pub fn from_reader<R>(reader: R) -> Result<Self, Error>
where
R: io::Read,
{
serde_json::from_reader(reader)
}
/// Serialize as a `String` of JSON.
pub fn to_string(&self) -> Result<String, Error> {
serde_json::to_string(self)
}
/// Serialize as a pretty-printed `String` of JSON.
pub fn to_string_pretty(&self) -> Result<String, Error> {
serde_json::to_string_pretty(self)
}
/// Serialize as a generic JSON value.
pub fn to_value(&self) -> Result<Value, Error> {
serde_json::to_value(self)
}
/// Serialize as a JSON byte vector.
pub fn to_vec(&self) -> Result<Vec<u8>, Error> {
serde_json::to_vec(self)
}
/// Serialize as a pretty-printed JSON byte vector.
pub fn to_vec_pretty(&self) -> Result<Vec<u8>, Error> {
serde_json::to_vec_pretty(self)
}
/// Serialize as a JSON byte writertor.
pub fn to_writer<W>(&self, writer: W) -> Result<(), Error>
where
W: io::Write,
{
serde_json::to_writer(writer, self)
}
/// Serialize as a pretty-printed JSON byte writertor.
pub fn to_writer_pretty<W>(&self, writer: W) -> Result<(), Error>
where
W: io::Write,
{
serde_json::to_writer_pretty(writer, self)
}
}
impl<T> Index<T> {
/// Creates a new `Index` representing an offset into an array containing `T`.
pub fn new(value: u32) -> Self {
Index(value, std::marker::PhantomData)
}
/// Returns the internal offset value.
pub fn value(&self) -> usize {
self.0 as usize
}
}
impl<T> serde::Serialize for Index<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ::serde::Serializer,
{
serializer.serialize_u64(self.value() as u64)
}
}
impl<'de, T> serde::Deserialize<'de> for Index<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct Visitor<T>(marker::PhantomData<T>);
impl<'de, T> serde::de::Visitor<'de> for Visitor<T> {
type Value = Index<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("index into child of root")
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Index::new(value as u32))
}
}
deserializer.deserialize_u64(Visitor::<T>(marker::PhantomData))
}
}
impl<T> Clone for Index<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for Index<T> {}
impl<T> Ord for Index<T> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.0.cmp(&other.0)
}
}
impl<T> PartialOrd for Index<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<T> Eq for Index<T> {}
impl<T> PartialEq for Index<T> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0
}
}
impl<T> std::hash::Hash for Index<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
}
impl<T> fmt::Debug for Index<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl<T> fmt::Display for Index<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl<T: Validate> Validate for Index<T>
where
Root: Get<T>,
{
fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, validation::Error),
{
if root.get(*self).is_none() {
report(&path, validation::Error::IndexOutOfBounds);
}
}
}
macro_rules! impl_get {
($ty:ty, $field:ident) => {
impl<'a> Get<$ty> for Root {
fn get(&self, index: Index<$ty>) -> Option<&$ty> {
self.$field.get(index.value())
}
}
impl AsRef<[$ty]> for Root {
fn as_ref(&self) -> &[$ty] {
&self.$field
}
}
impl AsMut<Vec<$ty>> for Root {
fn as_mut(&mut self) -> &mut Vec<$ty> {
&mut self.$field
}
}
};
}
impl_get!(Accessor, accessors);
impl_get!(Animation, animations);
impl_get!(Buffer, buffers);
impl_get!(buffer::View, buffer_views);
impl_get!(Camera, cameras);
impl_get!(Image, images);
impl_get!(Material, materials);
impl_get!(Mesh, meshes);
impl_get!(Node, nodes);
impl_get!(texture::Sampler, samplers);
impl_get!(Scene, scenes);
impl_get!(Skin, skins);
impl_get!(Texture, textures);
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
#[test]
fn index_is_partialeq() {
assert_eq!(Index::<Node>::new(1), Index::new(1));
assert_ne!(Index::<Node>::new(1), Index::new(2));
}
#[test]
fn index_is_hash() {
let set = HashSet::from([Index::<Node>::new(1), Index::new(1234)]);
assert!(set.contains(&Index::new(1234)));
assert!(!set.contains(&Index::new(999)));
assert_eq!(set.len(), 2);
}
#[test]
fn index_is_ord() {
assert!(Index::<Node>::new(1) < Index::new(1234));
}
fn _index_is_send_sync()
where
Index<Material>: Send + Sync,
{
}
#[test]
fn index_push() {
let some_object = "hello";
let mut vec = Vec::new();
assert_eq!(Index::push(&mut vec, some_object), Index::new(0));
assert_eq!(Index::push(&mut vec, some_object), Index::new(1));
}
#[test]
fn root_push() {
let some_object = Buffer {
byte_length: validation::USize64(1),
#[cfg(feature = "names")]
name: None,
uri: None,
extensions: None,
extras: Default::default(),
};
let mut root = Root::default();
assert_eq!(root.push(some_object.clone()), Index::new(0));
assert_eq!(root.push(some_object), Index::new(1));
}
#[test]
fn root_extensions() {
use crate::validation::Error;
use crate::Path;
let mut root = super::Root {
extensions_required: vec!["KHR_lights_punctual".to_owned()],
..Default::default()
};
let mut errors = Vec::new();
root.validate(&root, Path::new, &mut |path, error| {
errors.push((path(), error));
});
#[cfg(feature = "KHR_lights_punctual")]
{
assert!(errors.is_empty());
}
#[cfg(not(feature = "KHR_lights_punctual"))]
{
assert_eq!(1, errors.len());
let (path, error) = errors.get(0).unwrap();
assert_eq!(
path.as_str(),
"extensionsRequired[0] = \"KHR_lights_punctual\""
);
assert_eq!(*error, Error::Unsupported);
}
root.extensions_required = vec!["KHR_mesh_quantization".to_owned()];
errors.clear();
root.validate(&root, Path::new, &mut |path, error| {
errors.push((path(), error));
});
assert_eq!(1, errors.len());
let (path, error) = errors.get(0).unwrap();
assert_eq!(
path.as_str(),
"extensionsRequired[0] = \"KHR_mesh_quantization\""
);
assert_eq!(*error, Error::Unsupported);
}
}

114
vendor/gltf-json/src/scene.rs vendored Normal file
View File

@@ -0,0 +1,114 @@
use crate::validation::Validate;
use crate::{camera, extensions, mesh, scene, skin, Extras, Index};
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
/// A node in the node hierarchy. When the node contains `skin`, all
/// `mesh.primitives` must contain `JOINTS_0` and `WEIGHTS_0` attributes.
/// A node can have either a `matrix` or any combination of
/// `translation`/`rotation`/`scale` (TRS) properties. TRS properties are converted
/// to matrices and postmultiplied in the `T * R * S` order to compose the
/// transformation matrix; first the scale is applied to the vertices, then the
/// rotation, and then the translation. If none are provided, the transform is the
/// identity. When a node is targeted for animation (referenced by an
/// animation.channel.target), only TRS properties may be present; `matrix` will not
/// be present.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct Node {
/// The index of the camera referenced by this node.
#[serde(skip_serializing_if = "Option::is_none")]
pub camera: Option<Index<camera::Camera>>,
/// The indices of this node's children.
#[serde(skip_serializing_if = "Option::is_none")]
pub children: Option<Vec<Index<scene::Node>>>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::scene::Node>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
/// 4x4 column-major transformation matrix.
///
/// glTF 2.0 specification:
/// When a node is targeted for animation (referenced by an
/// animation.channel.target), only TRS properties may be present;
/// matrix will not be present.
///
/// TODO: Ensure that .matrix is set to None or otherwise skipped during
/// serialization, if the node is targeted for animation.
///
#[serde(skip_serializing_if = "Option::is_none")]
pub matrix: Option<[f32; 16]>,
/// The index of the mesh in this node.
#[serde(skip_serializing_if = "Option::is_none")]
pub mesh: Option<Index<mesh::Mesh>>,
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// The node's unit quaternion rotation in the order (x, y, z, w), where w is
/// the scalar.
#[serde(skip_serializing_if = "Option::is_none")]
pub rotation: Option<UnitQuaternion>,
/// The node's non-uniform scale.
#[serde(skip_serializing_if = "Option::is_none")]
pub scale: Option<[f32; 3]>,
/// The node's translation.
#[serde(skip_serializing_if = "Option::is_none")]
pub translation: Option<[f32; 3]>,
/// The index of the skin referenced by this node.
#[serde(skip_serializing_if = "Option::is_none")]
pub skin: Option<Index<skin::Skin>>,
/// The weights of the instantiated Morph Target. Number of elements must match
/// the number of Morph Targets of used mesh.
#[serde(skip_serializing_if = "Option::is_none")]
pub weights: Option<Vec<f32>>,
}
/// The root `Node`s of a scene.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Scene {
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::scene::Scene>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// The indices of each root node.
#[serde(skip_serializing_if = "Vec::is_empty")]
pub nodes: Vec<Index<Node>>,
}
/// Unit quaternion rotation in the order (x, y, z, w), where w is the scalar.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct UnitQuaternion(pub [f32; 4]);
impl Default for UnitQuaternion {
fn default() -> Self {
UnitQuaternion([0.0, 0.0, 0.0, 1.0])
}
}
impl Validate for UnitQuaternion {}

43
vendor/gltf-json/src/skin.rs vendored Normal file
View File

@@ -0,0 +1,43 @@
use crate::{accessor, extensions, scene, Extras, Index};
use gltf_derive::Validate;
use serde_derive::{Deserialize, Serialize};
/// Joints and matrices defining a skin.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
pub struct Skin {
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::skin::Skin>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
/// The index of the accessor containing the 4x4 inverse-bind matrices.
///
/// When `None`,each matrix is assumed to be the 4x4 identity matrix
/// which implies that the inverse-bind matrices were pre-applied.
#[serde(rename = "inverseBindMatrices")]
#[serde(skip_serializing_if = "Option::is_none")]
pub inverse_bind_matrices: Option<Index<accessor::Accessor>>,
/// Indices of skeleton nodes used as joints in this skin.
///
/// The array length must be the same as the `count` property of the
/// `inverse_bind_matrices` `Accessor` (when defined).
#[serde(skip_serializing_if = "Vec::is_empty")]
pub joints: Vec<Index<scene::Node>>,
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// The index of the node used as a skeleton root.
///
/// When `None`, joints transforms resolve to scene root.
#[serde(skip_serializing_if = "Option::is_none")]
pub skeleton: Option<Index<scene::Node>>,
}

479
vendor/gltf-json/src/texture.rs vendored Normal file
View File

@@ -0,0 +1,479 @@
use crate::validation::{Checked, Validate};
use crate::{extensions, image, Extras, Index};
use gltf_derive::Validate;
use serde::{de, ser};
use serde_derive::{Deserialize, Serialize};
use std::fmt;
/// Corresponds to `GL_NEAREST`.
pub const NEAREST: u32 = 9728;
/// Corresponds to `GL_LINEAR`.
pub const LINEAR: u32 = 9729;
/// Corresponds to `GL_NEAREST_MIPMAP_NEAREST`.
pub const NEAREST_MIPMAP_NEAREST: u32 = 9984;
/// Corresponds to `GL_LINEAR_MIPMAP_NEAREST`.
pub const LINEAR_MIPMAP_NEAREST: u32 = 9985;
/// Corresponds to `GL_NEAREST_MIPMAP_LINEAR`.
pub const NEAREST_MIPMAP_LINEAR: u32 = 9986;
/// Corresponds to `GL_LINEAR_MIPMAP_LINEAR`.
pub const LINEAR_MIPMAP_LINEAR: u32 = 9987;
/// Corresponds to `GL_CLAMP_TO_EDGE`.
pub const CLAMP_TO_EDGE: u32 = 33_071;
/// Corresponds to `GL_MIRRORED_REPEAT`.
pub const MIRRORED_REPEAT: u32 = 33_648;
/// Corresponds to `GL_REPEAT`.
pub const REPEAT: u32 = 10_497;
/// All valid magnification filters.
pub const VALID_MAG_FILTERS: &[u32] = &[NEAREST, LINEAR];
/// All valid minification filters.
pub const VALID_MIN_FILTERS: &[u32] = &[
NEAREST,
LINEAR,
NEAREST_MIPMAP_NEAREST,
LINEAR_MIPMAP_NEAREST,
NEAREST_MIPMAP_LINEAR,
LINEAR_MIPMAP_LINEAR,
];
/// All valid wrapping modes.
pub const VALID_WRAPPING_MODES: &[u32] = &[CLAMP_TO_EDGE, MIRRORED_REPEAT, REPEAT];
/// Magnification filter.
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
pub enum MagFilter {
/// Corresponds to `GL_NEAREST`.
Nearest = 1,
/// Corresponds to `GL_LINEAR`.
Linear,
}
impl MagFilter {
/// OpenGL enum
pub fn as_gl_enum(&self) -> u32 {
match *self {
MagFilter::Nearest => NEAREST,
MagFilter::Linear => LINEAR,
}
}
}
/// Minification filter.
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
pub enum MinFilter {
/// Corresponds to `GL_NEAREST`.
Nearest = 1,
/// Corresponds to `GL_LINEAR`.
Linear,
/// Corresponds to `GL_NEAREST_MIPMAP_NEAREST`.
NearestMipmapNearest,
/// Corresponds to `GL_LINEAR_MIPMAP_NEAREST`.
LinearMipmapNearest,
/// Corresponds to `GL_NEAREST_MIPMAP_LINEAR`.
NearestMipmapLinear,
/// Corresponds to `GL_LINEAR_MIPMAP_LINEAR`.
LinearMipmapLinear,
}
impl MinFilter {
/// Returns the corresponding OpenGL enum value.
pub fn as_gl_enum(&self) -> u32 {
match *self {
MinFilter::Nearest => NEAREST,
MinFilter::Linear => LINEAR,
MinFilter::NearestMipmapNearest => NEAREST_MIPMAP_NEAREST,
MinFilter::LinearMipmapNearest => LINEAR_MIPMAP_NEAREST,
MinFilter::NearestMipmapLinear => NEAREST_MIPMAP_LINEAR,
MinFilter::LinearMipmapLinear => LINEAR_MIPMAP_LINEAR,
}
}
}
/// Texture co-ordinate wrapping mode.
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
pub enum WrappingMode {
/// Corresponds to `GL_CLAMP_TO_EDGE`.
ClampToEdge = 1,
/// Corresponds to `GL_MIRRORED_REPEAT`.
MirroredRepeat,
/// Corresponds to `GL_REPEAT`.
Repeat,
}
impl WrappingMode {
/// Returns the corresponding OpenGL enum value.
pub fn as_gl_enum(&self) -> u32 {
match *self {
WrappingMode::ClampToEdge => CLAMP_TO_EDGE,
WrappingMode::MirroredRepeat => MIRRORED_REPEAT,
WrappingMode::Repeat => REPEAT,
}
}
}
/// Texture sampler properties for filtering and wrapping modes.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
#[serde(default)]
pub struct Sampler {
/// Magnification filter.
#[serde(rename = "magFilter")]
#[serde(skip_serializing_if = "Option::is_none")]
pub mag_filter: Option<Checked<MagFilter>>,
/// Minification filter.
#[serde(rename = "minFilter")]
#[serde(skip_serializing_if = "Option::is_none")]
pub min_filter: Option<Checked<MinFilter>>,
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// `s` wrapping mode.
#[serde(default, rename = "wrapS")]
pub wrap_s: Checked<WrappingMode>,
/// `t` wrapping mode.
#[serde(default, rename = "wrapT")]
pub wrap_t: Checked<WrappingMode>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::texture::Sampler>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
fn source_default() -> Index<image::Image> {
Index::new(u32::MAX)
}
fn source_is_empty(source: &Index<image::Image>) -> bool {
source.value() == u32::MAX as usize
}
fn source_validate<P, R>(source: &Index<image::Image>, root: &crate::Root, path: P, report: &mut R)
where
P: Fn() -> crate::Path,
R: FnMut(&dyn Fn() -> crate::Path, crate::validation::Error),
{
if cfg!(feature = "allow_empty_texture") {
if !source_is_empty(source) {
source.validate(root, path, report);
}
} else if source_is_empty(source) {
report(&path, crate::validation::Error::Missing);
} else {
source.validate(root, &path, report);
}
}
/// A texture and its sampler.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Texture {
/// Optional user-defined name for this object.
#[cfg(feature = "names")]
#[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
pub name: Option<String>,
/// The index of the sampler used by this texture.
#[serde(skip_serializing_if = "Option::is_none")]
pub sampler: Option<Index<Sampler>>,
/// The index of the image used by this texture.
#[serde(default = "source_default", skip_serializing_if = "source_is_empty")]
pub source: Index<image::Image>,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::texture::Texture>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
impl Validate for Texture {
fn validate<P, R>(&self, root: &crate::Root, path: P, report: &mut R)
where
P: Fn() -> crate::Path,
R: FnMut(&dyn Fn() -> crate::Path, crate::validation::Error),
{
self.sampler
.validate(root, || path().field("sampler"), report);
self.extensions
.validate(root, || path().field("extensions"), report);
source_validate(&self.source, root, || path().field("source"), report);
}
}
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
/// Reference to a `Texture`.
pub struct Info {
/// The index of the texture.
pub index: Index<Texture>,
/// The set index of the texture's `TEXCOORD` attribute.
#[serde(default, rename = "texCoord")]
pub tex_coord: u32,
/// Extension specific data.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub extensions: Option<extensions::texture::Info>,
/// Optional application specific data.
#[serde(default)]
#[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
#[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
pub extras: Extras,
}
impl<'de> de::Deserialize<'de> for Checked<MagFilter> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<MagFilter>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_MAG_FILTERS)
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::MagFilter::*;
use crate::validation::Checked::*;
Ok(match value as u32 {
NEAREST => Valid(Nearest),
LINEAR => Valid(Linear),
_ => Invalid,
})
}
}
deserializer.deserialize_u64(Visitor)
}
}
impl<'de> de::Deserialize<'de> for Checked<MinFilter> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<MinFilter>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_MIN_FILTERS)
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::MinFilter::*;
use crate::validation::Checked::*;
Ok(match value as u32 {
NEAREST => Valid(Nearest),
LINEAR => Valid(Linear),
NEAREST_MIPMAP_NEAREST => Valid(NearestMipmapNearest),
LINEAR_MIPMAP_NEAREST => Valid(LinearMipmapNearest),
NEAREST_MIPMAP_LINEAR => Valid(NearestMipmapLinear),
LINEAR_MIPMAP_LINEAR => Valid(LinearMipmapLinear),
_ => Invalid,
})
}
}
deserializer.deserialize_u64(Visitor)
}
}
impl ser::Serialize for MinFilter {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_u32(self.as_gl_enum())
}
}
impl<'de> de::Deserialize<'de> for Checked<WrappingMode> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl<'de> de::Visitor<'de> for Visitor {
type Value = Checked<WrappingMode>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "any of: {:?}", VALID_WRAPPING_MODES)
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
use self::WrappingMode::*;
use crate::validation::Checked::*;
Ok(match value as u32 {
CLAMP_TO_EDGE => Valid(ClampToEdge),
MIRRORED_REPEAT => Valid(MirroredRepeat),
REPEAT => Valid(Repeat),
_ => Invalid,
})
}
}
deserializer.deserialize_u64(Visitor)
}
}
impl ser::Serialize for MagFilter {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_u32(self.as_gl_enum())
}
}
impl Default for WrappingMode {
fn default() -> Self {
WrappingMode::Repeat
}
}
impl ser::Serialize for WrappingMode {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
serializer.serialize_u32(self.as_gl_enum())
}
}
#[cfg(test)]
mod tests {
#[test]
fn deserialize_source() {
let json = r#"{"asset":{"version":"2.0"},"textures":[{"source": 0}]}"#;
let root = serde_json::from_str::<crate::Root>(json).unwrap();
assert_eq!(0, root.textures[0].source.value());
}
#[test]
fn deserialize_empty_source() {
let json = r#"{"asset":{"version":"2.0"},"textures":[{}]}"#;
let root = serde_json::from_str::<crate::Root>(json).unwrap();
assert_eq!(u32::MAX as usize, root.textures[0].source.value());
}
#[test]
fn serialize_source() {
let root = crate::Root {
textures: vec![crate::Texture {
#[cfg(feature = "names")]
name: None,
sampler: None,
source: crate::Index::new(0),
extensions: None,
extras: Default::default(),
}],
..Default::default()
};
let json = serde_json::to_string(&root).unwrap();
assert_eq!(
r#"{"asset":{"version":"2.0"},"textures":[{"source":0}]}"#,
&json
);
}
#[test]
fn serialize_empty_source() {
let root = crate::Root {
textures: vec![crate::Texture {
#[cfg(feature = "names")]
name: None,
sampler: None,
source: crate::Index::new(u32::MAX),
extensions: None,
extras: Default::default(),
}],
..Default::default()
};
let json = serde_json::to_string(&root).unwrap();
assert_eq!(r#"{"asset":{"version":"2.0"},"textures":[{}]}"#, &json);
}
#[test]
fn validate_source() {
use crate::validation::{Error, Validate};
use crate::Path;
let json = r#"{"asset":{"version":"2.0"},"textures":[{"source":0}]}"#;
let root = serde_json::from_str::<crate::Root>(json).unwrap();
let mut errors = Vec::new();
root.textures[0].validate(
&root,
|| Path::new().field("textures").index(0),
&mut |path, error| {
errors.push((path(), error));
},
);
assert_eq!(1, errors.len());
let (path, error) = &errors[0];
assert_eq!("textures[0].source", path.as_str());
assert_eq!(Error::IndexOutOfBounds, *error);
}
#[test]
fn validate_empty_source() {
use crate::validation::{Error, Validate};
use crate::Path;
let json = r#"{"asset":{"version":"2.0"},"textures":[{}]}"#;
let root = serde_json::from_str::<crate::Root>(json).unwrap();
let mut errors = Vec::new();
root.textures[0].validate(
&root,
|| Path::new().field("textures").index(0),
&mut |path, error| {
errors.push((path(), error));
},
);
if cfg!(feature = "allow_empty_texture") {
assert!(errors.is_empty());
} else {
assert_eq!(1, errors.len());
let (path, error) = &errors[0];
assert_eq!("textures[0].source", path.as_str());
assert_eq!(Error::Missing, *error);
}
}
}

238
vendor/gltf-json/src/validation.rs vendored Normal file
View File

@@ -0,0 +1,238 @@
use serde::{ser, Serialize, Serializer};
use std::collections::BTreeMap;
use std::hash::Hash;
use crate::{Path, Root};
/// Trait for validating glTF JSON data so that the library can function without panicking.
pub trait Validate {
/// Validates the invariants required for the library to function safely.
fn validate<P, R>(&self, _root: &Root, _path: P, _report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
// nop
}
}
/// Specifies what kind of error occured during validation.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Error {
/// An index was found to be out of bounds.
IndexOutOfBounds,
/// An invalid value was identified.
Invalid,
/// Some required data has been omitted.
Missing,
/// A memory size or offset exceeds the system limits.
Oversize,
/// One of more required extensions is not supported by this crate version.
Unsupported,
}
/// Specifies a type that has been pre-validated during deserialization or otherwise.
#[derive(Debug, Eq, Hash, PartialEq, Ord, PartialOrd)]
pub enum Checked<T> {
/// The item is valid.
Valid(T),
/// The item is invalid.
Invalid,
}
impl<T> Checked<T> {
/// Converts from `Checked<T>` to `Checked<&T>`.
pub fn as_ref(&self) -> Checked<&T> {
match *self {
Checked::Valid(ref item) => Checked::Valid(item),
Checked::Invalid => Checked::Invalid,
}
}
/// Takes ownership of the contained item if it is `Valid`.
///
/// # Panics
///
/// Panics if called on an `Invalid` item.
pub fn unwrap(self) -> T {
match self {
Checked::Valid(item) => item,
Checked::Invalid => panic!("attempted to unwrap an invalid item"),
}
}
}
impl<T: Serialize> Serialize for Checked<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *self {
Checked::Valid(ref item) => item.serialize(serializer),
Checked::Invalid => Err(ser::Error::custom("invalid item")),
}
}
}
impl<T: Clone> Clone for Checked<T> {
fn clone(&self) -> Self {
match *self {
Checked::Valid(ref item) => Checked::Valid(item.clone()),
Checked::Invalid => Checked::Invalid,
}
}
}
impl<T: Copy> Copy for Checked<T> {}
impl<T: Default> Default for Checked<T> {
fn default() -> Self {
Checked::Valid(T::default())
}
}
impl<T> Validate for Checked<T> {
fn validate<P, R>(&self, _root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
match *self {
Checked::Valid(_) => {}
Checked::Invalid => report(&path, Error::Invalid),
}
}
}
/// Validates the suitability of 64-bit byte offsets/sizes on 32-bit systems.
#[derive(
Clone,
Copy,
Debug,
Default,
Eq,
Hash,
PartialEq,
serde_derive::Deserialize,
serde_derive::Serialize,
)]
pub struct USize64(pub u64);
impl From<u64> for USize64 {
fn from(value: u64) -> Self {
Self(value)
}
}
impl From<usize> for USize64 {
fn from(value: usize) -> Self {
Self(value as u64)
}
}
impl Validate for USize64 {
fn validate<P, R>(&self, _root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
if usize::try_from(self.0).is_err() {
report(&path, Error::Oversize);
}
}
}
impl<K: ToString + Validate, V: Validate> Validate for BTreeMap<K, V> {
fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
for (key, value) in self.iter() {
key.validate(root, || path().key(&key.to_string()), report);
value.validate(root, || path().key(&key.to_string()), report);
}
}
}
impl Validate for serde_json::Map<String, serde_json::Value> {
fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
for (key, value) in self.iter() {
key.validate(root, || path().key(&key.to_string()), report);
value.validate(root, || path().key(&key.to_string()), report);
}
}
}
impl<T: Validate> Validate for Option<T> {
fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
if let Some(value) = self.as_ref() {
value.validate(root, path, report);
}
}
}
impl<T: Validate> Validate for Vec<T> {
fn validate<P, R>(&self, root: &Root, path: P, report: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
for (index, value) in self.iter().enumerate() {
value.validate(root, || path().index(index), report);
}
}
}
impl Validate for std::boxed::Box<serde_json::value::RawValue> {
fn validate<P, R>(&self, _: &Root, _: P, _: &mut R)
where
P: Fn() -> Path,
R: FnMut(&dyn Fn() -> Path, Error),
{
// nop
}
}
impl std::error::Error for Error {}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"{}",
match *self {
Error::IndexOutOfBounds => "Index out of bounds",
Error::Invalid => "Invalid value",
Error::Missing => "Missing data",
Error::Oversize => "Size exceeds system limits",
Error::Unsupported => "Unsupported extension",
}
)
}
}
// These types are assumed to be always valid.
impl Validate for bool {}
impl Validate for u32 {}
impl Validate for i32 {}
impl Validate for f32 {}
impl Validate for [f32; 3] {}
impl Validate for [f32; 4] {}
impl Validate for [f32; 16] {}
impl Validate for () {}
impl Validate for String {}
impl Validate for serde_json::Value {}