rust/lib-hedgewars-engine/src/render/gear.rs
author alfadur
Thu, 12 Nov 2020 23:42:53 +0300
changeset 15760 ff1432e873bd
parent 15759 c929e25a7da2
child 15762 84c07aa94b61
permissions -rw-r--r--
safetize texture interface
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
     1
use crate::render::{
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
     2
    atlas::{AtlasCollection, SpriteIndex, SpriteLocation},
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
     3
    camera::Camera,
15760
ff1432e873bd safetize texture interface
alfadur
parents: 15759
diff changeset
     4
    gl::{Texture2D, TextureDataType, TextureFilter, TextureFormat, TextureInternalFormat},
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
     5
};
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
     6
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
     7
use integral_geometry::{Rect, Size};
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14729
diff changeset
     8
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
     9
use png::{ColorType, Decoder, DecodingError};
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    10
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    11
use std::{
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    12
    collections::HashMap,
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    13
    ffi::OsString,
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    14
    fs::{read_dir, File},
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    15
    io,
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    16
    io::BufReader,
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    17
    path::{Path, PathBuf},
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    18
};
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    19
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    20
#[derive(PartialEq, Debug, Clone, Copy)]
15760
ff1432e873bd safetize texture interface
alfadur
parents: 15759
diff changeset
    21
pub enum SpriteId {
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    22
    Mine = 0,
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    23
    Grenade,
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    24
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    25
    MaxSprite,
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    26
}
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    27
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    28
const SPRITE_LOAD_LIST: &[(SpriteId, &str)] = &[
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    29
    (
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    30
        SpriteId::Mine,
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    31
        "../../share/hedgewars/Data/Graphics/MineOn.png",
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    32
    ),
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    33
    (
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    34
        SpriteId::Grenade,
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    35
        "../../share/hedgewars/Data/Graphics/Bomb.png",
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    36
    ),
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    37
];
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    38
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    39
const MAX_SPRITES: usize = SpriteId::MaxSprite as usize + 1;
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    40
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    41
pub struct GearRenderer {
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14729
diff changeset
    42
    atlas: AtlasCollection,
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    43
    allocation: Box<[SpriteLocation; MAX_SPRITES]>,
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14729
diff changeset
    44
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14729
diff changeset
    45
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    46
struct SpriteData {
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    47
    size: Size,
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    48
    filename: PathBuf,
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    49
}
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    50
15290
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15288
diff changeset
    51
const ATLAS_SIZE: Size = Size::square(2048);
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14729
diff changeset
    52
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14729
diff changeset
    53
impl GearRenderer {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14729
diff changeset
    54
    pub fn new() -> Self {
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    55
        let mut atlas = AtlasCollection::new(ATLAS_SIZE);
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    56
15760
ff1432e873bd safetize texture interface
alfadur
parents: 15759
diff changeset
    57
        let texture = Texture2D::new(
ff1432e873bd safetize texture interface
alfadur
parents: 15759
diff changeset
    58
            ATLAS_SIZE,
ff1432e873bd safetize texture interface
alfadur
parents: 15759
diff changeset
    59
            TextureInternalFormat::Rgba8,
ff1432e873bd safetize texture interface
alfadur
parents: 15759
diff changeset
    60
            TextureFilter::Linear,
ff1432e873bd safetize texture interface
alfadur
parents: 15759
diff changeset
    61
        );
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    62
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    63
        let mut allocation = Box::new([(0, Rect::at_origin(Size::EMPTY)); MAX_SPRITES]);
15290
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15288
diff changeset
    64
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    65
        for (sprite, file) in SPRITE_LOAD_LIST {
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    66
            let path = Path::new(file);
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    67
            let size = load_sprite_size(path).expect(&format!("Unable to open {}", file));
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    68
            let index = atlas
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    69
                .insert_sprite(size)
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    70
                .expect(&format!("Could not store sprite {:?}", sprite));
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    71
            let (texture_index, rect) = atlas.get_rect(index).unwrap();
15290
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15288
diff changeset
    72
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    73
            let mut pixels = vec![0; size.area()].into_boxed_slice();
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    74
            load_sprite_pixels(path, mapgen::theme::slice_u32_to_u8_mut(&mut pixels[..]))
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    75
                .expect("Unable to load Graphics");
15290
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15288
diff changeset
    76
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    77
            texture.update(
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    78
                rect,
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    79
                mapgen::theme::slice_u32_to_u8_mut(&mut pixels[..]),
15760
ff1432e873bd safetize texture interface
alfadur
parents: 15759
diff changeset
    80
                None,
ff1432e873bd safetize texture interface
alfadur
parents: 15759
diff changeset
    81
                TextureFormat::Rgba,
ff1432e873bd safetize texture interface
alfadur
parents: 15759
diff changeset
    82
                TextureDataType::UnsignedByte,
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    83
            );
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    84
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    85
            allocation[*sprite as usize] = (texture_index, rect);
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    86
        }
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    87
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    88
        Self { atlas, allocation }
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14729
diff changeset
    89
    }
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    90
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    91
    pub fn render(&mut self, camera: &Camera) {
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    92
        let projection = camera.projection();
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    93
    }
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14729
diff changeset
    94
}
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    95
15290
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15288
diff changeset
    96
fn load_sprite_pixels(path: &Path, buffer: &mut [u8]) -> io::Result<Size> {
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    97
    let decoder = Decoder::new(BufReader::new(File::open(path)?));
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    98
    let (info, mut reader) = decoder.read_info()?;
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    99
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   100
    let size = Size::new(info.width as usize, info.height as usize);
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   101
    reader.next_frame(buffer)?;
15290
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15288
diff changeset
   102
    Ok(size)
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   103
}
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   104
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   105
fn load_sprite_size(path: &Path) -> io::Result<Size> {
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   106
    let decoder = Decoder::new(BufReader::new(File::open(path)?));
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   107
    let (info, mut reader) = decoder.read_info()?;
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   108
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   109
    let size = Size::new(info.width as usize, info.height as usize);
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   110
    Ok(size)
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   111
}
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   112
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   113
fn load_sprites(path: &Path) -> io::Result<Vec<SpriteData>> {
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   114
    let mut result = vec![];
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   115
    for file in read_dir(path)? {
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   116
        let file = file?;
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   117
        if let Some(extension) = file.path().extension() {
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   118
            if extension == "png" {
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   119
                let path = file.path();
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   120
                let sprite = load_sprite_size(&path)?;
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   121
                result.push(SpriteData {
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   122
                    size: sprite,
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   123
                    filename: path,
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   124
                });
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   125
            }
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   126
        }
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   127
    }
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   128
    Ok(result)
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   129
}