From 6b4abddc4ece7031b710aef57ef15ffeadcc060e Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Wed, 27 Oct 2021 21:46:17 +0100 Subject: [PATCH] Added floating scatter --- world/src/layer/scatter.rs | 151 ++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 68 deletions(-) diff --git a/world/src/layer/scatter.rs b/world/src/layer/scatter.rs index 01fef8e36a..7f072f0243 100644 --- a/world/src/layer/scatter.rs +++ b/world/src/layer/scatter.rs @@ -1,5 +1,5 @@ use crate::{column::ColumnSample, sim::SimChunk, Canvas, CONFIG}; -use common::terrain::SpriteKind; +use common::terrain::{Block, SpriteKind}; use noise::NoiseFn; use rand::prelude::*; use std::f32; @@ -13,17 +13,24 @@ const MUSH_FACT: f32 = 1.0e-4; // To balance things around the mushroom spawning const GRASS_FACT: f32 = 1.0e-3; // To balance things around the grass spawning rate const DEPTH_WATER_NORM: f32 = 15.0; // Water depth at which regular underwater sprites start spawning pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { + enum WaterMode { + Underwater, + Floating, + Surface, + } + use WaterMode::*; + use SpriteKind::*; #[allow(clippy::type_complexity)] // TODO: Add back all sprites we had before let scatter: &[( _, - bool, + WaterMode, fn(&SimChunk, &ColumnSample) -> (f32, Option<(f32, f32, f32)>), )] = &[ // (density, Option<(base_density_proportion, wavelen, threshold)>) // Flowers - (BlueFlower, false, |_, col| { + (BlueFlower, Surface, |_, col| { ( close(col.temp, CONFIG.temperate_temp, 0.7).min(close( col.humidity, @@ -35,7 +42,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.0, 256.0, 0.25)), ) }), - (PinkFlower, false, |_, col| { + (PinkFlower, Surface, |_, col| { ( close(col.temp, 0.0, 0.7).min(close(col.humidity, CONFIG.jungle_hum, 0.4)) * col.tree_density @@ -44,7 +51,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.0, 100.0, 0.1)), ) }), - (PurpleFlower, false, |_, col| { + (PurpleFlower, Surface, |_, col| { ( close(col.temp, CONFIG.temperate_temp, 0.7).min(close( col.humidity, @@ -56,7 +63,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.0, 100.0, 0.1)), ) }), - (RedFlower, false, |_, col| { + (RedFlower, Surface, |_, col| { ( close(col.temp, CONFIG.tropical_temp, 0.7).min(close( col.humidity, @@ -68,7 +75,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.0, 100.0, 0.1)), ) }), - (WhiteFlower, false, |_, col| { + (WhiteFlower, Surface, |_, col| { ( close(col.temp, 0.0, 0.7).min(close(col.humidity, CONFIG.jungle_hum, 0.4)) * col.tree_density @@ -77,7 +84,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.0, 100.0, 0.1)), ) }), - (YellowFlower, false, |_, col| { + (YellowFlower, Surface, |_, col| { ( close(col.temp, 0.0, 0.7).min(close(col.humidity, CONFIG.jungle_hum, 0.4)) * col.tree_density @@ -86,7 +93,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.0, 100.0, 0.1)), ) }), - (Cotton, false, |_, col| { + (Cotton, Surface, |_, col| { ( close(col.temp, CONFIG.temperate_temp, 0.7).min(close( col.humidity, @@ -98,7 +105,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.0, 256.0, 0.25)), ) }), - (Sunflower, false, |_, col| { + (Sunflower, Surface, |_, col| { ( close(col.temp, 0.0, 0.7).min(close(col.humidity, CONFIG.jungle_hum, 0.4)) * col.tree_density @@ -107,7 +114,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.0, 100.0, 0.15)), ) }), - (WildFlax, false, |_, col| { + (WildFlax, Surface, |_, col| { ( close(col.temp, 0.0, 0.7).min(close(col.humidity, CONFIG.jungle_hum, 0.4)) * col.tree_density @@ -117,7 +124,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Herbs and Spices - (LingonBerry, false, |_, col| { + (LingonBerry, Surface, |_, col| { ( close(col.temp, 0.3, 0.4).min(close(col.humidity, CONFIG.jungle_hum, 0.5)) * MUSH_FACT @@ -125,7 +132,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { None, ) }), - (LeafyPlant, false, |_, col| { + (LeafyPlant, Surface, |_, col| { ( close(col.temp, 0.3, 0.4).min(close(col.humidity, CONFIG.jungle_hum, 0.3)) * GRASS_FACT @@ -133,7 +140,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { None, ) }), - (Fern, false, |_, col| { + (Fern, Surface, |_, col| { ( close(col.temp, 0.3, 0.4).min(close(col.humidity, CONFIG.forest_hum, 0.5)) * GRASS_FACT @@ -141,7 +148,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.0, 64.0, 0.2)), ) }), - (Blueberry, false, |_, col| { + (Blueberry, Surface, |_, col| { ( close(col.temp, CONFIG.temperate_temp, 0.5).min(close( col.humidity, @@ -152,7 +159,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { None, ) }), - (Pumpkin, false, |_, col| { + (Pumpkin, Surface, |_, col| { ( close(col.temp, CONFIG.temperate_temp, 0.5).min(close( col.humidity, @@ -165,23 +172,23 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { }), // Collectable Objects // Only spawn twigs in temperate forests - (Twigs, false, |_, col| { + (Twigs, Surface, |_, col| { ( (col.tree_density * 1.25 - 0.25).powf(0.5).max(0.0) * 0.75e-3, None, ) }), - (Stones, false, |chunk, _| { + (Stones, Surface, |chunk, _| { ((chunk.rockiness - 0.5).max(0.025) * 1.0e-3, None) }), - (Copper, false, |chunk, _| { + (Copper, Surface, |chunk, _| { ((chunk.rockiness - 0.5).max(0.0) * 1.5e-3, None) }), - (Tin, false, |chunk, _| { + (Tin, Surface, |chunk, _| { ((chunk.rockiness - 0.5).max(0.0) * 1.5e-3, None) }), // Don't spawn Mushrooms in snowy regions - (Mushroom, false, |_, col| { + (Mushroom, Surface, |_, col| { ( close(col.temp, 0.3, 0.4).min(close(col.humidity, CONFIG.forest_hum, 0.35)) * MUSH_FACT, @@ -189,7 +196,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Grass - (ShortGrass, false, |_, col| { + (ShortGrass, Surface, |_, col| { ( close(col.temp, 0.2, 0.75).min(close(col.humidity, CONFIG.jungle_hum, 0.4)) * GRASS_FACT @@ -197,7 +204,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.3, 64.0, 0.3)), ) }), - (MediumGrass, false, |_, col| { + (MediumGrass, Surface, |_, col| { ( close(col.temp, 0.2, 0.6).min(close(col.humidity, CONFIG.jungle_hum, 0.4)) * GRASS_FACT @@ -205,7 +212,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.3, 64.0, 0.3)), ) }), - (LongGrass, false, |_, col| { + (LongGrass, Surface, |_, col| { ( close(col.temp, 0.3, 0.35).min(close(col.humidity, CONFIG.jungle_hum, 0.3)) * GRASS_FACT @@ -214,7 +221,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Jungle Sprites - // (LongGrass, false, |c, col| { + // (LongGrass, Surface, |c, col| { // ( // close(col.temp, CONFIG.tropical_temp, 0.4).min(close( // col.humidity, @@ -224,7 +231,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { // Some((0.0, 60.0, 5.0)), // ) // }), - /*(WheatGreen, false, |c, col| { + /*(WheatGreen, Surface, |c, col| { ( close(col.temp, 0.4, 0.2).min(close(col.humidity, CONFIG.forest_hum, 0.1)) * MUSH_FACT @@ -232,7 +239,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { None, ) }),*/ - (GrassSnow, false, |_, col| { + (GrassSnow, Surface, |_, col| { ( close(col.temp, CONFIG.snow_temp - 0.2, 0.4).min(close( col.humidity, @@ -243,7 +250,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.0, 48.0, 0.2)), ) }), - (Moonbell, false, |_, col| { + (Moonbell, Surface, |_, col| { ( close(col.temp, CONFIG.snow_temp - 0.2, 0.4).min(close( col.humidity, @@ -254,7 +261,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Savanna Plants - (SavannaGrass, false, |_, col| { + (SavannaGrass, Surface, |_, col| { ( { let savanna = close(col.temp, 1.0, 0.4) * close(col.humidity, 0.2, 0.25); @@ -264,7 +271,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.15, 64.0, 0.2)), ) }), - (TallSavannaGrass, false, |_, col| { + (TallSavannaGrass, Surface, |_, col| { ( { let savanna = close(col.temp, 1.0, 0.4) * close(col.humidity, 0.2, 0.25); @@ -274,7 +281,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.1, 48.0, 0.2)), ) }), - (RedSavannaGrass, false, |_, col| { + (RedSavannaGrass, Surface, |_, col| { ( { let savanna = close(col.temp, 1.0, 0.4) * close(col.humidity, 0.2, 0.25); @@ -284,7 +291,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { Some((0.15, 48.0, 0.25)), ) }), - (SavannaBush, false, |_, col| { + (SavannaBush, Surface, |_, col| { ( { let savanna = close(col.temp, 1.0, 0.4) * close(col.humidity, 0.2, 0.25); @@ -295,49 +302,49 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Desert Plants - (DeadBush, false, |_, col| { + (DeadBush, Surface, |_, col| { ( close(col.temp, 1.0, 0.95).min(close(col.humidity, 0.0, 0.3)) * MUSH_FACT * 7.5, None, ) }), - (Pyrebloom, false, |_, col| { + (Pyrebloom, Surface, |_, col| { ( close(col.temp, 1.0, 0.95).min(close(col.humidity, 0.0, 0.3)) * MUSH_FACT * 0.35, None, ) }), - (LargeCactus, false, |_, col| { + (LargeCactus, Surface, |_, col| { ( close(col.temp, 1.0, 0.25).min(close(col.humidity, 0.0, 0.1)) * MUSH_FACT * 1.5, None, ) }), - (RoundCactus, false, |_, col| { + (RoundCactus, Surface, |_, col| { ( close(col.temp, 1.0, 0.25).min(close(col.humidity, 0.0, 0.1)) * MUSH_FACT * 2.5, None, ) }), - (ShortCactus, false, |_, col| { + (ShortCactus, Surface, |_, col| { ( close(col.temp, 1.0, 0.25).min(close(col.humidity, 0.0, 0.1)) * MUSH_FACT * 2.5, None, ) }), - (MedFlatCactus, false, |_, col| { + (MedFlatCactus, Surface, |_, col| { ( close(col.temp, 1.0, 0.25).min(close(col.humidity, 0.0, 0.1)) * MUSH_FACT * 2.5, None, ) }), - (ShortFlatCactus, false, |_, col| { + (ShortFlatCactus, Surface, |_, col| { ( close(col.temp, 1.0, 0.25).min(close(col.humidity, 0.0, 0.1)) * MUSH_FACT * 2.5, None, ) }), - (Reed, false, |_, col| { + (Reed, Surface, |_, col| { ( close(col.humidity, CONFIG.jungle_hum, 0.9) * col @@ -349,7 +356,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Underwater chests - (ChestBuried, true, |_, col| { + (ChestBuried, Underwater, |_, col| { ( MUSH_FACT * 1.0e-6 @@ -362,7 +369,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Underwater mud piles - (Mud, true, |_, col| { + (Mud, Underwater, |_, col| { ( MUSH_FACT * 1.0e-3 @@ -375,7 +382,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Underwater grass - (GrassBlue, true, |_, col| { + (GrassBlue, Underwater, |_, col| { ( MUSH_FACT * 250.0 @@ -388,7 +395,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // seagrass - (Seagrass, true, |_, col| { + (Seagrass, Underwater, |_, col| { ( close(col.temp, CONFIG.temperate_temp, 0.8) * MUSH_FACT @@ -404,7 +411,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // seagrass, coastal patches - (Seagrass, true, |_, col| { + (Seagrass, Underwater, |_, col| { ( MUSH_FACT * 600.0 @@ -417,7 +424,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // scattered seaweed (temperate species) - (SeaweedTemperate, true, |_, col| { + (SeaweedTemperate, Underwater, |_, col| { ( close(col.temp, CONFIG.temperate_temp, 0.8) * MUSH_FACT @@ -433,7 +440,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // scattered seaweed (tropical species) - (SeaweedTropical, true, |_, col| { + (SeaweedTropical, Underwater, |_, col| { ( close(col.temp, 1.0, 0.95) * MUSH_FACT @@ -449,7 +456,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Caulerpa lentillifera algae patch - (SeaGrapes, true, |_, col| { + (SeaGrapes, Underwater, |_, col| { ( MUSH_FACT * 250.0 @@ -464,7 +471,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Caulerpa prolifera algae patch - (WavyAlgae, true, |_, col| { + (WavyAlgae, Underwater, |_, col| { ( MUSH_FACT * 250.0 @@ -479,7 +486,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Mermaids' fan algae patch - (MermaidsFan, true, |_, col| { + (MermaidsFan, Underwater, |_, col| { ( close(col.temp, 1.0, 0.95) * MUSH_FACT @@ -495,7 +502,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Sea anemones - (SeaAnemone, true, |_, col| { + (SeaAnemone, Underwater, |_, col| { ( close(col.temp, CONFIG.temperate_temp, 0.8) * MUSH_FACT @@ -511,7 +518,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Giant Kelp - (GiantKelp, true, |_, col| { + (GiantKelp, Underwater, |_, col| { ( close(col.temp, CONFIG.temperate_temp, 0.8) * MUSH_FACT @@ -527,7 +534,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Bull Kelp - (BullKelp, true, |_, col| { + (BullKelp, Underwater, |_, col| { ( close(col.temp, CONFIG.temperate_temp, 0.7) * MUSH_FACT @@ -543,7 +550,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Stony Corals - (StonyCoral, true, |_, col| { + (StonyCoral, Underwater, |_, col| { ( close(col.temp, 1.0, 0.9) * MUSH_FACT @@ -559,7 +566,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Soft Corals - (SoftCoral, true, |_, col| { + (SoftCoral, Underwater, |_, col| { ( close(col.temp, 1.0, 0.9) * MUSH_FACT @@ -575,7 +582,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { ) }), // Seashells - (Seashells, true, |c, col| { + (Seashells, Underwater, |c, col| { ( (c.rockiness - 0.5).max(0.0) * 1.0e-3 @@ -589,7 +596,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { None, ) }), - (Stones, true, |c, col| { + (Stones, Underwater, |c, col| { ( (c.rockiness - 0.5).max(0.0) * 1.0e-3 @@ -601,6 +608,15 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { None, ) }), + (CavernLillypadBlue, Floating, |_, col| { + ( + close(col.temp, 0.2, 0.6).min(close(col.humidity, CONFIG.jungle_hum, 0.4)) + * GRASS_FACT + * 120.0 + * ((col.alt - CONFIG.sea_level) / 12.0).clamped(0.0, 1.0), + Some((0.0, 256.0, 0.25)), + ) + }), ]; canvas.foreach_col(|canvas, wpos2d, col| { @@ -609,7 +625,7 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { let kind = scatter .iter() .enumerate() - .find_map(|(i, (kind, is_underwater, f))| { + .find_map(|(i, (kind, water_mode, f))| { let (density, patch) = f(canvas.chunk(), col); let density = patch .map(|(base_density_prop, wavelen, threshold)| { @@ -633,30 +649,29 @@ pub fn apply_scatter_to(canvas: &mut Canvas, rng: &mut impl Rng) { .unwrap_or(density); if density > 0.0 && rng.gen::() < density //RandomField::new(i as u32).chance(Vec3::new(wpos2d.x, wpos2d.y, 0), density) - && underwater == *is_underwater + && matches!(&water_mode, Underwater | Floating) == underwater { - Some(*kind) + Some((*kind, water_mode)) } else { None } }); - if let Some(kind) = kind { - let alt = col.alt as i32; + if let Some((kind, water_mode)) = kind { + let (alt, is_under): (_, fn(Block) -> bool) = match water_mode { + Surface | Underwater => (col.alt as i32, |block| block.is_solid()), + Floating => (col.water_level as i32, |block| !block.is_air()), + }; // Find the intersection between ground and air, if there is one near the // surface if let Some(solid_end) = (-4..8) .find(|z| { - canvas - .get(Vec3::new(wpos2d.x, wpos2d.y, alt + z)) - .is_solid() + is_under(canvas.get(Vec3::new(wpos2d.x, wpos2d.y, alt + z))) }) .and_then(|solid_start| { (1..8).map(|z| solid_start + z).find(|z| { - !canvas - .get(Vec3::new(wpos2d.x, wpos2d.y, alt + z)) - .is_solid() + !is_under(canvas.get(Vec3::new(wpos2d.x, wpos2d.y, alt + z))) }) }) {