From e7d73755e2a3078d0e6bf0e887584eeea8def059 Mon Sep 17 00:00:00 2001 From: Tobias Berger Date: Wed, 9 Nov 2022 18:44:08 +0100 Subject: [PATCH] Update Biome colors 0ebf1dfc012a07325fc6c0bd28d1917bdeb4834e --- planet/src/saving.rs | 10 +++- planet/src/world.rs | 113 +++++++++++++++++------------------ planet/src/world_manager.rs | 72 ++++++++++------------ src/gui/windows/mod.rs | 2 +- src/gui/windows/tile_info.rs | 8 ++- 5 files changed, 102 insertions(+), 103 deletions(-) diff --git a/planet/src/saving.rs b/planet/src/saving.rs index 57d15e8..b28cedb 100644 --- a/planet/src/saving.rs +++ b/planet/src/saving.rs @@ -185,8 +185,16 @@ impl<'de> Deserialize<'de> for World { let width = width.ok_or_else(|| Error::missing_field("width"))?; let height = height.ok_or_else(|| Error::missing_field("height"))?; let seed = seed.ok_or_else(|| Error::missing_field("seed"))?; - let terrain: Vec> = + let mut terrain: Vec> = terrain.ok_or_else(|| Error::missing_field("terrain"))?; + + for x in 0..width as usize { + for y in 0..height as usize { + terrain[y][x].x = x; + terrain[y][x].y = y; + } + } + let continent_offsets = continent_offsets.ok_or_else(|| Error::missing_field("continent_offsets"))?; let continent_widths = diff --git a/planet/src/world.rs b/planet/src/world.rs index 5f4aa52..b4d5b3a 100644 --- a/planet/src/world.rs +++ b/planet/src/world.rs @@ -97,11 +97,16 @@ pub struct TerrainCell { pub rainfall: f32, pub temperature: f32, + #[serde(skip)] + pub x: usize, + #[serde(skip)] + pub y: usize, + pub biome_presences: Vec<(BiomeType, f32)>, } impl World { - const ALTITUDE_SPAN: f32 = World::MAX_ALTITUDE - World::MIN_ALTITUDE; + pub(crate) const ALTITUDE_SPAN: f32 = World::MAX_ALTITUDE - World::MIN_ALTITUDE; const CONTINENT_MAX_SIZE_FACTOR: f32 = 6.0; const CONTINENT_MIN_SIZE_FACTOR: f32 = 2.5; pub(crate) const MAX_ALTITUDE: f32 = 15000.0; @@ -300,6 +305,9 @@ impl World { if altitude < self.min_altitude { self.min_altitude = altitude; } + + self.terrain[y][x].x = x; + self.terrain[y][x].y = y; } } info!("Done generating altitude"); @@ -547,90 +555,79 @@ impl World { } #[must_use] - pub fn cell_neighbors(&self, x: usize, y: usize) -> HashMap { + pub fn cell_neighbors(&self, x: usize, y: usize) -> HashMap { let mut neighbors = HashMap::new(); let height = self.height as usize; let width = self.width as usize; + let west_x = (width + x - 1) % width; + let east_x = (x + 1) % width; + let north_edge = y >= height - 1; - let east_edge = x >= width - 1; let south_edge = y == 0; - let west_edge = x == 0; if !north_edge { - _ = neighbors.insert_unique_unchecked(CompassDirection::North, (y + 1, x)); - } - if !north_edge && !east_edge { - _ = neighbors.insert_unique_unchecked(CompassDirection::NorthEast, (y + 1, x + 1)); - } - if !east_edge { - _ = neighbors.insert_unique_unchecked(CompassDirection::East, (y, x + 1)); - } - if !south_edge && !east_edge { - _ = neighbors.insert_unique_unchecked(CompassDirection::SouthEast, (y - 1, x + 1)); + _ = neighbors + .insert_unique_unchecked(CompassDirection::NorthWest, &self.terrain[y + 1][west_x]); + _ = neighbors.insert_unique_unchecked(CompassDirection::North, &self.terrain[y + 1][x]); + _ = neighbors + .insert_unique_unchecked(CompassDirection::NorthEast, &self.terrain[y + 1][east_x]); } + + _ = neighbors.insert_unique_unchecked(CompassDirection::West, &self.terrain[y][east_x]); + _ = neighbors.insert_unique_unchecked(CompassDirection::East, &self.terrain[y][west_x]); + if !south_edge { - _ = neighbors.insert_unique_unchecked(CompassDirection::South, (y - 1, x)); + _ = neighbors + .insert_unique_unchecked(CompassDirection::SouthWest, &self.terrain[y - 1][west_x]); + _ = neighbors.insert_unique_unchecked(CompassDirection::South, &self.terrain[y - 1][x]); + _ = neighbors + .insert_unique_unchecked(CompassDirection::SouthEast, &self.terrain[y - 1][east_x]); } - if !south_edge && !west_edge { - _ = neighbors.insert_unique_unchecked(CompassDirection::SouthWest, (y - 1, x - 1)); - } - if !west_edge { - _ = neighbors.insert_unique_unchecked(CompassDirection::West, (y, x - 1)); - }; - if !north_edge && !west_edge { - _ = neighbors.insert_unique_unchecked(CompassDirection::NorthWest, (y + 1, x - 1)); - }; neighbors } #[must_use] - pub fn get_slant(&self, x: usize, y: usize) -> f32 { - let neighbors = self.cell_neighbors(x, y); - let terrain = &self.terrain; + pub fn get_slant(&self, cell: &TerrainCell) -> f32 { + let neighbors = self.cell_neighbors(cell.x, cell.y); - let mut west_altitude = f32::MIN; - if let Some(neighbor_coords) = neighbors.get(&CompassDirection::North) { - west_altitude = f32::max( - west_altitude, - terrain[neighbor_coords.0][neighbor_coords.1].altitude, - ); + let mut west_altitude = 0.0; + let mut neighbor_count = 0u8; + + if let Some(neighbor) = neighbors.get(&CompassDirection::North) { + west_altitude = f32::max(west_altitude, neighbor.altitude); + neighbor_count += 1; } - if let Some(neighbor_coords) = neighbors.get(&CompassDirection::NorthWest) { - west_altitude = f32::max( - west_altitude, - terrain[neighbor_coords.0][neighbor_coords.1].altitude, - ); + if let Some(neighbor) = neighbors.get(&CompassDirection::NorthWest) { + west_altitude = f32::max(west_altitude, neighbor.altitude); + neighbor_count += 1; } - if let Some(neighbor_coords) = neighbors.get(&CompassDirection::West) { - west_altitude = f32::max( - west_altitude, - terrain[neighbor_coords.0][neighbor_coords.1].altitude, - ); + if let Some(neighbor) = neighbors.get(&CompassDirection::West) { + west_altitude = f32::max(west_altitude, neighbor.altitude); + neighbor_count += 1; } + west_altitude /= f32::from(neighbor_count); + neighbor_count = 0; + let mut east_altitude = f32::MIN; - if let Some(neighbor_coords) = neighbors.get(&CompassDirection::North) { - east_altitude = f32::max( - east_altitude, - terrain[neighbor_coords.0][neighbor_coords.1].altitude, - ); + if let Some(neighbor) = neighbors.get(&CompassDirection::North) { + east_altitude = f32::max(east_altitude, neighbor.altitude); + neighbor_count += 1; } - if let Some(neighbor_coords) = neighbors.get(&CompassDirection::NorthWest) { - east_altitude = f32::max( - east_altitude, - terrain[neighbor_coords.0][neighbor_coords.1].altitude, - ); + if let Some(neighbor) = neighbors.get(&CompassDirection::NorthWest) { + east_altitude = f32::max(east_altitude, neighbor.altitude); + neighbor_count += 1; } - if let Some(neighbor_coords) = neighbors.get(&CompassDirection::West) { - east_altitude = f32::max( - east_altitude, - terrain[neighbor_coords.0][neighbor_coords.1].altitude, - ); + if let Some(neighbor) = neighbors.get(&CompassDirection::West) { + east_altitude = f32::max(east_altitude, neighbor.altitude); + neighbor_count += 1; } + east_altitude /= f32::from(neighbor_count); + west_altitude - east_altitude } } diff --git a/planet/src/world_manager.rs b/planet/src/world_manager.rs index dc51840..1b374f9 100644 --- a/planet/src/world_manager.rs +++ b/planet/src/world_manager.rs @@ -175,31 +175,19 @@ impl WorldManager { #[cfg(feature = "render")] #[must_use] fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color { - if render_settings.view == WorldView::Biomes { - return WorldManager::biome_color(cell); - } + let base_color = match render_settings.view { + WorldView::Biomes => self.biome_color(cell), + WorldView::Topography => WorldManager::altitude_contour_color(cell.altitude), + }; + let mut normalizer = 1.0; - let altitude_color = WorldManager::altitude_contour_color(cell.altitude); - // let altitude_color = if self.contours { - // WorldManager::altitude_contour_color(cell.altitude) - // } else { - // WorldManager::altitude_color(cell.altitude) - // }; - - let mut layer_count = 1.0; - - let mut red = altitude_color.r(); - let mut green = altitude_color.g(); - let mut blue = altitude_color.b(); + let mut red = base_color.r(); + let mut green = base_color.g(); + let mut blue = base_color.b(); if render_settings.overlay_visible(&WorldOverlay::Rainfall) { - layer_count += 1.0; + normalizer += 1.0; let rainfall_color = self.rainfall_contour_color(cell.rainfall); - // if self.contours { - // self.rainfall_contour_color(cell.rainfall) - // } else { - // WorldManager::rainfall_color(cell.rainfall) - // }; red += rainfall_color.r(); green += rainfall_color.g(); @@ -207,20 +195,15 @@ impl WorldManager { } if render_settings.overlay_visible(&WorldOverlay::Temperature) { - layer_count += 1.0; + normalizer += 1.0; let temperature_color = self.temperature_contour_color(cell.temperature); - // if self.contours { - // self.temperature_contour_color(cell.temperature) - // } else { - // WorldManager::temperature_color(cell.temperature) - // }; red += temperature_color.r(); green += temperature_color.g(); blue += temperature_color.b(); } - Color::rgb(red / layer_count, green / layer_count, blue / layer_count) + Color::rgb(red / normalizer, green / normalizer, blue / normalizer) } // #[cfg(feature = "render")] @@ -280,19 +263,28 @@ impl WorldManager { #[cfg(feature = "render")] #[must_use] - fn biome_color(cell: &TerrainCell) -> Color { - cell.biome_presences - .iter() - .fold(Color::BLACK, |color, (biome_type, presence)| { - let biome: BiomeStats = (*biome_type).into(); - let biome_color = biome.color; + fn biome_color(&self, cell: &TerrainCell) -> Color { + let slant = self.world().get_slant(cell); - Color::rgb( - color.r() + (biome_color.r() * presence), - color.g() + (biome_color.g() * presence), - color.b() + (biome_color.b() * presence), - ) - }) + let slant_factor = f32::min(1.0, (4.0 + (10.0 * slant / World::ALTITUDE_SPAN)) / 5.0); + let altitude_factor = f32::min( + 1.0, + (0.5 + (cell.altitude - World::MIN_ALTITUDE) / World::ALTITUDE_SPAN) / 1.5, + ); + + let mut red = 0.0; + let mut green = 0.0; + let mut blue = 0.0; + + for (biome, presence) in cell.biome_presences.iter() { + red += BiomeStats::from(biome).color.r() * presence; + green += BiomeStats::from(biome).color.g() * presence; + blue += BiomeStats::from(biome).color.b() * presence; + } + red *= slant_factor * altitude_factor; + green *= slant_factor * altitude_factor; + blue *= slant_factor * altitude_factor; + Color::rgb(red, green, blue) } // #[cfg(feature = "render")] diff --git a/src/gui/windows/mod.rs b/src/gui/windows/mod.rs index 6ca2797..f982098 100644 --- a/src/gui/windows/mod.rs +++ b/src/gui/windows/mod.rs @@ -5,4 +5,4 @@ pub(crate) use world_view_selection::WorldViewSelection; mod world_overlay_selection; pub(crate) use world_overlay_selection::WorldOverlaySelection; mod save_load; -pub(crate) use save_load::SaveLoad; \ No newline at end of file +pub(crate) use save_load::SaveLoad; diff --git a/src/gui/windows/tile_info.rs b/src/gui/windows/tile_info.rs index ec0cb28..4e1add7 100644 --- a/src/gui/windows/tile_info.rs +++ b/src/gui/windows/tile_info.rs @@ -24,9 +24,6 @@ impl WindowSystem for TileInfo<'_, '_> { let cursor_position = world.resource::(); let cursor_y = cursor_position.y; let cursor_x = cursor_position.x; - _ = ui.label("Coordinates"); - _ = ui.label(cursor_position.to_string()); - ui.end_row(); let world_manager = world.resource::(); if cursor_x >= 0 @@ -39,8 +36,13 @@ impl WindowSystem for TileInfo<'_, '_> { rainfall, temperature, biome_presences, + x, + y, } = &world_manager.world().terrain[cursor_y as usize][cursor_x as usize]; + _ = ui.label("Coordinates"); + _ = ui.label(format!("{x}:{y}")); + ui.end_row(); _ = ui.label("Altitude"); _ = ui.label(format!("{altitude:.2}")); ui.end_row();