Files
fastvoxel/src/generation/simple_heightmap.rs
TheRealKaamy d3c1b7bb5b re-working the editor nodes
de-coupling godot resources from internal runtime logic
2026-03-28 03:12:31 +03:30

78 lines
2.2 KiB
Rust

use fastnoise_lite::{FastNoiseLite, FractalType};
use godot::classes::class_macros::private::virtuals::Os::Vector3i;
use crate::chunk::{Chunk, chunk::CHUNK_SIZE};
pub struct SimpleSurfaceGenerator {
noise: FastNoiseLite,
surface_height: u32,
}
impl SimpleSurfaceGenerator {
pub fn new(seed: i32, frequency: f32, surface_height: u32) -> 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,
}
}
#[inline]
pub fn normalize_value(value: f32) -> f32 {
(value + 1.0) * 0.5 // [0, value]
}
}
impl SimpleSurfaceGenerator {
fn generate(&self, column: &mut Chunk) {
let size_x = CHUNK_SIZE;
let size_z = CHUNK_SIZE;
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 = CHUNK_SIZE * self.surface_height as i32;
for x in 0..CHUNK_SIZE {
for z in 0..CHUNK_SIZE {
// 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 = CHUNK_SIZE * self.surface_height as i32;
let height = (noise.powi(2) * column_height as f32) as i32;
pos.y <= height
}
}