rust/lib-hedgewars-engine/src/render/gear.rs
author Wuzzy <Wuzzy2@mail.ru>
Fri, 11 Oct 2019 18:59:48 +0200
changeset 15493 b56c04fac6f9
parent 15312 07ab4206f2a9
child 15781 c929e25a7da2
permissions -rw-r--r--
Fix closing bracket
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
     1
use super::{atlas::AtlasCollection, gl::Texture2D};
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
     2
use crate::render::camera::Camera;
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
     3
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
     4
use integral_geometry::{Rect, Size};
15141
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14750
diff changeset
     5
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
     6
use crate::render::atlas::SpriteIndex;
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
     7
use png::{ColorType, Decoder, DecodingError};
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
     8
use std::path::PathBuf;
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
     9
use std::{
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    10
    collections::HashMap,
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    11
    ffi::OsString,
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    12
    fs::{read_dir, File},
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    13
    io,
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    14
    io::BufReader,
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    15
    path::Path,
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    16
};
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    17
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    18
pub struct GearRenderer {
15141
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14750
diff changeset
    19
    atlas: AtlasCollection,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14750
diff changeset
    20
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14750
diff changeset
    21
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    22
struct SpriteData {
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    23
    size: Size,
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    24
    filename: PathBuf,
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    25
}
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    26
15311
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    27
const ATLAS_SIZE: Size = Size::square(2048);
15141
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14750
diff changeset
    28
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14750
diff changeset
    29
impl GearRenderer {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14750
diff changeset
    30
    pub fn new() -> Self {
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    31
        let mut lookup = Vec::with_capacity(2048);
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    32
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    33
        let mut atlas = AtlasCollection::new(ATLAS_SIZE);
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    34
        let mut sprites = load_sprites(Path::new("../../share/hedgewars/Data/Graphics/"))
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    35
            .expect("Unable to load Graphics");
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    36
        let max_size = sprites
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    37
            .iter()
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    38
            .fold(Size::EMPTY, |size, sprite| size.join(sprite.size));
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    39
        for sprite in sprites.drain(..) {
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    40
            lookup.push((sprite.filename, atlas.insert_sprite(sprite.size).unwrap()));
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    41
        }
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    42
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    43
        println!(
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    44
            "Filled atlas with {} sprites:\n{}",
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    45
            sprites.len(),
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    46
            atlas.used_space()
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    47
        );
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    48
15311
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    49
        let texture = Texture2D::new(ATLAS_SIZE, gl::RGBA8, gl::LINEAR);
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    50
15311
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    51
        let mut pixels = vec![0; max_size.area()].into_boxed_slice();
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    52
        let mut pixels_transposed = vec![0; max_size.area()].into_boxed_slice();
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    53
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    54
        for (path, sprite_index) in lookup.drain(..) {
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    55
            if let Some((atlas_index, rect)) = atlas.get_rect(sprite_index) {
15311
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    56
                let size = load_sprite_pixels(&path, mapgen::theme::slice_u32_to_u8_mut(&mut pixels[..])).expect("Unable to load Graphics");
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    57
15312
07ab4206f2a9 fix condition
alfadur
parents: 15311
diff changeset
    58
                let used_pixels = if size.width != rect.width() {
15311
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    59
                    for y in 0..rect.height() {
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    60
                        for x in 0..rect.width() {
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    61
                            pixels_transposed[y * rect.width() + x] = pixels[x * rect.height() + y];
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    62
                        }
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    63
                    }
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    64
                    &mut pixels_transposed[..]
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    65
                } else {
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    66
                    &mut pixels[..]
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    67
                };
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    68
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    69
                texture.update(rect, mapgen::theme::slice_u32_to_u8_mut(used_pixels), 0, gl::RGBA, gl::UNSIGNED_BYTE);
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    70
            }
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    71
        }
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    72
15141
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14750
diff changeset
    73
        Self { atlas }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14750
diff changeset
    74
    }
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    75
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    76
    pub fn render(&mut self, camera: &Camera) {
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    77
        let projection = camera.projection();
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    78
    }
15141
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 14750
diff changeset
    79
}
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    80
15311
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    81
fn load_sprite_pixels(path: &Path, buffer: &mut [u8]) -> io::Result<Size> {
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    82
    let decoder = Decoder::new(BufReader::new(File::open(path)?));
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    83
    let (info, mut reader) = decoder.read_info()?;
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    84
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    85
    let size = Size::new(info.width as usize, info.height as usize);
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    86
    reader.next_frame(buffer)?;
15311
fcf0fb0cddbf transpose atlas sprites where necessary
alfadur
parents: 15309
diff changeset
    87
    Ok(size)
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    88
}
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    89
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    90
fn load_sprite_size(path: &Path) -> io::Result<Size> {
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    91
    let decoder = Decoder::new(BufReader::new(File::open(path)?));
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    92
    let (info, mut reader) = decoder.read_info()?;
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    93
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    94
    let size = Size::new(info.width as usize, info.height as usize);
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    95
    Ok(size)
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    96
}
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    97
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
    98
fn load_sprites(path: &Path) -> io::Result<Vec<SpriteData>> {
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
    99
    let mut result = vec![];
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
   100
    for file in read_dir(path)? {
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
   101
        let file = file?;
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
   102
        if let Some(extension) = file.path().extension() {
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
   103
            if extension == "png" {
15307
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
   104
                let path = file.path();
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
   105
                let sprite = load_sprite_size(&path)?;
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
   106
                result.push(SpriteData {
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
   107
                    size: sprite,
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
   108
                    filename: path,
16bd389fc735 ship the atlas to the gpu
alfadur
parents: 15211
diff changeset
   109
                });
15211
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
   110
            }
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
   111
        }
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
   112
    }
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
   113
    Ok(result)
e2adb40c7988 fill the atlas with sprites
alfadur
parents: 15141
diff changeset
   114
}