Add mountains on coastline map; Fix minimal builds
2a1277a83ae1668d31cf0950397fc816f8a508e8
This commit is contained in:
parent
9464a495ea
commit
df1172e9a9
7 changed files with 186 additions and 78 deletions
|
@ -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]
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue