--- a/rust/integral-geometry/src/lib.rs Sat Aug 03 00:54:29 2019 +0300
+++ b/rust/integral-geometry/src/lib.rs Sat Aug 03 01:13:45 2019 +0300
@@ -171,6 +171,14 @@
pub fn contains(&self, other: Self) -> bool {
self.width >= other.width && self.height >= other.height
}
+
+ #[inline]
+ pub fn join(&self, other: Self) -> Self {
+ Self {
+ width: max(self.width, other.width),
+ height: max(self.height, other.height)
+ }
+ }
}
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
--- a/rust/lib-hedgewars-engine/src/render/atlas.rs Sat Aug 03 00:54:29 2019 +0300
+++ b/rust/lib-hedgewars-engine/src/render/atlas.rs Sat Aug 03 01:13:45 2019 +0300
@@ -250,6 +250,10 @@
}
}
+ pub fn get_rect(&self, index: SpriteIndex) -> Option<(u32, Rect)> {
+ self.rects.get(index as usize).cloned()
+ }
+
pub fn used_space(&self) -> String {
self.atlases
.iter()
--- a/rust/lib-hedgewars-engine/src/render/gear.rs Sat Aug 03 00:54:29 2019 +0300
+++ b/rust/lib-hedgewars-engine/src/render/gear.rs Sat Aug 03 01:13:45 2019 +0300
@@ -1,10 +1,14 @@
-use super::atlas::AtlasCollection;
+use super::{atlas::AtlasCollection, gl::Texture2D};
use crate::render::camera::Camera;
-use integral_geometry::Size;
+use integral_geometry::{Rect, Size};
+use crate::render::atlas::SpriteIndex;
use png::{ColorType, Decoder, DecodingError};
+use std::path::PathBuf;
use std::{
+ collections::HashMap,
+ ffi::OsString,
fs::{read_dir, File},
io,
io::BufReader,
@@ -15,21 +19,43 @@
atlas: AtlasCollection,
}
-const ATLAS_SIZE: Size = Size::square(1024);
+struct SpriteData {
+ size: Size,
+ filename: PathBuf,
+}
+
+const ATLAS_SIZE: Size = Size::square(2024);
impl GearRenderer {
pub fn new() -> Self {
+ let mut lookup = Vec::with_capacity(2048);
+
let mut atlas = AtlasCollection::new(ATLAS_SIZE);
- let sprites = load_sprites(Path::new("../../share/hedgewars/Data/Graphics/"))
+ let mut sprites = load_sprites(Path::new("../../share/hedgewars/Data/Graphics/"))
.expect("Unable to load Graphics");
- for sprite in &sprites {
- atlas.insert_sprite(*sprite);
+ let max_size = sprites
+ .iter()
+ .fold(Size::EMPTY, |size, sprite| size.join(sprite.size));
+ for sprite in sprites.drain(..) {
+ lookup.push((sprite.filename, atlas.insert_sprite(sprite.size).unwrap()));
}
+
println!(
"Filled atlas with {} sprites:\n{}",
sprites.len(),
atlas.used_space()
);
+
+ let texture = Texture2D::new(max_size, gl::RGBA8, gl::LINEAR);
+
+ let mut pixels = Vec::with_capacity(max_size.area()).into_boxed_slice();
+ for (path, sprite_index) in lookup.drain(..) {
+ if let Some((atlas_index, rect)) = atlas.get_rect(sprite_index) {
+ load_sprite_pixels(&path, &mut pixels[..]).expect("Unable to load Graphics");
+ texture.update(rect, &pixels, 0, gl::RGBA, gl::UNSIGNED_BYTE);
+ }
+ }
+
Self { atlas }
}
@@ -38,7 +64,16 @@
}
}
-fn load_sprite(path: &Path) -> io::Result<Size> {
+fn load_sprite_pixels(path: &Path, buffer: &mut [u8]) -> io::Result<()> {
+ let decoder = Decoder::new(BufReader::new(File::open(path)?));
+ let (info, mut reader) = decoder.read_info()?;
+
+ let size = Size::new(info.width as usize, info.height as usize);
+ reader.next_frame(buffer)?;
+ Ok(())
+}
+
+fn load_sprite_size(path: &Path) -> io::Result<Size> {
let decoder = Decoder::new(BufReader::new(File::open(path)?));
let (info, mut reader) = decoder.read_info()?;
@@ -46,14 +81,18 @@
Ok(size)
}
-fn load_sprites(path: &Path) -> io::Result<Vec<Size>> {
+fn load_sprites(path: &Path) -> io::Result<Vec<SpriteData>> {
let mut result = vec![];
for file in read_dir(path)? {
let file = file?;
if let Some(extension) = file.path().extension() {
if extension == "png" {
- let sprite = load_sprite(&file.path())?;
- result.push(sprite);
+ let path = file.path();
+ let sprite = load_sprite_size(&path)?;
+ result.push(SpriteData {
+ size: sprite,
+ filename: path,
+ });
}
}
}
--- a/rust/lib-hedgewars-engine/src/render/gl.rs Sat Aug 03 00:54:29 2019 +0300
+++ b/rust/lib-hedgewars-engine/src/render/gl.rs Sat Aug 03 01:13:45 2019 +0300
@@ -63,7 +63,7 @@
}
impl Texture2D {
- pub fn new(size: Size, internal_format: u32, format: u32, ty: u32, filter: u32) -> Self {
+ pub fn new(size: Size, internal_format: u32, filter: u32) -> Self {
if let Some(handle) = new_texture() {
unsafe {
gl::BindTexture(gl::TEXTURE_2D, handle.get());
@@ -74,8 +74,8 @@
size.width as i32,
size.height as i32,
0,
- format as u32,
- ty,
+ gl::RGBA,
+ gl::UNSIGNED_BYTE,
std::ptr::null(),
)
}
--- a/rust/lib-hedgewars-engine/src/render/map.rs Sat Aug 03 00:54:29 2019 +0300
+++ b/rust/lib-hedgewars-engine/src/render/map.rs Sat Aug 03 01:13:45 2019 +0300
@@ -171,8 +171,7 @@
let texture = Texture2D::with_data(
data,
stride,
- self.tile_size.width as u32,
- self.tile_size.height as u32,
+ self.tile_size,
gl::RGBA8,
gl::RGBA,
gl::UNSIGNED_BYTE,