Update Biome colors

0ebf1dfc012a07325fc6c0bd28d1917bdeb4834e
This commit is contained in:
Tobias Berger 2022-11-09 18:44:08 +01:00
parent 234579f553
commit e7d73755e2
Signed by: toby
GPG key ID: 2D05EFAB764D6A88
5 changed files with 102 additions and 103 deletions

View file

@ -185,8 +185,16 @@ impl<'de> Deserialize<'de> for World {
let width = width.ok_or_else(|| Error::missing_field("width"))?; let width = width.ok_or_else(|| Error::missing_field("width"))?;
let height = height.ok_or_else(|| Error::missing_field("height"))?; let height = height.ok_or_else(|| Error::missing_field("height"))?;
let seed = seed.ok_or_else(|| Error::missing_field("seed"))?; let seed = seed.ok_or_else(|| Error::missing_field("seed"))?;
let terrain: Vec<Vec<TerrainCell>> = let mut terrain: Vec<Vec<TerrainCell>> =
terrain.ok_or_else(|| Error::missing_field("terrain"))?; 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 = let continent_offsets =
continent_offsets.ok_or_else(|| Error::missing_field("continent_offsets"))?; continent_offsets.ok_or_else(|| Error::missing_field("continent_offsets"))?;
let continent_widths = let continent_widths =

View file

@ -97,11 +97,16 @@ pub struct TerrainCell {
pub rainfall: f32, pub rainfall: f32,
pub temperature: f32, pub temperature: f32,
#[serde(skip)]
pub x: usize,
#[serde(skip)]
pub y: usize,
pub biome_presences: Vec<(BiomeType, f32)>, pub biome_presences: Vec<(BiomeType, f32)>,
} }
impl World { 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_MAX_SIZE_FACTOR: f32 = 6.0;
const CONTINENT_MIN_SIZE_FACTOR: f32 = 2.5; const CONTINENT_MIN_SIZE_FACTOR: f32 = 2.5;
pub(crate) const MAX_ALTITUDE: f32 = 15000.0; pub(crate) const MAX_ALTITUDE: f32 = 15000.0;
@ -300,6 +305,9 @@ impl World {
if altitude < self.min_altitude { if altitude < self.min_altitude {
self.min_altitude = altitude; self.min_altitude = altitude;
} }
self.terrain[y][x].x = x;
self.terrain[y][x].y = y;
} }
} }
info!("Done generating altitude"); info!("Done generating altitude");
@ -547,90 +555,79 @@ impl World {
} }
#[must_use] #[must_use]
pub fn cell_neighbors(&self, x: usize, y: usize) -> HashMap<CompassDirection, (usize, usize)> { pub fn cell_neighbors(&self, x: usize, y: usize) -> HashMap<CompassDirection, &TerrainCell> {
let mut neighbors = HashMap::new(); let mut neighbors = HashMap::new();
let height = self.height as usize; let height = self.height as usize;
let width = self.width 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 north_edge = y >= height - 1;
let east_edge = x >= width - 1;
let south_edge = y == 0; let south_edge = y == 0;
let west_edge = x == 0;
if !north_edge { if !north_edge {
_ = neighbors.insert_unique_unchecked(CompassDirection::North, (y + 1, x)); _ = neighbors
} .insert_unique_unchecked(CompassDirection::NorthWest, &self.terrain[y + 1][west_x]);
if !north_edge && !east_edge { _ = neighbors.insert_unique_unchecked(CompassDirection::North, &self.terrain[y + 1][x]);
_ = neighbors.insert_unique_unchecked(CompassDirection::NorthEast, (y + 1, x + 1)); _ = neighbors
} .insert_unique_unchecked(CompassDirection::NorthEast, &self.terrain[y + 1][east_x]);
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::West, &self.terrain[y][east_x]);
_ = neighbors.insert_unique_unchecked(CompassDirection::East, &self.terrain[y][west_x]);
if !south_edge { 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 neighbors
} }
#[must_use] #[must_use]
pub fn get_slant(&self, x: usize, y: usize) -> f32 { pub fn get_slant(&self, cell: &TerrainCell) -> f32 {
let neighbors = self.cell_neighbors(x, y); let neighbors = self.cell_neighbors(cell.x, cell.y);
let terrain = &self.terrain;
let mut west_altitude = f32::MIN; let mut west_altitude = 0.0;
if let Some(neighbor_coords) = neighbors.get(&CompassDirection::North) { let mut neighbor_count = 0u8;
west_altitude = f32::max(
west_altitude, if let Some(neighbor) = neighbors.get(&CompassDirection::North) {
terrain[neighbor_coords.0][neighbor_coords.1].altitude, west_altitude = f32::max(west_altitude, neighbor.altitude);
); neighbor_count += 1;
} }
if let Some(neighbor_coords) = neighbors.get(&CompassDirection::NorthWest) { if let Some(neighbor) = neighbors.get(&CompassDirection::NorthWest) {
west_altitude = f32::max( west_altitude = f32::max(west_altitude, neighbor.altitude);
west_altitude, neighbor_count += 1;
terrain[neighbor_coords.0][neighbor_coords.1].altitude,
);
} }
if let Some(neighbor_coords) = neighbors.get(&CompassDirection::West) { if let Some(neighbor) = neighbors.get(&CompassDirection::West) {
west_altitude = f32::max( west_altitude = f32::max(west_altitude, neighbor.altitude);
west_altitude, neighbor_count += 1;
terrain[neighbor_coords.0][neighbor_coords.1].altitude,
);
} }
west_altitude /= f32::from(neighbor_count);
neighbor_count = 0;
let mut east_altitude = f32::MIN; let mut east_altitude = f32::MIN;
if let Some(neighbor_coords) = neighbors.get(&CompassDirection::North) { if let Some(neighbor) = neighbors.get(&CompassDirection::North) {
east_altitude = f32::max( east_altitude = f32::max(east_altitude, neighbor.altitude);
east_altitude, neighbor_count += 1;
terrain[neighbor_coords.0][neighbor_coords.1].altitude,
);
} }
if let Some(neighbor_coords) = neighbors.get(&CompassDirection::NorthWest) { if let Some(neighbor) = neighbors.get(&CompassDirection::NorthWest) {
east_altitude = f32::max( east_altitude = f32::max(east_altitude, neighbor.altitude);
east_altitude, neighbor_count += 1;
terrain[neighbor_coords.0][neighbor_coords.1].altitude,
);
} }
if let Some(neighbor_coords) = neighbors.get(&CompassDirection::West) { if let Some(neighbor) = neighbors.get(&CompassDirection::West) {
east_altitude = f32::max( east_altitude = f32::max(east_altitude, neighbor.altitude);
east_altitude, neighbor_count += 1;
terrain[neighbor_coords.0][neighbor_coords.1].altitude,
);
} }
east_altitude /= f32::from(neighbor_count);
west_altitude - east_altitude west_altitude - east_altitude
} }
} }

