mesh_tools/
builder_texture.rs

1use crate::builder::GltfBuilder;
2use crate::constants::{sampler_filter, sampler_wrap};
3use crate::error::Result;
4use crate::models::{Image, Sampler, Texture};
5use crate::texture;
6use image::DynamicImage;
7
8impl GltfBuilder {
9    /// Add a material with a texture to the glTF document
10    pub fn add_textured_material(&mut self, name: Option<String>, 
11                               base_color_texture: Option<usize>,
12                               metallic_roughness_texture: Option<usize>,
13                               normal_texture: Option<usize>,
14                               occlusion_texture: Option<usize>,
15                               emissive_texture: Option<usize>,
16                               emissive_factor: Option<[f32; 3]>,
17                               metallic_factor: Option<f32>,
18                               roughness_factor: Option<f32>,
19                               alpha_mode: Option<String>,
20                               alpha_cutoff: Option<f32>,
21                               double_sided: Option<bool>) -> usize {
22        use crate::material;
23        
24        let material = material::create_textured_material(
25            name,
26            base_color_texture,
27            metallic_roughness_texture,
28            normal_texture,
29            occlusion_texture,
30            emissive_texture,
31            emissive_factor,
32            metallic_factor,
33            roughness_factor,
34            alpha_mode,
35            alpha_cutoff,
36            double_sided
37        );
38        
39        if let Some(materials) = &mut self.gltf.materials {
40            let index = materials.len();
41            materials.push(material);
42            index
43        } else {
44            self.gltf.materials = Some(vec![material]);
45            0
46        }
47    }
48    
49    /// Create a basic textured material
50    pub fn create_textured_material(&mut self, name: Option<String>, 
51                                  base_color_texture: usize) -> usize {
52        self.add_textured_material(
53            name,
54            Some(base_color_texture),
55            None,
56            None,
57            None,
58            None,
59            None,
60            Some(1.0),
61            Some(1.0),
62            None,
63            None,
64            None
65        )
66    }
67    
68    /// Add an image to the glTF document from a DynamicImage using the specified format
69    pub(crate) fn add_image_from_dynamic_image(&mut self, name: Option<String>, 
70                                       image: &DynamicImage, 
71                                       format: texture::TextureFormat) -> Result<usize> {
72        let bytes = texture::image_to_bytes(image, format)?;
73        
74        Ok(self.add_image_from_buffer(name, format.mime_type().to_string(), &bytes))
75    }
76    
77    /// Create a default texture sampler with reasonable settings
78    pub fn create_default_sampler(&mut self) -> usize {
79        self.add_sampler(
80            Some(sampler_filter::LINEAR),
81            Some(sampler_filter::LINEAR_MIPMAP_LINEAR),
82            Some(sampler_wrap::REPEAT),
83            Some(sampler_wrap::REPEAT)
84        )
85    }
86    
87    /// Create a default texture from a DynamicImage (uses default sampler)
88    pub fn create_texture_from_image(&mut self, name: Option<String>, 
89                                   image: &DynamicImage, 
90                                   format: texture::TextureFormat) -> Result<usize> {
91        // Add the image
92        let image_index = self.add_image_from_dynamic_image(name.clone(), image, format)?;
93        
94        // Create a new default sampler for this texture
95        let sampler_index = self.create_default_sampler();
96        
97        // Create the texture
98        Ok(self.add_texture(name, image_index, Some(sampler_index)))
99    }
100    
101    /// Create a checkerboard texture (for testing)
102    pub fn create_checkerboard_texture(&mut self, 
103                                     width: u32, 
104                                     height: u32, 
105                                     cell_size: u32,
106                                     color1: [u8; 3],
107                                     color2: [u8; 3]) -> Result<usize> {
108        let image = texture::create_colored_checkerboard(
109            width, 
110            height, 
111            cell_size, 
112            color1, 
113            color2
114        );
115        
116        self.create_texture_from_image(Some("checkerboard".to_string()), &image, texture::TextureFormat::PNG)
117    }
118    
119    /// Create a UV test pattern texture (for testing)
120    pub fn create_uv_test_texture(&mut self, width: u32, height: u32) -> Result<usize> {
121        let image = texture::create_uv_test_pattern(width, height);
122        
123        self.create_texture_from_image(Some("uv_test".to_string()), &image, texture::TextureFormat::PNG)
124    }
125    
126    /// Add a sampler to the glTF document
127    pub(crate) fn add_sampler(&mut self, mag_filter: Option<usize>, min_filter: Option<usize>,
128                      wrap_s: Option<usize>, wrap_t: Option<usize>) -> usize {
129        let sampler = Sampler {
130            mag_filter: mag_filter,
131            min_filter: min_filter,
132            wrap_s: wrap_s,
133            wrap_t: wrap_t,
134        };
135        
136        if let Some(samplers) = &mut self.gltf.samplers {
137            let index = samplers.len();
138            samplers.push(sampler);
139            index
140        } else {
141            self.gltf.samplers = Some(vec![sampler]);
142            0
143        }
144    }
145    
146    /// Add an image to the glTF document
147    pub(crate) fn add_image_from_buffer(&mut self, name: Option<String>, 
148                               mime_type: String, data: &[u8]) -> usize {
149        // Add image data to buffer
150        let (offset, length) = self.add_buffer_data(data);
151        
152        // Create buffer view for image data
153        let buffer_view = self.add_buffer_view(offset, length, None);
154        
155        // Create image that references buffer view
156        let image = Image {
157            name,
158            uri: None,
159            mime_type: Some(mime_type),
160            buffer_view: Some(buffer_view),
161        };
162        
163        if let Some(images) = &mut self.gltf.images {
164            let index = images.len();
165            images.push(image);
166            index
167        } else {
168            self.gltf.images = Some(vec![image]);
169            0
170        }
171    }
172    
173    /// Add a texture to the glTF document
174    pub(crate) fn add_texture(&mut self, name: Option<String>, source: usize, 
175                      sampler: Option<usize>) -> usize {
176        let texture = Texture {
177            name,
178            source,
179            sampler,
180        };
181        
182        if let Some(textures) = &mut self.gltf.textures {
183            let index = textures.len();
184            textures.push(texture);
185            index
186        } else {
187            self.gltf.textures = Some(vec![texture]);
188            0
189        }
190    }
191}