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 height = height.ok_or_else(|| Error::missing_field("height"))?;
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"))?;
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 =

View file

@ -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<CompassDirection, (usize, usize)> {
pub fn cell_neighbors(&self, x: usize, y: usize) -> HashMap<CompassDirection, &TerrainCell> {
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
}
}

View file

@ -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")]

View file

@ -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;
pub(crate) use save_load::SaveLoad;

View file

@ -24,9 +24,6 @@ impl WindowSystem for TileInfo<'_, '_> {
let cursor_position = world.resource::<CursorMapPosition>();
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::<WorldManager>();
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();