mesh_tools/
builder_material_specular.rs

1use crate::builder::GltfBuilder;
2use crate::models::{MaterialExtensions, PbrSpecularGlossiness, TextureInfo};
3
4impl GltfBuilder {
5    /// Add a material using the specular-glossiness workflow to the glTF document
6    /// 
7    /// This function allows you to create a PBR material using the specular-glossiness workflow
8    /// as defined in the KHR_materials_pbrSpecularGlossiness extension.
9    /// 
10    /// # Parameters
11    /// 
12    /// * `name` - Optional name for the material
13    /// * `diffuse_factor` - Optional RGBA diffuse color array `[r, g, b, a]` where each component is in range 0.0-1.0
14    /// * `diffuse_texture` - Optional index of a texture containing diffuse color values
15    /// * `specular_factor` - Optional RGB specular color array `[r, g, b]` where each component is in range 0.0-1.0
16    /// * `glossiness_factor` - Optional glossiness value in range 0.0-1.0 (0.0 = rough, 1.0 = smooth)
17    /// * `specular_glossiness_texture` - Optional index of a texture containing specular and glossiness values
18    /// * `normal_texture` - Optional index of a normal map texture
19    /// * `occlusion_texture` - Optional index of an occlusion map texture
20    /// * `emissive_texture` - Optional index of an emissive map texture
21    /// * `emissive_factor` - Optional RGB emissive color array `[r, g, b]` where each component is in range 0.0-1.0
22    /// * `alpha_mode` - Optional alpha rendering mode ("OPAQUE", "MASK", or "BLEND")
23    /// * `alpha_cutoff` - Optional alpha cutoff value for "MASK" mode
24    /// * `double_sided` - Optional flag to enable double-sided rendering
25    /// 
26    /// # Returns
27    /// 
28    /// The index of the created material in the glTF document
29    pub fn add_specular_glossiness_material(
30        &mut self,
31        name: Option<String>,
32        diffuse_factor: Option<[f32; 4]>,
33        diffuse_texture: Option<usize>,
34        specular_factor: Option<[f32; 3]>,
35        glossiness_factor: Option<f32>,
36        specular_glossiness_texture: Option<usize>,
37        normal_texture: Option<usize>,
38        occlusion_texture: Option<usize>,
39        emissive_texture: Option<usize>,
40        emissive_factor: Option<[f32; 3]>,
41        alpha_mode: Option<String>,
42        alpha_cutoff: Option<f32>,
43        double_sided: Option<bool>,
44    ) -> usize {
45        // Register the extension in the glTF document
46        if self.gltf.extensions_used.is_none() {
47            self.gltf.extensions_used = Some(vec!["KHR_materials_pbrSpecularGlossiness".to_string()]);
48        } else if let Some(ext_used) = &mut self.gltf.extensions_used {
49            if !ext_used.contains(&"KHR_materials_pbrSpecularGlossiness".to_string()) {
50                ext_used.push("KHR_materials_pbrSpecularGlossiness".to_string());
51            }
52        }
53        
54        // Create the material
55        let mut material = crate::models::Material::default();
56        material.name = name;
57        
58        // Set optional properties
59        if alpha_mode.is_some() {
60            material.alpha_mode = alpha_mode;
61        }
62        
63        if alpha_cutoff.is_some() {
64            material.alpha_cutoff = alpha_cutoff;
65        }
66        
67        if double_sided.is_some() {
68            material.double_sided = double_sided;
69        }
70        
71        if emissive_factor.is_some() {
72            material.emissive_factor = emissive_factor;
73        }
74        
75        // Create texture infos if needed
76        if let Some(normal_texture_index) = normal_texture {
77            material.normal_texture = Some(crate::models::NormalTextureInfo {
78                index: normal_texture_index,
79                tex_coord: Some(0),
80                scale: Some(1.0),
81            });
82        }
83        
84        if let Some(occlusion_texture_index) = occlusion_texture {
85            material.occlusion_texture = Some(crate::models::OcclusionTextureInfo {
86                index: occlusion_texture_index,
87                tex_coord: Some(0),
88                strength: Some(1.0),
89            });
90        }
91        
92        if let Some(emissive_texture_index) = emissive_texture {
93            material.emissive_texture = Some(TextureInfo {
94                index: emissive_texture_index,
95                tex_coord: Some(0),
96            });
97        }
98        
99        // Create specular-glossiness extension
100        let mut pbr_specular_glossiness = PbrSpecularGlossiness::default();
101        
102        pbr_specular_glossiness.diffuse_factor = diffuse_factor;
103        pbr_specular_glossiness.specular_factor = specular_factor;
104        pbr_specular_glossiness.glossiness_factor = glossiness_factor;
105        
106        if let Some(diffuse_texture_index) = diffuse_texture {
107            pbr_specular_glossiness.diffuse_texture = Some(TextureInfo {
108                index: diffuse_texture_index,
109                tex_coord: Some(0),
110            });
111        }
112        
113        if let Some(specular_glossiness_texture_index) = specular_glossiness_texture {
114            pbr_specular_glossiness.specular_glossiness_texture = Some(TextureInfo {
115                index: specular_glossiness_texture_index,
116                tex_coord: Some(0),
117            });
118        }
119        
120        // Add extension to material
121        let material_extensions = MaterialExtensions {
122            pbr_specular_glossiness: Some(pbr_specular_glossiness),
123        };
124        
125        material.extensions = Some(material_extensions);
126        
127        // Add the material to the glTF document
128        self.add_material_direct(material)
129    }
130    
131    /// Create a simple specular material with the specified diffuse and specular colors
132    ///
133    /// # Parameters
134    ///
135    /// * `name` - Optional name for the material
136    /// * `diffuse_color` - RGBA diffuse color array `[r, g, b, a]`
137    /// * `specular_color` - RGB specular color array `[r, g, b]`
138    /// * `glossiness` - Glossiness value between 0.0 (rough) and 1.0 (smooth)
139    ///
140    /// # Returns
141    ///
142    /// The index of the created material in the glTF document
143    pub fn create_specular_material(
144        &mut self,
145        name: Option<String>,
146        diffuse_color: [f32; 4],
147        specular_color: [f32; 3],
148        glossiness: f32,
149    ) -> usize {
150        self.add_specular_glossiness_material(
151            name,
152            Some(diffuse_color),
153            None,
154            Some(specular_color),
155            Some(glossiness),
156            None,
157            None,
158            None,
159            None,
160            None,
161            Some("OPAQUE".to_string()),
162            None,
163            Some(false),
164        )
165    }
166    
167    /// Add a material directly to the glTF document
168    ///
169    /// This is an internal helper method used by the material creation methods.
170    fn add_material_direct(&mut self, material: crate::models::Material) -> usize {
171        if let Some(materials) = &mut self.gltf.materials {
172            let index = materials.len();
173            materials.push(material);
174            index
175        } else {
176            self.gltf.materials = Some(vec![material]);
177            0
178        }
179    }
180}