From a933ef791b82d0f1c01d0018e23b0b45b2797255 Mon Sep 17 00:00:00 2001 From: Amatsugu Date: Tue, 30 Apr 2024 22:35:23 -0400 Subject: [PATCH] cleanup tried and failed to use convex colliders --- .vscode/launch.json | 8 +- .../world_generation/src/chunk_colliders.rs | 79 +++++++ engine/world_generation/src/lib.rs | 1 + engine/world_generation/src/mesh_generator.rs | 71 ------ game/main/src/main.rs | 1 + game/main/src/map_init.rs | 198 +++++++++++++++++ game/main/src/phos.rs | 210 +----------------- game/main/src/prelude.rs | 1 - 8 files changed, 297 insertions(+), 272 deletions(-) create mode 100644 engine/world_generation/src/chunk_colliders.rs create mode 100644 game/main/src/map_init.rs diff --git a/.vscode/launch.json b/.vscode/launch.json index 4243aed..2c57237 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -13,7 +13,13 @@ "program": "${workspaceRoot}/target/debug/phos.exe", "args": [], "cwd": "${workspaceRoot}/target/debug", - "preLaunchTask": "Build" + "preLaunchTask": "Build", + // "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 new file mode 100644 index 0000000..fdbadfe --- /dev/null +++ b/engine/world_generation/src/chunk_colliders.rs @@ -0,0 +1,79 @@ +use bevy::prelude::*; + +use crate::{hex_utils::*, prelude::*}; + +const CHUNK_TOTAL: usize = Chunk::SIZE * Chunk::SIZE; + + +pub fn generate_chunk_collider(chunk: &Chunk, map: &Map) -> (Vec, Vec<[u32; 3]>) { + let vertex_count: usize = CHUNK_TOTAL * 6; + let mut verts = Vec::with_capacity(vertex_count); + let mut indices = Vec::with_capacity(vertex_count); + 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 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); + } + } + return (verts, indices); +} + +fn create_tile_collider( + pos: Vec3, + verts: &mut Vec, + indices: &mut Vec<[u32; 3]>, + neighbors: &[Option; 6], +) { + let idx = verts.len() as u32; + for i in 0..6 { + let p = pos + HEX_CORNERS[i]; + verts.push(p); + } + for i in 0..3 { + let off = i * 2; + indices.push([off + idx, ((off + 1) % 6) + idx, ((off + 2) % 6) + idx]); + } + + indices.push([idx, idx + 2, 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, pos.z), + i, + verts, + indices, + ); + } + } + _ => {} + } + } +} + +fn create_tile_wall_collider( + idx: u32, + pos: Vec3, + dir: usize, + verts: &mut Vec, + indices: &mut Vec<[u32; 3]>, +) { + let idx2 = verts.len() as u32; + + verts.push(pos + HEX_CORNERS[dir]); + verts.push(pos + HEX_CORNERS[(dir + 1) % 6]); + + let off = dir as u32; + indices.push([idx + off, idx + ((off + 1) % 6), idx2 + 1]); + indices.push([idx + off, idx2 + 1, idx2]); +} diff --git a/engine/world_generation/src/lib.rs b/engine/world_generation/src/lib.rs index e67fd94..c31089f 100644 --- a/engine/world_generation/src/lib.rs +++ b/engine/world_generation/src/lib.rs @@ -1,4 +1,5 @@ pub mod biome_painter; +pub mod chunk_colliders; pub mod heightmap; pub mod hex_utils; pub mod mesh_generator; diff --git a/engine/world_generation/src/mesh_generator.rs b/engine/world_generation/src/mesh_generator.rs index f25480c..4ea2e27 100644 --- a/engine/world_generation/src/mesh_generator.rs +++ b/engine/world_generation/src/mesh_generator.rs @@ -11,78 +11,7 @@ use bevy::{ }, }; -pub fn generate_chunk_collider(chunk: &Chunk, map: &Map) -> (Vec, Vec<[u32; 3]>) { - let vertex_count: usize = Chunk::SIZE * Chunk::SIZE * 6; - let mut verts = Vec::with_capacity(vertex_count); - let mut indices = Vec::with_capacity(vertex_count); - 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 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); - } - } - return (verts, indices); -} -fn create_tile_collider( - pos: Vec3, - verts: &mut Vec, - indices: &mut Vec<[u32; 3]>, - neighbors: &[Option; 6], -) { - let idx = verts.len() as u32; - for i in 0..6 { - let p = pos + HEX_CORNERS[i]; - verts.push(p); - } - for i in 0..3 { - let off = i * 2; - indices.push([off + idx, ((off + 1) % 6) + idx, ((off + 2) % 6) + idx]); - } - - indices.push([idx, idx + 2, 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, pos.z), - i, - verts, - indices, - ); - } - } - _ => {} - } - } -} - -fn create_tile_wall_collider( - idx: u32, - pos: Vec3, - dir: usize, - verts: &mut Vec, - indices: &mut Vec<[u32; 3]>, -) { - let idx2 = verts.len() as u32; - - verts.push(pos + HEX_CORNERS[dir]); - verts.push(pos + HEX_CORNERS[(dir + 1) % 6]); - - let off = dir as u32; - indices.push([idx + off, idx + ((off + 1) % 6), idx2 + 1]); - indices.push([idx + off, idx2 + 1, idx2]); -} pub fn generate_chunk_mesh( chunk: &Chunk, diff --git a/game/main/src/main.rs b/game/main/src/main.rs index 3382061..c4c5552 100644 --- a/game/main/src/main.rs +++ b/game/main/src/main.rs @@ -4,6 +4,7 @@ use bevy::render::texture::{ImageAddressMode, ImageFilterMode, ImageSamplerDescr use bevy::window::PresentMode; use bevy_inspector_egui::quick::WorldInspectorPlugin; +mod map_init; mod phos; mod prelude; mod shader_extensions; diff --git a/game/main/src/map_init.rs b/game/main/src/map_init.rs new file mode 100644 index 0000000..0d7d68a --- /dev/null +++ b/game/main/src/map_init.rs @@ -0,0 +1,198 @@ +use bevy::{asset::LoadState, pbr::ExtendedMaterial, prelude::*}; +use bevy_rapier3d::geometry::Collider; +use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; +use world_generation::{ + biome_painter::*, chunk_colliders::generate_chunk_collider, heightmap::generate_heightmap, + hex_utils::offset_to_world, mesh_generator::generate_chunk_mesh, prelude::*, tile_manager::*, + tile_mapper::*, +}; + +use crate::{ + prelude::{ChunkAtlas, PhosChunk, PhosMap}, + shader_extensions::chunk_material::ChunkMaterial, +}; + +pub struct MapInitPlugin; + +impl Plugin for MapInitPlugin { + fn build(&self, app: &mut App) { + app.add_systems(Startup, init_map) + .add_systems(Startup, (load_textures, load_tiles, create_map).chain()); + + app.add_systems(Update, (finalize_texture, spawn_map)); + } +} + +fn init_map(mut commands: Commands) { + commands.insert_resource(PhosMap::default()); + commands.insert_resource(TileManager::default()); +} + +fn load_textures(mut commands: Commands, asset_server: Res) { + let main_tex = asset_server.load("textures/world/stack.png"); + commands.insert_resource(ChunkAtlas { + handle: main_tex.clone(), + is_loaded: false, + }); +} +#[derive(Resource)] +struct Painter(Handle); + +fn load_tiles(mut commands: Commands, asset_server: Res) { + let handle: Handle = asset_server.load("biome_painters/terra.biomes.json"); + commands.insert_resource(Painter(handle)); +} + +fn finalize_texture( + asset_server: Res, + mut atlas: ResMut, + mut map: ResMut, + mut images: ResMut>, + painter: Res, + painter_load: Res, + tile_load: Res, + mapper_load: Res, +) { + if atlas.is_loaded { + return; + } + + if !painter_load.is_all_loaded() || !tile_load.is_all_loaded() || !mapper_load.is_all_loaded() { + return; + } + + if asset_server.load_state(atlas.handle.clone()) != LoadState::Loaded { + return; + } + if asset_server.load_state(painter.0.clone()) != LoadState::Loaded { + return; + } + let image = images.get_mut(&atlas.handle).unwrap(); + + let array_layers = 14; + image.reinterpret_stacked_2d_as_array(array_layers); + + atlas.is_loaded = true; + map.ready = true; + map.regenerate = true; +} + +fn create_map(mut commands: Commands) { + let heightmap = generate_heightmap( + &GenerationConfig { + layers: vec![ + GeneratorLayer { + base_roughness: 2.14, + roughness: 0.87, + strength: 2.93, + min_value: -0.2, + persistence: 0.77, + is_rigid: false, + weight: 0., + weight_multi: 0., + layers: 4, + first_layer_mask: false, + }, + GeneratorLayer { + base_roughness: 2.85, + roughness: 2., + strength: -0.23, + min_value: -0., + persistence: 1., + is_rigid: false, + weight: 0., + weight_multi: 0., + layers: 4, + first_layer_mask: false, + }, + GeneratorLayer { + base_roughness: 2.6, + roughness: 4., + strength: 10.44, + min_value: 0., + persistence: 1.57, + is_rigid: true, + weight: 1., + weight_multi: 0.35, + layers: 4, + first_layer_mask: true, + }, + GeneratorLayer { + base_roughness: 3.87, + roughness: 5.8, + strength: -1., + min_value: 0., + persistence: 0., + is_rigid: true, + weight: 1., + weight_multi: 4.57, + layers: 3, + first_layer_mask: true, + }, + ], + noise_scale: 350., + sea_level: 4., + border_size: 64., + size: UVec2::splat(1024 / Chunk::SIZE as u32), + // size: UVec2::splat(1), + }, + 4, + ); + + commands.insert_resource(heightmap); +} + +fn spawn_map( + heightmap: Res, + mut commands: Commands, + mut materials: ResMut>>, + mut meshes: ResMut>, + atlas: Res, + mut map: ResMut, + tile_assets: Res>, + tile_mappers: Res>, + biome_painters: Res>, + painter: Res, +) { + if !map.ready || !map.regenerate { + return; + } + let b_painter = biome_painters.get(painter.0.clone()); + map.regenerate = false; + let chunk_material = materials.add(ExtendedMaterial { + base: StandardMaterial::default(), + extension: ChunkMaterial { + array_texture: atlas.handle.clone(), + }, + }); + + let cur_painter = b_painter.unwrap(); + + let chunk_meshes: Vec<_> = heightmap + .chunks + .par_iter() + .map(|chunk: &Chunk| { + let mesh = + generate_chunk_mesh(chunk, &heightmap, cur_painter, &tile_assets, &tile_mappers); + let collision = generate_chunk_collider(chunk, &heightmap); + return ( + mesh, + collision, + offset_to_world(chunk.chunk_offset * Chunk::SIZE as i32, 0.), + ); + }) + .collect(); + + for (mesh, (col_verts, col_indicies), pos) in chunk_meshes { + commands.spawn(( + MaterialMeshBundle { + mesh: meshes.add(mesh), + material: chunk_material.clone(), + transform: Transform::from_translation(pos), + ..default() + }, + PhosChunk, + Collider::trimesh(col_verts, col_indicies), + )); + } +} diff --git a/game/main/src/phos.rs b/game/main/src/phos.rs index f2c335d..9999918 100644 --- a/game/main/src/phos.rs +++ b/game/main/src/phos.rs @@ -1,53 +1,37 @@ +use crate::map_init::MapInitPlugin; use crate::prelude::*; use crate::shader_extensions::chunk_material::ChunkMaterial; -use bevy::asset::LoadState; -use bevy::pbr::{ExtendedMaterial, PbrPlugin}; +use bevy::pbr::ExtendedMaterial; use bevy::{ pbr::{wireframe::WireframeConfig, CascadeShadowConfig}, prelude::*, }; use bevy_rapier3d::dynamics::{RigidBody, Velocity}; -use bevy_rapier3d::geometry::{Collider, Restitution}; +use bevy_rapier3d::geometry::Collider; use bevy_rapier3d::plugin::{NoUserData, RapierPhysicsPlugin}; -use bevy_rapier3d::render::RapierDebugRenderPlugin; use camera_system::prelude::PhosCamera; use camera_system::PhosCameraPlugin; use iyes_perf_ui::prelude::*; -use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; -use world_generation::biome_painter::{ - BiomePainterAsset, BiomePainterLoadState, BiomePainterPlugin, -}; -use world_generation::hex_utils::offset_to_world; -use world_generation::mesh_generator::generate_chunk_collider; -use world_generation::tile_manager::{TileAsset, TileAssetLoadState, TileAssetPlugin, TileManager}; -use world_generation::tile_mapper::{TileMapperAsset, TileMapperAssetPlugin, TileMapperLoadState}; -use world_generation::{ - heightmap::generate_heightmap, mesh_generator::generate_chunk_mesh, prelude::*, -}; +use world_generation::biome_painter::BiomePainterPlugin; +use world_generation::prelude::*; +use world_generation::tile_manager::TileAssetPlugin; +use world_generation::tile_mapper::TileMapperAssetPlugin; pub struct PhosGamePlugin; impl Plugin for PhosGamePlugin { fn build(&self, app: &mut App) { app.add_plugins(PhosCameraPlugin) + .add_plugins(MapInitPlugin) .add_plugins(MaterialPlugin::< ExtendedMaterial, >::default()); //Systems - Startup - app.add_systems(Startup, init_game) - .add_systems(Startup, (load_textures, load_tiles, create_map).chain()); + app.add_systems(Startup, init_game); //Systems - Update - app.add_systems( - Update, - ( - finalize_texture, - spawn_map, - spawn_sphere, - render_distance_system, - ), - ); + app.add_systems(Update, (spawn_sphere, render_distance_system)); //Perf UI app.add_plugins(bevy::diagnostic::FrameTimeDiagnosticsPlugin) @@ -85,16 +69,13 @@ fn init_game(mut commands: Commands, mut materials: ResMut) { - let main_tex = asset_server.load("textures/world/stack.png"); - commands.insert_resource(ChunkAtlas { - handle: main_tex.clone(), - is_loaded: false, - }); -} -#[derive(Resource)] -struct Painter(Handle); - -fn load_tiles(mut commands: Commands, asset_server: Res) { - let handle: Handle = asset_server.load("biome_painters/terra.biomes.json"); - commands.insert_resource(Painter(handle)); -} - -fn finalize_texture( - asset_server: Res, - mut atlas: ResMut, - mut map: ResMut, - mut images: ResMut>, - painter: Res, - painter_load: Res, - tile_load: Res, - mapper_load: Res, -) { - if atlas.is_loaded { - return; - } - - if !painter_load.is_all_loaded() || !tile_load.is_all_loaded() || !mapper_load.is_all_loaded() { - return; - } - - if asset_server.load_state(atlas.handle.clone()) != LoadState::Loaded { - return; - } - if asset_server.load_state(painter.0.clone()) != LoadState::Loaded { - return; - } - let image = images.get_mut(&atlas.handle).unwrap(); - - let array_layers = 14; - image.reinterpret_stacked_2d_as_array(array_layers); - - atlas.is_loaded = true; - map.ready = true; - map.regenerate = true; -} - -fn create_map(mut commands: Commands) { - let heightmap = generate_heightmap( - &GenerationConfig { - layers: vec![ - GeneratorLayer { - base_roughness: 2.14, - roughness: 0.87, - strength: 2.93, - min_value: -0.2, - persistence: 0.77, - is_rigid: false, - weight: 0., - weight_multi: 0., - layers: 4, - first_layer_mask: false, - }, - GeneratorLayer { - base_roughness: 2.85, - roughness: 2., - strength: -0.23, - min_value: -0., - persistence: 1., - is_rigid: false, - weight: 0., - weight_multi: 0., - layers: 4, - first_layer_mask: false, - }, - GeneratorLayer { - base_roughness: 2.6, - roughness: 4., - strength: 10.44, - min_value: 0., - persistence: 1.57, - is_rigid: true, - weight: 1., - weight_multi: 0.35, - layers: 4, - first_layer_mask: true, - }, - GeneratorLayer { - base_roughness: 3.87, - roughness: 5.8, - strength: -1., - min_value: 0., - persistence: 0., - is_rigid: true, - weight: 1., - weight_multi: 4.57, - layers: 3, - first_layer_mask: true, - }, - ], - noise_scale: 350., - sea_level: 4., - border_size: 64., - size: UVec2::splat(1024 / Chunk::SIZE as u32), - // size: UVec2::splat(1), - }, - 4, - ); - - commands.insert_resource(heightmap); -} - -fn spawn_map( - heightmap: Res, - mut commands: Commands, - mut materials: ResMut>>, - mut meshes: ResMut>, - atlas: Res, - mut map: ResMut, - tile_assets: Res>, - tile_mappers: Res>, - biome_painters: Res>, - painter: Res, -) { - if !map.ready || !map.regenerate { - return; - } - let b_painter = biome_painters.get(painter.0.clone()); - map.regenerate = false; - let chunk_material = materials.add(ExtendedMaterial { - base: StandardMaterial::default(), - extension: ChunkMaterial { - array_texture: atlas.handle.clone(), - }, - }); - - let cur_painter = b_painter.unwrap(); - - let chunk_meshes: Vec<_> = heightmap - .chunks - .par_iter() - .map(|chunk: &Chunk| { - let mesh = - generate_chunk_mesh(chunk, &heightmap, cur_painter, &tile_assets, &tile_mappers); - let collision = generate_chunk_collider(chunk, &heightmap); - return ( - mesh, - collision, - offset_to_world(chunk.chunk_offset * Chunk::SIZE as i32, 0.), - ); - }) - .collect(); - - for (mesh, (col_verts, col_indicies), pos) in chunk_meshes { - commands.spawn(( - MaterialMeshBundle { - mesh: meshes.add(mesh), - material: chunk_material.clone(), - transform: Transform::from_translation(pos), - ..default() - }, - PhosChunk, - Collider::trimesh(col_verts, col_indicies), - )); - } -} - #[derive(Resource)] struct SphereMat(Handle); diff --git a/game/main/src/prelude.rs b/game/main/src/prelude.rs index bcc1d05..cfac76c 100644 --- a/game/main/src/prelude.rs +++ b/game/main/src/prelude.rs @@ -1,5 +1,4 @@ use bevy::asset::Handle; - use bevy::prelude::{Component, Image, Resource}; #[derive(Resource)]