1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 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 {}