From e6e969f053333612bf7a3653c02f253bb199f158 Mon Sep 17 00:00:00 2001 From: Amatsugu Date: Thu, 4 Jul 2024 13:11:54 -0400 Subject: [PATCH] biome sampling --- engine/world_generation/src/biome_asset.rs | 38 +++++++++++++++++++ engine/world_generation/src/biome_painter.rs | 32 ++++++++++++---- .../src/generators/packed_mesh_generator.rs | 11 ++++-- engine/world_generation/src/lib.rs | 1 + engine/world_generation/src/map/config.rs | 2 +- engine/world_generation/src/tile_mapper.rs | 1 - game/main/src/map_rendering/map_init.rs | 4 +- game/main/src/utlis/chunk_utils.rs | 12 ++++-- 8 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 engine/world_generation/src/biome_asset.rs diff --git a/engine/world_generation/src/biome_asset.rs b/engine/world_generation/src/biome_asset.rs new file mode 100644 index 0000000..dbd94d9 --- /dev/null +++ b/engine/world_generation/src/biome_asset.rs @@ -0,0 +1,38 @@ +use asset_loader::create_asset_loader; +use serde::{Deserialize, Serialize}; + +use crate::{prelude::GeneratorLayer, tile_mapper::TileMapperAsset}; + +#[derive(Serialize, Deserialize, Asset, TypePath, Debug, Clone)] +pub struct BiomeAsset { + pub moisture: f32, + pub temperature: f32, + pub continentality: f32, + pub name: String, + #[serde(skip)] + pub tile_mapper: Handle, + pub tile_mapper_path: String, + pub generator_layers: Vec, +} + +impl BiomeAsset { + pub fn distance(&self, moisture: f32, temperature: f32, continentality: f32) -> f32 { + let a = Vec3::new( + self.moisture - moisture, + self.temperature - temperature, + self.continentality - continentality, + ); + return a.length(); + } +} + +create_asset_loader!( + BiomeAssetPlugin, + BiomeAssetLoader, + BiomeAsset, + BiomeAssetLoadState, + &["bimoe.json"], + tile_mapper_path -> tile_mapper + ; + ? +); diff --git a/engine/world_generation/src/biome_painter.rs b/engine/world_generation/src/biome_painter.rs index 1dcf3db..eab74e8 100644 --- a/engine/world_generation/src/biome_painter.rs +++ b/engine/world_generation/src/biome_painter.rs @@ -2,23 +2,41 @@ use asset_loader::create_asset_loader; use bevy::{ asset::{Asset, Handle}, reflect::TypePath, + render::render_resource::encase::rts_array::Length, }; use serde::{Deserialize, Serialize}; -use crate::tile_mapper::TileMapperAsset; +use crate::biome_asset::BiomeAsset; #[derive(Serialize, Deserialize, Debug, TypePath, Asset, Clone)] pub struct BiomePainterAsset { #[serde(skip)] - pub biomes: Vec>, - pub biomes_path: [String; 16], + pub biomes: Vec>, + pub biomes_path: Vec, } impl BiomePainterAsset { - pub fn sample_biome(&self, moisture: f32, temperature: f32) -> Handle { - let x = (moisture.clamp(0., 1.) * 3.).ceil() as usize; - let y = (temperature.clamp(0., 1.) * 3.).ceil() as usize; - return self.biomes[x + y * 4].clone(); + pub fn sample_biome( + &self, + assets: &Assets, + moisture: f32, + temperature: f32, + continentality: f32, + ) -> Handle { + assert!(self.biomes.length() != 0, "There are no biomes"); + let mut biome = self.biomes.first().unwrap().clone(); + let mut dist = f32::INFINITY; + + for b in &self.biomes { + let asset = assets.get(b).unwrap(); + let d = asset.distance(moisture, temperature, continentality); + if d < dist { + biome = b.clone(); + dist = d; + } + } + + return biome; } } diff --git a/engine/world_generation/src/generators/packed_mesh_generator.rs b/engine/world_generation/src/generators/packed_mesh_generator.rs index 823f484..916bd17 100644 --- a/engine/world_generation/src/generators/packed_mesh_generator.rs +++ b/engine/world_generation/src/generators/packed_mesh_generator.rs @@ -1,8 +1,8 @@ -use crate::biome_painter::BiomePainterAsset; use crate::hex_utils::HexCoord; use crate::prelude::*; use crate::tile_manager::TileAsset; use crate::tile_mapper::TileMapperAsset; +use crate::{biome_asset::BiomeAsset, biome_painter::BiomePainterAsset}; use bevy::{ prelude::*, render::{ @@ -16,6 +16,7 @@ pub fn generate_packed_chunk_mesh( map: &Map, painter: &BiomePainterAsset, tiles: &Res>, + biomes: &Res>, mappers: &Res>, ) -> Mesh { let vertex_count: usize = Chunk::SIZE * Chunk::SIZE * 6; @@ -31,8 +32,12 @@ pub fn generate_packed_chunk_mesh( 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); - let biome = mappers.get(painter.sample_biome(moisture, temperature)); - let tile_handle = biome.unwrap().sample_tile(height); + let biome = biomes + .get(painter.sample_biome(biomes, moisture, temperature, 1.)) + .unwrap(); + + let mapper = mappers.get(biome.tile_mapper.clone()); + let tile_handle = mapper.unwrap().sample_tile(height); let tile = tiles.get(tile_handle).unwrap(); create_packed_tile( diff --git a/engine/world_generation/src/lib.rs b/engine/world_generation/src/lib.rs index e6de7b8..3326bb4 100644 --- a/engine/world_generation/src/lib.rs +++ b/engine/world_generation/src/lib.rs @@ -8,3 +8,4 @@ pub mod prelude; pub mod states; pub mod tile_manager; pub mod tile_mapper; +pub mod biome_asset; diff --git a/engine/world_generation/src/map/config.rs b/engine/world_generation/src/map/config.rs index 062dd15..201135d 100644 --- a/engine/world_generation/src/map/config.rs +++ b/engine/world_generation/src/map/config.rs @@ -24,7 +24,7 @@ impl GenerationConfig { } } -#[derive(Reflect, InspectorOptions, Serialize, Deserialize, Debug)] +#[derive(Reflect, InspectorOptions, Serialize, Deserialize, Debug, Clone)] pub struct GeneratorLayer { pub strength: f64, pub min_value: f64, diff --git a/engine/world_generation/src/tile_mapper.rs b/engine/world_generation/src/tile_mapper.rs index 9c2d4b3..dd514e6 100644 --- a/engine/world_generation/src/tile_mapper.rs +++ b/engine/world_generation/src/tile_mapper.rs @@ -17,7 +17,6 @@ pub struct TileMapperAsset { pub tiles: Vec>, pub tiles_path: Vec, pub thresholds: Vec, - pub generator_layers: Vec } impl TileMapperAsset { diff --git a/game/main/src/map_rendering/map_init.rs b/game/main/src/map_rendering/map_init.rs index c3822fc..359bc38 100644 --- a/game/main/src/map_rendering/map_init.rs +++ b/game/main/src/map_rendering/map_init.rs @@ -9,6 +9,7 @@ use bevy_inspector_egui::quick::ResourceInspectorPlugin; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use shared::states::{GameplayState, MenuState}; use world_generation::{ + biome_asset::BiomeAsset, biome_painter::*, heightmap::generate_heightmap, hex_utils::{offset_to_index, SHORT_DIAGONAL}, @@ -272,6 +273,7 @@ fn spawn_map( tile_assets: Res>, tile_mappers: Res>, biome_painters: Res>, + biome_assets: Res>, painter: Res, mut generator_state: ResMut>, cur_game_state: Res>, @@ -280,7 +282,7 @@ fn spawn_map( ) { let b_painter = biome_painters.get(painter.handle.clone()); let cur_painter = b_painter.unwrap(); - paint_map(&mut heightmap, cur_painter, &tile_assets, &tile_mappers); + paint_map(&mut heightmap, cur_painter, &tile_assets, &biome_assets, &tile_mappers); let chunk_meshes: Vec<_> = heightmap .chunks diff --git a/game/main/src/utlis/chunk_utils.rs b/game/main/src/utlis/chunk_utils.rs index 4e767f3..0aedf8d 100644 --- a/game/main/src/utlis/chunk_utils.rs +++ b/game/main/src/utlis/chunk_utils.rs @@ -9,6 +9,7 @@ use bevy::{ use bevy_rapier3d::geometry::{Collider, TriMeshFlags}; use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator}; use world_generation::{ + biome_asset::BiomeAsset, biome_painter::BiomePainterAsset, generators::{chunk_colliders::generate_chunk_collider, mesh_generator::generate_chunk_mesh}, hex_utils::offset_to_world, @@ -21,10 +22,11 @@ pub fn paint_map( map: &mut Map, painter: &BiomePainterAsset, tiles: &Res>, + biomes: &Res>, mappers: &Res>, ) { map.chunks.par_iter_mut().for_each(|chunk: &mut Chunk| { - paint_chunk(chunk, painter, tiles, mappers); + paint_chunk(chunk, painter, tiles, biomes, mappers); }); } @@ -32,6 +34,7 @@ pub fn paint_chunk( chunk: &mut Chunk, painter: &BiomePainterAsset, tiles: &Res>, + biomes: &Res>, mappers: &Res>, ) { for z in 0..Chunk::SIZE { @@ -40,8 +43,11 @@ pub fn paint_chunk( let height = chunk.heights[idx]; let moisture = chunk.moisture[idx]; let temperature = chunk.temperature[idx]; - let biome = mappers.get(painter.sample_biome(moisture, temperature)); - let tile_handle = biome.unwrap().sample_tile(height); + let biome = biomes + .get(painter.sample_biome(&biomes, moisture, temperature, 0.)) + .unwrap(); + let mapper = mappers.get(biome.tile_mapper.clone()); + let tile_handle = mapper.unwrap().sample_tile(height); let tile = tiles.get(tile_handle).unwrap(); chunk.textures[idx] = [tile.texture_id, tile.side_texture_id]; }