View file

@ -175,31 +175,19 @@ impl WorldManager {
#[cfg(feature = "render")] #[cfg(feature = "render")]
#[must_use] #[must_use]
fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color { fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color {
if render_settings.view == WorldView::Biomes { let base_color = match render_settings.view {
return WorldManager::biome_color(cell); 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 mut red = base_color.r();
// let altitude_color = if self.contours { let mut green = base_color.g();
// WorldManager::altitude_contour_color(cell.altitude) let mut blue = base_color.b();
// } 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();
if render_settings.overlay_visible(&WorldOverlay::Rainfall) { if render_settings.overlay_visible(&WorldOverlay::Rainfall) {
layer_count += 1.0; normalizer += 1.0;
let rainfall_color = self.rainfall_contour_color(cell.rainfall); 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(); red += rainfall_color.r();
green += rainfall_color.g(); green += rainfall_color.g();
@ -207,20 +195,15 @@ impl WorldManager {
} }
if render_settings.overlay_visible(&WorldOverlay::Temperature) { if render_settings.overlay_visible(&WorldOverlay::Temperature) {
layer_count += 1.0; normalizer += 1.0;
let temperature_color = self.temperature_contour_color(cell.temperature); 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(); red += temperature_color.r();
green += temperature_color.g(); green += temperature_color.g();
blue += temperature_color.b(); 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")] // #[cfg(feature = "render")]
@ -280,19 +263,28 @@ impl WorldManager {
#[cfg(feature = "render")] #[cfg(feature = "render")]
#[must_use] #[must_use]
fn biome_color(cell: &TerrainCell) -> Color { fn biome_color(&self, cell: &TerrainCell) -> Color {
cell.biome_presences let slant = self.world().get_slant(cell);
.iter()
.fold(Color::BLACK, |color, (biome_type, presence)| {
let biome: BiomeStats = (*biome_type).into();
let biome_color = biome.color;
Color::rgb( let slant_factor = f32::min(1.0, (4.0 + (10.0 * slant / World::ALTITUDE_SPAN)) / 5.0);
color.r() + (biome_color.r() * presence), let altitude_factor = f32::min(
color.g() + (biome_color.g() * presence), 1.0,
color.b() + (biome_color.b() * presence), (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")] // #[cfg(feature = "render")]

View file

@ -5,4 +5,4 @@ pub(crate) use world_view_selection::WorldViewSelection;
mod world_overlay_selection; mod world_overlay_selection;
pub(crate) use world_overlay_selection::WorldOverlaySelection; pub(crate) use world_overlay_selection::WorldOverlaySelection;
mod save_load; mod save_load;
pub(crate) use save_load::SaveLoad; pub(crate) use save_load::SaveLoad;

View file

@ -24,9 +24,6 @@ impl WindowSystem for TileInfo<'_, '_> {
let cursor_position = world.resource::<CursorMapPosition>(); let cursor_position = world.resource::<CursorMapPosition>();
let cursor_y = cursor_position.y; let cursor_y = cursor_position.y;
let cursor_x = cursor_position.x; let cursor_x = cursor_position.x;
_ = ui.label("Coordinates");
_ = ui.label(cursor_position.to_string());
ui.end_row();
let world_manager = world.resource::<WorldManager>(); let world_manager = world.resource::<WorldManager>();
if cursor_x >= 0 if cursor_x >= 0
@ -39,8 +36,13 @@ impl WindowSystem for TileInfo<'_, '_> {
rainfall, rainfall,
temperature, temperature,
biome_presences, biome_presences,
x,
y,
} = &world_manager.world().terrain[cursor_y as usize][cursor_x as usize]; } = &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("Altitude");
_ = ui.label(format!("{altitude:.2}")); _ = ui.label(format!("{altitude:.2}"));
ui.end_row(); ui.end_row();