Cache rendered maps
Plus some small tweaks
This commit is contained in:
parent
6cc04b48fd
commit
7d3e97da5a
4 changed files with 78 additions and 18 deletions
|
@ -32,7 +32,7 @@ impl From<BiomeType> for BiomeStats {
|
|||
BiomeType::IceCap => BiomeStats {
|
||||
name: "Ice Cap".into(),
|
||||
#[cfg(feature = "render")]
|
||||
color: Color::rgb_u8(253, 244, 235),
|
||||
color: Color::WHITE,
|
||||
min_altitude: World::MIN_ALTITUDE,
|
||||
max_altitude: World::MAX_ALTITUDE,
|
||||
min_rainfall: World::MIN_RAINFALL,
|
||||
|
|
|
@ -35,6 +35,7 @@ impl Display for CartesianError {
|
|||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn cartesian_coordinates(
|
||||
alpha: f32,
|
||||
mut beta: f32,
|
||||
|
@ -61,6 +62,7 @@ pub fn cartesian_coordinates(
|
|||
))
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn random_point_in_sphere(rng: &mut StdRng, radius: f32) -> Vec3A {
|
||||
// https://karthikkaranth.me/blog/generating-random-points-in-a-sphere/#better-choice-of-spherical-coordinates
|
||||
|
||||
|
@ -85,14 +87,19 @@ pub fn random_point_in_sphere(rng: &mut StdRng, radius: f32) -> Vec3A {
|
|||
)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
pub fn mix_values(a: f32, b: f32, weight_b: f32) -> f32 {
|
||||
(b * weight_b) + (a * (1.0 - weight_b))
|
||||
}
|
||||
|
||||
pub trait RepeatNum {
|
||||
#[must_use]
|
||||
fn repeat(self, length: Self) -> Self;
|
||||
}
|
||||
impl RepeatNum for f32 {
|
||||
#[inline(always)]
|
||||
#[must_use]
|
||||
fn repeat(self, length: f32) -> f32 {
|
||||
f32::clamp(self - (self / length).floor() * length, 0.0, length)
|
||||
}
|
||||
|
|
|
@ -233,6 +233,7 @@ fn update_gui(world: &mut World) {
|
|||
fn redraw_map(
|
||||
mut should_redraw: ResMut<ShouldRedraw>,
|
||||
world_manager: Res<WorldManager>,
|
||||
mut world_renderer: ResMut<WorldRenderer>,
|
||||
render_settings: Res<WorldRenderSettings>,
|
||||
mut images: ResMut<Assets<Image>>,
|
||||
mut map_sprite: Query<&mut Sprite>,
|
||||
|
@ -267,7 +268,7 @@ fn redraw_map(
|
|||
height: world.height,
|
||||
..default()
|
||||
});
|
||||
map_image.data = world_manager.map_color_bytes(render_settings);
|
||||
map_image.data = world_renderer.map_color_bytes(world_manager, render_settings);
|
||||
map_sprite.single_mut().custom_size = Some(Vec2 {
|
||||
x: (world.width * WORLD_SCALE as u32) as f32,
|
||||
y: (world.height * WORLD_SCALE as u32) as f32,
|
||||
|
@ -297,6 +298,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
.insert_resource(OpenedWindows::default())
|
||||
.insert_resource(WorldRenderSettings::default())
|
||||
.insert_resource(ShouldRedraw::default())
|
||||
.insert_resource(WorldRenderer::default())
|
||||
.add_startup_system(generate_graphics)
|
||||
.add_system(update_gui)
|
||||
.add_system(update_cursor_map_position)
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
use {
|
||||
crate::macros::iterable_enum_stringify,
|
||||
bevy::{
|
||||
asset::HandleId,
|
||||
prelude::{Color, Resource},
|
||||
utils::HashSet,
|
||||
},
|
||||
bevy::{asset::HandleId, prelude::*, utils::HashSet},
|
||||
planet::{BiomeStats, TerrainCell, World, WorldManager},
|
||||
};
|
||||
|
||||
|
@ -166,34 +162,89 @@ fn coastline_color(world: &World, cell: &TerrainCell) -> Color {
|
|||
COASTLINE_PALETTE[0]
|
||||
}
|
||||
}
|
||||
pub trait WorldRenderer {
|
||||
fn map_color_bytes(&self, render_settings: &WorldRenderSettings) -> Vec<u8>;
|
||||
fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color;
|
||||
|
||||
const CACHE_SIZE: usize =
|
||||
WorldOverlay::ITEM_COUNT * WorldOverlay::ITEM_COUNT * WorldView::ITEM_COUNT;
|
||||
|
||||
#[derive(Default, Resource)]
|
||||
pub struct WorldRenderer {
|
||||
cached_world_seed: u32,
|
||||
cache: [Option<Vec<u8>>; CACHE_SIZE],
|
||||
}
|
||||
impl WorldRenderer for WorldManager {
|
||||
|
||||
impl WorldRenderer {
|
||||
fn cache_index(render_settings: &WorldRenderSettings) -> usize {
|
||||
let view_num = match render_settings.view {
|
||||
WorldView::Biomes => 0,
|
||||
WorldView::Topography => 1,
|
||||
WorldView::Coastlines => 2,
|
||||
};
|
||||
let mut overlay_num = 0;
|
||||
for overlay in render_settings.visible_overlays.iter() {
|
||||
overlay_num |= match overlay {
|
||||
WorldOverlay::Temperature => 1,
|
||||
WorldOverlay::Rainfall => 2,
|
||||
};
|
||||
}
|
||||
#[cfg(feature = "logging")]
|
||||
debug!(overlay_num, view_num);
|
||||
(view_num << WorldOverlay::ITEM_COUNT) | overlay_num
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn map_color_bytes(&self, render_settings: &WorldRenderSettings) -> Vec<u8> {
|
||||
let Some(world) = self.get_world() else {
|
||||
pub fn map_color_bytes(
|
||||
&mut self,
|
||||
world_manager: &WorldManager,
|
||||
render_settings: &WorldRenderSettings,
|
||||
) -> Vec<u8> {
|
||||
let Some(world) = world_manager.get_world() else {
|
||||
return vec![];
|
||||
};
|
||||
world
|
||||
|
||||
let cache_index = WorldRenderer::cache_index(render_settings);
|
||||
#[cfg(feature = "logging")]
|
||||
debug!(cache_index);
|
||||
assert!(
|
||||
cache_index < CACHE_SIZE,
|
||||
"Generated cache index too large for render cache"
|
||||
);
|
||||
if world.seed != self.cached_world_seed {
|
||||
self.cache = default();
|
||||
self.cached_world_seed = world.seed;
|
||||
}
|
||||
if let Some(cached) = &self.cache[cache_index] {
|
||||
return cached.clone();
|
||||
}
|
||||
|
||||
let bytes: Vec<_> = world
|
||||
.terrain
|
||||
.iter()
|
||||
.rev()
|
||||
.flatten()
|
||||
.flat_map(|cell| {
|
||||
self.generate_color(cell, render_settings)
|
||||
self.generate_color(world_manager, cell, render_settings)
|
||||
.as_rgba_f32()
|
||||
.iter()
|
||||
.flat_map(|num| num.to_le_bytes())
|
||||
.collect::<Vec<u8>>()
|
||||
})
|
||||
.collect()
|
||||
.collect();
|
||||
let result = bytes.clone();
|
||||
self.cache[cache_index] = Some(bytes);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn generate_color(&self, cell: &TerrainCell, render_settings: &WorldRenderSettings) -> Color {
|
||||
let world = self.get_world().expect("No world in generate_color");
|
||||
pub fn generate_color(
|
||||
&self,
|
||||
world_manager: &WorldManager,
|
||||
cell: &TerrainCell,
|
||||
render_settings: &WorldRenderSettings,
|
||||
) -> Color {
|
||||
let world = world_manager
|
||||
.get_world()
|
||||
.expect("No world in generate_color");
|
||||
let base_color = match render_settings.view {
|
||||
WorldView::Biomes => biome_color(world, cell),
|
||||
WorldView::Topography => altitude_contour_color(world, cell.altitude),
|
||||
|
|
Loading…
Reference in a new issue