Add mountains on coastline map; Fix minimal builds

2a1277a83ae1668d31cf0950397fc816f8a508e8
This commit is contained in:
Tobias Berger 2022-11-13 12:40:50 +01:00
parent 9464a495ea
commit df1172e9a9
Signed by: toby
GPG key ID: 2D05EFAB764D6A88
7 changed files with 186 additions and 78 deletions

View file

@ -27,7 +27,7 @@ codegen-units = 1
# bevy/trace_chrome for tracing by function # bevy/trace_chrome for tracing by function
# https://github.com/bevyengine/bevy/blob/main/docs/profiling.md # https://github.com/bevyengine/bevy/blob/main/docs/profiling.md
logging = ["planet/logging"] logging = ["planet/logging"]
render = ["bevy/bevy_asset", "bevy/bevy_winit", "bevy/x11", "bevy/wayland", "bevy/render", "dep:fxhash", "dep:bevy_egui", "dep:tinyfiledialogs"] render = ["bevy/bevy_asset", "bevy/bevy_winit", "bevy/x11", "bevy/wayland", "bevy/render", "planet/render", "dep:fxhash", "dep:bevy_egui", "dep:tinyfiledialogs"]
default = ["render", "logging"] default = ["render", "logging"]
[dependencies.planet] [dependencies.planet]

View file

@ -8,7 +8,8 @@ release = { strip = "symbols", lto = "thin", opt-level = "z" }
[features] [features]
logging = [] logging = []
default = ["logging"] render = ["bevy/render"]
default = ["logging", "render"]
[dependencies.rand] [dependencies.rand]
version = "0.8.5" version = "0.8.5"

View file

