gltf_v1_json/
texture.rs

1use std::fmt;
2
3use super::{common::StringIndex, image::Image, validation::Checked};
4use gltf_v1_derive::Validate;
5use serde::de;
6use serde::{Deserialize, Serialize};
7
8pub const NEAREST: u32 = 9728;
9pub const LINEAR: u32 = 9729;
10pub const NEAREST_MIPMAP_NEAREST: u32 = 9984;
11pub const LINEAR_MIPMAP_NEAREST: u32 = 9985;
12pub const NEAREST_MIPMAP_LINEAR: u32 = 9986;
13pub const LINEAR_MIPMAP_LINEAR: u32 = 9987;
14
15#[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
16pub enum SamplerMagFilter {
17    #[default]
18    Nearest,
19    Linear,
20}
21
22impl SamplerMagFilter {
23    pub const VALID_SAMPLER_MAG_FILTER: &[u32] = &[NEAREST, LINEAR];
24}
25
26impl From<SamplerMagFilter> for u32 {
27    fn from(value: SamplerMagFilter) -> Self {
28        match value {
29            SamplerMagFilter::Nearest => NEAREST,
30            SamplerMagFilter::Linear => LINEAR,
31        }
32    }
33}
34
35impl TryFrom<u32> for SamplerMagFilter {
36    type Error = ();
37
38    fn try_from(value: u32) -> Result<Self, Self::Error> {
39        match value {
40            NEAREST => Ok(SamplerMagFilter::Nearest),
41            LINEAR => Ok(SamplerMagFilter::Linear),
42            _ => Err(()),
43        }
44    }
45}
46impl Serialize for SamplerMagFilter {
47    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
48    where
49        S: serde::Serializer,
50    {
51        serializer.serialize_u32((*self).into())
52    }
53}
54
55impl<'de> Deserialize<'de> for Checked<SamplerMagFilter> {
56    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
57    where
58        D: serde::Deserializer<'de>,
59    {
60        struct Visitor;
61        impl de::Visitor<'_> for Visitor {
62            type Value = Checked<SamplerMagFilter>;
63
64            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
65                write!(
66                    f,
67                    "any of: {:?}",
68                    SamplerMagFilter::VALID_SAMPLER_MAG_FILTER
69                )
70            }
71
72            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
73            where
74                E: de::Error,
75            {
76                Ok((value as u32)
77                    .try_into()
78                    .map(Checked::Valid)
79                    .unwrap_or(Checked::Invalid))
80            }
81        }
82        deserializer.deserialize_u32(Visitor)
83    }
84}
85
86#[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
87pub enum SamplerMinFilter {
88    #[default]
89    Nearest,
90    Linear,
91    NearestMipmapNearest,
92    LinearMipmapNearest,
93    NearestMipmapLinear,
94    LinearMipmapLinear,
95}
96
97impl From<SamplerMinFilter> for u32 {
98    fn from(value: SamplerMinFilter) -> Self {
99        match value {
100            SamplerMinFilter::Nearest => NEAREST,
101            SamplerMinFilter::Linear => LINEAR,
102            SamplerMinFilter::NearestMipmapNearest => NEAREST_MIPMAP_NEAREST,
103            SamplerMinFilter::LinearMipmapNearest => LINEAR_MIPMAP_NEAREST,
104            SamplerMinFilter::NearestMipmapLinear => NEAREST_MIPMAP_LINEAR,
105            SamplerMinFilter::LinearMipmapLinear => LINEAR_MIPMAP_LINEAR,
106        }
107    }
108}
109
110impl TryFrom<u32> for SamplerMinFilter {
111    type Error = ();
112
113    fn try_from(value: u32) -> Result<Self, Self::Error> {
114        match value {
115            NEAREST => Ok(SamplerMinFilter::Nearest),
116            LINEAR => Ok(SamplerMinFilter::Linear),
117            NEAREST_MIPMAP_NEAREST => Ok(SamplerMinFilter::NearestMipmapNearest),
118            LINEAR_MIPMAP_NEAREST => Ok(SamplerMinFilter::LinearMipmapNearest),
119            NEAREST_MIPMAP_LINEAR => Ok(SamplerMinFilter::NearestMipmapLinear),
120            LINEAR_MIPMAP_LINEAR => Ok(SamplerMinFilter::LinearMipmapLinear),
121            _ => Err(()),
122        }
123    }
124}
125
126impl SamplerMinFilter {
127    pub const VALID_SAMPLER_MIN_FILTER: &[u32] = &[
128        NEAREST,
129        LINEAR,
130        NEAREST_MIPMAP_NEAREST,
131        LINEAR_MIPMAP_NEAREST,
132        NEAREST_MIPMAP_LINEAR,
133        LINEAR_MIPMAP_LINEAR,
134    ];
135}
136
137impl Serialize for SamplerMinFilter {
138    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139    where
140        S: serde::Serializer,
141    {
142        serializer.serialize_u32((*self).into())
143    }
144}
145
146impl<'de> Deserialize<'de> for Checked<SamplerMinFilter> {
147    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
148    where
149        D: serde::Deserializer<'de>,
150    {
151        struct Visitor;
152        impl de::Visitor<'_> for Visitor {
153            type Value = Checked<SamplerMinFilter>;
154
155            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
156                write!(
157                    f,
158                    "any of: {:?}",
159                    SamplerMinFilter::VALID_SAMPLER_MIN_FILTER
160                )
161            }
162
163            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
164            where
165                E: de::Error,
166            {
167                Ok((value as u32)
168                    .try_into()
169                    .map(Checked::Valid)
170                    .unwrap_or(Checked::Invalid))
171            }
172        }
173        deserializer.deserialize_u32(Visitor)
174    }
175}
176
177pub const CLAMP_TO_EDGE: u32 = 33071;
178pub const MIRRORED_REPEAT: u32 = 33648;
179pub const REPEAT: u32 = 10497;
180
181#[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
182pub enum SamplerWrap {
183    #[default]
184    ClampToEdge,
185    MirroredRepeat,
186    Repeat,
187}
188
189impl From<SamplerWrap> for u32 {
190    fn from(value: SamplerWrap) -> Self {
191        match value {
192            SamplerWrap::ClampToEdge => CLAMP_TO_EDGE,
193            SamplerWrap::MirroredRepeat => MIRRORED_REPEAT,
194            SamplerWrap::Repeat => REPEAT,
195        }
196    }
197}
198
199impl TryFrom<u32> for SamplerWrap {
200    type Error = ();
201
202    fn try_from(value: u32) -> Result<Self, Self::Error> {
203        match value {
204            CLAMP_TO_EDGE => Ok(SamplerWrap::ClampToEdge),
205            MIRRORED_REPEAT => Ok(SamplerWrap::MirroredRepeat),
206            REPEAT => Ok(SamplerWrap::Repeat),
207            _ => Err(()),
208        }
209    }
210}
211
212impl SamplerWrap {
213    pub const VALID_SAMPLER_WRAP: &[u32] = &[CLAMP_TO_EDGE, MIRRORED_REPEAT, REPEAT];
214}
215
216impl Serialize for SamplerWrap {
217    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
218    where
219        S: serde::Serializer,
220    {
221        serializer.serialize_u32((*self).into())
222    }
223}
224
225impl<'de> Deserialize<'de> for Checked<SamplerWrap> {
226    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
227    where
228        D: serde::Deserializer<'de>,
229    {
230        struct Visitor;
231        impl de::Visitor<'_> for Visitor {
232            type Value = Checked<SamplerWrap>;
233
234            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
235                write!(f, "any of: {:?}", SamplerWrap::VALID_SAMPLER_WRAP)
236            }
237
238            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
239            where
240                E: de::Error,
241            {
242                Ok((value as u32)
243                    .try_into()
244                    .map(Checked::Valid)
245                    .unwrap_or(Checked::Invalid))
246            }
247        }
248        deserializer.deserialize_u32(Visitor)
249    }
250}
251
252#[derive(Clone, Debug, serde_derive::Deserialize, serde_derive::Serialize, Validate, Default)]
253pub struct Sampler {
254    #[serde(rename = "magFilter", default = "default_mag_filter")]
255    pub mag_filter: Checked<SamplerMagFilter>,
256    #[serde(rename = "minFilter", default = "default_min_filter")]
257    pub min_filter: Checked<SamplerMinFilter>,
258    #[serde(rename = "wrapS", default = "default_wrap")]
259    pub wrap_s: Checked<SamplerWrap>,
260    #[serde(rename = "wrapT", default = "default_wrap")]
261    pub wrap_t: Checked<SamplerWrap>,
262    #[serde(skip_serializing_if = "Option::is_none")]
263    pub name: Option<String>,
264}
265
266fn default_mag_filter() -> Checked<SamplerMagFilter> {
267    Checked::Valid(SamplerMagFilter::Linear)
268}
269
270fn default_min_filter() -> Checked<SamplerMinFilter> {
271    Checked::Valid(SamplerMinFilter::LinearMipmapNearest)
272}
273
274fn default_wrap() -> Checked<SamplerWrap> {
275    Checked::Valid(SamplerWrap::Repeat)
276}
277
278pub const ALPHA: u32 = 6406;
279pub const RGB: u32 = 6407;
280pub const RGBA: u32 = 6408;
281pub const LUMINANCE: u32 = 6409;
282pub const LUMINANCE_ALPHA: u32 = 6410;
283
284#[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
285pub enum TextureFormat {
286    Alpha,
287    Rgb,
288    #[default]
289    Rgba,
290    Luminance,
291    LuminanceAlpha,
292}
293
294impl From<TextureFormat> for u32 {
295    fn from(value: TextureFormat) -> Self {
296        match value {
297            TextureFormat::Alpha => ALPHA,
298            TextureFormat::Rgb => RGB,
299            TextureFormat::Rgba => RGBA,
300            TextureFormat::Luminance => LUMINANCE,
301            TextureFormat::LuminanceAlpha => LUMINANCE_ALPHA,
302        }
303    }
304}
305
306impl TryFrom<u32> for TextureFormat {
307    type Error = ();
308
309    fn try_from(value: u32) -> Result<Self, Self::Error> {
310        match value {
311            ALPHA => Ok(TextureFormat::Alpha),
312            RGB => Ok(TextureFormat::Rgb),
313            RGBA => Ok(TextureFormat::Rgba),
314            LUMINANCE => Ok(TextureFormat::Luminance),
315            LUMINANCE_ALPHA => Ok(TextureFormat::LuminanceAlpha),
316            _ => Err(()),
317        }
318    }
319}
320
321impl TextureFormat {
322    pub const VALID_TEXTURE_FORMAT: &[u32] = &[ALPHA, RGB, RGBA, LUMINANCE, LUMINANCE_ALPHA];
323}
324
325impl Serialize for TextureFormat {
326    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
327    where
328        S: serde::Serializer,
329    {
330        serializer.serialize_u32((*self).into())
331    }
332}
333
334impl<'de> Deserialize<'de> for Checked<TextureFormat> {
335    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
336    where
337        D: serde::Deserializer<'de>,
338    {
339        struct Visitor;
340        impl serde::de::Visitor<'_> for Visitor {
341            type Value = Checked<TextureFormat>;
342
343            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
344                write!(f, "any of: {:?}", TextureFormat::VALID_TEXTURE_FORMAT)
345            }
346
347            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
348            where
349                E: de::Error,
350            {
351                Ok((value as u32)
352                    .try_into()
353                    .map(Checked::Valid)
354                    .unwrap_or(Checked::Invalid))
355            }
356        }
357        deserializer.deserialize_u32(Visitor)
358    }
359}
360
361pub const TEXTURE_2D: u32 = 3553;
362
363#[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
364pub enum TextureTarget {
365    #[default]
366    Texture2d,
367}
368
369impl From<TextureTarget> for u32 {
370    fn from(value: TextureTarget) -> Self {
371        match value {
372            TextureTarget::Texture2d => TEXTURE_2D,
373        }
374    }
375}
376
377impl TryFrom<u32> for TextureTarget {
378    type Error = ();
379
380    fn try_from(value: u32) -> Result<Self, Self::Error> {
381        match value {
382            TEXTURE_2D => Ok(TextureTarget::Texture2d),
383            _ => Err(()),
384        }
385    }
386}
387
388impl TextureTarget {
389    pub const VALID_TEXTURE_TARGET: &[u32] = &[TEXTURE_2D];
390}
391
392impl Serialize for TextureTarget {
393    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
394    where
395        S: serde::Serializer,
396    {
397        serializer.serialize_u32((*self).into())
398    }
399}
400
401impl<'de> Deserialize<'de> for Checked<TextureTarget> {
402    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
403    where
404        D: serde::Deserializer<'de>,
405    {
406        struct Visitor;
407        impl de::Visitor<'_> for Visitor {
408            type Value = Checked<TextureTarget>;
409
410            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
411                write!(f, "any of: {:?}", TextureTarget::VALID_TEXTURE_TARGET)
412            }
413
414            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
415            where
416                E: de::Error,
417            {
418                Ok((value as u32)
419                    .try_into()
420                    .map(Checked::Valid)
421                    .unwrap_or(Checked::Invalid))
422            }
423        }
424        deserializer.deserialize_u32(Visitor)
425    }
426}
427
428pub const UNSIGNED_BYTE: u32 = 5121;
429pub const UNSIGNED_SHORT5_6_5: u32 = 33635;
430pub const UNSIGNED_SHORT4_4_4_4: u32 = 32819;
431pub const UNSIGNED_SHORT5_5_5_1: u32 = 32820;
432
433#[derive(Clone, Copy, Debug, Eq, PartialEq, Default)]
434pub enum TextureType {
435    #[default]
436    UnsignedByte,
437    UnsignedShort5_6_5,
438    UnsignedShort4_4_4_4,
439    UnsignedShort5_5_5_1,
440}
441
442impl From<TextureType> for u32 {
443    fn from(value: TextureType) -> Self {
444        match value {
445            TextureType::UnsignedByte => UNSIGNED_BYTE,
446            TextureType::UnsignedShort5_6_5 => UNSIGNED_SHORT5_6_5,
447            TextureType::UnsignedShort4_4_4_4 => UNSIGNED_SHORT4_4_4_4,
448            TextureType::UnsignedShort5_5_5_1 => UNSIGNED_SHORT5_5_5_1,
449        }
450    }
451}
452
453impl TryFrom<u32> for TextureType {
454    type Error = ();
455
456    fn try_from(value: u32) -> Result<Self, Self::Error> {
457        match value {
458            UNSIGNED_BYTE => Ok(TextureType::UnsignedByte),
459            UNSIGNED_SHORT5_6_5 => Ok(TextureType::UnsignedShort5_6_5),
460            UNSIGNED_SHORT4_4_4_4 => Ok(TextureType::UnsignedShort4_4_4_4),
461            UNSIGNED_SHORT5_5_5_1 => Ok(TextureType::UnsignedShort5_5_5_1),
462            _ => Err(()),
463        }
464    }
465}
466
467impl TextureType {
468    pub const VALID_TEXTURE_TYPE: &[u32] = &[
469        UNSIGNED_BYTE,
470        UNSIGNED_SHORT5_6_5,
471        UNSIGNED_SHORT4_4_4_4,
472        UNSIGNED_SHORT5_5_5_1,
473    ];
474}
475
476impl Serialize for TextureType {
477    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
478    where
479        S: serde::Serializer,
480    {
481        serializer.serialize_u32((*self).into())
482    }
483}
484
485impl<'de> Deserialize<'de> for Checked<TextureType> {
486    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
487    where
488        D: serde::Deserializer<'de>,
489    {
490        struct Visitor;
491        impl de::Visitor<'_> for Visitor {
492            type Value = Checked<TextureType>;
493
494            fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
495                write!(f, "any of: {:?}", TextureType::VALID_TEXTURE_TYPE)
496            }
497
498            fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
499            where
500                E: de::Error,
501            {
502                Ok((value as u32)
503                    .try_into()
504                    .map(Checked::Valid)
505                    .unwrap_or(Checked::Invalid))
506            }
507        }
508        deserializer.deserialize_u32(Visitor)
509    }
510}
511
512#[derive(Clone, Debug, serde_derive::Deserialize, serde_derive::Serialize, Validate)]
513pub struct Texture {
514    #[serde(default = "default_texture_format")]
515    pub format: Checked<TextureFormat>,
516    #[serde(rename = "internalFormat", default = "default_texture_format")]
517    pub internal_format: Checked<TextureFormat>,
518    pub sampler: StringIndex<Sampler>,
519    pub source: StringIndex<Image>,
520    #[serde(default = "default_texture_target")]
521    pub target: Checked<TextureTarget>,
522    #[serde(rename = "type", default = "default_texture_type")]
523    pub type_: Checked<TextureType>,
524    #[serde(skip_serializing_if = "Option::is_none")]
525    pub name: Option<String>,
526}
527
528impl Texture {
529    pub fn new(source: StringIndex<Image>, sampler: StringIndex<Sampler>) -> Self {
530        Self {
531            source,
532            format: Default::default(),
533            internal_format: Default::default(),
534            sampler,
535            target: Default::default(),
536            type_: Default::default(),
537            name: None,
538        }
539    }
540}
541
542fn default_texture_format() -> Checked<TextureFormat> {
543    Checked::Valid(TextureFormat::Rgba)
544}
545
546fn default_texture_target() -> Checked<TextureTarget> {
547    Checked::Valid(TextureTarget::Texture2d)
548}
549fn default_texture_type() -> Checked<TextureType> {
550    Checked::Valid(TextureType::UnsignedByte)
551}
552
553#[test]
554fn test_sampler_deserialize() {
555    let data = r#"{
556            "magFilter": 9729,
557            "minFilter": 9987,
558            "name": "user-defined sampler name",
559            "wrapS": 10497,
560            "wrapT": 10497,
561            "extensions" : {
562               "extension_name" : {
563                  "extension specific" : "value"
564               }
565            },
566            "extras" : {
567                "Application specific" : "The extra object can contain any properties."
568            }     
569        }"#;
570    let sampler: Result<Sampler, _> = serde_json::from_str(data);
571    let sampler_unwrap = sampler.unwrap();
572    println!("{}", serde_json::to_string(&sampler_unwrap).unwrap());
573    assert_eq!(
574        Some("user-defined sampler name".to_string()),
575        sampler_unwrap.name
576    );
577}
578
579#[test]
580fn test_texture_deserialize() {
581    let data = r#"{
582            "format": 6408,
583            "internalFormat": 6408,
584            "name": "user-defined texture name",
585            "sampler": "sampler_id",
586            "source": "image_id",
587            "target": 3553,
588            "type": 5121,
589            "extensions" : {
590               "extension_name" : {
591                  "extension specific" : "value"
592               }
593            },
594            "extras" : {
595                "Application specific" : "The extra object can contain any properties."
596            }     
597        }"#;
598    let texture: Result<Texture, _> = serde_json::from_str(data);
599    let texture_unwrap = texture.unwrap();
600    println!("{}", serde_json::to_string(&texture_unwrap).unwrap());
601    assert_eq!(
602        Some("user-defined texture name".to_string()),
603        texture_unwrap.name
604    );
605}