1use crate::models::{Material, NormalTextureInfo, OcclusionTextureInfo, PbrMetallicRoughness, TextureInfo};
31
32pub struct MaterialBuilder {
34 pub material: Material,
35}
36
37impl MaterialBuilder {
38 pub fn new(name: Option<String>) -> Self {
40 let mut material = Material::default();
41 material.name = name;
42
43 Self { material }
44 }
45
46 pub fn with_base_color(mut self, color: [f32; 4]) -> Self {
48 if self.material.pbr_metallic_roughness.is_none() {
49 self.material.pbr_metallic_roughness = Some(PbrMetallicRoughness::default());
50 }
51
52 if let Some(pbr) = &mut self.material.pbr_metallic_roughness {
53 pbr.base_color_factor = Some(color);
54 }
55
56 self
57 }
58
59 pub fn with_metallic_factor(mut self, factor: f32) -> Self {
61 if self.material.pbr_metallic_roughness.is_none() {
62 self.material.pbr_metallic_roughness = Some(PbrMetallicRoughness::default());
63 }
64
65 if let Some(pbr) = &mut self.material.pbr_metallic_roughness {
66 pbr.metallic_factor = Some(factor);
67 }
68
69 self
70 }
71
72 pub fn with_roughness_factor(mut self, factor: f32) -> Self {
74 if self.material.pbr_metallic_roughness.is_none() {
75 self.material.pbr_metallic_roughness = Some(PbrMetallicRoughness::default());
76 }
77
78 if let Some(pbr) = &mut self.material.pbr_metallic_roughness {
79 pbr.roughness_factor = Some(factor);
80 }
81
82 self
83 }
84
85 pub fn with_base_color_texture(mut self, texture_index: usize, tex_coord: Option<usize>) -> Self {
87 if self.material.pbr_metallic_roughness.is_none() {
88 self.material.pbr_metallic_roughness = Some(PbrMetallicRoughness::default());
89 }
90
91 if let Some(pbr) = &mut self.material.pbr_metallic_roughness {
92 let mut texture_info = TextureInfo::default();
93 texture_info.index = texture_index;
94 texture_info.tex_coord = tex_coord;
95
96 pbr.base_color_texture = Some(texture_info);
97 }
98
99 self
100 }
101
102 pub fn with_metallic_roughness_texture(mut self, texture_index: usize, tex_coord: Option<usize>) -> Self {
104 if self.material.pbr_metallic_roughness.is_none() {
105 self.material.pbr_metallic_roughness = Some(PbrMetallicRoughness::default());
106 }
107
108 if let Some(pbr) = &mut self.material.pbr_metallic_roughness {
109 let mut texture_info = TextureInfo::default();
110 texture_info.index = texture_index;
111 texture_info.tex_coord = tex_coord;
112
113 pbr.metallic_roughness_texture = Some(texture_info);
114 }
115
116 self
117 }
118
119 pub fn with_normal_texture(mut self, texture_index: usize, tex_coord: Option<usize>, scale: Option<f32>) -> Self {
121 let mut normal_info = NormalTextureInfo::default();
122 normal_info.index = texture_index;
123 normal_info.tex_coord = tex_coord;
124 normal_info.scale = scale;
125
126 self.material.normal_texture = Some(normal_info);
127
128 self
129 }
130
131 pub fn with_occlusion_texture(mut self, texture_index: usize, tex_coord: Option<usize>, strength: Option<f32>) -> Self {
133 let mut occlusion_info = OcclusionTextureInfo::default();
134 occlusion_info.index = texture_index;
135 occlusion_info.tex_coord = tex_coord;
136 occlusion_info.strength = strength;
137
138 self.material.occlusion_texture = Some(occlusion_info);
139
140 self
141 }
142
143 pub fn with_emissive_texture(mut self, texture_index: usize, tex_coord: Option<usize>) -> Self {
145 let mut texture_info = TextureInfo::default();
146 texture_info.index = texture_index;
147 texture_info.tex_coord = tex_coord;
148
149 self.material.emissive_texture = Some(texture_info);
150
151 self
152 }
153
154 pub fn with_emissive_factor(mut self, factor: [f32; 3]) -> Self {
156 self.material.emissive_factor = Some(factor);
157 self
158 }
159
160 pub fn with_alpha_mode(mut self, mode: String, cutoff: Option<f32>) -> Self {
162 self.material.alpha_mode = Some(mode);
163 self.material.alpha_cutoff = cutoff;
164 self
165 }
166
167 pub fn with_double_sided(mut self, double_sided: bool) -> Self {
169 self.material.double_sided = Some(double_sided);
170 self
171 }
172
173 pub fn build(self) -> Material {
175 self.material
176 }
177}
178
179pub fn create_basic_material(name: Option<String>, color: [f32; 4]) -> Material {
181 MaterialBuilder::new(name)
182 .with_base_color(color)
183 .build()
184}
185
186pub fn create_metallic_material(
188 name: Option<String>,
189 color: [f32; 4],
190 metallic: f32,
191 roughness: f32
192) -> Material {
193 MaterialBuilder::new(name)
194 .with_base_color(color)
195 .with_metallic_factor(metallic)
196 .with_roughness_factor(roughness)
197 .build()
198}
199
200pub fn create_textured_material(
202 name: Option<String>,
203 base_color_texture: Option<usize>,
204 metallic_roughness_texture: Option<usize>,
205 normal_texture: Option<usize>,
206 occlusion_texture: Option<usize>,
207 emissive_texture: Option<usize>,
208 emissive_factor: Option<[f32; 3]>,
209 metallic_factor: Option<f32>,
210 roughness_factor: Option<f32>,
211 alpha_mode: Option<String>,
212 alpha_cutoff: Option<f32>,
213 double_sided: Option<bool>
214) -> Material {
215 let mut builder = MaterialBuilder::new(name);
216
217 if let Some(texture) = base_color_texture {
218 builder = builder.with_base_color_texture(texture, None);
219 }
220
221 if let Some(texture) = metallic_roughness_texture {
222 builder = builder.with_metallic_roughness_texture(texture, None);
223 }
224
225 if let Some(texture) = normal_texture {
226 builder = builder.with_normal_texture(texture, None, None);
227 }
228
229 if let Some(texture) = occlusion_texture {
230 builder = builder.with_occlusion_texture(texture, None, None);
231 }
232
233 if let Some(texture) = emissive_texture {
234 builder = builder.with_emissive_texture(texture, None);
235 }
236
237 if let Some(factor) = emissive_factor {
238 builder = builder.with_emissive_factor(factor);
239 }
240
241 if let Some(factor) = metallic_factor {
242 builder = builder.with_metallic_factor(factor);
243 }
244
245 if let Some(factor) = roughness_factor {
246 builder = builder.with_roughness_factor(factor);
247 }
248
249 if let Some(mode) = alpha_mode {
250 builder = builder.with_alpha_mode(mode, alpha_cutoff);
251 }
252
253 if let Some(ds) = double_sided {
254 builder = builder.with_double_sided(ds);
255 }
256
257 builder.build()
258}