Skip to content

Commit

Permalink
garbage code
Browse files Browse the repository at this point in the history
  • Loading branch information
AnthonyTornetta committed Sep 3, 2023
1 parent 2d5f4f0 commit f078fc9
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 108 deletions.
83 changes: 73 additions & 10 deletions cosmos_client/src/rendering/lod_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ use cosmos_core::{
structure::{
block_storage::BlockStorer,
chunk::{CHUNK_DIMENSIONS, CHUNK_DIMENSIONSF},
coordinates::ChunkBlockCoordinate,
coordinates::{ChunkBlockCoordinate, ChunkCoordinate},
lod::Lod,
lod_chunk::LodChunk,
Structure,
},
utils::array_utils::expand,
};
use rayon::prelude::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
use rayon::prelude::{IndexedParallelIterator, IntoParallelRefMutIterator, ParallelIterator};

use crate::{
asset::asset_loading::{BlockTextureIndex, MainAtlas},
Expand Down Expand Up @@ -316,7 +316,7 @@ impl ChunkRenderer {
struct LodMeshes(Vec<Entity>);

fn recursively_process_lod(
lod: &Lod,
lod: &mut Lod,
offset: Vec3,
to_process: &Mutex<Option<Vec<(Entity, LodMesh, Vec3)>>>,
entity: Entity,
Expand All @@ -330,7 +330,7 @@ fn recursively_process_lod(
match lod {
Lod::None => {}
Lod::Children(children) => {
children.par_iter().enumerate().for_each(|(i, c)| {
children.par_iter_mut().enumerate().for_each(|(i, c)| {
let s4 = scale / 4.0;

let offset = match i {
Expand Down Expand Up @@ -359,7 +359,13 @@ fn recursively_process_lod(
);
});
}
Lod::Single(lod_chunk) => {
Lod::Single(lod_chunk, dirty) => {
if !*dirty {
return;
}

*dirty = false;

let mut renderer = ChunkRenderer::new();

renderer.render(
Expand Down Expand Up @@ -394,6 +400,38 @@ fn recursively_process_lod(
};
}

fn find_non_dirty(lod: &Lod, offset: Vec3, to_process: &mut Vec<Vec3>, scale: f32) {
match lod {
Lod::None => {}
Lod::Children(children) => {
children.iter().enumerate().for_each(|(i, c)| {
let s4 = scale / 4.0;

let offset = match i {
0 => offset + Vec3::new(-s4, -s4, -s4),
1 => offset + Vec3::new(-s4, -s4, s4),
2 => offset + Vec3::new(s4, -s4, s4),
3 => offset + Vec3::new(s4, -s4, -s4),
4 => offset + Vec3::new(-s4, s4, -s4),
5 => offset + Vec3::new(-s4, s4, s4),
6 => offset + Vec3::new(s4, s4, s4),
7 => offset + Vec3::new(s4, s4, -s4),
_ => unreachable!(),
};

find_non_dirty(c, offset, to_process, scale / 2.0);
});
}
Lod::Single(_, dirty) => {
if *dirty {
return;
}

to_process.push(offset);
}
};
}

/// Performance hot spot
fn monitor_lods_needs_rendered_system(
mut commands: Commands,
Expand All @@ -405,20 +443,34 @@ fn monitor_lods_needs_rendered_system(
meshes_registry: Res<BlockMeshRegistry>,
chunk_meshes_query: Query<&LodMeshes>,
block_textures: Res<Registry<BlockTextureIndex>>,
transform_query: Query<&Transform>,

lods_needed: Query<(Entity, &Lod, &Structure), Changed<Lod>>,
mut lods_needed: Query<(Entity, &mut Lod, &Structure), Changed<Lod>>,
) {
// by making the Vec an Option<Vec> I can take ownership of it later, which I cannot do with
// just a plain Mutex<Vec>.
// https://stackoverflow.com/questions/30573188/cannot-move-data-out-of-a-mutex
let to_process: Mutex<Option<Vec<(Entity, LodMesh, Vec3)>>> = Mutex::new(Some(Vec::new()));
let to_keep: Mutex<Option<HashMap<Entity, Vec<Vec3>>>> = Mutex::new(Some(HashMap::new()));

let todo = Vec::from_iter(lods_needed.iter());
let mut todo = Vec::from_iter(lods_needed.iter_mut());

// Render lods in parallel
todo.par_iter().for_each(|(entity, lod, structure)| {
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);

to_keep
.lock()
.expect("failed to lock mutex")
.as_mut()
.unwrap()
.insert(*entity, non_dirty);

recursively_process_lod(
lod,
lod.as_mut(),
Vec3::ZERO,
&to_process,
*entity,
Expand All @@ -427,7 +479,7 @@ fn monitor_lods_needs_rendered_system(
&materials,
&meshes_registry,
&block_textures,
structure.chunk_dimensions().x as f32,
scale,
);
});

Expand All @@ -444,6 +496,10 @@ fn monitor_lods_needs_rendered_system(
for (entity, mut lod_meshes) in ent_meshes {
let mut old_mesh_entities = Vec::new();

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.");
Expand Down Expand Up @@ -533,6 +589,13 @@ fn monitor_lods_needs_rendered_system(

// Any leftover 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;
}
}

commands.entity(mesh_entity).despawn_recursive();
}

Expand Down
30 changes: 24 additions & 6 deletions cosmos_client/src/structure/planet/lod.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,41 @@
use bevy::prelude::{in_state, App, Commands, IntoSystemConfigs, Res, ResMut, Update};
use bevy::prelude::{in_state, App, Commands, IntoSystemConfigs, Query, Res, ResMut, Update};
use bevy_renet::renet::RenetClient;
use cosmos_core::{
netty::{cosmos_encoder, NettyChannelServer},
structure::lod::{Lod, LodNetworkMessage},
structure::lod::{Lod, LodDelta, LodNetworkMessage},
};

use crate::{netty::mapping::NetworkMapping, state::game_state::GameState};

fn listen_for_new_lods(netty_mapping: Res<NetworkMapping>, mut client: ResMut<RenetClient>, mut commands: Commands) {
while let Some(message) = client.receive_message(NettyChannelServer::Lod) {
/// Note: this method will crash if the server sends 2 lod updates immediately, which could happen.
///
/// This should be updated to account for that. Perhaps send all deltas at once in a vec?
///
/// It will crash because it will insert the lod, but the query won't then return it for the next delta, which will rely on it
fn listen_for_new_lods(
netty_mapping: Res<NetworkMapping>,
mut lod_query: Query<&mut Lod>,
mut client: ResMut<RenetClient>,
mut commands: Commands,
) {
while let Some(message) = client.receive_message(NettyChannelServer::DeltaLod) {
let msg: LodNetworkMessage = cosmos_encoder::deserialize(&message).expect("Invalid LOD packet recieved from server!");

match msg {
LodNetworkMessage::SetLod(lod) => {
if let Some(structure_entity) = netty_mapping.client_from_server(&lod.structure) {
if let Some(mut ecmds) = commands.get_entity(structure_entity) {
let lod = cosmos_encoder::deserialize::<Lod>(&lod.serialized_lod).expect("Unable to deserialize lod");
let cur_lod = lod_query.get_mut(structure_entity);

ecmds.insert(lod);
let delta_lod = cosmos_encoder::deserialize::<LodDelta>(&lod.serialized_lod).expect("Unable to deserialize lod");

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();
}
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions cosmos_core/src/netty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ pub enum NettyChannelServer {
/// Used for asteroids
Asteroid,
/// Sending LOD information to the client
Lod,
DeltaLod,
}

/// Network channels that clients send to the server
Expand Down Expand Up @@ -82,7 +82,7 @@ impl From<NettyChannelServer> for u8 {
NettyChannelServer::Unreliable => 1,
NettyChannelServer::LaserCannonSystem => 2,
NettyChannelServer::Asteroid => 3,
NettyChannelServer::Lod => 4,
NettyChannelServer::DeltaLod => 4,
}
}
}
Expand Down Expand Up @@ -116,7 +116,7 @@ impl NettyChannelServer {
},
},
ChannelConfig {
channel_id: Self::Lod.into(),
channel_id: Self::DeltaLod.into(),
max_memory_usage_bytes: 5 * 1024 * 1024,
send_type: SendType::ReliableOrdered {
resend_time: Duration::from_millis(200),
Expand Down
103 changes: 101 additions & 2 deletions cosmos_core/src/structure/lod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,42 @@
//! Ways of displaying reduced-detail versions of dynamic structures
use std::backtrace::Backtrace;

use bevy::prelude::{Component, Entity};
use serde::{Deserialize, Serialize};

use super::lod_chunk::LodChunk;

#[derive(Serialize, Deserialize, Component, Debug)]
#[derive(Serialize, Deserialize, Component, Debug, Clone)]
/// Represents a reduced-detail version of a planet
pub enum Lod {
/// No Lod here - this means there should be an actual chunk here
None,
/// Represents a single chunk of blocks at any scale.
Single(Box<LodChunk>, bool),
/// Breaks a single cube into 8 sub-cubes.
///
/// The indicies of each cube follow a clockwise direction starting on the bottom-left-back
///
/// ```
/// +-----------+
/// / 5 6 /|
/// / 4 7 / |
/// +-----------+ |
/// | | |
/// | | +
/// | 1 2 | /
/// | 0 3 |/
/// +-----------+
/// ```
Children(Box<[Self; 8]>),
}

#[derive(Serialize, Deserialize, Component, Debug, Clone)]
/// Represents a change in the reduced-detail version of a planet
pub enum LodDelta {
/// Keep the current version of the lod
NoChange,
/// No Lod here - this means there should be an actual chunk here
None,
/// Represents a single chunk of blocks at any scale.
Expand All @@ -30,12 +59,82 @@ pub enum Lod {
Children(Box<[Self; 8]>),
}

impl LodDelta {
pub fn create_lod(self) -> Lod {
match self {
LodDelta::Children(children) => {
let [c0, c1, c2, c3, c4, c5, c6, c7] = *children;

Lod::Children(Box::new([
c0.create_lod(),
c1.create_lod(),
c2.create_lod(),
c3.create_lod(),
c4.create_lod(),
c5.create_lod(),
c6.create_lod(),
c7.create_lod(),
]))
}
LodDelta::None => Lod::None,
LodDelta::Single(chunk) => Lod::Single(chunk, true),
LodDelta::NoChange => {
// or forcibly capture the backtrace regardless of environment variable configuration
println!("Error backtrace: {}", Backtrace::force_capture());

// panic!("Cannot have no change with no lod given!");
Lod::None
}
}
}

pub fn apply_changes(self, lod: &mut Lod) {
match self {
LodDelta::Children(children) => {
let [c0, c1, c2, c3, c4, c5, c6, c7] = *children;

match lod {
Lod::Children(lod_children) => {
c0.apply_changes(&mut lod_children[0]);
c1.apply_changes(&mut lod_children[1]);
c2.apply_changes(&mut lod_children[2]);
c3.apply_changes(&mut lod_children[3]);
c4.apply_changes(&mut lod_children[4]);
c5.apply_changes(&mut lod_children[5]);
c6.apply_changes(&mut lod_children[6]);
c7.apply_changes(&mut lod_children[7]);
}
_ => {
*lod = Lod::Children(Box::new([
c0.create_lod(),
c1.create_lod(),
c2.create_lod(),
c3.create_lod(),
c4.create_lod(),
c5.create_lod(),
c6.create_lod(),
c7.create_lod(),
]));
}
}
}
LodDelta::None => {
*lod = Lod::None;
}
LodDelta::Single(chunk) => {
*lod = Lod::Single(chunk, true);
}
LodDelta::NoChange => {}
}
}
}

#[derive(Debug, Serialize, Deserialize)]
/// Sends an Lod to the client
pub struct SetLodMessage {
/// The structure this lod belongs to
pub structure: Entity,
/// The lod serialized
/// The LodDelta serialized
pub serialized_lod: Vec<u8>,
}

Expand Down
10 changes: 9 additions & 1 deletion cosmos_core/src/structure/lod_chunk.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Used to store the various blocks an Lod would be made of
use std::fmt::Debug;

use bevy::reflect::Reflect;
use serde::{Deserialize, Serialize};

Expand All @@ -14,12 +16,18 @@ use super::{
coordinates::ChunkBlockCoordinate,
};

#[derive(Debug, Reflect, Serialize, Deserialize, Clone)]
#[derive(Reflect, Serialize, Deserialize, Clone)]
/// A chunk that is scaled. The Lod's scale depends on the position in the octree and size of its structure.
///
/// Lods only function properly on structures whos sizes are powers of two.
pub struct LodChunk(BlockStorage);

impl Debug for LodChunk {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&format!("LodChunk (empty: {})", self.0.is_empty()))
}
}

impl LodChunk {
/// Creates a new Lod chunk
pub fn new() -> Self {
Expand Down
Loading

0 comments on commit f078fc9

Please sign in to comment.