Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
8228442
Add tallgrass texture/block definition
CuddlyBunion341 Mar 7, 2025
a8ef0c7
Refactor shared blocks (break serialization)
CuddlyBunion341 Mar 7, 2025
2d9fbfb
Update grass spawn rate
CuddlyBunion341 Mar 7, 2025
49784b8
Update client side block data representation
CuddlyBunion341 Mar 7, 2025
677ba20
Update client block represenation
CuddlyBunion341 Mar 8, 2025
fb45b6f
Make code compile again
CuddlyBunion341 Mar 8, 2025
e4ac51f
Fix linter
CuddlyBunion341 Mar 8, 2025
414350e
Fix panics, udpate colliders
CuddlyBunion341 Mar 8, 2025
9fd6984
Fix meshing
CuddlyBunion341 Mar 8, 2025
45fe0c8
Fix linter
CuddlyBunion341 Mar 8, 2025
f3af9fb
Refactor mesher
CuddlyBunion341 Mar 8, 2025
6b9c9f6
Add skip_terrain feature flag
CuddlyBunion341 Mar 8, 2025
2b99c2c
Impl get block positions
CuddlyBunion341 Mar 8, 2025
1af5ffe
Add handles for cross meshes, boilerplate for mesher
CuddlyBunion341 Mar 8, 2025
671bb70
Fix linter
CuddlyBunion341 Mar 8, 2025
522ac40
Update grass meshes
CuddlyBunion341 Mar 8, 2025
3350b0a
Fix linter
CuddlyBunion341 Mar 8, 2025
d9a21d9
Attempt add 2nd face
CuddlyBunion341 Mar 8, 2025
0e426fa
Fix face1
CuddlyBunion341 Mar 8, 2025
9fa2d7a
Fix Face2, linter
CuddlyBunion341 Mar 8, 2025
7697f16
Update normals
CuddlyBunion341 Mar 8, 2025
dddb991
Update grass material properties
CuddlyBunion341 Mar 8, 2025
c540744
Add grass slider
CuddlyBunion341 Mar 8, 2025
60e28b0
Make mesher more readable
CuddlyBunion341 Mar 8, 2025
1a66ca7
Update src/shared/chunk_serializer.rs
CuddlyBunion341 Mar 8, 2025
1b3dfe1
Update src/client/terrain/systems.rs
CuddlyBunion341 Mar 8, 2025
494671a
Refactor mesher
CuddlyBunion341 Mar 8, 2025
53fc448
Fix linter
CuddlyBunion341 Mar 8, 2025
1822949
Fix grass cleanup
CuddlyBunion341 Mar 8, 2025
3e530ac
Fix floating grass
CuddlyBunion341 Mar 8, 2025
b2dc458
Drastically improve performance by not instancing
CuddlyBunion341 Mar 9, 2025
2839670
Refactor materials :3
CuddlyBunion341 Mar 9, 2025
7c4495c
Refactor inline
CuddlyBunion341 Mar 9, 2025
b37d3f8
Refactor rename
CuddlyBunion341 Mar 9, 2025
74c2988
Update CHANGELOG.md
CuddlyBunion341 Mar 9, 2025
c8573bb
Fix block placing at chunk borders
CuddlyBunion341 Mar 9, 2025
92e34cf
Refactor rename mesher
CuddlyBunion341 Mar 9, 2025
60737df
Apply suggestions from code review
CuddlyBunion341 Mar 9, 2025
043808f
Apply suggestions from code review
CuddlyBunion341 Mar 9, 2025
8031577
Add test, fix padded check
CuddlyBunion341 Mar 9, 2025
595fab8
Reformat
CuddlyBunion341 Mar 9, 2025
6734257
Optimize grass generation
CuddlyBunion341 Mar 9, 2025
818d0d4
Refactor rename frequency
CuddlyBunion341 Mar 9, 2025
6db4279
Fix linter
CuddlyBunion341 Mar 9, 2025
4dad87e
Refactor
CuddlyBunion341 Mar 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Increase world size
- Fix issue where chunks were only serialized on the client
- Add feature flags for debug rendering
- Add grass

