1use {
4 std::{
5 sync::RwLock,
6 collections::HashMap,
7 fmt::{
8 self,
9 Formatter
10 },
11 fs::File,
12 io::{
13 Cursor,
14 Read
15 },
16 str::SplitWhitespace,
17 sync::Arc
18 },
19 lazy_static,
20 vulkano::{
21 sync::GpuFuture,
22 device::Queue,
23 format::Format,
24 image::{
25 ImageDimensions,
26 ImmutableImage,
27 MipmapsCount,
28 view::ImageView
29 },
30 memory::pool::{
31 PotentialDedicatedAllocation,
32 StdMemoryPoolAlloc
33 },
34 sampler::{
35 Filter,
36 MipmapMode,
37 Sampler,
38 SamplerAddressMode
39 }
40 },
41 image::{
42 ImageDecoder,
43 codecs::bmp::BmpDecoder,
44 codecs::jpeg::JpegDecoder,
45 codecs::png::PngDecoder
46 },
47};
48lazy_static!{
49 static ref DEFAULT_TEXTURES: Arc<RwLock<HashMap<u32, Arc<Texture>>>> = Arc::new(RwLock::new(HashMap::new()));
50}
51
52pub struct Texture {
54 #[allow(clippy::type_complexity)]
55 pub img_view: Arc<ImageView<Arc<ImmutableImage<Format, PotentialDedicatedAllocation<StdMemoryPoolAlloc>>>>>,
56 pub sampler: Arc<Sampler>,
57}
58
59impl fmt::Debug for Texture{
60 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
61 write!(f, "texture debug todo")
62 }
63}
64
65impl Texture {
66 pub fn default(queue: Arc<Queue>) -> Arc<Self> {
68 if let Some(texture) = DEFAULT_TEXTURES.read().unwrap().get(&queue.id_within_family()) { return texture.clone();
70 }
71
72 let png_bytes = include_bytes!("./default_texture.png").to_vec();
73 let cursor = Cursor::new(png_bytes);
74 let decoder = PngDecoder::new(cursor).unwrap();
75
76 let (width, height) = decoder.dimensions();
77
78 let mut reader = decoder.into_reader().unwrap();
79
80 let dimensions = ImageDimensions::Dim2d {
81 width,
82 height,
83 array_layers: 1,
84 };
85
86 let mut image_data = Vec::new();
87 image_data.resize((width * height * 4) as usize, 0);
88
89 reader.read_exact(&mut image_data).unwrap();
90
91 let (image, future) = match ImmutableImage::from_iter(
92 image_data.iter().cloned(),
93 dimensions,
94 MipmapsCount::One,
95 Format::R8G8B8A8Srgb,
96 queue.clone(),
97 ) {
98 Ok(img) => img,
99 _ => unreachable!(),
100 };
101
102 Arc::new(future.boxed().then_signal_fence_and_flush().unwrap()).wait(None).unwrap();
103
104 let texture = Arc::new(
105 Texture {
106 img_view: ImageView::new(image).unwrap(),
107 sampler: Sampler::new( queue.device().clone(),
109 Filter::Nearest,
110 Filter::Nearest,
111 MipmapMode::Linear,
112 SamplerAddressMode::Repeat, SamplerAddressMode::Repeat,
114 SamplerAddressMode::Repeat,
115 0.0,
116 1.0,
117 0.0,
118 0.0
119 ).unwrap()
120 }
121 );
122
123 DEFAULT_TEXTURES.write().unwrap().insert(queue.id_within_family(), texture.clone());
124
125 texture
126 }
127
128 #[allow(unused_variables, unused_assignments, clippy::unused_io_amount)]
129 pub fn from_mtl_line(params: &mut SplitWhitespace, path: &str, queue: Arc<Queue>) -> Result<(Arc<Texture>, Box<dyn GpuFuture>), &'static str> {
130 let mut blendu = Filter::Linear;
131 let mut blendv = Filter::Linear;
132 let mut cc = false;
133 let mut clamp = SamplerAddressMode::Repeat;
134 let mut mm = (0.0, 1.0); let mut o = (0.0, 0.0, 0.0); let mut s = (1.0, 1.0, 1.0);
137 let mut t = (0.0, 0.0, 0.0);
138 let mut texres = None;
139
140 let mut incomplete = String::new();
141 for part in params.clone() {
142 let part = incomplete + part;
143 incomplete = String::new();
144 match part.as_str() {
145 _ if part.ends_with(".png") => { let part = part.replace("\\", "/");
147 let texture_path = path.rsplitn(2, '/').nth(1).unwrap().to_owned() + "/" + part.as_str();
148 let (texture, tex_future) = {
149 let mut file = File::open(texture_path).unwrap();
150 let mut buffer = Vec::new();
151 file.read_to_end(&mut buffer).unwrap();
152 let cursor = Cursor::new(buffer);
153 let decoder = PngDecoder::new(cursor).unwrap();
154 let (width, height) = decoder.dimensions();
155 let mut reader = decoder.into_reader().unwrap();
156 let dimensions = ImageDimensions::Dim2d {
157 width,
158 height,
159 array_layers: 1,
160 };
161 let mut image_data = Vec::new();
162 image_data.resize((width * height * 4) as usize, 0);
163 reader.read_exact(&mut image_data).unwrap();
164
165 let (image, future) = ImmutableImage::from_iter(
166 image_data.iter().cloned(),
167 dimensions,
168 MipmapsCount::One,
169 Format::R8G8B8A8Srgb,
170 queue.clone(),
171 )
172 .unwrap();
173
174 (ImageView::new(image).unwrap(), future)
175 };
176
177 return Ok((
178 Arc::new(
179 Texture {
180 img_view: texture,
181 sampler: Sampler::new(
182 queue.device().clone(),
183 blendu,
184 blendv,
185 MipmapMode::Linear,
186 clamp,
187 clamp,
188 clamp,
189 0.0,
190 1.0,
191 0.0,
192 0.0
193 ).unwrap(),
194 }
196 ),
197 tex_future.boxed()
198 ));
199 },
200
201 _ if part.ends_with(".jpg") || part.ends_with(".jpeg") => {
203 let part = part.replace("\\", "/");
204 let texture_path = path.rsplitn(2, '/').nth(1).unwrap().to_owned() + "/" + part.as_str();
205 let (texture, tex_future) = {
206 let mut file = File::open(&texture_path).unwrap_or_else(|_| panic!("The texture \"{}\" does not exist.", texture_path));
207 let mut buffer = Vec::new();
208 file.read_to_end(&mut buffer).unwrap();
209 let cursor = Cursor::new(buffer);
210 let decoder = JpegDecoder::new(cursor).unwrap();
211 let (width, height) = decoder.dimensions();
212 let mut reader = decoder.into_reader().unwrap();
213 let dimensions = ImageDimensions::Dim2d {
214 width,
215 height,
216 array_layers: 1,
217 };
218 let mut image_data = Vec::new();
219 image_data.resize((width * height * 4) as usize, 0);
220 reader.read(&mut image_data).unwrap();
221
222 let (image, future) = ImmutableImage::from_iter(
223 image_data.iter().cloned(),
224 dimensions,
225 MipmapsCount::One,
226 Format::R8G8B8Srgb,
227 queue.clone(),
228 )
229 .unwrap();
230
231 (ImageView::new(image).unwrap(), future)
232 };
233 return Ok((
234 Arc::new(
235 Texture {
236 img_view: texture,
237 sampler: Sampler::new(
238 queue.device().clone(),
239 blendu,
240 blendv,
241 MipmapMode::Linear,
242 clamp,
243 clamp,
244 clamp,
245 0.0,
246 1.0,
247 0.0,
248 0.0
249 ).unwrap(),
250 }
252 ),
253 tex_future.boxed()
254 ));
255 },
256
257 _ if part.ends_with(".bmp") => { let part = part.replace("\\", "/");
260 let texture_path = path.rsplitn(2, '/').nth(1).unwrap().to_owned() + "/" + part.as_str();
261 let (texture, tex_future) = {
262 let mut file = File::open(texture_path).unwrap();
263 let mut buffer = Vec::new();
264 file.read_to_end(&mut buffer).unwrap();
265 let cursor = Cursor::new(buffer);
266 let decoder = BmpDecoder::new(cursor).unwrap();
267 let (width, height) = decoder.dimensions();
268 let mut reader = decoder.into_reader().unwrap();
269 let dimensions = ImageDimensions::Dim2d {
270 width,
271 height,
272 array_layers: 1, };
274 let mut image_data = Vec::new();
275 image_data.resize((width * height * 4) as usize, 0);
276 reader.read_exact(&mut image_data).unwrap();
277
278 let (image, future) = ImmutableImage::from_iter(
279 image_data.iter().cloned(),
280 dimensions,
281 MipmapsCount::One,
282 Format::R8G8B8Srgb,
283 queue.clone(),
284 ).unwrap();
285
286 (ImageView::new(image).unwrap(), future)
287 };
288 return Ok((
289 Arc::new(
290 Texture {
291 img_view: texture,
292 sampler: Sampler::new(
293 queue.device().clone(),
294 blendu,
295 blendv,
296 MipmapMode::Linear,
297 clamp,
298 clamp,
299 clamp,
300 0.0,
301 1.0,
302 0.0,
303 0.0
304 ).unwrap(),
305 }
307 ),
308 tex_future.boxed()
309 ));
310 },
311
312 "-blendu" => blendu = match params.next().unwrap() {
313 "on" => Filter::Nearest,
315 "off" => Filter::Linear,
316 _ => panic!("formatting error in {}", path)
317 },
318 "-blendv" => blendv = match params.next().unwrap() {
319 "on" => Filter::Nearest,
321 "off" => Filter::Linear,
322 _ => panic!("formatting error in {}", path)
323 },
324 "-cc" => cc = match params.next().unwrap() {
325 "on" => true,
327 "off" => false,
328 _ => panic!("formatting error in {}", path)
329 },
330 "-clamp" => clamp = match params.next().unwrap() {
331 "on" => SamplerAddressMode::ClampToEdge,
336 "off" => SamplerAddressMode::Repeat,
337 _ => panic!("formatting error in {}", path)
338 },
339 "-mm" => mm = (
343 params.next().unwrap().parse::<f32>().unwrap_or_else(|_| panic!("formatting error in {}", path)),
344 params.next().unwrap().parse::<f32>().unwrap_or_else(|_| panic!("formatting error in {}", path))
345 ),
346
347 "-o" => o = ( params.next().unwrap().parse::<f32>().unwrap_or_else(|_| panic!("formatting error in {}", path)),
353 params.next().unwrap().parse::<f32>().unwrap_or_else(|_| panic!("formatting error in {}", path)), params.next().unwrap().parse::<f32>().unwrap_or_else(|_| panic!("formatting error in {}", path)), ),
356 "-s" => s = ( params.next().unwrap().parse::<f32>().unwrap_or_else(|_| panic!("formatting error in {}", path)),
358 params.next().unwrap().parse::<f32>().unwrap_or_else(|_| panic!("formatting error in {}", path)), params.next().unwrap().parse::<f32>().unwrap_or_else(|_| panic!("formatting error in {}", path)), ),
361 "-t" => t = ( params.next().unwrap().parse::<f32>().unwrap_or_else(|_| panic!("formatting error in {}", path)),
363 params.next().unwrap().parse::<f32>().unwrap_or_else(|_| panic!("formatting error in {}", path)), params.next().unwrap().parse::<f32>().unwrap_or_else(|_| panic!("formatting error in {}", path)), ),
366
367 "-texres" => texres = Some(params.next().unwrap().parse::<u32>().unwrap_or_else(|_| panic!("formatting error in {}", path))),
369
370 _ => incomplete = format!("{} ", part),
371 }
372 }
373 Err("No image data found") }
375}