use fastnoise_lite::{FastNoiseLite, FractalType}; use glam::{IVec2, Vec2}; use crate::{ content::materials::MaterialId, proc_gen::{Biome, InterpolatedPixel}, sim::cell::Cell, }; const DISPLACEMENT_ROUGHNESS: f32 = 0.375; const BOUNDARY_ROUGHNESS: f32 = 0.375; pub struct MinesBiome { pub dirt_roughness: FastNoiseLite, pub water_roughness: FastNoiseLite, pub wood_roughness: FastNoiseLite, } impl MinesBiome { fn pixel_idx_to_type(idx: u8) -> MinesBiomePixelType { match idx { 1 => MinesBiomePixelType::Dirt, 12 => MinesBiomePixelType::Water, 13 => MinesBiomePixelType::Wood, _ => MinesBiomePixelType::Void, } } fn material_roughness(&self, pixel_type: MinesBiomePixelType, world: Vec2) -> f32 { match pixel_type { MinesBiomePixelType::Dirt => self.dirt_roughness.get_noise_2d(world.x, world.y), MinesBiomePixelType::Water => self.water_roughness.get_noise_2d(world.x, world.y), MinesBiomePixelType::Wood => self.wood_roughness.get_noise_2d(world.x, world.y), _ => self.dirt_roughness.get_noise_2d(world.x, world.y), } } pub fn new() -> Self { let mut dirt_roughness = FastNoiseLite::with_seed(0); dirt_roughness.set_fractal_type(Some(FractalType::Ridged)); dirt_roughness.set_fractal_octaves(Some(2)); let mut water_roughness = FastNoiseLite::with_seed(100); water_roughness.set_fractal_type(Some(FractalType::FBm)); water_roughness.set_frequency(Some(0.005)); water_roughness.set_fractal_octaves(Some(2)); let mut wood_roughness = FastNoiseLite::with_seed(200); wood_roughness.set_fractal_type(Some(FractalType::FBm)); wood_roughness.set_frequency(Some(0.02)); wood_roughness.set_fractal_octaves(Some(2)); MinesBiome { dirt_roughness, water_roughness, wood_roughness, } } } enum MinesBiomePixelType { Void, Dirt, Water, Wood, } impl Biome for MinesBiome { fn fragment(&self, pixel: InterpolatedPixel, world: IVec2) -> Cell { let world = world.as_vec2(); let pixel_idx = pixel .interpolated_pixel_indices .iter() .map(|&(i, s)| { ( i, s + self.material_roughness(MinesBiome::pixel_idx_to_type(i), world) * BOUNDARY_ROUGHNESS, ) }) .max_by(|&(_, s1), &(_, s2)| s1.total_cmp(&s2)) .map_or(0, |(i, _)| i); let displacement = DISPLACEMENT_ROUGHNESS * self.dirt_roughness.get_noise_2d(world.x, world.y); match pixel_idx { 1 => { if pixel.interpolated_solidity + displacement <= 0.0 { return Cell::void(); } Cell::from_material(MaterialId::Dirt) } 12 => { if pixel.interpolated_solidity + displacement <= 0.0 { return Cell::void(); } Cell::from_material(MaterialId::Water) } 13 => { if pixel.interpolated_solidity + displacement <= 0.0 { return Cell::void(); } Cell::from_material(MaterialId::Wood) } _ => Cell::void(), } } }