Skip to content

Commit

Permalink
mrrp :3
Browse files Browse the repository at this point in the history
  • Loading branch information
TheFelidae committed Dec 15, 2024
1 parent 28cd4f4 commit 55c9b17
Show file tree
Hide file tree
Showing 7 changed files with 417 additions and 81 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ bevy_flycam = "*"
rand = "*"
noise = "0.9"
bevy_meshem = { git = "https://github.com/TheFelidae/Meshem.git" }
rayon = "1.5.1"
rayon = "1.5.1"
bevy_egui = "0.31.1"
egui = "*"
4 changes: 3 additions & 1 deletion src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use bevy::{
text::TextFont,
DefaultPlugins,
};
use bevy_egui::EguiPlugin;
use bevy_flycam::PlayerPlugin;
use bevy_meshem::prelude::{generate_voxel_mesh, Face::Top};

Expand Down Expand Up @@ -42,8 +43,9 @@ impl Runtime {
};
app.insert_resource(block_registry);

app.add_plugins(FpsOverlayPlugin::default());
// app.add_plugins(FpsOverlayPlugin::default());
app.add_plugins(renderer::WorldRenderer::default());
app.add_plugins(EguiPlugin);
app.add_systems(Startup, systems::startup::setup_camera);
app.add_systems(Startup, systems::test_scene::register);
app.add_systems(Startup, systems::test_scene::setup);
Expand Down
197 changes: 181 additions & 16 deletions src/client/renderer/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use std::sync::{Mutex, RwLock};

use bevy::{
app::{App, Plugin, Startup, Update},
asset::{AssetServer, Assets, Handle},
color::{palettes::css::WHEAT, Color},
math::Vec3,
pbr::{MeshMaterial3d, StandardMaterial},
prelude::{
AlphaMode, Camera3d, Commands, Component, Entity, EventWriter, Mesh, Mesh3d, Query, Res,
ResMut, Transform, With,
AlphaMode, Camera3d, Commands, Component, Entity, EventReader, EventWriter, Mesh, Mesh3d,
Query, Res, ResMut, Transform, With,
},
};
use bevy_meshem::{
Expand All @@ -17,12 +19,13 @@ use bevy_meshem::{
},
Dimensions, VoxelRegistry,
};
use rayon::iter::{IntoParallelIterator, ParallelIterator};

use crate::{
data::world::{World, WorldChunk, WorldChunkStatus, WorldChunkStorage},
game::{
registry::BlockRegistry,
world_generator::{GameWorld, GenerateWorldSignal},
world_generator::{ChunkDroppedEvent, ChunkGeneratedEvent, GameWorld, GenerateWorldSignal},
},
};

Expand Down Expand Up @@ -56,6 +59,7 @@ impl Plugin for WorldRenderer {
fn build(&self, app: &mut App) {
app.add_systems(Startup, sys_setup);
app.add_systems(Update, sys_update);
app.add_systems(Update, sys_on_chunk_generated);
}
}

Expand Down Expand Up @@ -101,7 +105,7 @@ fn sys_update(
world: Query<&GameWorld>,
mut request_world: EventWriter<GenerateWorldSignal>,
) {
let mut renderer = renderer.single_mut();
/*let mut renderer = renderer.single_mut();
let world = world.single();
let block_registry = block_registry.into_inner();
let camera_translation = camera.single().1.translation;
Expand All @@ -112,29 +116,36 @@ fn sys_update(
// Identify chunks out of render distance (plus 2 for buffer), and remove them
for mut chunk in render_chunks.iter_mut() {
if (chunk.1.position.0 - camera_grid_x).abs() > renderer.render_distance + 2
|| (chunk.1.position.1 - camera_grid_y).abs() > renderer.render_distance + 2
|| (chunk.1.position.2 - camera_grid_z).abs() > renderer.render_distance + 2
if (chunk.1.position.0 - camera_grid_x).abs() > renderer.render_distance + 16
|| (chunk.1.position.1 - camera_grid_y).abs() > renderer.render_distance + 16
|| (chunk.1.position.2 - camera_grid_z).abs() > renderer.render_distance + 16
{
commands.entity(chunk.0).despawn();
// Remove chunk from renderer
renderer.chunks.retain(|c| c.position != chunk.1.position);
}
}
let render_chunks = RwLock::new(render_chunks.iter_mut().collect::<Vec<_>>());
let meshes = RwLock::new(&mut meshes);
let commands = RwLock::new(&mut commands);
// Identify chunks that should be loaded in by x y z
for x in camera_grid_x - renderer.render_distance..camera_grid_x + renderer.render_distance {
for y in camera_grid_y - renderer.render_distance..camera_grid_y + renderer.render_distance
{
let par_iter = (-renderer.render_distance..renderer.render_distance).into_par_iter();
par_iter.for_each(|x| {
let par_iter = (-renderer.render_distance..renderer.render_distance).into_par_iter();
par_iter.for_each(|y| {
for z in
camera_grid_z - renderer.render_distance..camera_grid_z + renderer.render_distance
{
let mut found = false;
// Check if chunk is already loaded (in ECS)
for chunk in render_chunks.iter_mut() {
if chunk.1.position == (x, y, z) {
found = true;
break;
{
let render_chunks = render_chunks.read().unwrap();
// Check if chunk is already loaded (in ECS)
for chunk in render_chunks.iter() {
if chunk.1.position == (x, y, z) {
found = true;
break;
}
}
}
Expand All @@ -159,13 +170,14 @@ fn sys_update(
println!("Loaded chunk at {}, {}, {}", x, y, z);
// Introduce adjacent chunks

let mut meshes = meshes.write().unwrap();
let mesh = meshes.add(mesh);
let new_chunk = WorldRendererChunk {
position: (x, y, z),
mesh: mesh.clone(),
meta,
};
let mut commands = commands.write().unwrap();
commands.spawn((
Mesh3d(mesh),
Transform::from_translation(Vec3::new(
Expand All @@ -189,6 +201,159 @@ fn sys_update(
}
}
}
});
});*/
}

