generator tweaks
data fixes wip biome map visualization
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*pixel = to_pixel(&color.into());
|
||||
});
|
||||
return color;
|
||||
}
|
||||
|
||||
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());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user