biome sampling
This commit is contained in:
38
engine/world_generation/src/biome_asset.rs
Normal file
38
engine/world_generation/src/biome_asset.rs
Normal 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
|
||||
;
|
||||
?
|
||||
);
|
||||
@@ -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<Handle<TileMapperAsset>>,
|
||||
pub biomes_path: [String; 16],
|
||||
pub biomes: Vec<Handle<BiomeAsset>>,
|
||||
pub biomes_path: Vec<String>,
|
||||
}
|
||||
|
||||
impl BiomePainterAsset {
|
||||
pub fn sample_biome(&self, moisture: f32, temperature: f32) -> Handle<TileMapperAsset> {
|
||||
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<BiomeAsset>,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<Assets<TileAsset>>,
|
||||
biomes: &Res<Assets<BiomeAsset>>,
|
||||
mappers: &Res<Assets<TileMapperAsset>>,
|
||||
) -> 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(
|
||||
|
||||
@@ -8,3 +8,4 @@ pub mod prelude;
|
||||
pub mod states;
|
||||
pub mod tile_manager;
|
||||
pub mod tile_mapper;
|
||||
pub mod biome_asset;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -17,7 +17,6 @@ pub struct TileMapperAsset {
|
||||
pub tiles: Vec<Handle<TileAsset>>,
|
||||
pub tiles_path: Vec<String>,
|
||||
pub thresholds: Vec<f32>,
|
||||
pub generator_layers: Vec<GeneratorLayer>
|
||||
}
|
||||
|
||||
impl TileMapperAsset {
|
||||
|
||||
@@ -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<Assets<TileAsset>>,
|
||||
tile_mappers: Res<Assets<TileMapperAsset>>,
|
||||
biome_painters: Res<Assets<BiomePainterAsset>>,
|
||||
biome_assets: Res<Assets<BiomeAsset>>,
|
||||
painter: Res<CurrentBiomePainter>,
|
||||
mut generator_state: ResMut<NextState<GeneratorState>>,
|
||||
cur_game_state: Res<State<MenuState>>,
|
||||
@@ -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
|
||||
|
||||
@@ -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<Assets<TileAsset>>,
|
||||
biomes: &Res<Assets<BiomeAsset>>,
|
||||
mappers: &Res<Assets<TileMapperAsset>>,
|
||||
) {
|
||||
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<Assets<TileAsset>>,
|
||||
biomes: &Res<Assets<BiomeAsset>>,
|
||||
mappers: &Res<Assets<TileMapperAsset>>,
|
||||
) {
|
||||
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];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user