rust/lib-hedgewars-engine/src/render/gear.rs
author alfadur
Thu, 12 Nov 2020 00:24:58 +0300
changeset 15759 c929e25a7da2
parent 15291 07ab4206f2a9
child 15760 ff1432e873bd
permissions -rw-r--r--
allow finding sprites
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,
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
     4
    gl::Texture2D,
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)]
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    21
enum SpriteId {
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
15290
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15288
diff changeset
    57
        let texture = Texture2D::new(ATLAS_SIZE, gl::RGBA8, gl::LINEAR);
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    58
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    59
        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
    60
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    61
        for (sprite, file) in SPRITE_LOAD_LIST {
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    62
            let path = Path::new(file);
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    63
            let size = load_sprite_size(path).expect(&format!("Unable to open {}", file));
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    64
            let index = atlas
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    65
                .insert_sprite(size)
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    66
                .expect(&format!("Could not store sprite {:?}", sprite));
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    67
            let (texture_index, rect) = atlas.get_rect(index).unwrap();
15290
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15288
diff changeset
    68
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    69
            let mut pixels = vec![0; size.area()].into_boxed_slice();
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    70
            load_sprite_pixels(path, mapgen::theme::slice_u32_to_u8_mut(&mut pixels[..]))
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    71
                .expect("Unable to load Graphics");
15290
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15288
diff changeset
    72
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    73
            texture.update(
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    74
                rect,
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    75
                mapgen::theme::slice_u32_to_u8_mut(&mut pixels[..]),
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    76
                0,
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    77
                gl::RGBA,
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    78
                gl::UNSIGNED_BYTE,
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    79
            );
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    80
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    81
            allocation[*sprite as usize] = (texture_index, rect);
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    82
        }
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    83
15759
c929e25a7da2 allow finding sprites
alfadur
parents: 15291
diff changeset
    84
        Self { atlas, allocation }
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14729
diff changeset
    85
    }
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    86
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    87
    pub fn render(&mut self, camera: &Camera) {
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    88
        let projection = camera.projection();
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    89
    }
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14729
diff changeset
    90
}
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
    91
15290
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15288
diff changeset
    92
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
    93
    let decoder = Decoder::new(BufReader::new(File::open(path)?));
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    94
    let (info, mut reader) = decoder.read_info()?;
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    95
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    96
    let size = Size::new(info.width as usize, info.height as usize);
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
    97
    reader.next_frame(buffer)?;
15290
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15288
diff changeset
    98
    Ok(size)
15286
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
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   101
fn load_sprite_size(path: &Path) -> io::Result<Size> {
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   102
    let decoder = Decoder::new(BufReader::new(File::open(path)?));
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   103
    let (info, mut reader) = decoder.read_info()?;
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   104
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   105
    let size = Size::new(info.width as usize, info.height as usize);
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   106
    Ok(size)
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   107
}
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   108
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   109
fn load_sprites(path: &Path) -> io::Result<Vec<SpriteData>> {
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   110
    let mut result = vec![];
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   111
    for file in read_dir(path)? {
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   112
        let file = file?;
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   113
        if let Some(extension) = file.path().extension() {
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   114
            if extension == "png" {
15286
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   115
                let path = file.path();
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   116
                let sprite = load_sprite_size(&path)?;
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   117
                result.push(SpriteData {
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   118
                    size: sprite,
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   119
                    filename: path,
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15190
diff changeset
   120
                });
15190
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   121
            }
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   122
        }
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   123
    }
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   124
    Ok(result)
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15120
diff changeset
   125
}