generator tweaks
data fixes wip biome map visualization
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
use crate::hex_utils::HexCoord;
|
use crate::hex_utils::HexCoord;
|
||||||
|
use crate::map::biome_map::{self, BiomeChunk, BiomeMap};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::tile_manager::TileAsset;
|
use crate::tile_manager::TileAsset;
|
||||||
use crate::tile_mapper::TileMapperAsset;
|
use crate::tile_mapper::TileMapperAsset;
|
||||||
@@ -14,6 +15,7 @@ use bevy::{
|
|||||||
pub fn generate_packed_chunk_mesh(
|
pub fn generate_packed_chunk_mesh(
|
||||||
chunk: &Chunk,
|
chunk: &Chunk,
|
||||||
map: &Map,
|
map: &Map,
|
||||||
|
biome_chunk: &BiomeChunk,
|
||||||
painter: &BiomePainterAsset,
|
painter: &BiomePainterAsset,
|
||||||
tiles: &Res<Assets<TileAsset>>,
|
tiles: &Res<Assets<TileAsset>>,
|
||||||
biomes: &Res<Assets<BiomeAsset>>,
|
biomes: &Res<Assets<BiomeAsset>>,
|
||||||
@@ -27,7 +29,7 @@ pub fn generate_packed_chunk_mesh(
|
|||||||
for z in 0..Chunk::SIZE {
|
for z in 0..Chunk::SIZE {
|
||||||
for x in 0..Chunk::SIZE {
|
for x in 0..Chunk::SIZE {
|
||||||
let height = chunk.heights[x + z * 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 =
|
let coord =
|
||||||
HexCoord::from_offset(IVec2::new(x as i32, z as i32) + (chunk.chunk_offset * Chunk::SIZE as i32));
|
HexCoord::from_offset(IVec2::new(x as i32, z as i32) + (chunk.chunk_offset * Chunk::SIZE as i32));
|
||||||
let n = map.get_neighbors(&coord);
|
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::map::biome_map::{BiomeChunk, BiomeData, BiomeMap};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub fn generate_heightmap(cfg: &GenerationConfig, seed: u32, painter: &BiomePainter) -> Map {
|
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);
|
||||||
|
let biomes_borrow = &biomes;
|
||||||
// let mut chunks: Vec<Chunk> = Vec::with_capacity(cfg.size.length_squared() as usize);
|
// let mut chunks: Vec<Chunk> = Vec::with_capacity(cfg.size.length_squared() as usize);
|
||||||
let chunks: Vec<Chunk> = (0..cfg.size.y)
|
let chunks: Vec<Chunk> = (0..cfg.size.y)
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.flat_map(|z| {
|
.flat_map(|z| {
|
||||||
(0..cfg.size.x).into_par_iter().map(move |x| {
|
(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);
|
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 (
|
||||||
chunks,
|
Map {
|
||||||
height: cfg.size.y as usize,
|
chunks,
|
||||||
width: cfg.size.x as usize,
|
height: cfg.size.y as usize,
|
||||||
sea_level: cfg.sea_level as f32,
|
width: cfg.size.x as usize,
|
||||||
min_level: min,
|
sea_level: cfg.sea_level as f32,
|
||||||
max_level: max,
|
min_level: min,
|
||||||
};
|
max_level: max,
|
||||||
|
biome_count: painter.biomes.len(),
|
||||||
|
},
|
||||||
|
biomes,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_biomes(cfg: &GenerationConfig, seed: u32, biome_painter: &BiomePainter) -> BiomeMap {
|
pub fn generate_biomes(cfg: &GenerationConfig, seed: u32, biome_painter: &BiomePainter) -> BiomeMap {
|
||||||
@@ -186,7 +191,6 @@ pub fn generate_chunk(
|
|||||||
}
|
}
|
||||||
return Chunk {
|
return Chunk {
|
||||||
heights: result,
|
heights: result,
|
||||||
biome_data: data,
|
|
||||||
biome_id: biome_ids,
|
biome_id: biome_ids,
|
||||||
chunk_offset: IVec2::new(chunk_x as i32, chunk_z as i32),
|
chunk_offset: IVec2::new(chunk_x as i32, chunk_z as i32),
|
||||||
max_level: max,
|
max_level: max,
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
use bevy::math::{UVec2, Vec3};
|
use bevy::{
|
||||||
|
math::{UVec2, Vec3},
|
||||||
|
prelude::Resource,
|
||||||
|
};
|
||||||
use noise::NoiseFn;
|
use noise::NoiseFn;
|
||||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||||
|
|
||||||
use super::chunk::Chunk;
|
use super::chunk::Chunk;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Resource)]
|
||||||
pub struct BiomeMap {
|
pub struct BiomeMap {
|
||||||
pub height: usize,
|
pub height: usize,
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use super::biome_map::BiomeData;
|
|||||||
pub struct Chunk {
|
pub struct Chunk {
|
||||||
pub heights: [f32; Chunk::AREA],
|
pub heights: [f32; Chunk::AREA],
|
||||||
pub textures: [[u32; 2]; 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 biome_id: [usize; Chunk::AREA],
|
||||||
pub chunk_offset: IVec2,
|
pub chunk_offset: IVec2,
|
||||||
pub min_level: f32,
|
pub min_level: f32,
|
||||||
@@ -19,7 +19,7 @@ impl Default for Chunk {
|
|||||||
Self {
|
Self {
|
||||||
heights: [0.; Chunk::AREA],
|
heights: [0.; Chunk::AREA],
|
||||||
textures: [[0; 2]; Chunk::AREA],
|
textures: [[0; 2]; Chunk::AREA],
|
||||||
biome_data: [BiomeData::default(); Chunk::AREA],
|
// biome_data: [BiomeData::default(); Chunk::AREA],
|
||||||
biome_id: [0; Chunk::AREA],
|
biome_id: [0; Chunk::AREA],
|
||||||
chunk_offset: Default::default(),
|
chunk_offset: Default::default(),
|
||||||
min_level: 0.0,
|
min_level: 0.0,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ pub struct Map {
|
|||||||
pub sea_level: f32,
|
pub sea_level: f32,
|
||||||
pub min_level: f32,
|
pub min_level: f32,
|
||||||
pub max_level: f32,
|
pub max_level: f32,
|
||||||
|
pub biome_count: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Map {
|
impl Map {
|
||||||
@@ -72,7 +73,18 @@ impl Map {
|
|||||||
return pos.is_in_bounds(self.height * Chunk::SIZE, self.width * Chunk::SIZE);
|
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!(
|
assert!(
|
||||||
self.is_in_bounds(pos),
|
self.is_in_bounds(pos),
|
||||||
"The provided coordinate is not within the map bounds"
|
"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)];
|
let chunk = &self.chunks[pos.to_chunk_index(self.width)];
|
||||||
return chunk.biome_data[pos.to_chunk_local_index()].continentality;
|
return chunk.biome_data[pos.to_chunk_local_index()].continentality;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
pub fn get_center(&self) -> Vec3 {
|
pub fn get_center(&self) -> Vec3 {
|
||||||
let w = self.get_world_width();
|
let w = self.get_world_width();
|
||||||
|
|||||||
@@ -2,9 +2,13 @@ use bevy::{math::VectorSpace, prelude::*};
|
|||||||
use image::ImageBuffer;
|
use image::ImageBuffer;
|
||||||
use rayon::prelude::*;
|
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(
|
pub fn render_image(
|
||||||
size: UVec2,
|
size: UVec2,
|
||||||
@@ -60,51 +64,58 @@ 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 coord = HexCoord::from_grid_pos(x as usize, y as usize);
|
||||||
let right = coord.get_neighbor(1);
|
let right = coord.get_neighbor(1);
|
||||||
let height = map.sample_height(&coord);
|
let height = map.sample_height(&coord);
|
||||||
|
|
||||||
let mut color = Hsla::hsl(138.0, 1.0, 0.4);
|
let mut color = Hsla::hsl(138.0, 1.0, 0.4);
|
||||||
if height < map.sea_level {
|
if height < map.sea_level {
|
||||||
color.hue = 217.0;
|
color.hue = 217.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if map.is_in_bounds(&right) {
|
if map.is_in_bounds(&right) {
|
||||||
let h2 = map.sample_height(&right);
|
let h2 = map.sample_height(&right);
|
||||||
let mut d = h2 - height;
|
color = get_height_color_blend(color, height, h2, smooth);
|
||||||
|
|
||||||
if smooth == 0.0 || d.abs() > smooth {
|
|
||||||
if d > 0.0 {
|
|
||||||
color.lightness += 0.1;
|
|
||||||
} else if d < 0.0 {
|
|
||||||
color.lightness -= 0.1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if d.abs() <= smooth {
|
|
||||||
d /= smooth;
|
|
||||||
if d > 0.0 {
|
|
||||||
let c2: LinearRgba = color.with_lightness(color.lightness + 0.1).into();
|
|
||||||
color = LinearRgba::lerp(&color.into(), c2, d).into();
|
|
||||||
} else {
|
|
||||||
let c2: LinearRgba = color.with_lightness(color.lightness - 0.1).into();
|
|
||||||
color = LinearRgba::lerp(&color.into(), c2, d.abs()).into();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*pixel = to_pixel(&color.into());
|
*pixel = to_pixel(&color.into());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_biome_map(map: &Map) -> ImageBuffer<image::Rgba<u8>, Vec<u8>> {
|
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;
|
||||||
|
} else if d < 0.0 {
|
||||||
|
color.lightness -= 0.1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if d.abs() <= smooth {
|
||||||
|
d /= smooth;
|
||||||
|
if d > 0.0 {
|
||||||
|
let c2: LinearRgba = color.with_lightness(color.lightness + 0.1).into();
|
||||||
|
color = LinearRgba::lerp(&color.into(), c2, d).into();
|
||||||
|
} else {
|
||||||
|
let c2: LinearRgba = color.with_lightness(color.lightness - 0.1).into();
|
||||||
|
color = LinearRgba::lerp(&color.into(), c2, d.abs()).into();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_biome_noise_map(map: &BiomeMap) -> ImageBuffer<image::Rgba<u8>, Vec<u8>> {
|
||||||
let mut image = ImageBuffer::new(
|
let mut image = ImageBuffer::new(
|
||||||
map.width as u32 * Chunk::SIZE as u32,
|
map.width as u32 * Chunk::SIZE as u32,
|
||||||
map.height 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;
|
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)| {
|
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_data(x as usize, y as usize);
|
||||||
let tile = map.get_biome(&coord);
|
|
||||||
|
|
||||||
let color = LinearRgba::rgb(
|
let color = LinearRgba::rgb(
|
||||||
tile.temperature / 100.0,
|
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);
|
*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::*,
|
biome_painter::*,
|
||||||
heightmap::generate_heightmap,
|
heightmap::generate_heightmap,
|
||||||
hex_utils::{offset_to_index, SHORT_DIAGONAL},
|
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::*,
|
prelude::*,
|
||||||
tile_manager::*,
|
tile_manager::*,
|
||||||
tile_mapper::*,
|
tile_mapper::*,
|
||||||
@@ -211,13 +214,14 @@ fn create_heightmap(
|
|||||||
size: UVec2::splat(16),
|
size: UVec2::splat(16),
|
||||||
// size: UVec2::splat(1),
|
// 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();
|
let (mut cam_t, cam_entity) = cam.single_mut();
|
||||||
cam_t.translation = heightmap.get_center();
|
cam_t.translation = heightmap.get_center();
|
||||||
|
|
||||||
commands.entity(cam_entity).insert(CameraBounds::from_size(config.size));
|
commands.entity(cam_entity).insert(CameraBounds::from_size(config.size));
|
||||||
commands.insert_resource(heightmap);
|
commands.insert_resource(heightmap);
|
||||||
|
commands.insert_resource(biome_map);
|
||||||
commands.insert_resource(config);
|
commands.insert_resource(config);
|
||||||
next_state.set(GeneratorState::SpawnMap);
|
next_state.set(GeneratorState::SpawnMap);
|
||||||
}
|
}
|
||||||
@@ -297,6 +301,7 @@ fn spawn_map(
|
|||||||
fn despawn_map(
|
fn despawn_map(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut heightmap: ResMut<Map>,
|
mut heightmap: ResMut<Map>,
|
||||||
|
mut biome_map: ResMut<BiomeMap>,
|
||||||
cfg: Res<GenerationConfig>,
|
cfg: Res<GenerationConfig>,
|
||||||
chunks: Query<Entity, With<PhosChunk>>,
|
chunks: Query<Entity, With<PhosChunk>>,
|
||||||
mut next_state: ResMut<NextState<GeneratorState>>,
|
mut next_state: ResMut<NextState<GeneratorState>>,
|
||||||
@@ -306,6 +311,6 @@ fn despawn_map(
|
|||||||
commands.entity(chunk).despawn();
|
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);
|
next_state.set(GeneratorState::SpawnMap);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user