## 0.1.1

Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,5 @@ ortho_camera = []
lock_player = []
physics_debug = []
raycast_debug = []
skip_terrain = []
visual_debug = ["wireframe", "physics_debug", "raycast_debug"]
Binary file modified assets/textures/texture_atlas.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions src/client/collider/systems.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use terrain_util::client_block::block_properties;

use crate::prelude::*;

static COLLIDER_GRID_SIZE: u32 = 4;
Expand Down Expand Up @@ -56,7 +58,7 @@ pub fn handle_collider_update_events_system(

match block {
Some(block) => {
if block != BlockId::Air {
if block_properties(block).has_collider {
transform.translation = collider_position + COLLIDER_CUBOID_WIDTH / 2.0;
} else {
transform.translation = COLLIDER_RESTING_POSITION;
Expand Down Expand Up @@ -133,7 +135,7 @@ mod tests {
Vec3::new(1.0, 1.0, 1.0),
);
resource.insert_chunks(chunks);
resource.set_block(
resource.update_block(
Vec3 {
x: 6.0,
y: 7.0,
Expand Down
8 changes: 6 additions & 2 deletions src/client/player/systems/controller.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
use crate::prelude::*;

#[cfg(not(feature = "lock_player"))]
#[cfg(feature = "skip_terrain")]
const SPAWN_POINT: Vec3 = Vec3::new(0.0, 1.0, 0.0);

#[cfg(all(not(feature = "skip_terrain"), not(feature = "lock_player")))]
const SPAWN_POINT: Vec3 = Vec3::new(0.0, 64.0, 0.0);
#[cfg(feature = "lock_player")]

#[cfg(all(not(feature = "skip_terrain"), feature = "lock_player"))]
const SPAWN_POINT: Vec3 = Vec3::new(128.0, 96.0, -128.0);

pub fn setup_player_camera(mut commands: Commands) {
Expand Down
2 changes: 1 addition & 1 deletion src/client/player/systems/terrain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pub fn handle_block_update_events(
mut client: ResMut<RenetClient>,
) {
for event in block_update_events.read() {
chunk_manager.set_block(event.position, event.block);
chunk_manager.update_block(event.position, event.block);
info!("Block update message: {:?}", event.position);

chunk_mesh_update_events.send(terrain_events::ChunkMeshUpdateEvent {
Expand Down
26 changes: 21 additions & 5 deletions src/client/terrain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,30 @@ impl Plugin for TerrainPlugin {
fn build(&self, app: &mut App) {
info!("Building TerrainPlugin");
app.insert_resource(ChunkManager::new());
app.insert_resource(terrain_resources::SpawnAreaLoaded(false));
app.insert_resource(util::TextureManager::new());
app.insert_resource(resources::RenderMaterials::new());
app.add_event::<terrain_events::BlockUpdateEvent>();
app.add_event::<terrain_events::ChunkMeshUpdateEvent>();
app.add_event::<terrain_events::WorldRegenerateEvent>();
app.add_systems(Startup, terrain_systems::prepare_spawn_area_system);
app.add_systems(Startup, terrain_systems::generate_world_system);
app.add_systems(Update, terrain_systems::handle_chunk_mesh_update_events);
app.add_systems(Update, terrain_systems::handle_terrain_regeneration_events);
app.add_systems(Startup, terrain_systems::prepare_mesher_materials_system);
#[cfg(feature = "skip_terrain")]
{
app.insert_resource(terrain_resources::SpawnAreaLoaded(true));
app.add_systems(Startup, terrain_systems::generate_simple_ground_system);
}
#[cfg(not(feature = "skip_terrain"))]
{
app.insert_resource(terrain_resources::SpawnAreaLoaded(false));
app.add_systems(Startup, terrain_systems::prepare_spawn_area_system);
app.add_systems(Startup, terrain_systems::generate_world_system);
app.add_systems(
Update,
terrain_systems::handle_chunk_mesh_update_events_system,
);
app.add_systems(
Update,
terrain_systems::handle_terrain_regeneration_events_system,
);
}
}
}
21 changes: 21 additions & 0 deletions src/client/terrain/resources.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,24 @@ impl SpawnAreaLoaded {
resource.0
}
}

#[derive(Resource)]
pub struct RenderMaterials {
pub transparent_material: Option<Handle<StandardMaterial>>,
pub chunk_material: Option<Handle<StandardMaterial>>,
}

impl Default for RenderMaterials {
fn default() -> Self {
Self::new()
}
}

impl RenderMaterials {
pub fn new() -> RenderMaterials {
RenderMaterials {
transparent_material: None,
chunk_material: None,
}
}
}
178 changes: 118 additions & 60 deletions src/client/terrain/systems.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
use terrain_resources::RenderMaterials;
use terrain_util::create_cross_mesh_for_chunk;

use crate::prelude::*;

pub fn prepare_mesher_materials_system(
mut render_materials: ResMut<RenderMaterials>,
mut materials: ResMut<Assets<StandardMaterial>>,
asset_server: Res<AssetServer>,
) {
let texture_handle = obtain_texture_handle(&asset_server);

let material = create_transparent_material(texture_handle.clone());
render_materials.transparent_material = Some(materials.add(material));

let material = create_chunk_material(texture_handle);
render_materials.chunk_material = Some(materials.add(material));
}

pub fn generate_simple_ground_system(
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut commands: Commands,
) {
let mesh = Cuboid::new(64.0, 1.0, 64.0);

commands.spawn((
Mesh3d(meshes.add(mesh)),
MeshMaterial3d(materials.add(Color::srgba(1.0, 0.0, 1.0, 1.0))),
Name::new("Simple Ground Plane"),
));
}

pub fn prepare_spawn_area_system(mut client: ResMut<RenetClient>) {
info!("Sending chunk requests for spawn area");

Expand Down Expand Up @@ -38,16 +69,14 @@ pub fn generate_world_system(
});
}

#[allow(clippy::too_many_arguments)]
pub fn handle_chunk_mesh_update_events(
pub fn handle_chunk_mesh_update_events_system(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
chunk_manager: ResMut<ChunkManager>,
mut chunk_mesh_update_events: EventReader<terrain_events::ChunkMeshUpdateEvent>,
mut mesh_query: Query<(Entity, &terrain_components::ChunkMesh)>,
texture_manager: ResMut<terrain_util::TextureManager>,
materials: Res<RenderMaterials>,
) {
for event in chunk_mesh_update_events.read() {
info!(
Expand All @@ -64,11 +93,17 @@ pub fn handle_chunk_mesh_update_events(
}
add_chunk_objects(
&mut commands,
&asset_server,
&mut meshes,
&mut materials,
chunk,
&texture_manager,
&materials,
);
add_cross_objects(
&mut commands,
chunk,
&materials,
&texture_manager,
&mut meshes,
);
}
None => {
Expand All @@ -80,90 +115,113 @@ pub fn handle_chunk_mesh_update_events(

fn add_chunk_objects(
commands: &mut Commands,
asset_server: &Res<AssetServer>,
meshes: &mut ResMut<Assets<Mesh>>,
materials: &mut ResMut<Assets<StandardMaterial>>,
chunk: &Chunk,
texture_manager: &terrain_util::TextureManager,
materials: &RenderMaterials,
) {
if let Some(mesh) = create_chunk_mesh(chunk, texture_manager) {
let texture_handle = obtain_texture_handle(asset_server).clone();
let material = create_chunk_material(texture_handle, &mut ResMut::reborrow(materials));
spawn_chunk(
commands,
&mut ResMut::reborrow(meshes),
material,
mesh,
chunk,
);
if let Some(mesh) = terrain_util::create_chunk_mesh(chunk, texture_manager) {
let material = materials
.chunk_material
.clone()
.expect("Chunk material is loaded");

let meshes: &mut Mut<Assets<Mesh>> = &mut ResMut::reborrow(meshes);
commands.spawn((
Mesh3d(meshes.add(mesh)),
Transform::from_xyz(
chunk.position.x * CHUNK_SIZE as f32,
chunk.position.y * CHUNK_SIZE as f32,
chunk.position.z * CHUNK_SIZE as f32,
),
MeshMaterial3d(material),
player_components::Raycastable,
terrain_components::ChunkMesh {
key: [
chunk.position.x as i32,
chunk.position.y as i32,
chunk.position.z as i32,
],
},
Name::from("Transparent Chunk Mesh"),
));
}
}

fn create_chunk_mesh(
fn add_cross_objects(
commands: &mut Commands,
chunk: &Chunk,
materials: &RenderMaterials,
texture_manager: &terrain_util::TextureManager,
) -> Option<Mesh> {
terrain_util::create_chunk_mesh(chunk, texture_manager)
meshes: &mut ResMut<Assets<Mesh>>,
) {
if let Some(mesh) = create_cross_mesh_for_chunk(chunk, texture_manager) {
let mesh_handle = meshes.add(mesh);

commands.spawn((
Mesh3d(mesh_handle),
MeshMaterial3d(
materials
.transparent_material
.clone()
.expect("Transparent material exists"),
),
Transform::from_xyz(
chunk.position.x * CHUNK_SIZE as f32,
chunk.position.y * CHUNK_SIZE as f32,
chunk.position.z * CHUNK_SIZE as f32,
),
terrain_components::ChunkMesh {
key: [
chunk.position.x as i32,
chunk.position.y as i32,
chunk.position.z as i32,
],
},
));
}
}

fn create_transparent_material(texture_handle: Handle<Image>) -> StandardMaterial {
StandardMaterial {
perceptual_roughness: 1.0,
double_sided: true,
cull_mode: None,
reflectance: 0.0,
unlit: false,
specular_transmission: 0.0,
alpha_mode: AlphaMode::Mask(1.0),
base_color_texture: Some(texture_handle),
..default()
}
}

#[cfg(not(feature = "wireframe"))]
fn create_chunk_material(
texture_handle: Handle<Image>,
materials: &mut Mut<Assets<StandardMaterial>>,
) -> Handle<StandardMaterial> {
materials.add(StandardMaterial {
fn create_chunk_material(texture_handle: Handle<Image>) -> StandardMaterial {
StandardMaterial {
perceptual_roughness: 0.5,
reflectance: 0.0,
unlit: false,
specular_transmission: 0.0,
base_color_texture: Some(texture_handle),
..default()
})
}
}

#[cfg(feature = "wireframe")]
fn create_chunk_material(
_texture_handle: Handle<Image>,
materials: &mut Mut<Assets<StandardMaterial>>,
) -> Handle<StandardMaterial> {
materials.add(StandardMaterial {
fn create_chunk_material(_texture_handle: Handle<Image>) -> StandardMaterial {
StandardMaterial {
base_color: Color::srgba(0.0, 0.0, 0.0, 0.0),
alpha_mode: AlphaMode::Mask(0.5),
..default()
})
}
}

fn obtain_texture_handle(asset_server: &Res<AssetServer>) -> Handle<Image> {
asset_server.load("textures/texture_atlas.png")
}

fn spawn_chunk(
commands: &mut Commands,
meshes: &mut Mut<Assets<Mesh>>,
material: Handle<StandardMaterial>,
mesh: Mesh,
chunk: &Chunk,
) {
commands.spawn((
Mesh3d(meshes.add(mesh)),
Transform::from_xyz(
chunk.position.x * CHUNK_SIZE as f32,
chunk.position.y * CHUNK_SIZE as f32,
chunk.position.z * CHUNK_SIZE as f32,
),
MeshMaterial3d(material),
player_components::Raycastable,
terrain_components::ChunkMesh {
key: [
chunk.position.x as i32,
chunk.position.y as i32,
chunk.position.z as i32,
],
},
));
}

pub fn handle_terrain_regeneration_events(
pub fn handle_terrain_regeneration_events_system(
mut client: ResMut<RenetClient>,
mut world_regenerate_events: EventReader<terrain_events::WorldRegenerateEvent>,
chunk_manager: ResMut<ChunkManager>,
Expand Down
Loading