generator tweaks

data fixes
wip biome map visualization
This commit is contained in:
2024-09-01 22:49:48 -04:00
parent 77fa421bb2
commit 1dc6329252
7 changed files with 114 additions and 48 deletions

View File

@@ -1,4 +1,5 @@
use crate::hex_utils::HexCoord;
use crate::map::biome_map::{self, BiomeChunk, BiomeMap};
use crate::prelude::*;
use crate::tile_manager::TileAsset;
use crate::tile_mapper::TileMapperAsset;
@@ -14,6 +15,7 @@ use bevy::{
pub fn generate_packed_chunk_mesh(
chunk: &Chunk,
map: &Map,
biome_chunk: &BiomeChunk,
painter: &BiomePainterAsset,
tiles: &Res<Assets<TileAsset>>,
biomes: &Res<Assets<BiomeAsset>>,
@@ -27,7 +29,7 @@ pub fn generate_packed_chunk_mesh(
for z in 0..Chunk::SIZE {
for x in 0..Chunk::SIZE {
let height = chunk.heights[x + z * Chunk::SIZE];
let data = chunk.biome_data[x + z * Chunk::SIZE];
let data = biome_chunk.data[x + z * Chunk::SIZE];
let coord =
HexCoord::from_offset(IVec2::new(x as i32, z as i32) + (chunk.chunk_offset * Chunk::SIZE as i32));
let n = map.get_neighbors(&coord);

View File

@@ -10,14 +10,15 @@ use crate::biome_painter::BiomePainter;
use crate::map::biome_map::{BiomeChunk, BiomeData, BiomeMap};
use crate::prelude::*;
pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePainter) -> Map {
let biomes = &generate_biomes(cfg, seed, painter);
pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePainter) -> (Map, BiomeMap) {
let biomes = generate_biomes(cfg, seed, painter);
let biomes_borrow = &biomes;
// let mut chunks: Vec<Chunk> = Vec::with_capacity(cfg.size.length_squared() as usize);
let chunks: Vec<Chunk> = (0..cfg.size.y)
.into_par_iter()
.flat_map(|z| {
(0..cfg.size.x).into_par_iter().map(move |x| {
let biome_chunk = &biomes.chunks[x as usize + z as usize * cfg.size.x as usize];
let biome_chunk = &biomes_borrow.chunks[x as usize + z as usize * cfg.size.x as usize];
return generate_chunk(x, z, cfg, seed, &biome_chunk, painter);
})
})
@@ -33,14 +34,18 @@ pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePain
}
}
return Map {
return (
Map {
chunks,
height: cfg.size.y as usize,
width: cfg.size.x as usize,
sea_level: cfg.sea_level as f32,
min_level: min,
max_level: max,
};
biome_count: painter.biomes.len(),
},
biomes,
);
}
pub fn generate_biomes(cfg: &GenerationConfig, seed: u32, biome_painter: &BiomePainter) -> BiomeMap {
@@ -186,7 +191,6 @@ pub fn generate_chunk(
}
return Chunk {
heights: result,
biome_data: data,
biome_id: biome_ids,
chunk_offset: IVec2::new(chunk_x as i32, chunk_z as i32),
max_level: max,

View File

@@ -1,10 +1,13 @@
use bevy::math::{UVec2, Vec3};
use bevy::{
math::{UVec2, Vec3},
prelude::Resource,
};
use noise::NoiseFn;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use super::chunk::Chunk;
#[derive(Clone)]
#[derive(Clone, Resource)]
pub struct BiomeMap {
pub height: usize,
pub width: usize,

View File

@@ -7,7 +7,7 @@ use super::biome_map::BiomeData;
pub struct Chunk {
pub heights: [f32; Chunk::AREA],
pub textures: [[u32; 2]; Chunk::AREA],
pub biome_data: [BiomeData; Chunk::AREA],
// pub biome_data: [BiomeData; Chunk::AREA],
pub biome_id: [usize; Chunk::AREA],
pub chunk_offset: IVec2,
pub min_level: f32,
@@ -19,7 +19,7 @@ impl Default for Chunk {
Self {
heights: [0.; Chunk::AREA],
textures: [[0; 2]; Chunk::AREA],
biome_data: [BiomeData::default(); Chunk::AREA],
// biome_data: [BiomeData::default(); Chunk::AREA],
biome_id: [0; Chunk::AREA],
chunk_offset: Default::default(),
min_level: 0.0,

View File

@@ -16,6 +16,7 @@ pub struct Map {
pub sea_level: f32,
pub min_level: f32,
pub max_level: f32,
pub biome_count: usize,
}
impl Map {
@@ -72,7 +73,18 @@ impl Map {
return pos.is_in_bounds(self.height * Chunk::SIZE, self.width * Chunk::SIZE);
}
pub fn get_biome(&self, pos: &HexCoord) -> &BiomeData {
pub fn get_biome_id(&self, pos: &HexCoord) -> usize {
assert!(
self.is_in_bounds(pos),
"The provided coordinate is not within the map bounds"
);
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
return chunk.biome_id[pos.to_chunk_local_index()];
}
/*
pub fn get_biome_noise(&self, pos: &HexCoord) -> &BiomeData {
assert!(
self.is_in_bounds(pos),
"The provided coordinate is not within the map bounds"
@@ -111,6 +123,7 @@ impl Map {
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
return chunk.biome_data[pos.to_chunk_local_index()].continentality;
}
*/
pub fn get_center(&self) -> Vec3 {
let w = self.get_world_width();

View File

@@ -2,9 +2,13 @@ use bevy::{math::VectorSpace, prelude::*};
use image::ImageBuffer;
use rayon::prelude::*;
use crate::hex_utils::HexCoord;
use crate::{biome_painter::BiomePainter, hex_utils::HexCoord};
use super::{biome_map::BiomeMap, chunk::Chunk, map::Map};
use super::{
biome_map::{self, BiomeMap},
chunk::Chunk,
map::Map,
};
pub fn render_image(
size: UVec2,
@@ -60,14 +64,24 @@ pub fn update_map(map: &Map, smooth: f32, image: &mut ImageBuffer<image::Rgba<u8
let coord = HexCoord::from_grid_pos(x as usize, y as usize);
let right = coord.get_neighbor(1);
let height = map.sample_height(&coord);
let mut color = Hsla::hsl(138.0, 1.0, 0.4);
if height < map.sea_level {
color.hue = 217.0;
}
if map.is_in_bounds(&right) {
let h2 = map.sample_height(&right);
let mut d = h2 - height;
color = get_height_color_blend(color, height, h2, smooth);
}
*pixel = to_pixel(&color.into());
});
}
fn get_height_color_blend(base_color: Hsla, height: f32, height2: f32, smooth: f32) -> Hsla {
let mut color = base_color;
let mut d = height2 - height;
if smooth == 0.0 || d.abs() > smooth {
if d > 0.0 {
color.lightness += 0.1;
@@ -86,25 +100,22 @@ pub fn update_map(map: &Map, smooth: f32, image: &mut ImageBuffer<image::Rgba<u8
}
}
}
return color;
}
*pixel = to_pixel(&color.into());
});
}
pub fn render_biome_map(map: &Map) -> ImageBuffer<image::Rgba<u8>, Vec<u8>> {
pub fn render_biome_noise_map(map: &BiomeMap) -> ImageBuffer<image::Rgba<u8>, Vec<u8>> {
let mut image = ImageBuffer::new(
map.width as u32 * Chunk::SIZE as u32,
map.height as u32 * Chunk::SIZE as u32,
);
update_biome_map(map, &mut image);
update_biome_noise_map(map, &mut image);
return image;
}
pub fn update_biome_map(map: &Map, image: &mut ImageBuffer<image::Rgba<u8>, Vec<u8>>) {
pub fn update_biome_noise_map(map: &BiomeMap, image: &mut ImageBuffer<image::Rgba<u8>, Vec<u8>>) {
image.par_enumerate_pixels_mut().for_each(|(x, y, pixel)| {
let coord = HexCoord::from_grid_pos(x as usize, y as usize);
let tile = map.get_biome(&coord);
let tile = map.get_biome_data(x as usize, y as usize);
let color = LinearRgba::rgb(
tile.temperature / 100.0,
@@ -114,3 +125,31 @@ pub fn update_biome_map(map: &Map, image: &mut ImageBuffer<image::Rgba<u8>, Vec<
*pixel = to_pixel(&color);
});
}
pub fn render_biome_map(map: &Map, biome_map: &BiomeMap) -> ImageBuffer<image::Rgba<u8>, Vec<u8>> {
let mut image = ImageBuffer::new(
map.width as u32 * Chunk::SIZE as u32,
map.height as u32 * Chunk::SIZE as u32,
);
update_biome_map(map, biome_map, &mut image);
return image;
}
pub fn update_biome_map(map: &Map, biome_map: &BiomeMap, image: &mut ImageBuffer<image::Rgba<u8>, Vec<u8>>) {
let map_biome_count = map.biome_count as f32;
image.par_enumerate_pixels_mut().for_each(|(x, y, pixel)| {
let coord = HexCoord::from_grid_pos(x as usize, y as usize);
let biome_blend = biome_map.get_biome(x as i32, y as i32);
let right = coord.get_neighbor(1);
let biome_id = map.get_biome_id(&coord) as f32;
let hue = (biome_id / map_biome_count) * 360.0;
let mut color = Hsla::hsl(hue, 0.8, 0.9);
if map.is_in_bounds(&right) {
let h1 = map.sample_height(&coord);
let h2 = map.sample_height(&right);
color = get_height_color_blend(color, h1, h2, 0.5);
}
*pixel = to_pixel(&color.into());
});
}

View File

@@ -16,7 +16,10 @@ use world_generation::{
biome_painter::*,
heightmap::generate_heightmap,
hex_utils::{offset_to_index, SHORT_DIAGONAL},
map::map_utils::{render_biome_map, render_map},
map::{
biome_map::{self, BiomeMap},
map_utils::{render_biome_noise_map, render_map},
},
prelude::*,
tile_manager::*,
tile_mapper::*,
@@ -211,13 +214,14 @@ fn create_heightmap(
size: UVec2::splat(16),
// size: UVec2::splat(1),
};
let heightmap = generate_heightmap(&config, 42069, &biome_painter);
let (heightmap, biome_map) = generate_heightmap(&config, 42069, &biome_painter);
let (mut cam_t, cam_entity) = cam.single_mut();
cam_t.translation = heightmap.get_center();
commands.entity(cam_entity).insert(CameraBounds::from_size(config.size));
commands.insert_resource(heightmap);
commands.insert_resource(biome_map);
commands.insert_resource(config);
next_state.set(GeneratorState::SpawnMap);
}
@@ -297,6 +301,7 @@ fn spawn_map(
fn despawn_map(
mut commands: Commands,
mut heightmap: ResMut<Map>,
mut biome_map: ResMut<BiomeMap>,
cfg: Res<GenerationConfig>,
chunks: Query<Entity, With<PhosChunk>>,
mut next_state: ResMut<NextState<GeneratorState>>,
@@ -306,6 +311,6 @@ fn despawn_map(
commands.entity(chunk).despawn();
}
*heightmap = generate_heightmap(&cfg, 4, &biome_painter);
(*heightmap, *biome_map) = generate_heightmap(&cfg, 4, &biome_painter);
next_state.set(GeneratorState::SpawnMap);
}