mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'crabman/lossy-compression-sprites' into 'master'
Store sprite data separately for compressed chunks See merge request veloren/veloren!4277
This commit is contained in:
commit
bfba00e39f
@ -1,5 +1,5 @@
|
|||||||
use common::{
|
use common::{
|
||||||
terrain::{chonk::Chonk, Block, BlockKind, SpriteKind},
|
terrain::{chonk::Chonk, Block, BlockKind},
|
||||||
vol::{BaseVol, ReadVol, RectVolSize, WriteVol},
|
vol::{BaseVol, ReadVol, RectVolSize, WriteVol},
|
||||||
volumes::vol_grid_2d::VolGrid2d,
|
volumes::vol_grid_2d::VolGrid2d,
|
||||||
};
|
};
|
||||||
@ -132,8 +132,7 @@ pub trait VoxelImageEncoding {
|
|||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
kind: BlockKind,
|
kind: BlockKind,
|
||||||
sprite: SpriteKind,
|
sprite_data: [u8; 3],
|
||||||
ori: Option<u8>,
|
|
||||||
);
|
);
|
||||||
fn finish(ws: &Self::Workspace) -> Option<Self::Output>;
|
fn finish(ws: &Self::Workspace) -> Option<Self::Output>;
|
||||||
}
|
}
|
||||||
@ -168,10 +167,9 @@ impl<'a, VIE: VoxelImageEncoding> VoxelImageEncoding for &'a VIE {
|
|||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
kind: BlockKind,
|
kind: BlockKind,
|
||||||
sprite: SpriteKind,
|
sprite_data: [u8; 3],
|
||||||
ori: Option<u8>,
|
|
||||||
) {
|
) {
|
||||||
(*self).put_sprite(ws, x, y, kind, sprite, ori)
|
(*self).put_sprite(ws, x, y, kind, sprite_data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(ws: &Self::Workspace) -> Option<Self::Output> { VIE::finish(ws) }
|
fn finish(ws: &Self::Workspace) -> Option<Self::Output> { VIE::finish(ws) }
|
||||||
@ -189,12 +187,14 @@ impl<'a, VIE: VoxelImageDecoding> VoxelImageDecoding for &'a VIE {
|
|||||||
pub struct QuadPngEncoding<const RESOLUTION_DIVIDER: u32>();
|
pub struct QuadPngEncoding<const RESOLUTION_DIVIDER: u32>();
|
||||||
|
|
||||||
impl<const N: u32> VoxelImageEncoding for QuadPngEncoding<N> {
|
impl<const N: u32> VoxelImageEncoding for QuadPngEncoding<N> {
|
||||||
type Output = CompressedData<(Vec<u8>, [usize; 3])>;
|
type Output = CompressedData<(Vec<u8>, [usize; 3], Vec<[u8; 3]>)>;
|
||||||
type Workspace = (
|
type Workspace = (
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
ImageBuffer<image::Rgb<u8>, Vec<u8>>,
|
ImageBuffer<image::Rgb<u8>, Vec<u8>>,
|
||||||
|
Vec<[u8; 3]>,
|
||||||
|
HashMap<[u8; 3], u16>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn create(width: u32, height: u32) -> Self::Workspace {
|
fn create(width: u32, height: u32) -> Self::Workspace {
|
||||||
@ -203,6 +203,8 @@ impl<const N: u32> VoxelImageEncoding for QuadPngEncoding<N> {
|
|||||||
ImageBuffer::new(width, height),
|
ImageBuffer::new(width, height),
|
||||||
ImageBuffer::new(width, height),
|
ImageBuffer::new(width, height),
|
||||||
ImageBuffer::new(width / N, height / N),
|
ImageBuffer::new(width / N, height / N),
|
||||||
|
Vec::new(),
|
||||||
|
HashMap::new(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -219,12 +221,22 @@ impl<const N: u32> VoxelImageEncoding for QuadPngEncoding<N> {
|
|||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
kind: BlockKind,
|
kind: BlockKind,
|
||||||
sprite: SpriteKind,
|
sprite_data: [u8; 3],
|
||||||
ori: Option<u8>,
|
|
||||||
) {
|
) {
|
||||||
|
let index = ws.5.entry(sprite_data).or_insert_with(|| {
|
||||||
|
let index =
|
||||||
|
ws.4.len()
|
||||||
|
.try_into()
|
||||||
|
.expect("Cannot have more than 2^16 unique sprites in one chunk");
|
||||||
|
ws.4.push(sprite_data);
|
||||||
|
index
|
||||||
|
});
|
||||||
|
|
||||||
|
let index = index.to_be_bytes();
|
||||||
|
|
||||||
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
||||||
ws.1.put_pixel(x, y, image::Luma([sprite as u8]));
|
ws.1.put_pixel(x, y, image::Luma([index[0]]));
|
||||||
ws.2.put_pixel(x, y, image::Luma([ori.unwrap_or(0)]));
|
ws.2.put_pixel(x, y, image::Luma([index[1]]));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
||||||
@ -261,7 +273,7 @@ impl<const N: u32> VoxelImageEncoding for QuadPngEncoding<N> {
|
|||||||
.ok()?;
|
.ok()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(CompressedData::compress(&(buf, indices), 4))
|
Some(CompressedData::compress(&(buf, indices, ws.4.clone()), 4))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,7 +332,7 @@ const fn gen_lanczos_lookup<const N: u32, const R: u32>(
|
|||||||
impl<const N: u32> VoxelImageDecoding for QuadPngEncoding<N> {
|
impl<const N: u32> VoxelImageDecoding for QuadPngEncoding<N> {
|
||||||
fn start(data: &Self::Output) -> Option<Self::Workspace> {
|
fn start(data: &Self::Output) -> Option<Self::Workspace> {
|
||||||
use image::codecs::png::PngDecoder;
|
use image::codecs::png::PngDecoder;
|
||||||
let (quad, indices) = data.decompress()?;
|
let (quad, indices, sprite_data) = data.decompress()?;
|
||||||
let ranges: [_; 4] = [
|
let ranges: [_; 4] = [
|
||||||
0..indices[0],
|
0..indices[0],
|
||||||
indices[0]..indices[1],
|
indices[0]..indices[1],
|
||||||
@ -331,7 +343,7 @@ impl<const N: u32> VoxelImageDecoding for QuadPngEncoding<N> {
|
|||||||
let b = image_from_bytes(PngDecoder::new(&quad[ranges[1].clone()]).ok()?)?;
|
let b = image_from_bytes(PngDecoder::new(&quad[ranges[1].clone()]).ok()?)?;
|
||||||
let c = image_from_bytes(PngDecoder::new(&quad[ranges[2].clone()]).ok()?)?;
|
let c = image_from_bytes(PngDecoder::new(&quad[ranges[2].clone()]).ok()?)?;
|
||||||
let d = image_from_bytes(PngDecoder::new(&quad[ranges[3].clone()]).ok()?)?;
|
let d = image_from_bytes(PngDecoder::new(&quad[ranges[3].clone()]).ok()?)?;
|
||||||
Some((a, b, c, d))
|
Some((a, b, c, d, sprite_data, HashMap::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_block(ws: &Self::Workspace, x: u32, y: u32, is_border: bool) -> Block {
|
fn get_block(ws: &Self::Workspace, x: u32, y: u32, is_border: bool) -> Block {
|
||||||
@ -444,14 +456,9 @@ impl<const N: u32> VoxelImageDecoding for QuadPngEncoding<N> {
|
|||||||
b: rgb.z as u8,
|
b: rgb.z as u8,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let mut block = Block::new(kind, Rgb { r: 0, g: 0, b: 0 });
|
let index =
|
||||||
if let Some(spritekind) = SpriteKind::from_u8(ws.1.get_pixel(x, y).0[0]) {
|
u16::from_be_bytes([ws.1.get_pixel(x, y).0[0], ws.2.get_pixel(x, y).0[0]]);
|
||||||
block = block.with_sprite(spritekind);
|
Block::from_raw(kind, ws.4[index as usize])
|
||||||
}
|
|
||||||
if let Some(oriblock) = block.with_ori(ws.2.get_pixel(x, y).0[0]) {
|
|
||||||
block = oriblock;
|
|
||||||
}
|
|
||||||
block
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Block::empty()
|
Block::empty()
|
||||||
@ -463,12 +470,14 @@ impl<const N: u32> VoxelImageDecoding for QuadPngEncoding<N> {
|
|||||||
pub struct TriPngEncoding<const AVERAGE_PALETTE: bool>();
|
pub struct TriPngEncoding<const AVERAGE_PALETTE: bool>();
|
||||||
|
|
||||||
impl<const AVERAGE_PALETTE: bool> VoxelImageEncoding for TriPngEncoding<AVERAGE_PALETTE> {
|
impl<const AVERAGE_PALETTE: bool> VoxelImageEncoding for TriPngEncoding<AVERAGE_PALETTE> {
|
||||||
type Output = CompressedData<(Vec<u8>, Vec<Rgb<u8>>, [usize; 3])>;
|
type Output = CompressedData<(Vec<u8>, Vec<Rgb<u8>>, [usize; 3], Vec<[u8; 3]>)>;
|
||||||
type Workspace = (
|
type Workspace = (
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
HashMap<BlockKind, HashMap<Rgb<u8>, usize>>,
|
HashMap<BlockKind, HashMap<Rgb<u8>, usize>>,
|
||||||
|
Vec<[u8; 3]>,
|
||||||
|
HashMap<[u8; 3], u16>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn create(width: u32, height: u32) -> Self::Workspace {
|
fn create(width: u32, height: u32) -> Self::Workspace {
|
||||||
@ -477,6 +486,8 @@ impl<const AVERAGE_PALETTE: bool> VoxelImageEncoding for TriPngEncoding<AVERAGE_
|
|||||||
ImageBuffer::new(width, height),
|
ImageBuffer::new(width, height),
|
||||||
ImageBuffer::new(width, height),
|
ImageBuffer::new(width, height),
|
||||||
HashMap::new(),
|
HashMap::new(),
|
||||||
|
Vec::new(),
|
||||||
|
HashMap::new(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,12 +506,21 @@ impl<const AVERAGE_PALETTE: bool> VoxelImageEncoding for TriPngEncoding<AVERAGE_
|
|||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
kind: BlockKind,
|
kind: BlockKind,
|
||||||
sprite: SpriteKind,
|
sprite_data: [u8; 3],
|
||||||
ori: Option<u8>,
|
|
||||||
) {
|
) {
|
||||||
|
let index = ws.5.entry(sprite_data).or_insert_with(|| {
|
||||||
|
let index =
|
||||||
|
ws.4.len()
|
||||||
|
.try_into()
|
||||||
|
.expect("Cannot have more than 2^16 sprites in one chunk");
|
||||||
|
ws.4.push(sprite_data);
|
||||||
|
index
|
||||||
|
});
|
||||||
|
let index = index.to_be_bytes();
|
||||||
|
|
||||||
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
||||||
ws.1.put_pixel(x, y, image::Luma([sprite as u8]));
|
ws.1.put_pixel(x, y, image::Luma([index[0]]));
|
||||||
ws.2.put_pixel(x, y, image::Luma([ori.unwrap_or(0)]));
|
ws.2.put_pixel(x, y, image::Luma([index[1]]));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
||||||
@ -545,14 +565,17 @@ impl<const AVERAGE_PALETTE: bool> VoxelImageEncoding for TriPngEncoding<AVERAGE_
|
|||||||
Vec::new()
|
Vec::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(CompressedData::compress(&(buf, palette, indices), 4))
|
Some(CompressedData::compress(
|
||||||
|
&(buf, palette, indices, ws.4.clone()),
|
||||||
|
4,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const AVERAGE_PALETTE: bool> VoxelImageDecoding for TriPngEncoding<AVERAGE_PALETTE> {
|
impl<const AVERAGE_PALETTE: bool> VoxelImageDecoding for TriPngEncoding<AVERAGE_PALETTE> {
|
||||||
fn start(data: &Self::Output) -> Option<Self::Workspace> {
|
fn start(data: &Self::Output) -> Option<Self::Workspace> {
|
||||||
use image::codecs::png::PngDecoder;
|
use image::codecs::png::PngDecoder;
|
||||||
let (quad, palette, indices) = data.decompress()?;
|
let (quad, palette, indices, sprite_data) = data.decompress()?;
|
||||||
let ranges: [_; 3] = [
|
let ranges: [_; 3] = [
|
||||||
0..indices[0],
|
0..indices[0],
|
||||||
indices[0]..indices[1],
|
indices[0]..indices[1],
|
||||||
@ -573,7 +596,7 @@ impl<const AVERAGE_PALETTE: bool> VoxelImageDecoding for TriPngEncoding<AVERAGE_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some((a, b, c, d))
|
Some((a, b, c, d, sprite_data, HashMap::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_block(ws: &Self::Workspace, x: u32, y: u32, _: bool) -> Block {
|
fn get_block(ws: &Self::Workspace, x: u32, y: u32, _: bool) -> Block {
|
||||||
@ -662,14 +685,9 @@ impl<const AVERAGE_PALETTE: bool> VoxelImageDecoding for TriPngEncoding<AVERAGE_
|
|||||||
};
|
};
|
||||||
Block::new(kind, rgb)
|
Block::new(kind, rgb)
|
||||||
} else {
|
} else {
|
||||||
let mut block = Block::new(kind, Rgb { r: 0, g: 0, b: 0 });
|
let index =
|
||||||
if let Some(spritekind) = SpriteKind::from_u8(ws.1.get_pixel(x, y).0[0]) {
|
u16::from_be_bytes([ws.1.get_pixel(x, y).0[0], ws.2.get_pixel(x, y).0[0]]);
|
||||||
block = block.with_sprite(spritekind);
|
Block::from_raw(kind, ws.4[index as usize])
|
||||||
}
|
|
||||||
if let Some(oriblock) = block.with_ori(ws.2.get_pixel(x, y).0[0]) {
|
|
||||||
block = oriblock;
|
|
||||||
}
|
|
||||||
block
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Block::empty()
|
Block::empty()
|
||||||
@ -754,8 +772,10 @@ pub fn image_terrain<
|
|||||||
(Some(rgb), None) => {
|
(Some(rgb), None) => {
|
||||||
VIE::put_solid(vie, &mut image, i, j, *block, rgb);
|
VIE::put_solid(vie, &mut image, i, j, *block, rgb);
|
||||||
},
|
},
|
||||||
(None, Some(sprite)) => {
|
(None, Some(_)) => {
|
||||||
VIE::put_sprite(vie, &mut image, i, j, *block, sprite, block.get_ori());
|
let data = block.to_u32().to_le_bytes();
|
||||||
|
|
||||||
|
VIE::put_sprite(vie, &mut image, i, j, *block, [data[1], data[2], data[3]]);
|
||||||
},
|
},
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
"attr being used for color vs sprite is mutually exclusive (and that's \
|
"attr being used for color vs sprite is mutually exclusive (and that's \
|
||||||
|
@ -157,7 +157,7 @@ impl Block {
|
|||||||
/* Constructors */
|
/* Constructors */
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(super) const fn from_raw(kind: BlockKind, data: [u8; 3]) -> Self { Self { kind, data } }
|
pub const fn from_raw(kind: BlockKind, data: [u8; 3]) -> Self { Self { kind, data } }
|
||||||
|
|
||||||
// TODO: Rename to `filled`, make caller guarantees stronger
|
// TODO: Rename to `filled`, make caller guarantees stronger
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -21,6 +21,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use std::{
|
use std::{
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
|
mem,
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
time::Instant,
|
time::Instant,
|
||||||
};
|
};
|
||||||
@ -164,16 +165,19 @@ impl PackingFormula for TallPacking {
|
|||||||
pub struct PngEncoding;
|
pub struct PngEncoding;
|
||||||
|
|
||||||
impl VoxelImageEncoding for PngEncoding {
|
impl VoxelImageEncoding for PngEncoding {
|
||||||
type Output = Vec<u8>;
|
type Output = (Vec<u8>, Vec<[u8; 3]>);
|
||||||
type Workspace = ImageBuffer<image::Rgba<u8>, Vec<u8>>;
|
type Workspace = (ImageBuffer<image::Rgba<u8>, Vec<u8>>, Vec<[u8; 3]>);
|
||||||
|
|
||||||
fn create(width: u32, height: u32) -> Self::Workspace {
|
fn create(width: u32, height: u32) -> Self::Workspace {
|
||||||
use image::Rgba;
|
use image::Rgba;
|
||||||
ImageBuffer::<Rgba<u8>, Vec<u8>>::new(width, height)
|
(
|
||||||
|
ImageBuffer::<Rgba<u8>, Vec<u8>>::new(width, height),
|
||||||
|
Vec::new(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
|
fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
|
||||||
ws.put_pixel(x, y, image::Rgba([rgb.r, rgb.g, rgb.b, 255 - kind as u8]));
|
ws.0.put_pixel(x, y, image::Rgba([rgb.r, rgb.g, rgb.b, 255 - kind as u8]));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put_sprite(
|
fn put_sprite(
|
||||||
@ -182,14 +186,11 @@ impl VoxelImageEncoding for PngEncoding {
|
|||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
kind: BlockKind,
|
kind: BlockKind,
|
||||||
sprite: SpriteKind,
|
sprite_data: [u8; 3],
|
||||||
ori: Option<u8>,
|
|
||||||
) {
|
) {
|
||||||
ws.put_pixel(
|
let index = (ws.1.len() as u16).to_be_bytes();
|
||||||
x,
|
ws.1.push(sprite_data);
|
||||||
y,
|
ws.0.put_pixel(x, y, image::Rgba([kind as u8, index[0], index[1], 255]));
|
||||||
image::Rgba([kind as u8, sprite as u8, ori.unwrap_or(0), 255]),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
||||||
@ -201,13 +202,13 @@ impl VoxelImageEncoding for PngEncoding {
|
|||||||
FilterType::Up,
|
FilterType::Up,
|
||||||
);
|
);
|
||||||
png.write_image(
|
png.write_image(
|
||||||
ws.as_raw(),
|
ws.0.as_raw(),
|
||||||
ws.width(),
|
ws.0.width(),
|
||||||
ws.height(),
|
ws.0.height(),
|
||||||
image::ColorType::Rgba8,
|
image::ColorType::Rgba8,
|
||||||
)
|
)
|
||||||
.ok()?;
|
.ok()?;
|
||||||
Some(buf)
|
Some((buf, ws.1.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,16 +216,19 @@ impl VoxelImageEncoding for PngEncoding {
|
|||||||
pub struct JpegEncoding;
|
pub struct JpegEncoding;
|
||||||
|
|
||||||
impl VoxelImageEncoding for JpegEncoding {
|
impl VoxelImageEncoding for JpegEncoding {
|
||||||
type Output = Vec<u8>;
|
type Output = (Vec<u8>, Vec<[u8; 3]>);
|
||||||
type Workspace = ImageBuffer<image::Rgba<u8>, Vec<u8>>;
|
type Workspace = (ImageBuffer<image::Rgba<u8>, Vec<u8>>, Vec<[u8; 3]>);
|
||||||
|
|
||||||
fn create(width: u32, height: u32) -> Self::Workspace {
|
fn create(width: u32, height: u32) -> Self::Workspace {
|
||||||
use image::Rgba;
|
use image::Rgba;
|
||||||
ImageBuffer::<Rgba<u8>, Vec<u8>>::new(width, height)
|
(
|
||||||
|
ImageBuffer::<Rgba<u8>, Vec<u8>>::new(width, height),
|
||||||
|
Vec::new(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
|
fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
|
||||||
ws.put_pixel(x, y, image::Rgba([rgb.r, rgb.g, rgb.b, 255 - kind as u8]));
|
ws.0.put_pixel(x, y, image::Rgba([rgb.r, rgb.g, rgb.b, 255 - kind as u8]));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put_sprite(
|
fn put_sprite(
|
||||||
@ -233,17 +237,18 @@ impl VoxelImageEncoding for JpegEncoding {
|
|||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
kind: BlockKind,
|
kind: BlockKind,
|
||||||
sprite: SpriteKind,
|
sprite_data: [u8; 3],
|
||||||
_: Option<u8>,
|
|
||||||
) {
|
) {
|
||||||
ws.put_pixel(x, y, image::Rgba([kind as u8, sprite as u8, 255, 255]));
|
let index = (ws.1.len() as u16).to_be_bytes();
|
||||||
|
ws.1.push(sprite_data);
|
||||||
|
ws.0.put_pixel(x, y, image::Rgba([kind as u8, index[0], index[0], 255]));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
let mut jpeg = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut buf, 1);
|
let mut jpeg = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut buf, 1);
|
||||||
jpeg.encode_image(ws).ok()?;
|
jpeg.encode_image(&ws.0).ok()?;
|
||||||
Some(buf)
|
Some((buf, ws.1.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,12 +256,13 @@ impl VoxelImageEncoding for JpegEncoding {
|
|||||||
pub struct MixedEncoding;
|
pub struct MixedEncoding;
|
||||||
|
|
||||||
impl VoxelImageEncoding for MixedEncoding {
|
impl VoxelImageEncoding for MixedEncoding {
|
||||||
type Output = (Vec<u8>, [usize; 3]);
|
type Output = (Vec<u8>, [usize; 4]);
|
||||||
type Workspace = (
|
type Workspace = (
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
ImageBuffer<image::Rgb<u8>, Vec<u8>>,
|
ImageBuffer<image::Rgb<u8>, Vec<u8>>,
|
||||||
|
Vec<[u8; 3]>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn create(width: u32, height: u32) -> Self::Workspace {
|
fn create(width: u32, height: u32) -> Self::Workspace {
|
||||||
@ -265,6 +271,7 @@ impl VoxelImageEncoding for MixedEncoding {
|
|||||||
ImageBuffer::new(width, height),
|
ImageBuffer::new(width, height),
|
||||||
ImageBuffer::new(width, height),
|
ImageBuffer::new(width, height),
|
||||||
ImageBuffer::new(width, height),
|
ImageBuffer::new(width, height),
|
||||||
|
Vec::new(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,19 +288,20 @@ impl VoxelImageEncoding for MixedEncoding {
|
|||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
kind: BlockKind,
|
kind: BlockKind,
|
||||||
sprite: SpriteKind,
|
sprite_data: [u8; 3],
|
||||||
ori: Option<u8>,
|
|
||||||
) {
|
) {
|
||||||
|
let index = (ws.4.len() as u16).to_be_bytes();
|
||||||
|
ws.4.push(sprite_data);
|
||||||
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
||||||
ws.1.put_pixel(x, y, image::Luma([sprite as u8]));
|
ws.1.put_pixel(x, y, image::Luma([index[0]]));
|
||||||
ws.2.put_pixel(x, y, image::Luma([ori.unwrap_or(0)]));
|
ws.2.put_pixel(x, y, image::Luma([index[1]]));
|
||||||
ws.3.put_pixel(x, y, image::Rgb([0; 3]));
|
ws.3.put_pixel(x, y, image::Rgb([0; 3]));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
use image::codecs::png::{CompressionType, FilterType};
|
use image::codecs::png::{CompressionType, FilterType};
|
||||||
let mut indices = [0; 3];
|
let mut indices = [0; 4];
|
||||||
let mut f = |x: &ImageBuffer<_, Vec<u8>>, i| {
|
let mut f = |x: &ImageBuffer<_, Vec<u8>>, i| {
|
||||||
let png = image::codecs::png::PngEncoder::new_with_quality(
|
let png = image::codecs::png::PngEncoder::new_with_quality(
|
||||||
&mut buf,
|
&mut buf,
|
||||||
@ -309,6 +317,10 @@ impl VoxelImageEncoding for MixedEncoding {
|
|||||||
f(&ws.1, 1)?;
|
f(&ws.1, 1)?;
|
||||||
f(&ws.2, 2)?;
|
f(&ws.2, 2)?;
|
||||||
|
|
||||||
|
buf.write_all(&bincode::serialize(&CompressedData::compress(&ws.4, 1)).unwrap())
|
||||||
|
.unwrap();
|
||||||
|
indices[3] = buf.len();
|
||||||
|
|
||||||
let mut jpeg = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut buf, 10);
|
let mut jpeg = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut buf, 10);
|
||||||
jpeg.encode_image(&ws.3).ok()?;
|
jpeg.encode_image(&ws.3).ok()?;
|
||||||
Some((buf, indices))
|
Some((buf, indices))
|
||||||
@ -318,17 +330,22 @@ impl VoxelImageEncoding for MixedEncoding {
|
|||||||
impl VoxelImageDecoding for MixedEncoding {
|
impl VoxelImageDecoding for MixedEncoding {
|
||||||
fn start((quad, indices): &Self::Output) -> Option<Self::Workspace> {
|
fn start((quad, indices): &Self::Output) -> Option<Self::Workspace> {
|
||||||
use image::codecs::{jpeg::JpegDecoder, png::PngDecoder};
|
use image::codecs::{jpeg::JpegDecoder, png::PngDecoder};
|
||||||
let ranges: [_; 4] = [
|
let ranges: [_; 5] = [
|
||||||
0..indices[0],
|
0..indices[0],
|
||||||
indices[0]..indices[1],
|
indices[0]..indices[1],
|
||||||
indices[1]..indices[2],
|
indices[1]..indices[2],
|
||||||
indices[2]..quad.len(),
|
indices[2]..indices[3],
|
||||||
|
indices[3]..quad.len(),
|
||||||
];
|
];
|
||||||
let a = image_from_bytes(PngDecoder::new(&quad[ranges[0].clone()]).ok()?)?;
|
let a = image_from_bytes(PngDecoder::new(&quad[ranges[0].clone()]).ok()?)?;
|
||||||
let b = image_from_bytes(PngDecoder::new(&quad[ranges[1].clone()]).ok()?)?;
|
let b = image_from_bytes(PngDecoder::new(&quad[ranges[1].clone()]).ok()?)?;
|
||||||
let c = image_from_bytes(PngDecoder::new(&quad[ranges[2].clone()]).ok()?)?;
|
let c = image_from_bytes(PngDecoder::new(&quad[ranges[2].clone()]).ok()?)?;
|
||||||
|
let sprite_data =
|
||||||
|
bincode::deserialize::<CompressedData<Vec<[u8; 3]>>>(&quad[ranges[4].clone()])
|
||||||
|
.ok()?
|
||||||
|
.decompress()?;
|
||||||
let d = image_from_bytes(JpegDecoder::new(&quad[ranges[3].clone()]).ok()?)?;
|
let d = image_from_bytes(JpegDecoder::new(&quad[ranges[3].clone()]).ok()?)?;
|
||||||
Some((a, b, c, d))
|
Some((a, b, c, d, sprite_data))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_block(ws: &Self::Workspace, x: u32, y: u32, _: bool) -> Block {
|
fn get_block(ws: &Self::Workspace, x: u32, y: u32, _: bool) -> Block {
|
||||||
@ -341,14 +358,9 @@ impl VoxelImageDecoding for MixedEncoding {
|
|||||||
b: rgb[2],
|
b: rgb[2],
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let mut block = Block::new(kind, Rgb { r: 0, g: 0, b: 0 });
|
let index =
|
||||||
if let Some(spritekind) = SpriteKind::from_u8(ws.1.get_pixel(x, y).0[0]) {
|
u16::from_be_bytes([ws.1.get_pixel(x, y).0[0], ws.2.get_pixel(x, y).0[0]]);
|
||||||
block = block.with_sprite(spritekind);
|
Block::from_raw(kind, ws.4[index as usize])
|
||||||
}
|
|
||||||
if let Some(oriblock) = block.with_ori(ws.2.get_pixel(x, y).0[0]) {
|
|
||||||
block = oriblock;
|
|
||||||
}
|
|
||||||
block
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Block::empty()
|
Block::empty()
|
||||||
@ -360,15 +372,11 @@ impl VoxelImageDecoding for MixedEncoding {
|
|||||||
pub struct MixedEncodingSparseSprites;
|
pub struct MixedEncodingSparseSprites;
|
||||||
|
|
||||||
impl VoxelImageEncoding for MixedEncodingSparseSprites {
|
impl VoxelImageEncoding for MixedEncodingSparseSprites {
|
||||||
type Output = (
|
type Output = (Vec<u8>, usize, CompressedData<HashMap<Vec2<u32>, [u8; 3]>>);
|
||||||
Vec<u8>,
|
|
||||||
usize,
|
|
||||||
CompressedData<HashMap<Vec2<u32>, (SpriteKind, u8)>>,
|
|
||||||
);
|
|
||||||
type Workspace = (
|
type Workspace = (
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
ImageBuffer<image::Rgb<u8>, Vec<u8>>,
|
ImageBuffer<image::Rgb<u8>, Vec<u8>>,
|
||||||
HashMap<Vec2<u32>, (SpriteKind, u8)>,
|
HashMap<Vec2<u32>, [u8; 3]>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn create(width: u32, height: u32) -> Self::Workspace {
|
fn create(width: u32, height: u32) -> Self::Workspace {
|
||||||
@ -390,12 +398,11 @@ impl VoxelImageEncoding for MixedEncodingSparseSprites {
|
|||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
kind: BlockKind,
|
kind: BlockKind,
|
||||||
sprite: SpriteKind,
|
sprite_data: [u8; 3],
|
||||||
ori: Option<u8>,
|
|
||||||
) {
|
) {
|
||||||
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
||||||
ws.1.put_pixel(x, y, image::Rgb([0; 3]));
|
ws.1.put_pixel(x, y, image::Rgb([0; 3]));
|
||||||
ws.2.insert(Vec2::new(x, y), (sprite, ori.unwrap_or(0)));
|
ws.2.insert(Vec2::new(x, y), sprite_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
||||||
@ -424,11 +431,10 @@ impl VoxelImageEncoding for MixedEncodingSparseSprites {
|
|||||||
pub struct MixedEncodingDenseSprites;
|
pub struct MixedEncodingDenseSprites;
|
||||||
|
|
||||||
impl VoxelImageEncoding for MixedEncodingDenseSprites {
|
impl VoxelImageEncoding for MixedEncodingDenseSprites {
|
||||||
type Output = (Vec<u8>, [usize; 3]);
|
type Output = (Vec<u8>, [usize; 2]);
|
||||||
type Workspace = (
|
type Workspace = (
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
Vec<u8>,
|
Vec<[u8; 3]>,
|
||||||
Vec<u8>,
|
|
||||||
ImageBuffer<image::Rgb<u8>, Vec<u8>>,
|
ImageBuffer<image::Rgb<u8>, Vec<u8>>,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -436,14 +442,13 @@ impl VoxelImageEncoding for MixedEncodingDenseSprites {
|
|||||||
(
|
(
|
||||||
ImageBuffer::new(width, height),
|
ImageBuffer::new(width, height),
|
||||||
Vec::new(),
|
Vec::new(),
|
||||||
Vec::new(),
|
|
||||||
ImageBuffer::new(width, height),
|
ImageBuffer::new(width, height),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
|
fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
|
||||||
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
||||||
ws.3.put_pixel(x, y, image::Rgb([rgb.r, rgb.g, rgb.b]));
|
ws.2.put_pixel(x, y, image::Rgb([rgb.r, rgb.g, rgb.b]));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put_sprite(
|
fn put_sprite(
|
||||||
@ -452,19 +457,17 @@ impl VoxelImageEncoding for MixedEncodingDenseSprites {
|
|||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
kind: BlockKind,
|
kind: BlockKind,
|
||||||
sprite: SpriteKind,
|
sprite_data: [u8; 3],
|
||||||
ori: Option<u8>,
|
|
||||||
) {
|
) {
|
||||||
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
||||||
ws.1.push(sprite as u8);
|
ws.1.push(sprite_data);
|
||||||
ws.2.push(ori.unwrap_or(0));
|
ws.2.put_pixel(x, y, image::Rgb([0; 3]));
|
||||||
ws.3.put_pixel(x, y, image::Rgb([0; 3]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
use image::codecs::png::{CompressionType, FilterType};
|
use image::codecs::png::{CompressionType, FilterType};
|
||||||
let mut indices = [0; 3];
|
let mut indices = [0; 2];
|
||||||
let mut f = |x: &ImageBuffer<_, Vec<u8>>, i| {
|
let mut f = |x: &ImageBuffer<_, Vec<u8>>, i| {
|
||||||
let png = image::codecs::png::PngEncoder::new_with_quality(
|
let png = image::codecs::png::PngEncoder::new_with_quality(
|
||||||
&mut buf,
|
&mut buf,
|
||||||
@ -477,16 +480,15 @@ impl VoxelImageEncoding for MixedEncodingDenseSprites {
|
|||||||
Some(())
|
Some(())
|
||||||
};
|
};
|
||||||
f(&ws.0, 0)?;
|
f(&ws.0, 0)?;
|
||||||
let mut g = |x: &[u8], i| {
|
let mut g = |x: &[[u8; 3]], i| {
|
||||||
buf.extend_from_slice(&CompressedData::compress(&x, 4).data);
|
buf.extend_from_slice(&CompressedData::compress(&x, 4).data);
|
||||||
indices[i] = buf.len();
|
indices[i] = buf.len();
|
||||||
};
|
};
|
||||||
|
|
||||||
g(&ws.1, 1);
|
g(&ws.1, 1);
|
||||||
g(&ws.2, 2);
|
|
||||||
|
|
||||||
let mut jpeg = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut buf, 1);
|
let mut jpeg = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut buf, 1);
|
||||||
jpeg.encode_image(&ws.3).ok()?;
|
jpeg.encode_image(&ws.2).ok()?;
|
||||||
Some((buf, indices))
|
Some((buf, indices))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -590,12 +592,13 @@ impl<P: RTreeParams> NearestNeighbor for RTree<ColorPoint, P> {
|
|||||||
pub struct PaletteEncoding<'a, NN: NearestNeighbor, const N: u32>(&'a HashMap<BlockKind, NN>);
|
pub struct PaletteEncoding<'a, NN: NearestNeighbor, const N: u32>(&'a HashMap<BlockKind, NN>);
|
||||||
|
|
||||||
impl<'a, NN: NearestNeighbor, const N: u32> VoxelImageEncoding for PaletteEncoding<'a, NN, N> {
|
impl<'a, NN: NearestNeighbor, const N: u32> VoxelImageEncoding for PaletteEncoding<'a, NN, N> {
|
||||||
type Output = CompressedData<(Vec<u8>, [usize; 4])>;
|
type Output = CompressedData<(Vec<u8>, [usize; 4], Vec<[u8; 3]>)>;
|
||||||
type Workspace = (
|
type Workspace = (
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
ImageBuffer<image::Luma<u8>, Vec<u8>>,
|
||||||
|
Vec<[u8; 3]>,
|
||||||
);
|
);
|
||||||
|
|
||||||
fn create(width: u32, height: u32) -> Self::Workspace {
|
fn create(width: u32, height: u32) -> Self::Workspace {
|
||||||
@ -604,12 +607,17 @@ impl<'a, NN: NearestNeighbor, const N: u32> VoxelImageEncoding for PaletteEncodi
|
|||||||
ImageBuffer::new(width, height),
|
ImageBuffer::new(width, height),
|
||||||
ImageBuffer::new(width, height),
|
ImageBuffer::new(width, height),
|
||||||
ImageBuffer::new(width / N, height / N),
|
ImageBuffer::new(width / N, height / N),
|
||||||
|
Vec::new(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
|
fn put_solid(&self, ws: &mut Self::Workspace, x: u32, y: u32, kind: BlockKind, rgb: Rgb<u8>) {
|
||||||
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
||||||
let i = self.0[&kind].nearest_neighbor(&rgb).unwrap_or(0);
|
let i = self
|
||||||
|
.0
|
||||||
|
.get(&kind)
|
||||||
|
.and_then(|v| v.nearest_neighbor(&rgb))
|
||||||
|
.unwrap_or(0);
|
||||||
ws.3.put_pixel(x / N, y / N, image::Luma([i]));
|
ws.3.put_pixel(x / N, y / N, image::Luma([i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,12 +627,13 @@ impl<'a, NN: NearestNeighbor, const N: u32> VoxelImageEncoding for PaletteEncodi
|
|||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
kind: BlockKind,
|
kind: BlockKind,
|
||||||
sprite: SpriteKind,
|
sprite_data: [u8; 3],
|
||||||
ori: Option<u8>,
|
|
||||||
) {
|
) {
|
||||||
|
let index = (ws.4.len() as u16).to_be_bytes();
|
||||||
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
ws.0.put_pixel(x, y, image::Luma([kind as u8]));
|
||||||
ws.1.put_pixel(x, y, image::Luma([sprite as u8]));
|
ws.1.put_pixel(x, y, image::Luma([index[0]]));
|
||||||
ws.2.put_pixel(x, y, image::Luma([ori.unwrap_or(0)]));
|
ws.2.put_pixel(x, y, image::Luma([index[1]]));
|
||||||
|
ws.4.push(sprite_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
fn finish(ws: &Self::Workspace) -> Option<Self::Output> {
|
||||||
@ -647,7 +656,7 @@ impl<'a, NN: NearestNeighbor, const N: u32> VoxelImageEncoding for PaletteEncodi
|
|||||||
f(&ws.2, 2)?;
|
f(&ws.2, 2)?;
|
||||||
f(&ws.3, 3)?;
|
f(&ws.3, 3)?;
|
||||||
|
|
||||||
Some(CompressedData::compress(&(buf, indices), 1))
|
Some(CompressedData::compress(&(buf, indices, ws.4.clone()), 1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,20 +721,38 @@ fn main() {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"castle",
|
"gnarling_fort",
|
||||||
world
|
world
|
||||||
.civs()
|
.civs()
|
||||||
.sites()
|
.sites()
|
||||||
.find(|s| s.is_castle())
|
.find(|s| matches!(s.kind, SiteKind::Gnarling))
|
||||||
.map(|s| s.center.as_())
|
.map(|s| s.center.as_())
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"tree",
|
"desert_city",
|
||||||
world
|
world
|
||||||
.civs()
|
.civs()
|
||||||
.sites()
|
.sites()
|
||||||
.find(|s| matches!(s.kind, SiteKind::Tree))
|
.find(|s| matches!(s.kind, SiteKind::DesertCity))
|
||||||
|
.map(|s| s.center.as_())
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"giant_tree",
|
||||||
|
world
|
||||||
|
.civs()
|
||||||
|
.sites()
|
||||||
|
.find(|s| matches!(s.kind, SiteKind::GiantTree))
|
||||||
|
.map(|s| s.center.as_())
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"haniwa",
|
||||||
|
world
|
||||||
|
.civs()
|
||||||
|
.sites()
|
||||||
|
.find(|s| matches!(s.kind, SiteKind::Haniwa))
|
||||||
.map(|s| s.center.as_())
|
.map(|s| s.center.as_())
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
),
|
),
|
||||||
@ -955,7 +982,7 @@ fn main() {
|
|||||||
spiralpos.x, spiralpos.y
|
spiralpos.x, spiralpos.y
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
f.write_all(&jpegchonkgrid).unwrap();
|
f.write_all(&jpegchonkgrid.0).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let jpegchonktall_pre = Instant::now();
|
let jpegchonktall_pre = Instant::now();
|
||||||
@ -976,10 +1003,33 @@ fn main() {
|
|||||||
let pngchonk_post = Instant::now();
|
let pngchonk_post = Instant::now();
|
||||||
|
|
||||||
sizes.extend_from_slice(&[
|
sizes.extend_from_slice(&[
|
||||||
("jpegchonkgrid", jpegchonkgrid.len() as f32 / n as f32),
|
(
|
||||||
("jpegchonktall", jpegchonktall.len() as f32 / n as f32),
|
"jpegchonkgrid",
|
||||||
("jpegchonkflip", jpegchonkflip.len() as f32 / n as f32),
|
(jpegchonkgrid.0.len()
|
||||||
("pngchonk", pngchonk.len() as f32 / n as f32),
|
+ jpegchonkgrid.1.len() * mem::size_of::<[u8; 3]>())
|
||||||
|
as f32
|
||||||
|
/ n as f32,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"jpegchonktall",
|
||||||
|
(jpegchonktall.0.len()
|
||||||
|
+ jpegchonktall.1.len() * mem::size_of::<[u8; 3]>())
|
||||||
|
as f32
|
||||||
|
/ n as f32,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"jpegchonkflip",
|
||||||
|
(jpegchonkflip.0.len()
|
||||||
|
+ jpegchonkflip.1.len() * mem::size_of::<[u8; 3]>())
|
||||||
|
as f32
|
||||||
|
/ n as f32,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"pngchonk",
|
||||||
|
(pngchonk.0.len() + pngchonk.1.len() * mem::size_of::<[u8; 3]>())
|
||||||
|
as f32
|
||||||
|
/ n as f32,
|
||||||
|
),
|
||||||
]);
|
]);
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
timings.extend_from_slice(&[
|
timings.extend_from_slice(&[
|
||||||
@ -1154,7 +1204,7 @@ fn main() {
|
|||||||
bucket.0 += 1;
|
bucket.0 += 1;
|
||||||
bucket.1 += (tripngconst_post - tripngconst_pre).subsec_nanos() as f32;
|
bucket.1 += (tripngconst_post - tripngconst_pre).subsec_nanos() as f32;
|
||||||
}
|
}
|
||||||
if true {
|
if false {
|
||||||
let bucket = z_buckets
|
let bucket = z_buckets
|
||||||
.entry("palette_kdtree")
|
.entry("palette_kdtree")
|
||||||
.or_default()
|
.or_default()
|
||||||
@ -1163,7 +1213,7 @@ fn main() {
|
|||||||
bucket.0 += 1;
|
bucket.0 += 1;
|
||||||
bucket.1 += (palette_kdtree_post - palette_kdtree_pre).subsec_nanos() as f32;
|
bucket.1 += (palette_kdtree_post - palette_kdtree_pre).subsec_nanos() as f32;
|
||||||
}
|
}
|
||||||
if true {
|
if false {
|
||||||
let bucket = z_buckets
|
let bucket = z_buckets
|
||||||
.entry("palette_rtree")
|
.entry("palette_rtree")
|
||||||
.or_default()
|
.or_default()
|
||||||
@ -1197,7 +1247,7 @@ fn main() {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let jpeg_volgrid =
|
let jpeg_volgrid =
|
||||||
image_terrain_volgrid(&JpegEncoding, GridLtrPacking, &volgrid).unwrap();
|
image_terrain_volgrid(&JpegEncoding, GridLtrPacking, &volgrid).unwrap();
|
||||||
f.write_all(&jpeg_volgrid).unwrap();
|
f.write_all(&jpeg_volgrid.0).unwrap();
|
||||||
|
|
||||||
let mixedgrid_pre = Instant::now();
|
let mixedgrid_pre = Instant::now();
|
||||||
let (mixed_volgrid, indices) =
|
let (mixed_volgrid, indices) =
|
||||||
|
Loading…
Reference in New Issue
Block a user