Compressing with lz4
This commit is contained in:
+39
-24
@@ -7,6 +7,7 @@ use byteorder::ByteOrder;
|
||||
use cgmath::Point3;
|
||||
use std::io::Write;
|
||||
use std::convert::TryInto;
|
||||
use lzzzz::lz4;
|
||||
use std::io::Read;
|
||||
use crate::game::world::{WorldBlock, block};
|
||||
|
||||
@@ -29,21 +30,24 @@ impl WorldChunk {
|
||||
|
||||
pub fn from_bytes(bytes: Vec<u8>) -> Self {
|
||||
let mut instance = Self::new();
|
||||
let (node_bytes, block_bytes) = bytes.split_at((SIZE_QB*4) as usize);
|
||||
let (header_bytes, bytes) = bytes.split_at(128);
|
||||
let (node_bytes, block_bytes_compressed) = bytes.split_at((SIZE_QB*4) as usize);
|
||||
|
||||
// Header
|
||||
let file_ver = header_bytes[0];
|
||||
let num_blocks = LittleEndian::read_u32(&header_bytes[1..5]) as usize;
|
||||
assert_eq!(file_ver, 1);
|
||||
|
||||
// Nodes
|
||||
let mut num_blocks = 0;
|
||||
for i in 0..SIZE_QB {
|
||||
let idx = (i*4) as usize;
|
||||
let val = u32::from_le_bytes([node_bytes[idx], node_bytes[idx+1], node_bytes[idx+2], node_bytes[idx+3]]);
|
||||
instance.nodes[i as usize] = val;
|
||||
if val > 0 { num_blocks+=1; }
|
||||
}
|
||||
|
||||
// Blocks
|
||||
let mut decoder = DeflateDecoder::new(block_bytes);
|
||||
let mut block_bytes = Vec::with_capacity(SIZE_QB);
|
||||
decoder.read_to_end(&mut block_bytes).expect("Failed to decode");
|
||||
let mut block_bytes = vec![0_u8; num_blocks*SIZE_QB];
|
||||
lz4::decompress(&block_bytes_compressed, &mut block_bytes[0..num_blocks*SIZE_QB]).unwrap();
|
||||
|
||||
for i in 0..num_blocks {
|
||||
let mut block = WorldBlock::new();
|
||||
@@ -55,6 +59,35 @@ impl WorldChunk {
|
||||
instance
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
|
||||
// Header
|
||||
let mut bytes: Vec<u8> = vec![0_u8; 5];
|
||||
bytes[0] = 1_u8; // 1b -> File version
|
||||
LittleEndian::write_u32(&mut bytes[1..5], self.blocks.len() as u32); // 4b -> Number of blocks in this file
|
||||
bytes.extend((0..128-5).map(|_| 0)); // Reserved 128b - 5b used
|
||||
|
||||
// Nodes
|
||||
let mut node_bytes = [0_u8; (SIZE_QB*4) as usize];
|
||||
LittleEndian::write_u32_into(&self.nodes, &mut node_bytes);
|
||||
bytes.extend(node_bytes.iter());
|
||||
|
||||
// Blocks
|
||||
let mut buf = Vec::new();
|
||||
for block in self.blocks.iter() {
|
||||
buf.extend(&block.materials);
|
||||
}
|
||||
lz4::compress_to_vec(&buf, &mut bytes, lz4::ACC_LEVEL_DEFAULT).unwrap();
|
||||
|
||||
|
||||
// alg | size | compr | decom
|
||||
// raw 32.89kB 0.06s 1.19s
|
||||
// deflate fast 1.23kB 1.22s 5.46s
|
||||
// lz4 1.6kB 0.07s 1.23s
|
||||
|
||||
bytes
|
||||
}
|
||||
|
||||
pub fn all_blocks(&self) -> Vec<(Point3<u32>, &WorldBlock)> {
|
||||
self.nodes.iter().enumerate()
|
||||
.filter(|(_, n)| **n != 0)
|
||||
@@ -87,22 +120,4 @@ impl WorldChunk {
|
||||
// Return block reference
|
||||
&mut self.blocks[(value-1) as usize]
|
||||
}
|
||||
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = Vec::with_capacity(self.nodes.len()*4 + self.blocks.len()* 32*32*32);
|
||||
|
||||
// Nodes
|
||||
let mut node_bytes = [0_u8; (SIZE_QB*4) as usize];
|
||||
LittleEndian::write_u32_into(&self.nodes, &mut node_bytes);
|
||||
bytes.extend(node_bytes.iter());
|
||||
|
||||
// Blocks
|
||||
let mut encoder = DeflateEncoder::new(Vec::new(), Compression::fast());
|
||||
for block in self.blocks.iter() {
|
||||
encoder.write_all(&block.materials).unwrap();
|
||||
}
|
||||
bytes.extend(encoder.finish().unwrap());
|
||||
|
||||
bytes
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user