biome sampling

This commit is contained in:
2024-07-04 13:11:54 -04:00
parent 9a960bbec9
commit e6e969f053
8 changed files with 85 additions and 16 deletions

View File

@@ -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<TileMapperAsset>,
pub tile_mapper_path: String,
pub generator_layers: Vec<GeneratorLayer>,
}
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
;
?
);

View File

@@ -2,23 +2,41 @@ use asset_loader::create_asset_loader;
use bevy::{ use bevy::{
asset::{Asset, Handle}, asset::{Asset, Handle},
reflect::TypePath, reflect::TypePath,
render::render_resource::encase::rts_array::Length,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::tile_mapper::TileMapperAsset; use crate::biome_asset::BiomeAsset;
#[derive(Serialize, Deserialize, Debug, TypePath, Asset, Clone)] #[derive(Serialize, Deserialize, Debug, TypePath, Asset, Clone)]
pub struct BiomePainterAsset { pub struct BiomePainterAsset {
#[serde(skip)] #[serde(skip)]
pub biomes: Vec<Handle<TileMapperAsset>>, pub biomes: Vec<Handle<BiomeAsset>>,
pub biomes_path: [String; 16], pub biomes_path: Vec<String>,
} }
impl BiomePainterAsset { impl BiomePainterAsset {
pub fn sample_biome(&self, moisture: f32, temperature: f32) -> Handle<TileMapperAsset> { pub fn sample_biome(
let x = (moisture.clamp(0., 1.) * 3.).ceil() as usize; &self,
let y = (temperature.clamp(0., 1.) * 3.).ceil() as usize; assets: &Assets<BiomeAsset>,
return self.biomes[x + y * 4].clone(); moisture: f32,
temperature: f32,
continentality: f32,
) -> Handle<BiomeAsset> {
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;
} }
} }

View File

@@ -1,8 +1,8 @@
use crate::biome_painter::BiomePainterAsset;
use crate::hex_utils::HexCoord; use crate::hex_utils::HexCoord;
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;
use crate::{biome_asset::BiomeAsset, biome_painter::BiomePainterAsset};
use bevy::{ use bevy::{
prelude::*, prelude::*,
render::{ render::{
@@ -16,6 +16,7 @@ pub fn generate_packed_chunk_mesh(
map: &Map, map: &Map,
painter: &BiomePainterAsset, painter: &BiomePainterAsset,
tiles: &Res<Assets<TileAsset>>, tiles: &Res<Assets<TileAsset>>,
biomes: &Res<Assets<BiomeAsset>>,
mappers: &Res<Assets<TileMapperAsset>>, mappers: &Res<Assets<TileMapperAsset>>,
) -> Mesh { ) -> Mesh {
let vertex_count: usize = Chunk::SIZE * Chunk::SIZE * 6; let vertex_count: usize = Chunk::SIZE * Chunk::SIZE * 6;
@@ -31,8 +32,12 @@ pub fn generate_packed_chunk_mesh(
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);
let biome = mappers.get(painter.sample_biome(moisture, temperature)); let biome = biomes
let tile_handle = biome.unwrap().sample_tile(height); .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(); let tile = tiles.get(tile_handle).unwrap();
create_packed_tile( create_packed_tile(

View File

@@ -8,3 +8,4 @@ pub mod prelude;
pub mod states; pub mod states;
pub mod tile_manager; pub mod tile_manager;
pub mod tile_mapper; pub mod tile_mapper;
pub mod biome_asset;

View File

@@ -24,7 +24,7 @@ impl GenerationConfig {
} }
} }
#[derive(Reflect, InspectorOptions, Serialize, Deserialize, Debug)] #[derive(Reflect, InspectorOptions, Serialize, Deserialize, Debug, Clone)]
pub struct GeneratorLayer { pub struct GeneratorLayer {
pub strength: f64, pub strength: f64,
pub min_value: f64, pub min_value: f64,

View File

@@ -17,7 +17,6 @@ pub struct TileMapperAsset {
pub tiles: Vec<Handle<TileAsset>>, pub tiles: Vec<Handle<TileAsset>>,
pub tiles_path: Vec<String>, pub tiles_path: Vec<String>,
pub thresholds: Vec<f32>, pub thresholds: Vec<f32>,
pub generator_layers: Vec<GeneratorLayer>
} }
impl TileMapperAsset { impl TileMapperAsset {

View File

@@ -9,6 +9,7 @@ use bevy_inspector_egui::quick::ResourceInspectorPlugin;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use shared::states::{GameplayState, MenuState}; use shared::states::{GameplayState, MenuState};
use world_generation::{ use world_generation::{
biome_asset::BiomeAsset,
biome_painter::*, biome_painter::*,
heightmap::generate_heightmap, heightmap::generate_heightmap,
hex_utils::{offset_to_index, SHORT_DIAGONAL}, hex_utils::{offset_to_index, SHORT_DIAGONAL},
@@ -272,6 +273,7 @@ fn spawn_map(
tile_assets: Res<Assets<TileAsset>>, tile_assets: Res<Assets<TileAsset>>,
tile_mappers: Res<Assets<TileMapperAsset>>, tile_mappers: Res<Assets<TileMapperAsset>>,
biome_painters: Res<Assets<BiomePainterAsset>>, biome_painters: Res<Assets<BiomePainterAsset>>,
biome_assets: Res<Assets<BiomeAsset>>,
painter: Res<CurrentBiomePainter>, painter: Res<CurrentBiomePainter>,
mut generator_state: ResMut<NextState<GeneratorState>>, mut generator_state: ResMut<NextState<GeneratorState>>,
cur_game_state: Res<State<MenuState>>, cur_game_state: Res<State<MenuState>>,
@@ -280,7 +282,7 @@ fn spawn_map(
) { ) {
let b_painter = biome_painters.get(painter.handle.clone()); let b_painter = biome_painters.get(painter.handle.clone());
let cur_painter = b_painter.unwrap(); 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 let chunk_meshes: Vec<_> = heightmap
.chunks .chunks

View File

@@ -9,6 +9,7 @@ use bevy::{
use bevy_rapier3d::geometry::{Collider, TriMeshFlags}; use bevy_rapier3d::geometry::{Collider, TriMeshFlags};
use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator}; use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator};
use world_generation::{ use world_generation::{
biome_asset::BiomeAsset,
biome_painter::BiomePainterAsset, biome_painter::BiomePainterAsset,
generators::{chunk_colliders::generate_chunk_collider, mesh_generator::generate_chunk_mesh}, generators::{chunk_colliders::generate_chunk_collider, mesh_generator::generate_chunk_mesh},
hex_utils::offset_to_world, hex_utils::offset_to_world,
@@ -21,10 +22,11 @@ pub fn paint_map(
map: &mut Map, map: &mut Map,
painter: &BiomePainterAsset, painter: &BiomePainterAsset,
tiles: &Res<Assets<TileAsset>>, tiles: &Res<Assets<TileAsset>>,
biomes: &Res<Assets<BiomeAsset>>,
mappers: &Res<Assets<TileMapperAsset>>, mappers: &Res<Assets<TileMapperAsset>>,
) { ) {
map.chunks.par_iter_mut().for_each(|chunk: &mut Chunk| { 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, chunk: &mut Chunk,
painter: &BiomePainterAsset, painter: &BiomePainterAsset,
tiles: &Res<Assets<TileAsset>>, tiles: &Res<Assets<TileAsset>>,
biomes: &Res<Assets<BiomeAsset>>,
mappers: &Res<Assets<TileMapperAsset>>, mappers: &Res<Assets<TileMapperAsset>>,
) { ) {
for z in 0..Chunk::SIZE { for z in 0..Chunk::SIZE {
@@ -40,8 +43,11 @@ pub fn paint_chunk(
let height = chunk.heights[idx]; let height = chunk.heights[idx];
let moisture = chunk.moisture[idx]; let moisture = chunk.moisture[idx];
let temperature = chunk.temperature[idx]; let temperature = chunk.temperature[idx];
let biome = mappers.get(painter.sample_biome(moisture, temperature)); let biome = biomes
let tile_handle = biome.unwrap().sample_tile(height); .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(); let tile = tiles.get(tile_handle).unwrap();
chunk.textures[idx] = [tile.texture_id, tile.side_texture_id]; chunk.textures[idx] = [tile.texture_id, tile.side_texture_id];
} }