Clean up figure cache models when necessary

Former-commit-id: 7653217b2f4c02f5c179e35907fa47c3526b2a2e
This commit is contained in:
timokoesters 2019-04-23 13:55:48 +02:00
parent df7a145bbc
commit 7baecff1f0
3 changed files with 57 additions and 37 deletions

View File

@ -48,7 +48,7 @@ use crate::{
}; };
pub struct FigureCache { pub struct FigureCache {
models: HashMap<Character, Model<FigurePipeline>>, models: HashMap<Character, (Model<FigurePipeline>, u64)>,
states: HashMap<EcsEntity, FigureState<CharacterSkeleton>>, states: HashMap<EcsEntity, FigureState<CharacterSkeleton>>,
} }
@ -61,11 +61,17 @@ impl FigureCache {
} }
pub fn get_or_create_model<'a>( pub fn get_or_create_model<'a>(
models: &'a mut HashMap<Character, Model<FigurePipeline>>, models: &'a mut HashMap<Character, (Model<FigurePipeline>, u64)>,
renderer: &mut Renderer, renderer: &mut Renderer,
tick: u64,
character: Character) character: Character)
-> &'a Model<FigurePipeline> { -> &'a (Model<FigurePipeline>, u64) {
models.entry(character).or_insert_with(|| { match models.get_mut(&character) {
Some((model, last_used)) => {
*last_used = tick;
}
None => {
models.insert(character, ({
let bone_meshes = [ let bone_meshes = [
Some(Self::load_head(character.head)), Some(Self::load_head(character.head)),
Some(Self::load_chest(character.chest)), Some(Self::load_chest(character.chest)),
@ -95,7 +101,16 @@ impl FigureCache {
}); });
renderer.create_model(&mesh).unwrap() renderer.create_model(&mesh).unwrap()
}) }, tick));
}
}
&models[&character]
}
pub fn clean(&mut self, tick: u64) {
// TODO: Don't hard-code this
self.models.retain(|_, (_, last_used)| *last_used + 60 > tick);
} }
fn load_mesh(filename: &'static str, position: Vec3<f32>) -> Mesh<FigurePipeline> { fn load_mesh(filename: &'static str, position: Vec3<f32>) -> Mesh<FigurePipeline> {
@ -191,17 +206,19 @@ impl FigureCache {
self.states.retain(|entity, _| ecs.entities().is_alive(*entity)); self.states.retain(|entity, _| ecs.entities().is_alive(*entity));
} }
pub fn render(&mut self, renderer: &mut Renderer, client: &Client, globals: &Consts<Globals>) { pub fn render(&mut self, renderer: &mut Renderer, client: &mut Client, globals: &Consts<Globals>) {
let tick = client.get_tick();
let ecs = client.state().ecs(); let ecs = client.state().ecs();
let models = &mut self.models; let models = &mut self.models;
for (entity, &character) in ( for (entity, &character) in (
&ecs.entities(), &ecs.entities(),
&ecs.read_storage::<comp::Character>(), &ecs.read_storage::<comp::Character>(),
).join() { ).join() {
let model = Self::get_or_create_model(models, renderer, character); let model = Self::get_or_create_model(models, renderer, tick, character);
let state = self.states.get(&entity).unwrap(); let state = self.states.get(&entity).unwrap();
renderer.render_figure( renderer.render_figure(
model, &model.0,
globals, globals,
&state.locals, &state.locals,
&state.bone_consts, &state.bone_consts,

View File

@ -139,10 +139,13 @@ impl Scene {
// Maintain the figures // Maintain the figures
self.figure_cache.maintain(renderer, client); self.figure_cache.maintain(renderer, client);
// Remove unused figures
self.figure_cache.clean(client.get_tick());
} }
/// Render the scene using the provided `Renderer` /// Render the scene using the provided `Renderer`
pub fn render(&mut self, renderer: &mut Renderer, client: &Client) { pub fn render(&mut self, renderer: &mut Renderer, client: &mut Client) {
// Render the skybox first (it appears over everything else so must be rendered first) // Render the skybox first (it appears over everything else so must be rendered first)
renderer.render_skybox( renderer.render_skybox(
&self.skybox.model, &self.skybox.model,

View File

@ -87,7 +87,7 @@ impl SessionState {
renderer.clear(BG_COLOR); renderer.clear(BG_COLOR);
// Render the screen using the global renderer // Render the screen using the global renderer
self.scene.render(renderer, &self.client.borrow()); self.scene.render(renderer, &mut self.client.borrow_mut());
// Draw the UI to the screen // Draw the UI to the screen
self.hud.render(renderer); self.hud.render(renderer);