misc fixes

This commit is contained in:
2024-09-02 19:53:13 -04:00
parent f98173d00a
commit 9613e3ae0d
4 changed files with 71 additions and 27 deletions

View File

@@ -3,12 +3,12 @@ use core::f32;
use bevy::math::{IVec2, UVec2}; use bevy::math::{IVec2, UVec2};
use bevy::prelude::{FloatExt, Vec2}; use bevy::prelude::{FloatExt, Vec2};
use bevy::utils::default; use bevy::utils::default;
use noise::{NoiseFn, SuperSimplex}; use noise::{NoiseFn, Simplex, SuperSimplex};
use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon::iter::{IntoParallelIterator, ParallelIterator};
use crate::biome_painter::BiomePainter; use crate::biome_painter::BiomePainter;
use crate::map::biome_map::{BiomeChunk, BiomeData, BiomeMap}; use crate::map::biome_map::{BiomeChunk, BiomeData, BiomeMap};
use crate::prelude::*; use crate::{map, prelude::*};
pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePainter) -> (Map, BiomeMap) { pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePainter) -> (Map, BiomeMap) {
let biomes = generate_biomes(cfg, seed, painter); let biomes = generate_biomes(cfg, seed, painter);
@@ -74,9 +74,9 @@ pub fn generate_biome_chunk(
data: [BiomeData::default(); Chunk::AREA], data: [BiomeData::default(); Chunk::AREA],
tiles: Vec::with_capacity(Chunk::AREA), tiles: Vec::with_capacity(Chunk::AREA),
}; };
let noise_m = SuperSimplex::new(seed + 1); let noise_m = Simplex::new(seed + 1);
let noise_t = SuperSimplex::new(seed + 2); let noise_t = Simplex::new(seed + 2);
let noise_c = SuperSimplex::new(seed + 3); let noise_c = Simplex::new(seed + 3);
for z in 0..Chunk::SIZE { for z in 0..Chunk::SIZE {
for x in 0..Chunk::SIZE { for x in 0..Chunk::SIZE {
@@ -86,7 +86,8 @@ pub fn generate_biome_chunk(
&cfg.moisture_noise, &cfg.moisture_noise,
&noise_m, &noise_m,
cfg.size.as_vec2(), cfg.size.as_vec2(),
0.0, cfg.border_size,
100.0,
); );
let temperature = sample_point( let temperature = sample_point(
x as f64 + chunk_x as f64 * Chunk::SIZE as f64, x as f64 + chunk_x as f64 * Chunk::SIZE as f64,
@@ -94,7 +95,8 @@ pub fn generate_biome_chunk(
&cfg.temperature_noise, &cfg.temperature_noise,
&noise_t, &noise_t,
cfg.size.as_vec2(), cfg.size.as_vec2(),
0.0, cfg.border_size,
50.0,
); );
let continentality = sample_point( let continentality = sample_point(
x as f64 + chunk_x as f64 * Chunk::SIZE as f64, x as f64 + chunk_x as f64 * Chunk::SIZE as f64,
@@ -102,6 +104,7 @@ pub fn generate_biome_chunk(
&cfg.continent_noise, &cfg.continent_noise,
&noise_c, &noise_c,
cfg.size.as_vec2(), cfg.size.as_vec2(),
cfg.border_size,
0.0, 0.0,
); );
let data = BiomeData { let data = BiomeData {
@@ -135,6 +138,7 @@ pub fn generate_noise_map(size: UVec2, seed: u32, cfg: &NoiseConfig, border_size
&noise, &noise,
size.as_vec2(), size.as_vec2(),
border_size, border_size,
0.0,
)); ));
} }
return row; return row;
@@ -154,7 +158,7 @@ pub fn generate_chunk(
let mut result: [f32; Chunk::SIZE * Chunk::SIZE] = [0.; Chunk::AREA]; let mut result: [f32; Chunk::SIZE * Chunk::SIZE] = [0.; Chunk::AREA];
let mut data = [BiomeData::default(); Chunk::AREA]; let mut data = [BiomeData::default(); Chunk::AREA];
let mut biome_ids = [0; Chunk::AREA]; let mut biome_ids = [0; Chunk::AREA];
let noise = SuperSimplex::new(seed); let noise = Simplex::new(seed);
let mut min = f32::MAX; let mut min = f32::MAX;
let mut max = f32::MIN; let mut max = f32::MIN;
for z in 0..Chunk::SIZE { for z in 0..Chunk::SIZE {
@@ -175,6 +179,7 @@ pub fn generate_chunk(
&noise, &noise,
cfg.size.as_vec2(), cfg.size.as_vec2(),
cfg.border_size, cfg.border_size,
0.0,
) * blend; ) * blend;
} }
let idx = x + z * Chunk::SIZE; let idx = x + z * Chunk::SIZE;
@@ -199,7 +204,15 @@ pub fn generate_chunk(
}; };
} }
fn sample_point(x: f64, z: f64, cfg: &NoiseConfig, noise: &impl NoiseFn<f64, 2>, size: Vec2, border_size: f32) -> f32 { fn sample_point(
x: f64,
z: f64,
cfg: &NoiseConfig,
noise: &impl NoiseFn<f64, 2>,
size: Vec2,
border_size: f32,
border_value: f32,
) -> f32 {
let x_s = x / cfg.scale; let x_s = x / cfg.scale;
let z_s = z / cfg.scale; let z_s = z / cfg.scale;
@@ -221,7 +234,7 @@ fn sample_point(x: f64, z: f64, cfg: &NoiseConfig, noise: &impl NoiseFn<f64, 2>,
} else { } else {
elevation += value; elevation += value;
} }
} }
if border_size == 0.0 { if border_size == 0.0 {
return elevation as f32; return elevation as f32;
@@ -235,7 +248,7 @@ fn sample_point(x: f64, z: f64, cfg: &NoiseConfig, noise: &impl NoiseFn<f64, 2>,
let d2 = od.x.min(od.y); let d2 = od.x.min(od.y);
let d = d1.min(d2).min(border_size).remap(0., border_size, 0., 1.); let d = d1.min(d2).min(border_size).remap(0., border_size, 0., 1.);
return (elevation as f32) * d; return border_value.lerp(elevation as f32, d);
} }
fn mask(mask: f64, value: f64) -> f64 { fn mask(mask: f64, value: f64) -> f64 {

View File

@@ -106,20 +106,20 @@ fn get_height_color_blend(base_color: Hsla, height: f32, height2: f32, smooth: f
return color; return color;
} }
pub fn render_biome_noise_map(map: &BiomeMap) -> ImageBuffer<image::Rgba<u8>, Vec<u8>> { pub fn render_biome_noise_map(map: &BiomeMap, multi: Vec3) -> ImageBuffer<image::Rgba<u8>, Vec<u8>> {
let mut image = ImageBuffer::new(map.width as u32, map.height as u32); let mut image = ImageBuffer::new(map.width as u32, map.height as u32);
update_biome_noise_map(map, &mut image); update_biome_noise_map(map, multi, &mut image);
return image; return image;
} }
pub fn update_biome_noise_map(map: &BiomeMap, image: &mut ImageBuffer<image::Rgba<u8>, Vec<u8>>) { pub fn update_biome_noise_map(map: &BiomeMap, multi: Vec3, image: &mut ImageBuffer<image::Rgba<u8>, Vec<u8>>) {
image.par_enumerate_pixels_mut().for_each(|(x, y, pixel)| { image.par_enumerate_pixels_mut().for_each(|(x, y, pixel)| {
let tile = map.get_biome_data(x as usize, y as usize); let tile = map.get_biome_data(x as usize, y as usize);
let color = LinearRgba::rgb( let color = LinearRgba::rgb(
tile.temperature / 100.0, (tile.temperature / 100.0) * multi.x,
tile.continentality / 100.0, (tile.continentality / 100.0) * multi.y,
tile.moisture / 100.0, (tile.moisture / 100.0) * multi.z,
); );
*pixel = to_pixel(&color); *pixel = to_pixel(&color);
}); });

View File

@@ -162,10 +162,10 @@ fn create_heightmap(
biome_painter: Res<BiomePainter>, biome_painter: Res<BiomePainter>,
) { ) {
let config = GenerationConfig { let config = GenerationConfig {
biome_blend: 16, biome_blend: 32,
biome_dither: 16., biome_dither: 16.,
continent_noise: NoiseConfig { continent_noise: NoiseConfig {
scale: 1000., scale: 800.,
layers: vec![GeneratorLayer { layers: vec![GeneratorLayer {
base_roughness: 2.14, base_roughness: 2.14,
roughness: 0.87, roughness: 0.87,
@@ -180,7 +180,7 @@ fn create_heightmap(
}], }],
}, },
moisture_noise: NoiseConfig { moisture_noise: NoiseConfig {
scale: 500., scale: 900.,
layers: vec![GeneratorLayer { layers: vec![GeneratorLayer {
base_roughness: 2.14, base_roughness: 2.14,
roughness: 0.87, roughness: 0.87,
@@ -195,7 +195,7 @@ fn create_heightmap(
}], }],
}, },
temperature_noise: NoiseConfig { temperature_noise: NoiseConfig {
scale: 900., scale: 700.,
layers: vec![GeneratorLayer { layers: vec![GeneratorLayer {
base_roughness: 2.14, base_roughness: 2.14,
roughness: 0.87, roughness: 0.87,

View File

@@ -2,6 +2,7 @@ use bevy::{prelude::*, render::render_asset::RenderAssetUsages};
use bevy_inspector_egui::bevy_egui::EguiContexts; use bevy_inspector_egui::bevy_egui::EguiContexts;
use bevy_inspector_egui::egui::{self}; use bevy_inspector_egui::egui::{self};
use bevy_rapier3d::rapier::crossbeam::deque::Steal; use bevy_rapier3d::rapier::crossbeam::deque::Steal;
use image::{ImageBuffer, Rgba};
use world_generation::map::biome_map::{self, BiomeMap}; use world_generation::map::biome_map::{self, BiomeMap};
use world_generation::map::map_utils::{render_biome_map, render_biome_noise_map, update_map}; use world_generation::map::map_utils::{render_biome_map, render_biome_noise_map, update_map};
use world_generation::{map::map_utils::render_map, prelude::Map, states::GeneratorState}; use world_generation::{map::map_utils::render_map, prelude::Map, states::GeneratorState};
@@ -53,9 +54,12 @@ enum MapDisplayType {
HeightMap, HeightMap,
Biomes, Biomes,
BiomeNoise, BiomeNoise,
BiomeNoiseTemp,
BiomeNoiseContinent,
BiomeNoiseMoisture,
} }
fn render_map_ui(image: Res<MapImage>, mut contexts: EguiContexts, mut state: ResMut<UIState>) { fn render_map_ui(image: Res<MapImage>, heightmap: Res<Map>, biome_map: Res<BiomeMap>, mut contexts: EguiContexts, mut state: ResMut<UIState>) {
let id = contexts.add_image(image.0.clone_weak()); let id = contexts.add_image(image.0.clone_weak());
let mut map_type = state.target_map_type; let mut map_type = state.target_map_type;
@@ -68,12 +72,32 @@ fn render_map_ui(image: Res<MapImage>, mut contexts: EguiContexts, mut state: Re
ui.selectable_value(&mut map_type, MapDisplayType::HeightMap, "Heightmap"); ui.selectable_value(&mut map_type, MapDisplayType::HeightMap, "Heightmap");
ui.selectable_value(&mut map_type, MapDisplayType::Biomes, "Biomes"); ui.selectable_value(&mut map_type, MapDisplayType::Biomes, "Biomes");
ui.selectable_value(&mut map_type, MapDisplayType::BiomeNoise, "Biome Noise"); ui.selectable_value(&mut map_type, MapDisplayType::BiomeNoise, "Biome Noise");
ui.selectable_value(
&mut map_type,
MapDisplayType::BiomeNoiseTemp,
"Biome Noise: Tempurature",
);
ui.selectable_value(
&mut map_type,
MapDisplayType::BiomeNoiseContinent,
"Biome Noise: Continent",
);
ui.selectable_value(
&mut map_type,
MapDisplayType::BiomeNoiseMoisture,
"Biome Noise: Moisture",
);
}); });
ui.add(egui::widgets::Image::new(egui::load::SizedTexture::new( ui.add(egui::widgets::Image::new(egui::load::SizedTexture::new(
id, id,
[512.0, 512.0], [512.0, 512.0],
))); )));
if ui.button("Save Image").clicked() {
let img = get_map_image(&heightmap, &biome_map, map_type);
_ = img.save(format!("{:?}.png", map_type));
}
}); });
state.target_map_type = map_type; state.target_map_type = map_type;
@@ -90,11 +114,7 @@ fn update_map_render(
return; return;
} }
let result = match state.target_map_type { let result = get_map_image(&heightmap, &biome_map, state.target_map_type);
MapDisplayType::HeightMap => render_map(&heightmap, 0.1),
MapDisplayType::Biomes => render_biome_map(&heightmap, &biome_map),
MapDisplayType::BiomeNoise => render_biome_noise_map(&biome_map),
};
images.insert( images.insert(
image.0.id(), image.0.id(),
Image::from_dynamic(result.into(), true, RenderAssetUsages::RENDER_WORLD), Image::from_dynamic(result.into(), true, RenderAssetUsages::RENDER_WORLD),
@@ -102,3 +122,14 @@ fn update_map_render(
state.cur_map_type = state.target_map_type; state.cur_map_type = state.target_map_type;
} }
fn get_map_image(heightmap: &Map, biome_map: &BiomeMap, map_type: MapDisplayType) -> ImageBuffer<Rgba<u8>, Vec<u8>> {
return match map_type {
MapDisplayType::HeightMap => render_map(&heightmap, 0.1),
MapDisplayType::Biomes => render_biome_map(&heightmap, &biome_map),
MapDisplayType::BiomeNoise => render_biome_noise_map(&biome_map, Vec3::ONE),
MapDisplayType::BiomeNoiseTemp => render_biome_noise_map(&biome_map, Vec3::X),
MapDisplayType::BiomeNoiseContinent => render_biome_noise_map(&biome_map, Vec3::Y),
MapDisplayType::BiomeNoiseMoisture => render_biome_noise_map(&biome_map, Vec3::Z),
};
}