fn sys_on_chunk_generated(
mut commands: Commands,
mut ev_chunk_generated: EventReader<ChunkGeneratedEvent>,
data: ResMut<Assets<Mesh>>,
block_registry: Res<BlockRegistry>,
world: Query<&GameWorld>,
renderer: Query<&WorldRenderer>,
chunks: Query<(Entity, &mut WorldRendererChunk, &mut Mesh3d)>,
) {
let world = world.single();
let block_registry = block_registry.into_inner();
let mesh_registry = Mutex::new(data);
let commands = Mutex::new(commands);

let par_iter = ev_chunk_generated.par_read();
let adj_faces = [Bottom, Top, Left, Right, Forward, Back];
let adj_offsets = [
(0, -1, 0),
(0, 1, 0),
(-1, 0, 0),
(1, 0, 0),
(0, 0, 1),
(0, 0, -1),
];

par_iter.for_each(|event| {
let event = event;
let chunk = world.map.chunk_at(event.x, event.y, event.z);
let x = event.x;
let y = event.y;
let z = event.z;
match chunk {
WorldChunkStatus::Stored(stored) => {
let mut loaded = false;
{
let r = stored.read().unwrap();
loaded = r.is_loaded();
}
if loaded {
let r = stored.read().unwrap();
let r_arc = r.unwrap().clone();
let r_arc_3 = r_arc.read().unwrap();
let data = r_arc_3.data();
match mesh_grid(
(WorldChunk::SIZE, WorldChunk::SIZE, WorldChunk::SIZE),
&[],
data,
block_registry,
MeshingAlgorithm::Culling,
None,
) {
Some((mesh, meta)) => {
let mut mesh = mesh;
let mut meta = meta;

// Optimize mesh by introducing adjacent chunks
for i in 0..6 {
let offset = adj_offsets[i];
let face = adj_faces[i];
let adj_chunk =
world.map.chunk_at(x + offset.0, y + offset.1, z + offset.2);
match adj_chunk {
WorldChunkStatus::Stored(adj_stored) => {
let adj_r = adj_stored.read().unwrap();
if adj_r.is_loaded() {
let adj_r_arc = adj_r.unwrap().clone();
let adj_r_arc_3 = adj_r_arc.read().unwrap();
let adj_data = adj_r_arc_3.data();
introduce_adjacent_chunks(
block_registry,
&mut mesh,
&mut meta,
face,
adj_data,
);
}
}
_ => {}
}
}

// Optimize neighboring WorldRendererChunks by introducing this chunk
/* for i in 0..6 {
let offset = adj_offsets[i];
let face = adj_faces[i];
// Find WorldRendererChunk with the same position
for (entity, chunk, mesh) in chunks.iter() {
if chunk.position == (x + offset.0, y + offset.1, z + offset.2) {
// introduce_adjacent_chunks(
// block_registry,
// &mut mesh_registry.lock().unwrap().get_mut(mesh).unwrap(),
// &mut chunk.meta,
// face,
// data
// );
}
}
}*/

println!("Meshed chunk at {}, {}, {}", x, y, z);

let mesh = mesh_registry.lock().unwrap().add(mesh);
let mut commands = commands.lock().unwrap();
commands.spawn((
Mesh3d(mesh),
Transform::from_translation(Vec3::new(
x as f32 * WorldChunk::SIZE as f32,
y as f32 * WorldChunk::SIZE as f32,
z as f32 * WorldChunk::SIZE as f32,
)),
MeshMaterial3d(renderer.single().material.clone()),
WorldRendererChunk {
position: (x, y, z),
mesh: Handle::default(),
meta,
},
));
}
None => {}
}
}
}
WorldChunkStatus::Unloaded => {}
}
});
}

fn sys_on_chunk_dropped(
mut commands: Commands,
mut ev_chunk_dropped: EventReader<ChunkDroppedEvent>,
world: Query<&GameWorld>,
renderer: Query<&WorldRenderer>,
chunks: Query<(Entity, &WorldRendererChunk)>,
) {
let world = world.single();
let renderer = renderer.single();
// find all WorldRendererChunks that are in the dropped chunks
for event in ev_chunk_dropped.par_read() {
let event = event.0;
let chunk = world.map.chunk_at(event.x, event.y, event.z);
let x = event.x;
let y = event.y;
let z = event.z;

// Search for WorldRendererChunk with the same position
for (entity, chunk) in chunks.iter() {
if chunk.position == (x, y, z) {
commands.entity(entity).despawn();
}
}
}
}
Loading

0 comments on commit 55c9b17

Please sign in to comment.