diff --git a/Cargo.toml b/Cargo.toml index 55130f4..9ecf5e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,9 +4,6 @@ version = "0.1.0" edition = "2024" [dependencies] -noise = "0.9.0" -image = "0.25.5" -rayon = "1.10.0" [lib] name = "worldgen" path = "src/lib.rs" diff --git a/src/.vscode/launch.json b/src/.vscode/launch.json new file mode 100644 index 0000000..10efcb2 --- /dev/null +++ b/src/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "request": "launch", + "name": "Debug", + "program": "${workspaceFolder}/", + "args": [], + "cwd": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 9a2da68..078ba93 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,59 +1,70 @@ -use noise::{Fbm, MultiFractal, NoiseFn, Perlin}; - -/// Generates a 16x16 noise map for a given chunk using fractal noise with multiple octaves -/// to avoid repetitive patterns. -/// -/// # Arguments -/// - `seed`: A number influencing the noise generation (e.g., 42). -/// - `chunk_x`: The X coordinate of the chunk. -/// - `chunk_z`: The Z coordinate of the chunk. -/// - `scale`: The noise scale (smaller = more detailed noise). -/// -/// # Returns -/// - A **16x16 noise map** as `[[f64; 16]; 16]`, normalized between -64 and 324. -pub fn generate_normalized_noise_map( - seed: u32, - chunk_x: i32, - chunk_z: i32, +pub struct Noise { scale: f64, -) -> [[f64; 16]; 16] { - // Spécifier explicitement que Fbm utilise Perlin comme bruit de base - let fbm = Fbm::::new(seed).set_octaves(15); - let mut noise_map = [[0.0; 16]; 16]; - - // Define normalization range - let min_range = -64.0; - let max_range = 320.0; - - for x in 0..16 { - for z in 0..16 { - // Convert chunk-local coordinates to global world coordinates - let world_x = (chunk_x * 16 + x as i32) as f64 * scale; - let world_z = (chunk_z * 16 + z as i32) as f64 * scale; - - // Generate fractal noise value (with multiple octaves) - let noise_value = fbm.get([world_x, world_z]); - - // Normalize noise from [-1,1] to [-64,324] - let normalized_noise = (noise_value + 1.0) / 2.0 * (max_range - min_range) + min_range; - - // Store the normalized noise value - noise_map[x][z] = normalized_noise; - } - } - noise_map + amplitude: f64, +} +pub struct Vector { + x: f32, + y: f32, +} +impl Noise { + pub fn new(scale: f64, amplitude: f64) -> Self { + Self { scale, amplitude } + } + pub fn get(&self, x: f64, z: f64) -> f64 { + let xs = x / self.scale; + let zs = z / self.scale; + self.perlin(xs, zs) * self.amplitude + } + fn perlin(&self, x: f64, z: f64) -> f64 { + // implement Perlin noise here (then simplex because it's harder) + todo!() + } +} +fn dot_product(v1: Vector, v2: Vector) -> f32 { + // Calculate the dot product between v1 and v2 using their coordinates. the result->f32. + v1.x * v2.x + v1.y * v2.y +} +fn calculate_norm(v1: &Vector) -> f32 { + // Calculate the norm of a vector using it's coordinates. the result -> f32. + (v1.x.powi(2) + v1.y.powi(2)).sqrt() +} +fn normalize(v1: &Vector) -> Vector { + // This function aim that every vector created randomly has the same norm (1). + Vector { + x: v1.x / calculate_norm(v1), + y: v1.y / calculate_norm(v1), + } } - #[cfg(test)] mod tests { - use super::*; - + use crate::{Vector, calculate_norm, dot_product, normalize}; #[test] - fn test_generate_normalized_noise_map() { - let noise_map = generate_normalized_noise_map(456, 0, 0, 0.1); - assert_eq!(noise_map.len(), 16); - for row in noise_map.iter() { - assert_eq!(row.len(), 16); - } + fn test_dot_product() { + assert_eq!( + dot_product(Vector { x: 1.0, y: 0.0 }, Vector { x: 0.0, y: 1.0 }), + 0.0 + ); + assert_eq!( + dot_product(Vector { x: 1.0, y: 0.5 }, Vector { x: 0.2, y: 1.0 }), + 0.7, + ); + assert_eq!( + dot_product(Vector { x: 1.0, y: 0.5 }, Vector { x: -0.2, y: -1.0 }), + -0.7, + ); + } + #[test] + fn test_calculate_norm() { + assert_eq!(calculate_norm(&Vector { x: 0.5, y: 0.5 }), 0.5_f32.sqrt()); + assert_eq!(calculate_norm(&Vector { x: 0.7, y: 0.3 }), 0.58_f32.sqrt()); + assert_eq!( + calculate_norm(&Vector { x: -0.7, y: -0.3 }), + calculate_norm(&Vector { x: 0.7, y: 0.3 }) + ); + } + #[test] + fn test_normalize() { + let v1 = Vector { x: 0.5, y: 0.5 }; + assert_eq!(calculate_norm(&normalize(&v1)).round(), 1_f32); } } diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 00c2ec6..0000000 --- a/src/main.rs +++ /dev/null @@ -1,69 +0,0 @@ -use image::{GrayImage, Luma}; -use rayon::prelude::*; -use worldgen::generate_normalized_noise_map; // Import rayon for parallel processing - -fn main() { - // Define parameters - let radius = 300; - let chunk_size = 16; - let num_chunks = 2 * radius + 1; // number of chunks per dimension (65 here) - let img_width = num_chunks * chunk_size; - let img_height = num_chunks * chunk_size; - - // Generate all chunk coordinates from -radius to +radius - let chunk_coords: Vec<(i32, i32)> = (-radius..=radius) - .flat_map(|cx| (-radius..=radius).map(move |cz| (cx, cz))) - .collect(); - - // Compute noise maps for each chunk in parallel using Rayon - let chunk_results: Vec<(i32, i32, [[f64; 16]; 16])> = chunk_coords - .into_par_iter() - .map(|(cx, cz)| { - let noise_map = generate_normalized_noise_map(42, cx, cz, 0.001); - (cx, cz, noise_map) - }) - .collect(); - - // Create the big image with the appropriate dimensions - let mut big_img: GrayImage = GrayImage::new(img_width as u32, img_height as u32); - - // Write each chunk's noise map into the global image at the corresponding position - for (cx, cz, noise_map) in chunk_results { - // Compute pixel offset: we shift de coordonnées de chunk pour obtenir des indices positifs - let offset_x = ((cx + radius) * chunk_size) as u32; - let offset_y = ((cz + radius) * chunk_size) as u32; - write_chunk_to_image(&mut big_img, offset_x, offset_y, noise_map); - } - - // Save the generated image to a file - big_img - .save("big_noise_map.png") - .expect("Failed to save image"); - println!("Image saved as big_noise_map.png"); -} - -/// Writes a 16x16 chunk noise map into the provided image at the specified offset. -/// Noise values are normalized from the range [-64, 324] to [0, 255]. -fn write_chunk_to_image( - img: &mut GrayImage, - offset_x: u32, - offset_y: u32, - noise_map: [[f64; 16]; 16], -) { - let min_val = -64.0; - let max_val = 324.0; - let scale = 255.0 / (max_val - min_val); - - // Iterate over each pixel in the 16x16 noise map - for (row_index, row) in noise_map.iter().enumerate() { - for (col_index, &value) in row.iter().enumerate() { - // Map noise value from [-64, 324] to [0, 255] - let pixel_value = (((value - min_val) * scale).round() as u8).min(255); - img.put_pixel( - offset_x + col_index as u32, - offset_y + row_index as u32, - Luma([pixel_value]), - ); - } - } -}