rust/lib-hedgewars-engine/src/render/gear.rs
changeset 15765 713f89f6c6ab
parent 15764 b10bbfb2b354
child 15766 19ad3fe48ea6
equal deleted inserted replaced
15764:b10bbfb2b354 15765:713f89f6c6ab
     1 use crate::render::{
     1 use crate::render::{
     2     atlas::{AtlasCollection, SpriteIndex, SpriteLocation},
     2     atlas::{AtlasCollection, SpriteIndex},
     3     camera::Camera,
     3     camera::Camera,
     4     gl::{
     4     gl::{
     5         Buffer, BufferType, BufferUsage, InputElement, InputFormat, InputLayout, PipelineState,
     5         Buffer, BufferType, BufferUsage, InputElement, InputFormat, InputLayout, PipelineState,
     6         Shader, Texture2D, TextureDataType, TextureFilter, TextureFormat, TextureInternalFormat,
     6         Shader, Texture2D, TextureDataType, TextureFilter, TextureFormat, TextureInternalFormat,
     7         VariableBinding,
     7         VariableBinding,
    10 
    10 
    11 use integral_geometry::{Rect, Size};
    11 use integral_geometry::{Rect, Size};
    12 
    12 
    13 use png::{ColorType, Decoder, DecodingError};
    13 use png::{ColorType, Decoder, DecodingError};
    14 
    14 
       
    15 use std::ops::BitAnd;
    15 use std::{
    16 use std::{
    16     collections::HashMap,
    17     collections::HashMap,
    17     ffi::OsString,
    18     ffi::OsString,
    18     fs::{read_dir, File},
    19     fs::{read_dir, File},
    19     io,
    20     io,
    58     position: [f32; 2],
    59     position: [f32; 2],
    59     tex_coords: [f32; 2],
    60     tex_coords: [f32; 2],
    60 }
    61 }
    61 
    62 
    62 #[derive(PartialEq, Debug, Clone, Copy)]
    63 #[derive(PartialEq, Debug, Clone, Copy)]
       
    64 #[repr(u32)]
    63 pub enum SpriteId {
    65 pub enum SpriteId {
    64     Mine = 0,
    66     Mine = 0,
    65     Grenade,
    67     Grenade,
       
    68     Cheese,
       
    69     Cleaver,
    66 
    70 
    67     MaxSprite,
    71     MaxSprite,
    68 }
    72 }
    69 
    73 
    70 const SPRITE_LOAD_LIST: &[(SpriteId, &str)] = &[
    74 const SPRITE_LOAD_LIST: &[(SpriteId, &str)] = &[
    74     ),
    78     ),
    75     (
    79     (
    76         SpriteId::Grenade,
    80         SpriteId::Grenade,
    77         "../../share/hedgewars/Data/Graphics/Bomb.png",
    81         "../../share/hedgewars/Data/Graphics/Bomb.png",
    78     ),
    82     ),
       
    83     (
       
    84         SpriteId::Cheese,
       
    85         "../../share/hedgewars/Data/Graphics/cheese.png",
       
    86     ),
       
    87     (
       
    88         SpriteId::Cleaver,
       
    89         "../../share/hedgewars/Data/Graphics/cleaver.png",
       
    90     ),
    79 ];
    91 ];
    80 
    92 
    81 const MAX_SPRITES: usize = SpriteId::MaxSprite as usize + 1;
    93 const MAX_SPRITES: usize = SpriteId::MaxSprite as usize + 1;
       
    94 
       
    95 type SpriteTexCoords = (u32, [[f32; 2]; 4]);
    82 
    96 
    83 pub struct GearEntry {
    97 pub struct GearEntry {
    84     position: [f32; 2],
    98     position: [f32; 2],
    85     size: Size,
    99     size: Size,
    86 }
   100 }
    95 }
   109 }
    96 
   110 
    97 pub struct GearRenderer {
   111 pub struct GearRenderer {
    98     atlas: AtlasCollection,
   112     atlas: AtlasCollection,
    99     texture: Texture2D,
   113     texture: Texture2D,
   100     allocation: Box<[SpriteLocation; MAX_SPRITES]>,
   114     allocation: Box<[SpriteTexCoords; MAX_SPRITES]>,
   101     shader: Shader,
   115     shader: Shader,
   102     layout: InputLayout,
   116     layout: InputLayout,
   103     vertex_buffer: Buffer,
   117     vertex_buffer: Buffer,
   104 }
   118 }
   105 
   119 
   118             ATLAS_SIZE,
   132             ATLAS_SIZE,
   119             TextureInternalFormat::Rgba8,
   133             TextureInternalFormat::Rgba8,
   120             TextureFilter::Linear,
   134             TextureFilter::Linear,
   121         );
   135         );
   122 
   136 
   123         let mut allocation = Box::new([(0, Rect::at_origin(Size::EMPTY)); MAX_SPRITES]);
   137         let mut allocation = Box::new([Default::default(); MAX_SPRITES]);
   124 
   138 
   125         for (sprite, file) in SPRITE_LOAD_LIST {
   139         for (sprite, file) in SPRITE_LOAD_LIST {
   126             let path = Path::new(file);
   140             let path = Path::new(file);
   127             let size = load_sprite_size(path).expect(&format!("Unable to open {}", file));
   141             let size = load_sprite_size(path).expect(&format!("Unable to open {}", file));
   128             let index = atlas
   142             let index = atlas
   139                 None,
   153                 None,
   140                 TextureFormat::Rgba,
   154                 TextureFormat::Rgba,
   141                 TextureDataType::UnsignedByte,
   155                 TextureDataType::UnsignedByte,
   142             );
   156             );
   143 
   157 
   144             allocation[*sprite as usize] = (texture_index, rect);
   158             let mut tex_coords = [
       
   159                 [rect.left() as f32, rect.bottom() as f32 + 1.0],
       
   160                 [rect.right() as f32 + 1.0, rect.bottom() as f32 + 1.0],
       
   161                 [rect.left() as f32, rect.top() as f32],
       
   162                 [rect.right() as f32 + 1.0, rect.top() as f32],
       
   163             ]; //.map(|n| n as f32 / ATLAS_SIZE as f32);
       
   164 
       
   165             for coords in &mut tex_coords {
       
   166                 coords[0] /= ATLAS_SIZE.width as f32;
       
   167                 coords[1] /= ATLAS_SIZE.height as f32;
       
   168             }
       
   169 
       
   170             allocation[*sprite as usize] = (texture_index, tex_coords);
   145         }
   171         }
   146 
   172 
   147         let shader = Shader::new(
   173         let shader = Shader::new(
   148             VERTEX_SHADER,
   174             VERTEX_SHADER,
   149             Some(PIXEL_SHADER),
   175             Some(PIXEL_SHADER),
   183     }
   209     }
   184 
   210 
   185     pub fn render(&mut self, camera: &Camera, entries: &[GearEntry]) {
   211     pub fn render(&mut self, camera: &Camera, entries: &[GearEntry]) {
   186         let mut data = Vec::with_capacity(entries.len() * 6);
   212         let mut data = Vec::with_capacity(entries.len() * 6);
   187 
   213 
   188         for entry in entries {
   214         for (index, entry) in entries.iter().enumerate() {
       
   215             let sprite_id = match index & 0b11 {
       
   216                 0 => SpriteId::Mine,
       
   217                 1 => SpriteId::Grenade,
       
   218                 2 => SpriteId::Cheese,
       
   219                 _ => SpriteId::Cleaver,
       
   220             };
       
   221             let sprite_coords = &self.allocation[sprite_id as usize].1;
       
   222 
   189             let v = [
   223             let v = [
   190                 Vertex {
   224                 Vertex {
   191                     position: [
   225                     position: [
   192                         entry.position[0] - entry.size.width as f32 / 2.0,
   226                         entry.position[0] - entry.size.width as f32 / 2.0,
   193                         entry.position[1] + entry.size.height as f32 / 2.0,
   227                         entry.position[1] + entry.size.height as f32 / 2.0,
   194                     ],
   228                     ],
   195                     tex_coords: [0.0, 0.015625],
   229                     tex_coords: sprite_coords[0],
   196                 },
   230                 },
   197                 Vertex {
   231                 Vertex {
   198                     position: [
   232                     position: [
   199                         entry.position[0] + entry.size.width as f32 / 2.0,
   233                         entry.position[0] + entry.size.width as f32 / 2.0,
   200                         entry.position[1] + entry.size.height as f32 / 2.0,
   234                         entry.position[1] + entry.size.height as f32 / 2.0,
   201                     ],
   235                     ],
   202                     tex_coords: [0.015625, 0.015625],
   236                     tex_coords: sprite_coords[1],
   203                 },
   237                 },
   204                 Vertex {
   238                 Vertex {
   205                     position: [
   239                     position: [
   206                         entry.position[0] - entry.size.width as f32 / 2.0,
   240                         entry.position[0] - entry.size.width as f32 / 2.0,
   207                         entry.position[1] - entry.size.height as f32 / 2.0,
   241                         entry.position[1] - entry.size.height as f32 / 2.0,
   208                     ],
   242                     ],
   209                     tex_coords: [0.0, 0.0],
   243                     tex_coords: sprite_coords[2],
   210                 },
   244                 },
   211                 Vertex {
   245                 Vertex {
   212                     position: [
   246                     position: [
   213                         entry.position[0] + entry.size.width as f32 / 2.0,
   247                         entry.position[0] + entry.size.width as f32 / 2.0,
   214                         entry.position[1] - entry.size.height as f32 / 2.0,
   248                         entry.position[1] - entry.size.height as f32 / 2.0,
   215                     ],
   249                     ],
   216                     tex_coords: [0.015625, 0.0],
   250                     tex_coords: sprite_coords[3],
   217                 },
   251                 },
   218             ];
   252             ];
   219 
   253 
   220             data.extend_from_slice(&[v[0], v[1], v[2], v[1], v[3], v[2]]);
   254             data.extend_from_slice(&[v[0], v[1], v[2], v[1], v[3], v[2]]);
   221         }
   255         }