1use alloc::borrow::Cow;
2use ownable::IntoOwned;
3use serde::Deserialize;
4
5use crate::texture::Texture;
6use crate::{Extensions, Extras, Idx};
7
8fn default_base_color_factor() -> [f32; 4] {
9 [1.0; 4]
10}
11
12fn one_f32() -> f32 {
13 1.0
14}
15
16fn half_f32() -> f32 {
17 0.5
18}
19
20#[derive(Debug, Clone, Deserialize, IntoOwned)]
22pub struct TextureInfo<'a> {
23 pub index: Idx<Texture<'static>>,
25 #[serde(rename = "texCoord")]
27 #[serde(default)]
28 pub texcoord: u64,
29
30 #[serde(borrow)]
31 pub extensions: Option<Extensions<'a>>,
32 #[serde(borrow)]
33 pub extras: Option<Extras<'a>>,
34}
35
36#[derive(Debug, Clone, Deserialize, IntoOwned)]
38pub struct NormalTextureInfo<'a> {
39 #[serde(flatten, borrow)]
40 pub inner: TextureInfo<'a>,
41 #[serde(default = "one_f32")]
43 pub scale: f32,
44}
45
46#[derive(Debug, Clone, Deserialize, IntoOwned)]
48pub struct OcclusionTextureInfo<'a> {
49 #[serde(flatten, borrow)]
50 pub inner: TextureInfo<'a>,
51 #[serde(default = "one_f32")]
53 pub strength: f32,
54}
55
56#[derive(Debug, Clone, Deserialize, IntoOwned)]
59pub struct PbrMetallicRoughness<'a> {
60 #[serde(rename = "baseColorTexture")]
62 #[serde(borrow)]
63 pub base_color_texture: Option<TextureInfo<'a>>,
64 #[serde(rename = "metallicRoughnessTexture")]
65 #[serde(borrow)]
66 pub metallic_roughness_texture: Option<TextureInfo<'a>>,
67
68 #[serde(rename = "baseColorFactor")]
70 #[serde(default = "default_base_color_factor")]
71 pub base_color_factor: [f32; 4],
72 #[serde(rename = "metallicFactor")]
74 #[serde(default = "one_f32")]
75 pub metallic_factor: f32,
76 #[serde(rename = "roughnessFactor")]
78 #[serde(default = "one_f32")]
79 pub roughness_factor: f32,
80
81 #[serde(borrow)]
82 pub extensions: Option<Extensions<'a>>,
83 #[serde(borrow)]
84 pub extras: Option<Extras<'a>>,
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq)]
89pub enum AlphaModeEnum {
90 Opaque,
91 Mask,
92 Blend,
93}
94
95#[derive(Clone, PartialEq, Eq, Deserialize, IntoOwned)]
97#[serde(transparent)]
98pub struct AlphaMode<'a>(#[serde(borrow)] pub Cow<'a, str>);
99
100impl Default for AlphaMode<'_> {
101 fn default() -> Self {
102 Self::OPAQUE
103 }
104}
105
106impl core::fmt::Debug for AlphaMode<'_> {
107 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
108 if let Some(e) = self.to_enum() {
109 e.fmt(f)
110 } else {
111 self.0.fmt(f)
112 }
113 }
114}
115
116impl AlphaMode<'_> {
117 pub const OPAQUE: Self = Self(Cow::Borrowed("OPAQUE"));
118 pub const MASK: Self = Self(Cow::Borrowed("MASK"));
119 pub const BLEND: Self = Self(Cow::Borrowed("BLEND"));
120
121 pub fn to_enum(&self) -> Option<AlphaModeEnum> {
122 if *self == Self::OPAQUE {
123 return Some(AlphaModeEnum::Opaque);
124 } else if *self == Self::MASK {
125 return Some(AlphaModeEnum::Mask);
126 } else if *self == Self::BLEND {
127 return Some(AlphaModeEnum::Blend);
128 }
129
130 None
131 }
132}
133
134#[derive(Debug, Clone, Deserialize, IntoOwned)]
136pub struct Material<'a> {
137 #[serde(borrow)]
139 pub name: Option<Cow<'a, str>>,
140
141 #[serde(rename = "pbrMetallicRoughness")]
144 #[serde(borrow)]
145 pub pbr_metallic_roughness: Option<PbrMetallicRoughness<'a>>,
146 #[serde(rename = "normalTexture")]
148 #[serde(borrow)]
149 pub normal_texture: Option<NormalTextureInfo<'a>>,
150 #[serde(rename = "occlusionTexture")]
152 #[serde(borrow)]
153 pub occlusion_texture: Option<OcclusionTextureInfo<'a>>,
154 #[serde(rename = "emissiveTexture")]
156 #[serde(borrow)]
157 pub emissive_texture: Option<TextureInfo<'a>>,
158 #[serde(rename = "emissiveFactor")]
160 #[serde(default)]
161 pub emissive_factor: [f32; 3],
162 #[serde(rename = "alphaMode")]
164 #[serde(default)]
165 pub alpha_mode: AlphaMode<'a>,
166 #[serde(rename = "alphaCutoff")]
168 #[serde(default = "half_f32")]
169 pub alpha_cutoff: f32,
170 #[serde(rename = "doubleSided")]
172 #[serde(default)]
173 pub double_sided: bool,
174
175 #[serde(borrow)]
176 pub extensions: Option<Extensions<'a>>,
177 #[serde(borrow)]
178 pub extras: Option<Extras<'a>>,
179}