80 lines
2.4 KiB
Rust
80 lines
2.4 KiB
Rust
use fastnoise_lite::{FastNoiseLite, FractalType};
|
|
use godot::{classes::class_macros::private::virtuals::Os::Vector3i, global::pow};
|
|
|
|
use crate::{chunk::ChunkColumn, generation::generator::SurfaceGenerator};
|
|
|
|
pub struct SimpleSurfaceGenerator {
|
|
noise: FastNoiseLite,
|
|
surface_height: u32,
|
|
chunk_size: Vector3i,
|
|
}
|
|
|
|
impl SimpleSurfaceGenerator {
|
|
pub fn new(seed: i32, frequency: f32, surface_height: u32, chunk_size: Vector3i) -> Self {
|
|
let mut noise = FastNoiseLite::new();
|
|
noise.frequency = frequency;
|
|
noise.noise_type = fastnoise_lite::NoiseType::OpenSimplex2;
|
|
noise.seed = seed;
|
|
noise.set_fractal_type(Some(FractalType::Ridged));
|
|
noise.set_fractal_octaves(Some(4));
|
|
Self {
|
|
noise,
|
|
surface_height,
|
|
chunk_size,
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn normalize_value(value: f32) -> f32 {
|
|
(value + 1.0) * 0.5 // [0, value]
|
|
}
|
|
}
|
|
|
|
impl SurfaceGenerator for SimpleSurfaceGenerator {
|
|
fn generate(&self, column: &mut ChunkColumn) {
|
|
let size_x = self.chunk_size.x;
|
|
let size_z = self.chunk_size.z;
|
|
|
|
let base_x = column.world_position.0 * size_x;
|
|
let base_z = column.world_position.1 * size_z;
|
|
|
|
let freq = 1.0 / 32.0;
|
|
|
|
let column_height = self.chunk_size.y * self.surface_height as i32;
|
|
|
|
for x in 0..self.chunk_size.x {
|
|
for z in 0..self.chunk_size.z {
|
|
// world coordinates of this column
|
|
let world_x = base_x + x;
|
|
let world_z = base_z + z;
|
|
|
|
let noise = self
|
|
.noise
|
|
.get_noise_2d(world_x as f32 * freq, world_z as f32 * freq);
|
|
|
|
let noise = Self::normalize_value(noise);
|
|
|
|
let height = (noise.powi(2) * column_height as f32) as i32;
|
|
|
|
for y in 1..=height {
|
|
column.set_voxel(Vector3i::new(world_x, y, world_z), true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
fn sample_voxel(&self, pos: Vector3i) -> bool {
|
|
let freq = 1.0 / 32.0;
|
|
|
|
let noise = self
|
|
.noise
|
|
.get_noise_2d(pos.x as f32 * freq, pos.z as f32 * freq);
|
|
|
|
let noise = Self::normalize_value(noise);
|
|
|
|
let column_height = self.chunk_size.y * self.surface_height as i32;
|
|
let height = (noise.powi(2) * column_height as f32) as i32;
|
|
|
|
pos.y <= height
|
|
}
|
|
}
|