Skip to content

Commit

Permalink
Add InNoise filter.
Browse files Browse the repository at this point in the history
  • Loading branch information
TheGrimsey committed Dec 12, 2024
1 parent 6db9655 commit ea0e9a7
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 53 deletions.
10 changes: 6 additions & 4 deletions examples/many_tiles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ use bevy::{
math::{Vec3, Vec3Swizzles},
pbr::{DirectionalLight, DirectionalLightBundle, PbrBundle, StandardMaterial},
prelude::{
default, BuildChildren, Commands, Cuboid, GlobalTransform, Mesh, PluginGroup, Res,
ResMut, Transform, TransformBundle, VisibilityBundle, With, World,
default, BuildChildren, Commands, Cone, Cuboid, GlobalTransform, Mesh, PluginGroup, Res, ResMut, Transform, TransformBundle, VisibilityBundle, With, World
},
DefaultPlugins,
};
Expand Down Expand Up @@ -335,7 +334,10 @@ fn insert_rules(
]);

let cube_mesh_handle = meshes.add(Cuboid::from_length(1.0));
let red_cube_mesh_handle = cube_mesh_handle.clone();
let red_cube_mesh_handle = meshes.add(Cone {
radius: 0.5,
height: 1.0,
});
let blue_material_handle = material.add(StandardMaterial::from_color(Srgba::BLUE));

let red_material_handle = material.add(StandardMaterial::from_color(Srgba::RED));
Expand Down Expand Up @@ -409,7 +411,7 @@ fn insert_rules(
max_angle_radians: 45.0_f32.to_radians(),
}],
randomize_yaw_rotation: true,
align_to_terrain_normal: false,
align_to_terrain_normal: true,
scale_randomization: FeatureScaleRandomization::Uniform { min: 1.0, max: 2.0 },
spawn_strategy: red_spawn_strategy,
despawn_strategy: FeatureDespawnStrategy::Default,
Expand Down
22 changes: 17 additions & 5 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, info_span};
use bevy_log::info_span;
use bevy_ecs::prelude::{
on_event, Commands, Component, Entity, EventReader, IntoSystemConfigs,
Query, ReflectComponent, Res, Resource
Expand All @@ -13,7 +13,7 @@ use bevy_reflect::Reflect;
use turborand::{rng::Rng, SeededCore, TurboRand};

use crate::{
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
noise::{NoiseCache, NoiseFilterCondition, 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,6 +45,11 @@ pub enum FeaturePlacementCondition {
},
InBiome {
biome: u32
},
InNoise {
noise: u32,
condition: NoiseFilterCondition,
falloff: f32
}
/*HeightDeltaInRadiusLessThan {
radius: f32,
Expand Down Expand Up @@ -137,14 +142,21 @@ impl Feature {
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
}
},
FeaturePlacementCondition::InNoise { noise, condition, falloff } => {
if let Some(noise_layer) = terrain_noise_layers.data.get(*noise as usize) {
let pos = tile_translation + placement_position.xz();
let sample = noise_layer.sample_scaled_raw(pos.x, pos.y, unsafe { noise_cache.get_by_index(noise_index_cache.data_index_cache[*noise as usize] as usize) });

rng.f32() <= condition.evaluate_condition(sample, *falloff)
} else {
false
}
},
})
}
}
Expand Down
97 changes: 53 additions & 44 deletions src/noise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,57 +661,15 @@ impl NoiseFilter {
&self,
noise_value: f32,
) -> f32 {
let strength = match &self.condition {
NoiseFilterCondition::Above(threshold) => {
1.0 - ((threshold - noise_value) / self.falloff.max(f32::EPSILON)).clamp(0.0, 1.0)
}
NoiseFilterCondition::Below(threshold) => {
1.0 - ((noise_value - threshold) / self.falloff.max(f32::EPSILON)).clamp(0.0, 1.0)
}
NoiseFilterCondition::Between { min, max } => {
let strength_below = 1.0
- ((min - noise_value) / self.falloff.max(f32::EPSILON))
.clamp(0.0, 1.0);
let strength_above = 1.0
- ((noise_value - max) / self.falloff.max(f32::EPSILON))
.clamp(0.0, 1.0);

strength_below.min(strength_above)
}
};
let strength = self.condition.evaluate_condition(noise_value, self.falloff);

self.falloff_easing_function.ease(strength)
}
fn get_filter_simd(
&self,
noise_value: Vec4,
) -> Vec4 {
let strength = match &self.condition {
NoiseFilterCondition::Above(threshold) => {
Vec4::ONE
- ((Vec4::splat(*threshold) - noise_value)
/ self.falloff.max(f32::EPSILON))
.clamp(Vec4::ZERO, Vec4::ONE)
}
NoiseFilterCondition::Below(threshold) => {
Vec4::ONE
- ((noise_value - Vec4::splat(*threshold))
/ self.falloff.max(f32::EPSILON))
.clamp(Vec4::ZERO, Vec4::ONE)
}
NoiseFilterCondition::Between { min, max } => {
let strength_below = 1.0
- ((Vec4::splat(*min) - noise_value)
/ self.falloff.max(f32::EPSILON))
.clamp(Vec4::ZERO, Vec4::ONE);
let strength_above = 1.0
- ((noise_value - Vec4::splat(*max))
/ self.falloff.max(f32::EPSILON))
.clamp(Vec4::ZERO, Vec4::ONE);

strength_below.min(strength_above)
}
};
let strength = self.condition.evaluate_condition_simd(noise_value, self.falloff);

self.falloff_easing_function.ease_simd(strength)
}
Expand Down Expand Up @@ -766,6 +724,57 @@ impl Default for NoiseFilterCondition {
Self::Above(0.5)
}
}
impl NoiseFilterCondition {
pub fn evaluate_condition(&self, value: f32, falloff: f32) -> f32 {
match &self {
NoiseFilterCondition::Above(threshold) => {
1.0 - ((threshold - value) / falloff.max(f32::EPSILON)).clamp(0.0, 1.0)
}
NoiseFilterCondition::Below(threshold) => {
1.0 - ((value - threshold) / falloff.max(f32::EPSILON)).clamp(0.0, 1.0)
}
NoiseFilterCondition::Between { min, max } => {
let strength_below = 1.0
- ((min - value) / falloff.max(f32::EPSILON))
.clamp(0.0, 1.0);
let strength_above = 1.0
- ((value - max) / falloff.max(f32::EPSILON))
.clamp(0.0, 1.0);

strength_below.min(strength_above)
}
}
}

pub fn evaluate_condition_simd(&self, value: Vec4, falloff: f32) -> Vec4 {
match &self {
NoiseFilterCondition::Above(threshold) => {
Vec4::ONE
- ((Vec4::splat(*threshold) - value)
/ falloff.max(f32::EPSILON))
.clamp(Vec4::ZERO, Vec4::ONE)
}
NoiseFilterCondition::Below(threshold) => {
Vec4::ONE
- ((value - Vec4::splat(*threshold))
/ falloff.max(f32::EPSILON))
.clamp(Vec4::ZERO, Vec4::ONE)
}
NoiseFilterCondition::Between { min, max } => {
let strength_below = 1.0
- ((Vec4::splat(*min) - value)
/ falloff.max(f32::EPSILON))
.clamp(Vec4::ZERO, Vec4::ONE);
let strength_above = 1.0
- ((value - Vec4::splat(*max))
/ falloff.max(f32::EPSILON))
.clamp(Vec4::ZERO, Vec4::ONE);

strength_below.min(strength_above)
}
}
}
}

/**
* A biome.
Expand Down

0 comments on commit ea0e9a7

Please sign in to comment.