move stuff, forests!

This commit is contained in:
griffi-gh 2024-05-03 01:21:56 +02:00
parent 91326ce2dc
commit 875f131fe1
10 changed files with 138 additions and 15 deletions

View file

@ -9,11 +9,8 @@ use crate::{
queue::QueuedBlock,
};
mod _01_terrain;
mod _02_water;
mod _03_caves;
mod _04_layers;
mod _05_decorate;
pub mod steps;
pub mod structures;
#[repr(u8)]
#[derive(Clone, Copy, Debug, Default, NoUninit, CheckedBitPattern)]
@ -186,11 +183,12 @@ impl WorldGenerator {
/// Will return `None` only if the generation was aborted.
pub fn generate(mut self, abort: Option<Arc<Atomic<AbortState>>>) -> Option<(BlockData, Vec<QueuedBlock>)> {
run_steps!(&mut self, abort, [
_01_terrain::TerrainStep,
_02_water::WaterStep,
_03_caves::CaveStep,
_04_layers::LayersStep,
_05_decorate::DecorateStep,
steps::_01_terrain::TerrainStep,
steps::_02_water::WaterStep,
steps::_03_caves::CaveStep,
steps::_04_layers::LayersStep,
steps::_05_decorate::DecorateStep,
steps::_06_trees::TreesStep,
]).then_some((self.blocks, self.queue))
}
}

View file

@ -0,0 +1,6 @@
pub mod _01_terrain;
pub mod _02_water;
pub mod _03_caves;
pub mod _04_layers;
pub mod _05_decorate;
pub mod _06_trees;

View file

@ -1,7 +1,7 @@
use fastnoise_lite::{FastNoiseLite, FractalType};
use glam::ivec3;
use crate::{block::Block, chunk::CHUNK_SIZE};
use super::{SeedThingy, WorldGenStep, WorldGenerator};
use super::super::{SeedThingy, WorldGenStep, WorldGenerator};
pub struct TerrainStep {
noise: FastNoiseLite,

View file

@ -1,6 +1,6 @@
use glam::ivec3;
use crate::{block::Block, chunk::CHUNK_SIZE};
use super::{WorldGenerator, WorldGenStep};
use super::super::{WorldGenerator, WorldGenStep};
pub const WATER_LEVEL: i32 = 0;

View file

@ -1,7 +1,7 @@
use fastnoise_lite::{FastNoiseLite, FractalType};
use glam::{ivec3, FloatExt, IVec3};
use crate::{block::Block, chunk::CHUNK_SIZE};
use super::{SeedThingy, WorldGenStep, WorldGenerator};
use super::super::{SeedThingy, WorldGenStep, WorldGenerator};
pub struct CaveStep {
a: FastNoiseLite,

View file

@ -1,6 +1,10 @@
use glam::ivec3;
use crate::{block::Block, chunk::CHUNK_SIZE};
use super::{WorldGenStep, WorldGenerator, _02_water::WATER_LEVEL};
use super::{
_02_water::WATER_LEVEL,
super::{WorldGenStep, WorldGenerator}
};
pub struct LayersStep;
impl WorldGenStep for LayersStep {

View file

@ -1,6 +1,9 @@
use glam::ivec3;
use crate::{block::Block, chunk::CHUNK_SIZE};
use super::{WorldGenStep, WorldGenerator, _02_water::WATER_LEVEL};
use super::{
_02_water::WATER_LEVEL,
super::{WorldGenStep, WorldGenerator},
};
pub struct DecorateStep;

View file

@ -0,0 +1,45 @@
use bincode::de;
use fastnoise_lite::{FastNoiseLite, NoiseType};
use glam::ivec3;
use crate::{block::Block, chunk::CHUNK_SIZE, worldgen::SeedThingy};
use super::_02_water::WATER_LEVEL;
use crate::worldgen::{
WorldGenStep, WorldGenerator,
structures::{Structure, TreeStructure},
};
pub struct TreesStep {
density_noise: FastNoiseLite,
}
impl WorldGenStep for TreesStep {
fn initialize(gen: &WorldGenerator) -> Self {
let mut seeder = SeedThingy::new(gen.seed.rotate_left(5));
let mut density_noise = FastNoiseLite::with_seed(seeder.next_seed());
density_noise.set_noise_type(Some(NoiseType::OpenSimplex2));
density_noise.set_frequency(Some(0.008));
Self { density_noise }
}
fn generate(&mut self, gen: &mut WorldGenerator) {
for x in 0..CHUNK_SIZE as i32 {
for z in 0..CHUNK_SIZE as i32 {
let terrain_height = gen.data.master_height_map.as_ref().unwrap()[x as usize][z as usize];
if terrain_height < WATER_LEVEL { continue }
let global_xz = gen.global_position(ivec3(x, 0, z));
let mut density = self.density_noise.get_noise_2d(global_xz.x as f64, global_xz.z as f64) * 0.5 + 0.5;
density = density.powi(3);
if gen.seeded_hash((global_xz.x, global_xz.z, 0xfef)) & 0xff >= (density * 7.).round() as u64 {
continue
}
let tree = TreeStructure::default();
if let Some(local_y) = gen.local_y_position(terrain_height) {
tree.place(gen, ivec3(x, local_y, z));
}
}
}
}
}

View file

@ -0,0 +1,9 @@
use glam::IVec3;
use super::WorldGenerator;
mod tree;
pub use tree::TreeStructure;
pub trait Structure {
fn place(&self, gen: &mut WorldGenerator, root_pos: IVec3);
}

View file

@ -0,0 +1,58 @@
use glam::IVec3;
use super::Structure;
use crate::{block::Block, worldgen::WorldGenerator};
#[derive(Clone, Copy, Debug)]
pub struct TreeStructure {
pub height: i32,
}
impl Default for TreeStructure {
fn default() -> Self {
Self { height: 5 }
}
}
impl Structure for TreeStructure {
fn place(&self, gen: &mut WorldGenerator, root: IVec3) {
//check the block below the tree, if it's grass, replace it with dirt
//XXX: This won't work if root.y == 0
if root.y != 0 && gen.query(root - IVec3::Y) == Block::Grass {
gen.place(root - IVec3::Y, Block::Dirt);
}
//Tree stem
for y in root.y..root.y + self.height {
gen.place_or_queue(IVec3::new(root.x, y, root.z), Block::Wood);
}
//Tree leaves
//Try to create the following shape:
//(a 5x2x5 cube that wraps around the stem with a 3x1x3 cube on top)
// xxx
// xx|xx
// xx|xx
// |
for y in 0..=4_i32 {
for x in -2..=2_i32 {
for z in -2..=2_i32 {
//Do not overwrite the stem
if y < 3 && x == 0 && z == 0 {
continue
}
// Cut off the corners of the top layer
if y >= 3 && (x.abs() > 1 || z.abs() > 1) {
continue
}
let position = IVec3::new(
root.x + x,
root.y + self.height - 3 + y,
root.z + z
);
gen.place_or_queue(position, Block::Leaf);
}
}
}
}
}