1 use super::{atlas::AtlasCollection, gl::Texture2D}; |
1 use crate::render::{ |
2 use crate::render::camera::Camera; |
2 atlas::{AtlasCollection, SpriteIndex, SpriteLocation}, |
|
3 camera::Camera, |
|
4 gl::Texture2D, |
|
5 }; |
3 |
6 |
4 use integral_geometry::{Rect, Size}; |
7 use integral_geometry::{Rect, Size}; |
5 |
8 |
6 use crate::render::atlas::SpriteIndex; |
|
7 use png::{ColorType, Decoder, DecodingError}; |
9 use png::{ColorType, Decoder, DecodingError}; |
8 use std::path::PathBuf; |
10 |
9 use std::{ |
11 use std::{ |
10 collections::HashMap, |
12 collections::HashMap, |
11 ffi::OsString, |
13 ffi::OsString, |
12 fs::{read_dir, File}, |
14 fs::{read_dir, File}, |
13 io, |
15 io, |
14 io::BufReader, |
16 io::BufReader, |
15 path::Path, |
17 path::{Path, PathBuf}, |
16 }; |
18 }; |
|
19 |
|
20 #[derive(PartialEq, Debug, Clone, Copy)] |
|
21 enum SpriteId { |
|
22 Mine = 0, |
|
23 Grenade, |
|
24 |
|
25 MaxSprite, |
|
26 } |
|
27 |
|
28 const SPRITE_LOAD_LIST: &[(SpriteId, &str)] = &[ |
|
29 ( |
|
30 SpriteId::Mine, |
|
31 "../../share/hedgewars/Data/Graphics/MineOn.png", |
|
32 ), |
|
33 ( |
|
34 SpriteId::Grenade, |
|
35 "../../share/hedgewars/Data/Graphics/Bomb.png", |
|
36 ), |
|
37 ]; |
|
38 |
|
39 const MAX_SPRITES: usize = SpriteId::MaxSprite as usize + 1; |
17 |
40 |
18 pub struct GearRenderer { |
41 pub struct GearRenderer { |
19 atlas: AtlasCollection, |
42 atlas: AtlasCollection, |
|
43 allocation: Box<[SpriteLocation; MAX_SPRITES]>, |
20 } |
44 } |
21 |
45 |
22 struct SpriteData { |
46 struct SpriteData { |
23 size: Size, |
47 size: Size, |
24 filename: PathBuf, |
48 filename: PathBuf, |
26 |
50 |
27 const ATLAS_SIZE: Size = Size::square(2048); |
51 const ATLAS_SIZE: Size = Size::square(2048); |
28 |
52 |
29 impl GearRenderer { |
53 impl GearRenderer { |
30 pub fn new() -> Self { |
54 pub fn new() -> Self { |
31 let mut lookup = Vec::with_capacity(2048); |
|
32 |
|
33 let mut atlas = AtlasCollection::new(ATLAS_SIZE); |
55 let mut atlas = AtlasCollection::new(ATLAS_SIZE); |
34 let mut sprites = load_sprites(Path::new("../../share/hedgewars/Data/Graphics/")) |
|
35 .expect("Unable to load Graphics"); |
|
36 let max_size = sprites |
|
37 .iter() |
|
38 .fold(Size::EMPTY, |size, sprite| size.join(sprite.size)); |
|
39 for sprite in sprites.drain(..) { |
|
40 lookup.push((sprite.filename, atlas.insert_sprite(sprite.size).unwrap())); |
|
41 } |
|
42 |
|
43 println!( |
|
44 "Filled atlas with {} sprites:\n{}", |
|
45 sprites.len(), |
|
46 atlas.used_space() |
|
47 ); |
|
48 |
56 |
49 let texture = Texture2D::new(ATLAS_SIZE, gl::RGBA8, gl::LINEAR); |
57 let texture = Texture2D::new(ATLAS_SIZE, gl::RGBA8, gl::LINEAR); |
50 |
58 |
51 let mut pixels = vec![0; max_size.area()].into_boxed_slice(); |
59 let mut allocation = Box::new([(0, Rect::at_origin(Size::EMPTY)); MAX_SPRITES]); |
52 let mut pixels_transposed = vec![0; max_size.area()].into_boxed_slice(); |
|
53 |
60 |
54 for (path, sprite_index) in lookup.drain(..) { |
61 for (sprite, file) in SPRITE_LOAD_LIST { |
55 if let Some((atlas_index, rect)) = atlas.get_rect(sprite_index) { |
62 let path = Path::new(file); |
56 let size = load_sprite_pixels(&path, mapgen::theme::slice_u32_to_u8_mut(&mut pixels[..])).expect("Unable to load Graphics"); |
63 let size = load_sprite_size(path).expect(&format!("Unable to open {}", file)); |
|
64 let index = atlas |
|
65 .insert_sprite(size) |
|
66 .expect(&format!("Could not store sprite {:?}", sprite)); |
|
67 let (texture_index, rect) = atlas.get_rect(index).unwrap(); |
57 |
68 |
58 let used_pixels = if size.width != rect.width() { |
69 let mut pixels = vec![0; size.area()].into_boxed_slice(); |
59 for y in 0..rect.height() { |
70 load_sprite_pixels(path, mapgen::theme::slice_u32_to_u8_mut(&mut pixels[..])) |
60 for x in 0..rect.width() { |
71 .expect("Unable to load Graphics"); |
61 pixels_transposed[y * rect.width() + x] = pixels[x * rect.height() + y]; |
|
62 } |
|
63 } |
|
64 &mut pixels_transposed[..] |
|
65 } else { |
|
66 &mut pixels[..] |
|
67 }; |
|
68 |
72 |
69 texture.update(rect, mapgen::theme::slice_u32_to_u8_mut(used_pixels), 0, gl::RGBA, gl::UNSIGNED_BYTE); |
73 texture.update( |
70 } |
74 rect, |
|
75 mapgen::theme::slice_u32_to_u8_mut(&mut pixels[..]), |
|
76 0, |
|
77 gl::RGBA, |
|
78 gl::UNSIGNED_BYTE, |
|
79 ); |
|
80 |
|
81 allocation[*sprite as usize] = (texture_index, rect); |
71 } |
82 } |
72 |
83 |
73 Self { atlas } |
84 Self { atlas, allocation } |
74 } |
85 } |
75 |
86 |
76 pub fn render(&mut self, camera: &Camera) { |
87 pub fn render(&mut self, camera: &Camera) { |
77 let projection = camera.projection(); |
88 let projection = camera.projection(); |
78 } |
89 } |