1use crate::validation::{Checked, Validate};
2use crate::{extensions, texture, Extras, Index};
3use gltf_derive::Validate;
4use serde::{de, ser};
5use serde_derive::{Deserialize, Serialize};
6use std::fmt;
7
8pub const VALID_ALPHA_MODES: &[&str] = &["OPAQUE", "MASK", "BLEND"];
10
11#[derive(Clone, Copy, Eq, PartialEq, Debug)]
13pub enum AlphaMode {
14 Opaque = 1,
16
17 Mask,
20
21 Blend,
24}
25
26impl ser::Serialize for AlphaMode {
27 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
28 where
29 S: ser::Serializer,
30 {
31 match *self {
32 AlphaMode::Opaque => serializer.serialize_str("OPAQUE"),
33 AlphaMode::Mask => serializer.serialize_str("MASK"),
34 AlphaMode::Blend => serializer.serialize_str("BLEND"),
35 }
36 }
37}
38
39#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
41#[serde(default)]
42pub struct Material {
43 #[serde(rename = "alphaCutoff")]
45 #[serde(skip_serializing_if = "Option::is_none")]
47 pub alpha_cutoff: Option<AlphaCutoff>,
48
49 #[serde(rename = "alphaMode")]
66 pub alpha_mode: Checked<AlphaMode>,
67
68 #[serde(rename = "doubleSided")]
78 pub double_sided: bool,
79
80 #[cfg(feature = "names")]
82 #[cfg_attr(feature = "names", serde(skip_serializing_if = "Option::is_none"))]
83 pub name: Option<String>,
84
85 #[serde(default, rename = "pbrMetallicRoughness")]
89 pub pbr_metallic_roughness: PbrMetallicRoughness,
90
91 #[serde(rename = "normalTexture")]
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub normal_texture: Option<NormalTexture>,
100
101 #[serde(rename = "occlusionTexture")]
107 #[serde(skip_serializing_if = "Option::is_none")]
108 pub occlusion_texture: Option<OcclusionTexture>,
109
110 #[serde(rename = "emissiveTexture")]
114 #[serde(skip_serializing_if = "Option::is_none")]
115 pub emissive_texture: Option<texture::Info>,
116
117 #[serde(rename = "emissiveFactor")]
119 pub emissive_factor: EmissiveFactor,
120
121 #[serde(default, skip_serializing_if = "Option::is_none")]
123 pub extensions: Option<extensions::material::Material>,
124
125 #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
127 #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
128 pub extras: Extras,
129}
130
131#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
134#[serde(default)]
135pub struct PbrMetallicRoughness {
136 #[serde(rename = "baseColorFactor")]
138 pub base_color_factor: PbrBaseColorFactor,
139
140 #[serde(rename = "baseColorTexture")]
142 #[serde(skip_serializing_if = "Option::is_none")]
143 pub base_color_texture: Option<texture::Info>,
144
145 #[serde(rename = "metallicFactor")]
147 pub metallic_factor: StrengthFactor,
148
149 #[serde(rename = "roughnessFactor")]
154 pub roughness_factor: StrengthFactor,
155
156 #[serde(rename = "metallicRoughnessTexture")]
165 #[serde(skip_serializing_if = "Option::is_none")]
166 pub metallic_roughness_texture: Option<texture::Info>,
167
168 #[serde(default, skip_serializing_if = "Option::is_none")]
170 pub extensions: Option<extensions::material::PbrMetallicRoughness>,
171
172 #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
174 #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
175 pub extras: Extras,
176}
177
178#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
180pub struct NormalTexture {
181 pub index: Index<texture::Texture>,
183
184 #[serde(default = "material_normal_texture_scale_default")]
188 pub scale: f32,
189
190 #[serde(default, rename = "texCoord")]
192 pub tex_coord: u32,
193
194 #[serde(default, skip_serializing_if = "Option::is_none")]
196 pub extensions: Option<extensions::material::NormalTexture>,
197
198 #[serde(default)]
200 #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
201 #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
202 pub extras: Extras,
203}
204
205fn material_normal_texture_scale_default() -> f32 {
206 1.0
207}
208
209#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
211pub struct OcclusionTexture {
212 pub index: Index<texture::Texture>,
214
215 #[serde(default)]
217 pub strength: StrengthFactor,
218
219 #[serde(default, rename = "texCoord")]
221 pub tex_coord: u32,
222
223 #[serde(default, skip_serializing_if = "Option::is_none")]
225 pub extensions: Option<extensions::material::OcclusionTexture>,
226
227 #[serde(default)]
229 #[cfg_attr(feature = "extras", serde(skip_serializing_if = "Option::is_none"))]
230 #[cfg_attr(not(feature = "extras"), serde(skip_serializing))]
231 pub extras: Extras,
232}
233
234#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
236pub struct AlphaCutoff(pub f32);
237
238#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
240pub struct EmissiveFactor(pub [f32; 3]);
241
242#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
244pub struct PbrBaseColorFactor(pub [f32; 4]);
245
246#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
248pub struct StrengthFactor(pub f32);
249
250impl Default for AlphaCutoff {
251 fn default() -> Self {
252 AlphaCutoff(0.5)
253 }
254}
255
256impl Validate for AlphaCutoff {}
257
258impl Default for AlphaMode {
259 fn default() -> Self {
260 AlphaMode::Opaque
261 }
262}
263
264impl<'de> de::Deserialize<'de> for Checked<AlphaMode> {
265 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
266 where
267 D: de::Deserializer<'de>,
268 {
269 struct Visitor;
270 impl<'de> de::Visitor<'de> for Visitor {
271 type Value = Checked<AlphaMode>;
272
273 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
274 write!(f, "any of: {:?}", VALID_ALPHA_MODES)
275 }
276
277 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
278 where
279 E: de::Error,
280 {
281 use self::AlphaMode::*;
282 use crate::validation::Checked::*;
283 Ok(match value {
284 "OPAQUE" => Valid(Opaque),
285 "MASK" => Valid(Mask),
286 "BLEND" => Valid(Blend),
287 _ => Invalid,
288 })
289 }
290 }
291 deserializer.deserialize_str(Visitor)
292 }
293}
294
295impl Validate for EmissiveFactor {}
296
297impl Default for PbrBaseColorFactor {
298 fn default() -> Self {
299 PbrBaseColorFactor([1.0, 1.0, 1.0, 1.0])
300 }
301}
302
303impl Validate for PbrBaseColorFactor {}
304
305impl Default for StrengthFactor {
306 fn default() -> Self {
307 StrengthFactor(1.0)
308 }
309}
310
311impl Validate for StrengthFactor {}