fixes to biome blending
This commit is contained in:
@@ -1,54 +1,59 @@
|
|||||||
use bevy::math::UVec2;
|
use bevy::math::UVec2;
|
||||||
|
use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||||
|
|
||||||
use super::chunk::Chunk;
|
use super::chunk::Chunk;
|
||||||
|
|
||||||
pub struct BiomeMap {
|
pub struct BiomeMap {
|
||||||
pub height: usize,
|
pub height: usize,
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
pub chunks: Vec<[Vec<f32>; Chunk::AREA]>,
|
pub biome_count: usize,
|
||||||
|
pub tiles: Vec<Vec<f32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BiomeMap {
|
impl BiomeMap {
|
||||||
pub fn new(size: UVec2) -> Self {
|
pub fn new(size: UVec2, biome_count: usize) -> Self {
|
||||||
return BiomeMap {
|
return BiomeMap {
|
||||||
height: size.y as usize,
|
height: size.y as usize * Chunk::SIZE,
|
||||||
width: size.x as usize,
|
width: size.x as usize * Chunk::SIZE,
|
||||||
chunks: Vec::with_capacity(size.length_squared() as usize),
|
biome_count,
|
||||||
|
tiles: Vec::with_capacity(size.x as usize * size.y as usize * Chunk::AREA),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blend(&mut self, count: usize) {
|
pub fn blend(&mut self, count: usize) {
|
||||||
|
assert!(count != 0, "Count cannot be 0");
|
||||||
for _ in 0..count {
|
for _ in 0..count {
|
||||||
self.blend_once();
|
self.blend_once();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn blend_once(&mut self) {
|
fn blend_once(&mut self) {
|
||||||
for y in 0..self.height {
|
let t: Vec<_> = (0..self.height)
|
||||||
|
.into_par_iter()
|
||||||
|
.map(|y| {
|
||||||
|
let mut new_tiles = Vec::with_capacity(self.width);
|
||||||
for x in 0..self.width {
|
for x in 0..self.width {
|
||||||
let kernel = self.get_kernel(x as i32, y as i32);
|
let kernel = self.get_kernel(x as i32, y as i32);
|
||||||
let r = kernel.iter().filter_map(|f| *f).fold(Vec::new(), |a, b| {
|
let r = kernel
|
||||||
if a.len() != b.len() {
|
.iter()
|
||||||
return b.iter().map(|f| *f).collect();
|
.filter_map(|f| *f)
|
||||||
}
|
.fold(vec![0.; self.biome_count], |a, b| {
|
||||||
return a.iter().zip(b).map(|v| v.0 + v.1).collect();
|
return a.iter().zip(b).map(|v| v.0 + v.1).collect();
|
||||||
});
|
});
|
||||||
|
|
||||||
let sum: f32 = r.iter().sum();
|
let sum: f32 = r.iter().sum();
|
||||||
|
if sum == 0. {
|
||||||
|
new_tiles.push(vec![0.; self.biome_count]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
new_tiles.push(r.iter().map(|f| f / sum).collect());
|
||||||
|
}
|
||||||
|
return new_tiles;
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
|
.collect();
|
||||||
|
|
||||||
*self.get_biome_mut(x, y) = r.iter().map(|f| f / sum).collect();
|
self.tiles = t;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_biome_mut(&mut self, x: usize, y: usize) -> &mut Vec<f32> {
|
|
||||||
let cx = x as usize / Chunk::SIZE;
|
|
||||||
let cy = y as usize / Chunk::SIZE;
|
|
||||||
let chunk_index = cy * self.width as usize + cx;
|
|
||||||
let ix = x as usize - (x as usize * Chunk::SIZE);
|
|
||||||
let iy = y as usize - (y as usize * Chunk::SIZE);
|
|
||||||
let index = iy * self.width as usize + ix;
|
|
||||||
return &mut self.chunks[chunk_index][index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_kernel(&self, x: i32, y: i32) -> [Option<&Vec<f32>>; 9] {
|
pub fn get_kernel(&self, x: i32, y: i32) -> [Option<&Vec<f32>>; 9] {
|
||||||
@@ -73,12 +78,30 @@ impl BiomeMap {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cx = x as usize / Chunk::SIZE;
|
return Some(&self.tiles[x as usize + y as usize * self.width]);
|
||||||
let cy = y as usize / Chunk::SIZE;
|
}
|
||||||
let chunk_index = cy * self.width as usize + cx;
|
}
|
||||||
let ix = x as usize - (x as usize * Chunk::SIZE);
|
|
||||||
let iy = y as usize - (y as usize * Chunk::SIZE);
|
#[cfg(test)]
|
||||||
let index = iy * self.width as usize + ix;
|
mod tests {
|
||||||
return Some(&self.chunks[chunk_index][index]);
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn biome_blend() {
|
||||||
|
let mut biome = BiomeMap::new(UVec2::ONE * 16, 8);
|
||||||
|
|
||||||
|
for y in 0..biome.height {
|
||||||
|
for x in 0..biome.width {
|
||||||
|
let mut b = vec![0.; biome.biome_count];
|
||||||
|
let i = x / Chunk::SIZE;
|
||||||
|
let z = y / Chunk::SIZE;
|
||||||
|
let idx = (i + z) % biome.biome_count;
|
||||||
|
b[idx] = 1.;
|
||||||
|
biome.tiles.push(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
biome.blend(8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user