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
# https://github.com/bevyengine/bevy/blob/main/docs/profiling.md
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"]
[dependencies.planet]

View file

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

View file

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

View file

@ -631,6 +631,56 @@ impl World {
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]
pub fn is_cell_coastline(&self, cell: &TerrainCell) -> bool {
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 {
crate::{World, WorldGenError},
bevy::{log::warn, utils::default},

View file

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

View file

@ -45,24 +45,34 @@ impl WorldRenderSettings {
}
#[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 {
Color::rgb(0.0, 0.0, (2.0 - altitude / World::MIN_ALTITUDE) / 2.0)
} else {
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)
value = f32::max(0.0, 1.0 - (altitude / world.min_altitude));
color = Color::BLUE;
}
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]
fn rainfall_contour_color(world: &World, rainfall: f32) -> Color {
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 {
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)
}
#[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]
fn temperature_contour_color(world: &World, temperature: f32) -> Color {
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)
}
#[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]
fn biome_color(world: &World, cell: &TerrainCell) -> Color {
let slant = world.get_slant(cell);
@ -109,14 +135,31 @@ fn biome_color(world: &World, cell: &TerrainCell) -> Color {
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]
fn coastline_color(world: &World, cell: &TerrainCell) -> Color {
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 {
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 {
Color::ANTIQUE_WHITE
COASTLINE_PALETTE[0]
}
}
pub(crate) trait WorldRenderer {
@ -144,9 +187,9 @@ impl WorldRenderer for WorldManager {
#[must_use]
fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color {
let base_color = match render_settings.view {
WorldView::Biomes => biome_color(&self.world(), cell),
WorldView::Topography => altitude_contour_color(cell.altitude),
WorldView::Coastlines => coastline_color(&self.world(), cell),
WorldView::Biomes => biome_color(self.world(), cell),
WorldView::Topography => altitude_contour_color(self.world(), cell.altitude),
WorldView::Coastlines => coastline_color(self.world(), cell),
};
let mut normalizer = 1.0;
@ -154,9 +197,18 @@ impl WorldRenderer for WorldManager {
let mut green = base_color.g();
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) {
normalizer += 1.0;
let rainfall_color = rainfall_contour_color(self.world(), cell.rainfall);
let rainfall_color = rainfall_color(cell.rainfall);
red += rainfall_color.r();
green += rainfall_color.g();
@ -165,7 +217,7 @@ impl WorldRenderer for WorldManager {
if render_settings.overlay_visible(&WorldOverlay::Temperature) {
normalizer += 1.0;
let temperature_color = temperature_contour_color(self.world(), cell.temperature);
let temperature_color = temperature_color(cell.temperature);
red += temperature_color.r();
green += temperature_color.g();