@ -1,11 +1,11 @@
use { use crate::{macros::iterable_enum, World};
crate::{macros::iterable_enum, World}, #[cfg(feature = "render")]
bevy::render::color::Color, use bevy::prelude::Color;
};
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct BiomeStats { pub struct BiomeStats {
pub name: String, pub name: String,
#[cfg(feature = "render")]
pub color: Color, pub color: Color,
pub min_altitude: f32, pub min_altitude: f32,
pub max_altitude: f32, pub max_altitude: f32,
@ -30,82 +30,90 @@ impl From<BiomeType> for BiomeStats {
fn from(biome_type: BiomeType) -> BiomeStats { fn from(biome_type: BiomeType) -> BiomeStats {
match biome_type { match biome_type {
BiomeType::IceCap => BiomeStats { BiomeType::IceCap => BiomeStats {
name: "Ice Cap".into(), name: "Ice Cap".into(),
color: Color::rgb_u8(253, 244, 235), #[cfg(feature = "render")]
min_altitude: World::MIN_ALTITUDE, color: Color::rgb_u8(253, 244, 235),
max_altitude: World::MAX_ALTITUDE, min_altitude: World::MIN_ALTITUDE,
min_rainfall: World::MIN_RAINFALL, max_altitude: World::MAX_ALTITUDE,
max_rainfall: World::MAX_RAINFALL, min_rainfall: World::MIN_RAINFALL,
max_rainfall: World::MAX_RAINFALL,
min_temperature: World::MIN_TEMPERATURE, min_temperature: World::MIN_TEMPERATURE,
max_temperature: -15.0, max_temperature: -15.0,
}, },
BiomeType::Ocean => BiomeStats { BiomeType::Ocean => BiomeStats {
name: "Ocean".into(), name: "Ocean".into(),
color: Color::rgb_u8(28, 66, 84), #[cfg(feature = "render")]
min_altitude: World::MIN_ALTITUDE, color: Color::rgb_u8(28, 66, 84),
max_altitude: 0.0, min_altitude: World::MIN_ALTITUDE,
min_rainfall: World::MIN_RAINFALL, max_altitude: 0.0,
max_rainfall: World::MAX_RAINFALL, min_rainfall: World::MIN_RAINFALL,
max_rainfall: World::MAX_RAINFALL,
min_temperature: -15.0, min_temperature: -15.0,
max_temperature: World::MAX_TEMPERATURE, max_temperature: World::MAX_TEMPERATURE,
}, },
BiomeType::Grassland => BiomeStats { BiomeType::Grassland => BiomeStats {
name: "Grassland".into(), name: "Grassland".into(),
color: Color::rgb_u8(167, 177, 84), #[cfg(feature = "render")]
min_altitude: 0.0, color: Color::rgb_u8(167, 177, 84),
max_altitude: World::MAX_ALTITUDE, min_altitude: 0.0,
min_rainfall: 25.0, max_altitude: World::MAX_ALTITUDE,
max_rainfall: 1475.0, min_rainfall: 25.0,
max_rainfall: 1475.0,
min_temperature: -5.0, min_temperature: -5.0,
max_temperature: World::MAX_TEMPERATURE, max_temperature: World::MAX_TEMPERATURE,
}, },
BiomeType::Forest => BiomeStats { BiomeType::Forest => BiomeStats {
name: "Forest".into(), name: "Forest".into(),
color: Color::rgb_u8(76, 132, 55), #[cfg(feature = "render")]
min_altitude: 0.0, color: Color::rgb_u8(76, 132, 55),
max_altitude: World::MAX_ALTITUDE, min_altitude: 0.0,
min_rainfall: 975.0, max_altitude: World::MAX_ALTITUDE,
max_rainfall: 2475.0, min_rainfall: 975.0,
max_rainfall: 2475.0,
min_temperature: -5.0, min_temperature: -5.0,
max_temperature: World::MAX_TEMPERATURE, max_temperature: World::MAX_TEMPERATURE,
}, },
BiomeType::Taiga => BiomeStats { BiomeType::Taiga => BiomeStats {
name: "Taiga".into(), name: "Taiga".into(),
color: Color::rgb_u8(43, 63, 40), #[cfg(feature = "render")]
min_altitude: 0.0, color: Color::rgb_u8(43, 63, 40),
max_altitude: World::MAX_ALTITUDE, min_altitude: 0.0,
min_rainfall: 475.0, max_altitude: World::MAX_ALTITUDE,
max_rainfall: World::MAX_RAINFALL, min_rainfall: 475.0,
max_rainfall: World::MAX_RAINFALL,
min_temperature: -15.0, min_temperature: -15.0,
max_temperature: -0.0, max_temperature: -0.0,
}, },
BiomeType::Tundra => BiomeStats { BiomeType::Tundra => BiomeStats {
name: "Tundra ".into(), name: "Tundra ".into(),
color: Color::rgb_u8(139, 139, 128), #[cfg(feature = "render")]
min_altitude: 0.0, color: Color::rgb_u8(139, 139, 128),
max_altitude: World::MAX_ALTITUDE, min_altitude: 0.0,
min_rainfall: World::MIN_RAINFALL, max_altitude: World::MAX_ALTITUDE,
max_rainfall: 725.0, min_rainfall: World::MIN_RAINFALL,
max_rainfall: 725.0,
min_temperature: -20.0, min_temperature: -20.0,
max_temperature: -0.0, max_temperature: -0.0,
}, },
BiomeType::Desert => BiomeStats { BiomeType::Desert => BiomeStats {
name: "Desert ".into(), name: "Desert ".into(),
color: Color::rgb_u8(253, 225, 171), #[cfg(feature = "render")]
min_altitude: 0.0, color: Color::rgb_u8(253, 225, 171),
max_altitude: World::MAX_ALTITUDE, min_altitude: 0.0,
min_rainfall: World::MIN_RAINFALL, max_altitude: World::MAX_ALTITUDE,
max_rainfall: 125.0, min_rainfall: World::MIN_RAINFALL,
max_rainfall: 125.0,
min_temperature: -5.0, min_temperature: -5.0,
max_temperature: World::MAX_TEMPERATURE, max_temperature: World::MAX_TEMPERATURE,
}, },
BiomeType::Rainforest => BiomeStats { BiomeType::Rainforest => BiomeStats {
name: "Rainforest".into(), name: "Rainforest".into(),
color: Color::rgb_u8(59, 103, 43), #[cfg(feature = "render")]
min_altitude: 0.0, color: Color::rgb_u8(59, 103, 43),
max_altitude: World::MAX_ALTITUDE, min_altitude: 0.0,
min_rainfall: 1975.0, max_altitude: World::MAX_ALTITUDE,
max_rainfall: World::MAX_RAINFALL, min_rainfall: 1975.0,
max_rainfall: World::MAX_RAINFALL,
min_temperature: -5.0, min_temperature: -5.0,
max_temperature: World::MAX_TEMPERATURE, max_temperature: World::MAX_TEMPERATURE,
}, },

View file

@ -631,6 +631,56 @@ impl World {
west_altitude - east_altitude west_altitude - east_altitude
} }
pub fn is_cell_near_coastline(&self, cell: &TerrainCell) -> bool {
if cell.altitude >= 0.0 {
return false;
}
let neighbors = self.cell_neighbors(cell.x, cell.y);
if let Some(neighbor) = neighbors.get(&CompassDirection::West) {
if neighbor.altitude >= 0.0 {
return true;
}
}
if let Some(neighbor) = neighbors.get(&CompassDirection::NorthWest) {
if neighbor.altitude >= 0.0 {
return true;
}
}
if let Some(neighbor) = neighbors.get(&CompassDirection::North) {
if neighbor.altitude >= 0.0 {
return true;
}
}
if let Some(neighbor) = neighbors.get(&CompassDirection::NorthEast) {
if neighbor.altitude >= 0.0 {
return true;
}
}
if let Some(neighbor) = neighbors.get(&CompassDirection::East) {
if neighbor.altitude >= 0.0 {
return true;
}
}
if let Some(neighbor) = neighbors.get(&CompassDirection::SouthEast) {
if neighbor.altitude >= 0.0 {
return true;
}
}
if let Some(neighbor) = neighbors.get(&CompassDirection::South) {
if neighbor.altitude >= 0.0 {
return true;
}
}
if let Some(neighbor) = neighbors.get(&CompassDirection::SouthWest) {
if neighbor.altitude >= 0.0 {
return true;
}
}
return false;
}
#[must_use] #[must_use]
pub fn is_cell_coastline(&self, cell: &TerrainCell) -> bool { pub fn is_cell_coastline(&self, cell: &TerrainCell) -> bool {
if cell.altitude <= 0.0 { if cell.altitude <= 0.0 {

View file

@ -1,8 +1,3 @@
#[cfg(feature = "render")]
use {
crate::{BiomeStats, TerrainCell, WorldOverlay, WorldRenderSettings, WorldView},
bevy::render::color::Color,
};
use { use {
crate::{World, WorldGenError}, crate::{World, WorldGenError},
bevy::{log::warn, utils::default}, bevy::{log::warn, utils::default},

View file

@ -16,6 +16,7 @@ macro_rules! iterable_enum {
} }
} }
} }
#[cfg(feature = "render")]
macro_rules! iterable_enum_stringify { macro_rules! iterable_enum_stringify {
($Name:ident { $($Variant:ident),*$(,)? }) => ($Name:ident { $($Variant:ident),*$(,)? }) =>
{ {
@ -38,4 +39,5 @@ macro_rules! iterable_enum_stringify {
} }
#[cfg(feature = "render")] #[cfg(feature = "render")]
pub(crate) use iterable_enum; pub(crate) use iterable_enum;
#[cfg(feature = "render")]
pub(crate) use iterable_enum_stringify; pub(crate) use iterable_enum_stringify;

View file

@ -45,24 +45,34 @@ impl WorldRenderSettings {
} }
#[must_use] #[must_use]
fn altitude_contour_color(altitude: f32) -> Color { fn altitude_contour_color(world: &World, altitude: f32) -> Color {
let mut color = Color::rgb(1.0, 0.6, 0.0);
let mut shade_value = 1.0;
let mut value = f32::max(0.0, altitude / world.max_altitude);
if altitude < 0.0 { if altitude < 0.0 {
Color::rgb(0.0, 0.0, (2.0 - altitude / World::MIN_ALTITUDE) / 2.0) value = f32::max(0.0, 1.0 - (altitude / world.min_altitude));
} else { color = Color::BLUE;
let mut shade_value = 1.0;
while shade_value > altitude / World::MAX_ALTITUDE {
shade_value -= 0.05;
}
Color::rgb(shade_value, shade_value, shade_value)
} }
while shade_value > value {
shade_value -= 0.15;
}
shade_value = 0.5 * shade_value + 0.5;
Color::rgb(
color.r() * shade_value,
color.g() * shade_value,
color.b() * shade_value,
)
} }
#[cfg(feature = "placeholder")]
#[must_use] #[must_use]
fn rainfall_contour_color(world: &World, rainfall: f32) -> Color { fn rainfall_contour_color(world: &World, rainfall: f32) -> Color {
let mut shade_value = 1.0; let mut shade_value = 1.0;
let value = rainfall / world.max_rainfall; let value = f32::max(0.0, rainfall / world.max_rainfall);
while shade_value > value { while shade_value > value {
shade_value -= 0.1; shade_value -= 0.1;
@ -71,6 +81,16 @@ fn rainfall_contour_color(world: &World, rainfall: f32) -> Color {
Color::rgb(0.0, shade_value, 0.0) Color::rgb(0.0, shade_value, 0.0)
} }
#[must_use]
fn rainfall_color(rainfall: f32) -> Color {
if rainfall <= 0.0 {
Color::BLACK
} else {
Color::rgb(rainfall / World::MAX_RAINFALL, 0.0, 0.0)
}
}
#[cfg(feature = "placeholder")]
#[must_use] #[must_use]
fn temperature_contour_color(world: &World, temperature: f32) -> Color { fn temperature_contour_color(world: &World, temperature: f32) -> Color {
let mut shade_value = 1.0; let mut shade_value = 1.0;
@ -84,6 +104,12 @@ fn temperature_contour_color(world: &World, temperature: f32) -> Color {
Color::rgb(shade_value, 0.0, 1.0 - shade_value) Color::rgb(shade_value, 0.0, 1.0 - shade_value)
} }
#[must_use]
fn temperature_color(temperature: f32) -> Color {
let value = (temperature - World::MIN_TEMPERATURE) / World::TEMPERATURE_SPAN;
Color::rgb(value, 0.0, 1.0 - value)
}
#[must_use] #[must_use]
fn biome_color(world: &World, cell: &TerrainCell) -> Color { fn biome_color(world: &World, cell: &TerrainCell) -> Color {
let slant = world.get_slant(cell); let slant = world.get_slant(cell);
@ -109,14 +135,31 @@ fn biome_color(world: &World, cell: &TerrainCell) -> Color {
Color::rgb(red, green, blue) Color::rgb(red, green, blue)
} }
const COASTLINE_PALETTE: [Color; 5] = [
Color::rgb(251.0 / 255.0, 230.0 / 255.0, 197.0 / 255.0),
Color::rgb(233.0 / 255.0, 192.0 / 255.0, 136.0 / 255.0),
Color::rgb(74.0 / 255.0, 39.0 / 255.0, 13.0 / 255.0),
Color::rgb(155.0 / 255.0, 105.0 / 255.0, 72.0 / 255.0),
Color::rgb(188.0 / 255.0, 136.0 / 255.0, 84.0 / 255.0),
];
#[must_use] #[must_use]
fn coastline_color(world: &World, cell: &TerrainCell) -> Color { fn coastline_color(world: &World, cell: &TerrainCell) -> Color {
if world.is_cell_coastline(cell) { if world.is_cell_coastline(cell) {
Color::BLACK COASTLINE_PALETTE[2]
} else if world.is_cell_near_coastline(cell) {
COASTLINE_PALETTE[3]
} else if cell.altitude > 0.0 { } else if cell.altitude > 0.0 {
Color::rgb(0.75, 0.75, 0.75) let slant = world.get_slant(cell);
let altitude_span = world.max_altitude - world.min_altitude;
let slant_factor = f32::min(1.0, -(500.0 * (slant / altitude_span)));
if slant_factor > 0.9 {
COASTLINE_PALETTE[4] * slant_factor + COASTLINE_PALETTE[1] * (1.0 - slant_factor)
} else {
COASTLINE_PALETTE[1]
}
} else { } else {
Color::ANTIQUE_WHITE COASTLINE_PALETTE[0]
} }
} }
pub(crate) trait WorldRenderer { pub(crate) trait WorldRenderer {
@ -144,9 +187,9 @@ impl WorldRenderer for WorldManager {
#[must_use] #[must_use]
fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color { fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color {
let base_color = match render_settings.view { let base_color = match render_settings.view {
WorldView::Biomes => biome_color(&self.world(), cell), WorldView::Biomes => biome_color(self.world(), cell),
WorldView::Topography => altitude_contour_color(cell.altitude), WorldView::Topography => altitude_contour_color(self.world(), cell.altitude),
WorldView::Coastlines => coastline_color(&self.world(), cell), WorldView::Coastlines => coastline_color(self.world(), cell),
}; };
let mut normalizer = 1.0; let mut normalizer = 1.0;
@ -154,9 +197,18 @@ impl WorldRenderer for WorldManager {
let mut green = base_color.g(); let mut green = base_color.g();
let mut blue = base_color.b(); let mut blue = base_color.b();
if render_settings.overlay_visible(&WorldOverlay::Rainfall)
|| render_settings.overlay_visible(&WorldOverlay::Temperature)
{
let grey = (red + green + blue) / 3.0;
red = grey;
green = grey;
blue = grey;
}
if render_settings.overlay_visible(&WorldOverlay::Rainfall) { if render_settings.overlay_visible(&WorldOverlay::Rainfall) {
normalizer += 1.0; normalizer += 1.0;
let rainfall_color = rainfall_contour_color(self.world(), cell.rainfall); let rainfall_color = rainfall_color(cell.rainfall);
red += rainfall_color.r(); red += rainfall_color.r();
green += rainfall_color.g(); green += rainfall_color.g();
@ -165,7 +217,7 @@ impl WorldRenderer for WorldManager {
if render_settings.overlay_visible(&WorldOverlay::Temperature) { if render_settings.overlay_visible(&WorldOverlay::Temperature) {
normalizer += 1.0; normalizer += 1.0;
let temperature_color = temperature_contour_color(self.world(), cell.temperature); let temperature_color = temperature_color(cell.temperature);
red += temperature_color.r(); red += temperature_color.r();
green += temperature_color.g(); green += temperature_color.g();