From 2092e02c807a1942ba5a8da7eca7b07307491498 Mon Sep 17 00:00:00 2001 From: AnthonyTornetta Date: Sun, 3 Sep 2023 22:59:58 -0400 Subject: [PATCH] Got lods to not rerender everything every time --- cosmos_client/src/rendering/lod_renderer.rs | 134 +++++------------- .../structure/planet/client_planet_builder.rs | 57 +------- cosmos_client/src/structure/planet/lod.rs | 2 - cosmos_client/src/structure/planet/mod.rs | 1 - cosmos_core/src/structure/lod.rs | 8 ++ .../structure/planet/lods/generate_lods.rs | 3 - 6 files changed, 46 insertions(+), 159 deletions(-) diff --git a/cosmos_client/src/rendering/lod_renderer.rs b/cosmos_client/src/rendering/lod_renderer.rs index 0776e8022..af39d7ea3 100644 --- a/cosmos_client/src/rendering/lod_renderer.rs +++ b/cosmos_client/src/rendering/lod_renderer.rs @@ -1,13 +1,13 @@ use std::{f32::consts::PI, sync::Mutex}; -use bevy::{pbr::NotShadowCaster, prelude::*, render::primitives::Aabb, utils::HashMap}; +use bevy::{prelude::*, render::primitives::Aabb, utils::HashMap}; use cosmos_core::{ block::{Block, BlockFace}, registry::{identifiable::Identifiable, many_to_one::ManyToOneRegistry, Registry}, structure::{ block_storage::BlockStorer, chunk::{CHUNK_DIMENSIONS, CHUNK_DIMENSIONSF}, - coordinates::{ChunkBlockCoordinate, ChunkCoordinate}, + coordinates::ChunkBlockCoordinate, lod::Lod, lod_chunk::LodChunk, Structure, @@ -423,11 +423,9 @@ fn find_non_dirty(lod: &Lod, offset: Vec3, to_process: &mut Vec, scale: f3 }); } Lod::Single(_, dirty) => { - if *dirty { - return; + if !*dirty { + to_process.push(offset); } - - to_process.push(offset); } }; } @@ -436,7 +434,6 @@ fn find_non_dirty(lod: &Lod, offset: Vec3, to_process: &mut Vec, scale: f3 fn monitor_lods_needs_rendered_system( mut commands: Commands, atlas: Res, - mesh_query: Query>>, mut meshes: ResMut>, blocks: Res>, materials: Res>, @@ -457,10 +454,8 @@ fn monitor_lods_needs_rendered_system( // Render lods in parallel todo.par_iter_mut().for_each(|(entity, lod, structure)| { - let scale = structure.chunk_dimensions().x as f32; - let mut non_dirty = vec![]; - find_non_dirty(lod, Vec3::ZERO, &mut non_dirty, scale); + find_non_dirty(lod, Vec3::ZERO, &mut non_dirty, structure.block_dimensions().x as f32); to_keep .lock() @@ -479,7 +474,7 @@ fn monitor_lods_needs_rendered_system( &materials, &meshes_registry, &block_textures, - scale, + structure.chunk_dimensions().x as f32, ); }); @@ -493,110 +488,53 @@ fn monitor_lods_needs_rendered_system( ent_meshes.get_mut(&entity).expect("Just added").push((chunk_mesh, offset)); } - for (entity, mut lod_meshes) in ent_meshes { - let mut old_mesh_entities = Vec::new(); + for (entity, lod_meshes) in ent_meshes { + let old_mesh_entities = chunk_meshes_query.get(entity).map(|x| x.0.clone()).unwrap_or_default(); let to_keep_locations = to_keep.lock().unwrap().take().unwrap_or_default(); let to_keep_locations = to_keep_locations.get(&entity); - if let Ok(chunk_meshes_component) = chunk_meshes_query.get(entity) { - for ent in chunk_meshes_component.0.iter() { - let old_mesh_handle = mesh_query.get(*ent).expect("This should have a mesh component."); - - if let Some(old_mesh_handle) = old_mesh_handle { - meshes.remove(old_mesh_handle); - } - - old_mesh_entities.push(*ent); - } - } - let mut entities_to_add = Vec::new(); - // If the structure previously only had one chunk mesh, then it would be on - // the structure entity instead of child entities - commands - .entity(entity) - .remove::>() - .remove::>(); - let mut structure_meshes_component = LodMeshes::default(); - let single = lod_meshes.len() == 1 && lod_meshes.first().map(|(x, _)| x.mesh_materials.len() == 1).unwrap_or(false); + for (lod_mesh, offset) in lod_meshes { + for mesh_material in lod_mesh.mesh_materials { + let mesh = meshes.add(mesh_material.mesh); - if !single { - for (lod_mesh, offset) in lod_meshes { - for mesh_material in lod_mesh.mesh_materials { - let mesh = meshes.add(mesh_material.mesh); + let s = (CHUNK_DIMENSIONS / 2) as f32 * lod_mesh.scale; - let s = (CHUNK_DIMENSIONS / 2) as f32 * lod_mesh.scale; - - let ent = if let Some(ent) = old_mesh_entities.pop() { - commands.entity(ent).insert(( - TransformBundle::from_transform(Transform::from_translation(offset)), + let ent = commands + .spawn(( + PbrBundle { mesh, - mesh_material.material, - // Remove this once https://github.com/bevyengine/bevy/issues/4294 is done (bevy 0.12 released) - Aabb::from_min_max(Vec3::new(-s, -s, -s), Vec3::new(s, s, s)), - )); - - ent - } else { - let s = (CHUNK_DIMENSIONS / 2) as f32 * lod_mesh.scale; - - let ent = commands - .spawn(( - PbrBundle { - mesh, - material: mesh_material.material, - transform: Transform::from_translation(offset), - ..Default::default() - }, - NotShadowCaster, - // Remove this once https://github.com/bevyengine/bevy/issues/4294 is done (bevy 0.12 released) - Aabb::from_min_max(Vec3::new(-s, -s, -s), Vec3::new(s, s, s)), - )) - .id(); - - entities_to_add.push(ent); - - ent - }; - - structure_meshes_component.0.push(ent); - } + material: mesh_material.material, + transform: Transform::from_translation(offset), + ..Default::default() + }, + // Remove this once https://github.com/bevyengine/bevy/issues/4294 is done (bevy 0.12 released) + Aabb::from_min_max(Vec3::new(-s, -s, -s), Vec3::new(s, s, s)), + )) + .id(); + + entities_to_add.push(ent); + + structure_meshes_component.0.push(ent); } - } else { - // To avoid making too many entities (and tanking performance), if only one mesh - // is present, just stick the mesh info onto the chunk itself. - - // offset (_) will always be Vec3::ZERO when there is just one - let (chunk_mesh, _) = &mut lod_meshes[0]; - let mesh_material = chunk_mesh.mesh_materials.pop().expect("This has one element in it"); - - let mesh = meshes.add(mesh_material.mesh); - let s = (CHUNK_DIMENSIONS / 2) as f32 * chunk_mesh.scale; - - commands.entity(entity).insert(( - mesh, - mesh_material.material, - NotShadowCaster, - // Remove this once https://github.com/bevyengine/bevy/issues/4294 is done (bevy 0.12 released) - Aabb::from_min_max(Vec3::new(-s, -s, -s), Vec3::new(s, s, s)), - )); } - // Any leftover entities are useless now, so kill them + // Any dirty entities are useless now, so kill them for mesh_entity in old_mesh_entities { - if let Ok(transform) = transform_query.get(mesh_entity) { - if to_keep_locations.map(|x| x.contains(&transform.translation)).unwrap_or(false) { - structure_meshes_component.0.push(mesh_entity); - continue; - } + let is_clean = transform_query + .get(mesh_entity) + .map(|transform| to_keep_locations.map(|x| x.contains(&transform.translation)).unwrap_or(false)) + .unwrap_or(false); + if is_clean { + structure_meshes_component.0.push(mesh_entity); + } else { + commands.entity(mesh_entity).despawn_recursive(); } - - commands.entity(mesh_entity).despawn_recursive(); } let mut entity_commands = commands.entity(entity); diff --git a/cosmos_client/src/structure/planet/client_planet_builder.rs b/cosmos_client/src/structure/planet/client_planet_builder.rs index 04d846871..3c2be0d39 100644 --- a/cosmos_client/src/structure/planet/client_planet_builder.rs +++ b/cosmos_client/src/structure/planet/client_planet_builder.rs @@ -1,26 +1,16 @@ //! Responsible for building planets for the client. -use bevy::{ - ecs::system::EntityCommands, - pbr::NotShadowCaster, - prelude::{ - shape::UVSphere, Added, App, Assets, Color, Commands, ComputedVisibility, Entity, Mesh, Query, Res, ResMut, StandardMaterial, - Update, Visibility, - }, -}; +use bevy::ecs::system::EntityCommands; use cosmos_core::{ physics::location::Location, - registry::Registry, structure::{ - planet::{biosphere::BiosphereMarker, planet_builder::PlanetBuilder, planet_builder::TPlanetBuilder, Planet}, + planet::{planet_builder::PlanetBuilder, planet_builder::TPlanetBuilder, Planet}, Structure, }, }; use crate::structure::client_structure_builder::ClientStructureBuilder; -use super::biosphere::BiosphereColor; - /// Responsible for building planets for the client. pub struct ClientPlanetBuilder { planet_builder: PlanetBuilder, @@ -39,46 +29,3 @@ impl TPlanetBuilder for ClientPlanetBuilder { self.planet_builder.insert_planet(entity, location, structure, planet); } } - -fn added_planet( - query: Query<(Entity, &Structure, &BiosphereMarker), Added>, - mut commands: Commands, - mut meshes: ResMut>, - mut materials: ResMut>, - color_registry: Res>, -) { - for (ent, structure, marker) in query.iter() { - let Structure::Dynamic(structure) = structure else { - panic!("Invalid planet structure! It must be dynamic!"); - }; - - let blocks_radius = structure.block_dimensions() as f32 / 2.0; - - commands.entity(ent).insert(( - meshes.add( - UVSphere { - radius: (blocks_radius * blocks_radius * 2.0).sqrt() * 1.1, - sectors: 128, - stacks: 128, - } - .into(), - ), - materials.add(StandardMaterial { - base_color: color_registry - .from_id(marker.biosphere_name()) - .map(|x| x.color()) - .unwrap_or(Color::WHITE), - - perceptual_roughness: 1.0, - ..Default::default() - }), - Visibility::default(), - ComputedVisibility::default(), - NotShadowCaster, - )); - } -} - -pub(super) fn register(app: &mut App) { - app.add_systems(Update, added_planet); -} diff --git a/cosmos_client/src/structure/planet/lod.rs b/cosmos_client/src/structure/planet/lod.rs index 478bba26e..38b330fed 100644 --- a/cosmos_client/src/structure/planet/lod.rs +++ b/cosmos_client/src/structure/planet/lod.rs @@ -32,9 +32,7 @@ fn listen_for_new_lods( if let Ok(mut cur_lod) = cur_lod { delta_lod.apply_changes(&mut cur_lod); } else { - println!("Creating delta: {delta_lod:?}"); ecmds.insert(delta_lod.create_lod()); - ecmds.log_components(); } } } diff --git a/cosmos_client/src/structure/planet/mod.rs b/cosmos_client/src/structure/planet/mod.rs index d3147a256..fb3deb196 100644 --- a/cosmos_client/src/structure/planet/mod.rs +++ b/cosmos_client/src/structure/planet/mod.rs @@ -136,7 +136,6 @@ pub fn unload_chunks_far_from_players( pub(super) fn register(app: &mut App) { align_player::register(app); - client_planet_builder::register(app); biosphere::register(app); lod::register(app); diff --git a/cosmos_core/src/structure/lod.rs b/cosmos_core/src/structure/lod.rs index c848e83d8..f131d5193 100644 --- a/cosmos_core/src/structure/lod.rs +++ b/cosmos_core/src/structure/lod.rs @@ -60,6 +60,10 @@ pub enum LodDelta { } impl LodDelta { + /// Creates an lod based off this delta. + /// + /// # Panics + /// if self contains any LodDelta::NoChange because these must have a corresponding lod. pub fn create_lod(self) -> Lod { match self { LodDelta::Children(children) => { @@ -88,6 +92,10 @@ impl LodDelta { } } + /// Applies the delta changes to a present lod + /// + /// # Panics + /// if self contains any LodDelta::NoChange and there is no matching lod for that. pub fn apply_changes(self, lod: &mut Lod) { match self { LodDelta::Children(children) => { diff --git a/cosmos_server/src/structure/planet/lods/generate_lods.rs b/cosmos_server/src/structure/planet/lods/generate_lods.rs index 69604a5bf..42efb399a 100644 --- a/cosmos_server/src/structure/planet/lods/generate_lods.rs +++ b/cosmos_server/src/structure/planet/lods/generate_lods.rs @@ -157,9 +157,6 @@ fn check_done_generating( let cloned_delta = lod_delta.clone(); if let Some(Ok(mut current_lod)) = current_lod { - println!("{lod_delta:?}"); - println!("=========================="); - println!("{current_lod:?}"); cloned_delta.apply_changes(&mut current_lod.lod); current_lod.deltas.push(lod_delta); } else {