Skip to content

Commit

Permalink
Add InBiome condition for features.
Browse files Browse the repository at this point in the history
  • Loading branch information
TheGrimsey committed Dec 8, 2024
1 parent d03ec96 commit 6db9655
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 10 deletions.
9 changes: 6 additions & 3 deletions examples/many_tiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,19 +199,19 @@ fn main() {
BiomeSettings {
filters: vec![NoiseFilter {
condition: NoiseFilterCondition::Above(0.5),
falloff: 0.25,
falloff: 0.1,
falloff_easing_function: EasingFunction::SmoothStep,
compare_to: FilterComparingTo::Data { index: 0 }
},
NoiseFilter {
condition: NoiseFilterCondition::Above(0.5),
falloff: 0.25,
falloff: 0.1,
falloff_easing_function: EasingFunction::SmoothStep,
compare_to: FilterComparingTo::Data { index: 1 }
},
NoiseFilter {
condition: NoiseFilterCondition::Above(0.5),
falloff: 0.25,
falloff: 0.1,
falloff_easing_function: EasingFunction::SmoothStep,
compare_to: FilterComparingTo::Data { index: 2 }
}],
Expand Down Expand Up @@ -391,6 +391,9 @@ fn insert_rules(
placement_conditions: vec![FeaturePlacementCondition::SlopeBetween {
min_angle_radians: 0.0,
max_angle_radians: 45.0_f32.to_radians(),
},
FeaturePlacementCondition::InBiome {
biome: 0
}],
randomize_yaw_rotation: true,
align_to_terrain_normal: true,
Expand Down
56 changes: 49 additions & 7 deletions src/feature_placement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use core::f32;
use std::f32::consts::TAU;
use bevy_app::{App, Plugin, PostUpdate};
use bevy_math::{IVec2, Quat, Vec2, Vec3, Vec3Swizzles};
use bevy_log::info_span;
use bevy_log::{info, info_span};
use bevy_ecs::prelude::{
on_event, Commands, Component, Entity, EventReader, IntoSystemConfigs,
Query, ReflectComponent, Res, Resource
Expand All @@ -13,9 +13,7 @@ use bevy_reflect::Reflect;
use turborand::{rng::Rng, SeededCore, TurboRand};

use crate::{
terrain::TileToTerrain,
utils::{get_flat_normal_at_position_in_tile, get_height_at_position_in_tile},
Heights, TerrainSets, TerrainSettings, TileHeightsRebuilt,
noise::{NoiseCache, NoiseIndexCache, TerrainNoiseSettings, TileBiomes}, terrain::TileToTerrain, utils::{get_flat_normal_at_position_in_tile, get_height_at_position_in_tile}, Heights, TerrainSets, TerrainSettings, TileHeightsRebuilt
};

pub struct FeaturePlacementPlugin;
Expand Down Expand Up @@ -45,11 +43,15 @@ pub enum FeaturePlacementCondition {
min_angle_radians: f32,
max_angle_radians: f32,
},
InBiome {
biome: u32
}
/*HeightDeltaInRadiusLessThan {
radius: f32,
max_increase: f32,
max_decrease: f32
}*/

}

pub enum FeatureSpawnStrategy {
Expand Down Expand Up @@ -94,11 +96,17 @@ pub struct Feature {
impl Feature {
pub fn check_conditions(
&self,
tile_translation: Vec2,
placement_position: Vec3,
// If not provided, generated in condition.
terrain_normal: Option<Vec3>,
heights: &Heights,
biome_values: &[f32],
terrain_settings: &TerrainSettings,
terrain_noise_layers: &TerrainNoiseSettings,
noise_cache: &NoiseCache,
noise_index_cache: &NoiseIndexCache,
rng: &Rng
) -> bool {
self.placement_conditions
.iter()
Expand All @@ -119,6 +127,24 @@ impl Feature {

*min_angle_radians <= angle && angle <= *max_angle_radians
}
FeaturePlacementCondition::InBiome { biome } => {
if biome_values.get(*biome as usize).is_some_and(|biome| *biome > f32::EPSILON) {
let pos = tile_translation + placement_position.xz();
// TODO: Cache this...
let mut data = Vec::with_capacity(terrain_noise_layers.data.len());
terrain_noise_layers.sample_data(noise_cache, noise_index_cache, pos, &mut data);

let mut biomes = Vec::with_capacity(terrain_noise_layers.biome.len());
terrain_noise_layers.sample_biomes(noise_cache, noise_index_cache, pos, &data, &mut biomes);

if biome_values[*biome as usize] < 1.0 {
info!("{}", biomes[*biome as usize]);
}
biomes.get(*biome as usize).is_some_and(|biomeness| rng.f32() <= *biomeness)
} else {
false
}
},
})
}
}
Expand All @@ -136,8 +162,13 @@ impl FeatureGroup {
pub fn generate_placements(
&self,
rng: &Rng,
tile_translation: Vec2,
heights: &Heights,
tile_biomes: &TileBiomes,
terrain_settings: &TerrainSettings,
terrain_noise_layers: &TerrainNoiseSettings,
noise_cache: &NoiseCache,
noise_index_cache: &NoiseIndexCache,
) -> Vec<FeaturePlacement> {
let tile_size = terrain_settings.tile_size();
let total_weight = self.features.iter().fold(0.0, |acc, feature| acc + feature.weight);
Expand Down Expand Up @@ -201,10 +232,16 @@ impl FeatureGroup {
}

if feature.check_conditions(
tile_translation,
position,
terrain_normal,
heights,
&tile_biomes.0,
terrain_settings,
terrain_noise_layers,
noise_cache,
noise_index_cache,
rng
) {
Some(FeaturePlacement {
index,
Expand Down Expand Up @@ -391,7 +428,10 @@ fn update_features_on_tile_built(
tile_to_terrain: Res<TileToTerrain>,
terrain_features: Res<TerrainFeatures>,
terrain_settings: Res<TerrainSettings>,
mut query: Query<(&Heights, &mut SpawnedFeatures)>,
terrain_noise_layers: Res<TerrainNoiseSettings>,
noise_cache: Res<NoiseCache>,
noise_index_cache: Res<NoiseIndexCache>,
mut query: Query<(&Heights, &mut SpawnedFeatures, &TileBiomes)>,
) {
for TileHeightsRebuilt(tile) in events.read() {
let _span = info_span!("Spawn features for tile").entered();
Expand All @@ -401,10 +441,12 @@ fn update_features_on_tile_built(
else {
continue;
};
let Ok((heights, mut spawned_features)) = query.get_mut(tile_entity) else {
let Ok((heights, mut spawned_features, tile_biomes)) = query.get_mut(tile_entity) else {
continue;
};

let tile_translation = (*tile << terrain_settings.tile_size_power.get() as u32).as_vec2();

for spawned_feature in spawned_features.spawned.drain(..) {
let feature_group = &terrain_features.feature_groups[spawned_feature.group as usize];
let feature = &feature_group.features[spawned_feature.feature as usize];
Expand All @@ -430,7 +472,7 @@ fn update_features_on_tile_built(
let seed = seed_hash(*tile, feature_group.feature_seed as u64);
let rng = Rng::with_seed(seed);

feature_group.generate_placements(&rng, heights, &terrain_settings)
feature_group.generate_placements(&rng, tile_translation, heights, tile_biomes, &terrain_settings, &terrain_noise_layers, &noise_cache, &noise_index_cache)
})
.collect::<Vec<_>>()
};
Expand Down
1 change: 1 addition & 0 deletions src/noise.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::cell::Cell;

#[cfg(feature = "count_samples")]
use bevy_log::info;
use ::noise::{NoiseFn, Simplex};
use bevy_asset::{Assets, Handle};
Expand Down

0 comments on commit 6db9655

Please sign in to comment.