diff --git a/.vscode/launch.json b/.vscode/launch.json index 476c68c..2c57237 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -14,12 +14,12 @@ "args": [], "cwd": "${workspaceRoot}/target/debug", "preLaunchTask": "Build", - "environment": [ - { - "name": "RUST_BACKTRACE", - "value": "1" - } - ] + // "environment": [ + // { + // "name": "RUST_BACKTRACE", + // "value": "1" + // } + // ] } ] } \ No newline at end of file diff --git a/engine/world_generation/src/chunk_colliders.rs b/engine/world_generation/src/chunk_colliders.rs index c5fc6d4..6d72be7 100644 --- a/engine/world_generation/src/chunk_colliders.rs +++ b/engine/world_generation/src/chunk_colliders.rs @@ -5,7 +5,7 @@ use bevy::prelude::*; const CHUNK_TOTAL: usize = Chunk::SIZE * Chunk::SIZE; -pub fn generate_chunk_collider(chunk: &Chunk, map: &Map) -> (Vec, Vec<[u32; 3]>) { +pub fn generate_chunk_collider(chunk: &MeshChunkData) -> (Vec, Vec<[u32; 3]>) { #[cfg(feature = "tracing")] let span = info_span!("generate_chunk_collider").entered(); let vertex_count: usize = CHUNK_TOTAL * 6; @@ -14,9 +14,8 @@ pub fn generate_chunk_collider(chunk: &Chunk, map: &Map) -> (Vec, Vec<[u32 for z in 0..Chunk::SIZE { for x in 0..Chunk::SIZE { let height = chunk.heights[x + z * Chunk::SIZE]; - let coord = - HexCoord::from_offset(IVec2::new(x as i32, z as i32) + (chunk.chunk_offset * Chunk::SIZE as i32)); - let neighbors = map.get_neighbors(&coord); + let coord = HexCoord::from_grid_pos(x, z); + let neighbors = chunk.get_neighbors(&coord); let off_pos = Vec3::new(x as f32, height, z as f32); let tile_pos = offset3d_to_world(off_pos); create_tile_collider(tile_pos, &mut verts, &mut indices, &neighbors); @@ -25,7 +24,7 @@ pub fn generate_chunk_collider(chunk: &Chunk, map: &Map) -> (Vec, Vec<[u32 return (verts, indices); } -fn create_tile_collider(pos: Vec3, verts: &mut Vec, indices: &mut Vec<[u32; 3]>, neighbors: &[Option; 6]) { +fn create_tile_collider(pos: Vec3, verts: &mut Vec, indices: &mut Vec<[u32; 3]>, neighbors: &[f32; 6]) { let idx = verts.len() as u32; for i in 0..6 { let p = pos + HEX_CORNERS[i]; @@ -39,20 +38,15 @@ fn create_tile_collider(pos: Vec3, verts: &mut Vec, indices: &mut Vec<[u32 indices.push([idx + 2, idx + 3, idx + 4]); for i in 0..neighbors.len() { - let cur_n = neighbors[i]; - match cur_n { - Some(n_height) => { - if n_height < pos.y { - create_tile_wall_collider( - idx, - Vec3::new(pos.x, n_height.min(pos.y - OUTER_RADIUS / 2.), pos.z), - i, - verts, - indices, - ); - } - } - _ => {} + let n_height = neighbors[i]; + if n_height < pos.y { + create_tile_wall_collider( + idx, + Vec3::new(pos.x, n_height.min(pos.y - OUTER_RADIUS / 2.), pos.z), + i, + verts, + indices, + ); } } } diff --git a/engine/world_generation/src/lib.rs b/engine/world_generation/src/lib.rs index ca084e0..d5edb9f 100644 --- a/engine/world_generation/src/lib.rs +++ b/engine/world_generation/src/lib.rs @@ -15,6 +15,7 @@ pub mod prelude { use bevy::render::mesh::MeshVertexAttribute; use bevy::render::render_resource::VertexFormat; use bevy_inspector_egui::InspectorOptions; + use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator}; pub const TEX_MULTI: Vec2 = Vec2::new(1000., 1.); pub const HEX_CORNERS: [Vec3; 6] = [ @@ -70,20 +71,20 @@ pub mod prelude { #[derive(Clone)] pub struct Chunk { - pub heights: [f32; Chunk::SIZE * Chunk::SIZE], - pub textures: [[u32; 2]; Chunk::SIZE * Chunk::SIZE], - pub moisture: [f32; Chunk::SIZE * Chunk::SIZE], - pub temperature: [f32; Chunk::SIZE * Chunk::SIZE], + pub heights: [f32; Chunk::AREA], + pub textures: [[u32; 2]; Chunk::AREA], + pub moisture: [f32; Chunk::AREA], + pub temperature: [f32; Chunk::AREA], pub chunk_offset: IVec2, } impl Default for Chunk { fn default() -> Self { Self { - heights: [0.; Chunk::SIZE * Chunk::SIZE], - textures: [[0; 2]; Chunk::SIZE * Chunk::SIZE], - moisture: [0.; Chunk::SIZE * Chunk::SIZE], - temperature: [0.; Chunk::SIZE * Chunk::SIZE], + heights: [0.; Chunk::AREA], + textures: [[0; 2]; Chunk::AREA], + moisture: [0.; Chunk::AREA], + temperature: [0.; Chunk::AREA], chunk_offset: Default::default(), } } @@ -91,9 +92,74 @@ pub mod prelude { impl Chunk { pub const SIZE: usize = 64; + pub const AREA: usize = Chunk::SIZE * Chunk::SIZE; pub const WORLD_WIDTH: f32 = Chunk::SIZE as f32 * SHORT_DIAGONAL; pub const WORLD_HEIGHT: f32 = Chunk::SIZE as f32 * 1.5; pub const WORLD_SIZE: Vec2 = Vec2::new(Chunk::WORLD_WIDTH, Chunk::WORLD_HEIGHT); + + pub fn get_pos_z_edge(&self) -> [f32; Chunk::SIZE] { + let mut data = [0.; Chunk::SIZE]; + + for x in 0..Chunk::SIZE { + let idx = x + (Chunk::SIZE - 1) * Chunk::SIZE; + data[x] = self.heights[idx]; + } + + return data; + } + + pub fn get_neg_z_edge(&self) -> [f32; Chunk::SIZE] { + let mut data = [0.; Chunk::SIZE]; + + for x in 0..Chunk::SIZE { + data[x] = self.heights[x]; + } + + return data; + } + + pub fn get_pos_x_edge(&self) -> [f32; Chunk::SIZE] { + let mut data = [0.; Chunk::SIZE]; + + for z in 0..Chunk::SIZE { + let idx = (Chunk::SIZE - 1) + z * Chunk::SIZE; + data[z] = self.heights[idx]; + } + + return data; + } + + pub fn get_neg_x_edge(&self) -> [f32; Chunk::SIZE] { + let mut data = [0.; Chunk::SIZE]; + + for z in 0..Chunk::SIZE { + let idx = z * Chunk::SIZE; + data[z] = self.heights[idx]; + } + + return data; + } + } + + pub struct MeshChunkData { + pub heights: [f32; Chunk::AREA], + pub textures: [[u32; 2]; Chunk::AREA], + } + + impl MeshChunkData { + pub fn get_neighbors(&self, coord: &HexCoord) -> [f32; 6] { + let mut data = [0.; 6]; + let n_tiles = coord.get_neighbors(); + for i in 0..6 { + let n = n_tiles[i]; + if !n.is_in_bounds(Chunk::SIZE, Chunk::SIZE) { + continue; + } + data[i] = self.heights[n.to_index(Chunk::SIZE)]; + } + + return data; + } } #[derive(Resource, Clone)] @@ -105,6 +171,17 @@ pub mod prelude { } impl Map { + pub fn get_chunk_mesh_data(&self, chunk_index: usize) -> MeshChunkData { + #[cfg(feature = "tracing")] + let _spawn_span = info_span!("Chunk Mesh Data").entered(); + let chunk = &self.chunks[chunk_index]; + + return MeshChunkData { + heights: chunk.heights.clone(), + textures: chunk.textures.clone(), + }; + } + pub fn get_neighbors(&self, pos: &HexCoord) -> [Option; 6] { let mut results: [Option; 6] = [None; 6]; let w = self.width * Chunk::SIZE; diff --git a/engine/world_generation/src/mesh_generator.rs b/engine/world_generation/src/mesh_generator.rs index 22ff1b3..17747d1 100644 --- a/engine/world_generation/src/mesh_generator.rs +++ b/engine/world_generation/src/mesh_generator.rs @@ -1,7 +1,4 @@ -use crate::biome_painter::BiomePainterAsset; use crate::hex_utils::HexCoord; -use crate::tile_manager::TileAsset; -use crate::tile_mapper::TileMapperAsset; use crate::{hex_utils::offset3d_to_world, prelude::*}; #[cfg(feature = "tracing")] use bevy::log::*; @@ -13,7 +10,7 @@ use bevy::{ }, }; -pub fn generate_chunk_mesh(chunk: &Chunk, map: &Map) -> Mesh { +pub fn generate_chunk_mesh(chunk: &MeshChunkData) -> Mesh { #[cfg(feature = "tracing")] let span = info_span!("generate_chunk_mesh").entered(); @@ -29,9 +26,8 @@ pub fn generate_chunk_mesh(chunk: &Chunk, map: &Map) -> Mesh { let height = chunk.heights[idx]; let off_pos = Vec3::new(x as f32, height, z as f32); let tile_pos = offset3d_to_world(off_pos); - let coord = - HexCoord::from_offset(IVec2::new(x as i32, z as i32) + (chunk.chunk_offset * Chunk::SIZE as i32)); - let n = map.get_neighbors(&coord); + let coord = HexCoord::from_grid_pos(x, z); + let n = chunk.get_neighbors(&coord); create_tile( tile_pos, @@ -60,7 +56,7 @@ pub fn generate_chunk_mesh(chunk: &Chunk, map: &Map) -> Mesh { fn create_tile( pos: Vec3, - neighbors: &[Option; 6], + neighbors: &[f32; 6], verts: &mut Vec, uvs: &mut Vec, indices: &mut Vec, @@ -91,14 +87,9 @@ fn create_tile( indices.push(idx + 4); for i in 0..neighbors.len() { - let cur_n = neighbors[i]; - match cur_n { - Some(n_height) => { - if n_height < pos.y { - create_tile_wall(pos, i, n_height, verts, uvs, indices, normals, side_tex_off); - } - } - _ => {} + let n_height = neighbors[i]; + if n_height < pos.y { + create_tile_wall(pos, i, n_height, verts, uvs, indices, normals, side_tex_off); } } } diff --git a/game/main/src/map_rendering/chunk_rebuild.rs b/game/main/src/map_rendering/chunk_rebuild.rs index fc9a0e1..65adbce 100644 --- a/game/main/src/map_rendering/chunk_rebuild.rs +++ b/game/main/src/map_rendering/chunk_rebuild.rs @@ -35,33 +35,31 @@ fn chunk_rebuilder( ) { let pool = AsyncComputeTaskPool::get(); - for (chunk, idx) in &chunk_query { + for (chunk_entity, idx) in &chunk_query { #[cfg(feature = "tracing")] let _spawn_span = info_span!("Rebuild Chunk").entered(); - let map: Map; - { - let _clone_span = info_span!("Clone").entered(); - map = heightmap.clone(); - } + let chunk_index = idx.index; + let chunk_data = heightmap.get_chunk_mesh_data(chunk_index); + let chunk_offset = heightmap.chunks[chunk_index].chunk_offset; let task = pool.spawn(async move { #[cfg(feature = "tracing")] let _spawn_span = info_span!("Rebuild Task").entered(); let mut queue = CommandQueue::default(); - let (mesh, collider_data, _, _) = prepare_chunk_mesh(&map.chunks[chunk_index], &map); + let (mesh, collider_data, _, _) = prepare_chunk_mesh(&chunk_data, chunk_offset, chunk_index); let c = Collider::trimesh_with_flags( collider_data.0, collider_data.1, TriMeshFlags::DELETE_DUPLICATE_TRIANGLES, ); queue.push(move |world: &mut World| { - world.entity_mut(chunk).insert(c).remove::(); + world.entity_mut(chunk_entity).insert(c).remove::(); }); return (queue, mesh); }); commands - .entity(chunk) + .entity(chunk_entity) .insert(ChunkRebuildTask { task }) .remove::(); } diff --git a/game/main/src/map_rendering/map_init.rs b/game/main/src/map_rendering/map_init.rs index ab591ef..d359fa7 100644 --- a/game/main/src/map_rendering/map_init.rs +++ b/game/main/src/map_rendering/map_init.rs @@ -4,7 +4,11 @@ use bevy::{asset::LoadState, pbr::ExtendedMaterial, prelude::*}; use bevy_inspector_egui::quick::ResourceInspectorPlugin; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use world_generation::{ - biome_painter::*, heightmap::generate_heightmap, hex_utils::SHORT_DIAGONAL, prelude::*, tile_manager::*, + biome_painter::*, + heightmap::generate_heightmap, + hex_utils::{offset_to_index, SHORT_DIAGONAL}, + prelude::*, + tile_manager::*, tile_mapper::*, }; @@ -214,7 +218,8 @@ fn spawn_map( .chunks .par_iter() .map(|chunk: &Chunk| { - return prepare_chunk_mesh_with_collider(chunk, &heightmap); + let index = offset_to_index(chunk.chunk_offset, heightmap.width); + return prepare_chunk_mesh_with_collider(&heightmap.get_chunk_mesh_data(index), chunk.chunk_offset, index); }) .collect(); diff --git a/game/main/src/utlis/chunk_utils.rs b/game/main/src/utlis/chunk_utils.rs index e8c8161..1a783bb 100644 --- a/game/main/src/utlis/chunk_utils.rs +++ b/game/main/src/utlis/chunk_utils.rs @@ -1,6 +1,11 @@ #[cfg(feature = "tracing")] use bevy::log::*; -use bevy::{asset::Assets, ecs::system::Res, math::Vec3, render::mesh::Mesh}; +use bevy::{ + asset::Assets, + ecs::system::Res, + math::{IVec2, Vec3}, + render::mesh::Mesh, +}; use bevy_rapier3d::geometry::{Collider, TriMeshFlags}; use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator}; use world_generation::{ @@ -8,7 +13,7 @@ use world_generation::{ chunk_colliders::generate_chunk_collider, hex_utils::{offset_to_index, offset_to_world}, mesh_generator::generate_chunk_mesh, - prelude::{Chunk, Map}, + prelude::{Chunk, Map, MeshChunkData}, tile_manager::TileAsset, tile_mapper::TileMapperAsset, }; @@ -44,22 +49,30 @@ pub fn paint_chunk( } } -pub fn prepare_chunk_mesh(chunk: &Chunk, heightmap: &Map) -> (Mesh, (Vec, Vec<[u32; 3]>), Vec3, usize) { +pub fn prepare_chunk_mesh( + chunk: &MeshChunkData, + chunk_offset: IVec2, + chunk_index: usize, +) -> (Mesh, (Vec, Vec<[u32; 3]>), Vec3, usize) { #[cfg(feature = "tracing")] let _gen_mesh = info_span!("Generate Chunk").entered(); - let mesh = generate_chunk_mesh(chunk, &heightmap); - let col_data = generate_chunk_collider(chunk, &heightmap); + let mesh = generate_chunk_mesh(chunk); + let col_data = generate_chunk_collider(chunk); return ( mesh, col_data, - offset_to_world(chunk.chunk_offset * Chunk::SIZE as i32, 0.), - offset_to_index(chunk.chunk_offset, heightmap.width), + offset_to_world(chunk_offset * Chunk::SIZE as i32, 0.), + chunk_index, ); } -pub fn prepare_chunk_mesh_with_collider(chunk: &Chunk, heightmap: &Map) -> (Mesh, Collider, Vec3, usize) { - let (mesh, (col_verts, col_indicies), pos, index) = prepare_chunk_mesh(chunk, heightmap); +pub fn prepare_chunk_mesh_with_collider( + chunk: &MeshChunkData, + chunk_offset: IVec2, + chunk_index: usize, +) -> (Mesh, Collider, Vec3, usize) { + let (mesh, (col_verts, col_indicies), pos, index) = prepare_chunk_mesh(chunk, chunk_offset, chunk_index); let collider: Collider; { #[cfg(feature = "tracing")]