From 45d4e8cfa0fc65a70a71db5bf7290931273918a0 Mon Sep 17 00:00:00 2001 From: Amatsugu Date: Sun, 31 Mar 2024 01:37:25 -0400 Subject: [PATCH] fixed hex coords, added tile walls --- engine/world_generation/src/heightmap.rs | 7 +-- engine/world_generation/src/hex_utils.rs | 52 +++++++++++------- engine/world_generation/src/lib.rs | 8 +-- engine/world_generation/src/mesh_generator.rs | 54 ++++--------------- game/camera_system/src/lib.rs | 1 - game/main/src/main.rs | 2 +- game/main/src/phos.rs | 39 +++++++------- 7 files changed, 74 insertions(+), 89 deletions(-) diff --git a/engine/world_generation/src/heightmap.rs b/engine/world_generation/src/heightmap.rs index 9b0d792..fd4d318 100644 --- a/engine/world_generation/src/heightmap.rs +++ b/engine/world_generation/src/heightmap.rs @@ -17,16 +17,17 @@ pub fn generate_heightmap(height: usize, width: usize, cfg: &GenerationConfig, s } pub fn generate_chunk(chunk_x: f64, chunk_z: f64, cfg: &GenerationConfig, seed: u32) -> Chunk { - let mut result: Vec = Vec::with_capacity(Chunk::SIZE * Chunk::SIZE); + let mut result: [f32; Chunk::SIZE * Chunk::SIZE] = [0.; Chunk::SIZE * Chunk::SIZE]; let noise = SuperSimplex::new(seed); for z in 0..Chunk::SIZE { for x in 0..Chunk::SIZE { - result.push(sample_point( + let sample = sample_point( x as f64 + chunk_x * Chunk::SIZE as f64, z as f64 + chunk_z * Chunk::SIZE as f64, &cfg, &noise, - )); + ); + result[x + z * Chunk::SIZE] = sample; } } return Chunk { diff --git a/engine/world_generation/src/hex_utils.rs b/engine/world_generation/src/hex_utils.rs index 288a573..7e2ebe8 100644 --- a/engine/world_generation/src/hex_utils.rs +++ b/engine/world_generation/src/hex_utils.rs @@ -16,11 +16,13 @@ pub fn offset_to_world(offset: IVec2, height: f32) -> Vec3 { } pub fn offset_to_hex(offset: IVec2) -> IVec3 { - return IVec3 { - x: offset.x, + let mut v = IVec3 { + x: offset.x - (offset.y / 2), y: offset.y, - z: -offset.x - offset.y, + z: 0, }; + v.z = -v.x - v.y; + return v; } pub fn snap_to_hex_grid(world_pos: Vec3) -> Vec3 { @@ -54,21 +56,29 @@ pub struct HexCoord { impl HexCoord { pub const DIRECTIONS: [IVec3; 6] = [ - IVec3::new(1, 1, 0), + IVec3::new(0, 1, -1), IVec3::new(1, 0, -1), IVec3::new(1, -1, 0), IVec3::new(0, -1, 1), IVec3::new(-1, 0, 1), - IVec3::new(0, 1, -1), + IVec3::new(-1, 1, 0), ]; pub const ZERO: HexCoord = HexCoord { hex: IVec3::ZERO }; pub fn new(x: i32, z: i32) -> Self { - return Self::from_offset(IVec2::new(x, z)); + return HexCoord { + hex: IVec3::new(x, z, -x - z), + }; + } + + pub fn from_hex(hex: IVec2) -> Self { + return HexCoord { + hex: IVec3::new(hex.x, hex.y, -hex.x - hex.y), + }; } pub fn from_grid_pos(x: usize, z: usize) -> Self { - return HexCoord::new(x as i32, z as i32); + return HexCoord::new(x as i32 - (z as i32 / 2), z as i32); } pub fn from_offset(offset_pos: IVec2) -> Self { return HexCoord { @@ -77,11 +87,12 @@ impl HexCoord { } pub fn is_in_bounds(&self, map_height: usize, map_width: usize) -> bool { - if self.hex.x < 0 || self.hex.y < 0 { + let off = self.to_offset(); + if off.x < 0 || off.y < 0 { return false; } - if self.hex.x >= map_width as i32 || self.hex.y >= map_height as i32 { + if off.x >= map_width as i32 || off.y >= map_height as i32 { return false; } @@ -89,33 +100,36 @@ impl HexCoord { } pub fn to_chunk_pos(&self) -> IVec2 { + let off = self.to_offset(); + return IVec2 { - x: (self.hex.x as f32 / Chunk::SIZE as f32).floor() as i32, - y: (self.hex.y as f32 / Chunk::SIZE as f32).floor() as i32, + x: (off.x as f32 / Chunk::SIZE as f32).floor() as i32, + y: (off.y as f32 / Chunk::SIZE as f32).floor() as i32, }; } pub fn to_chunk(&self) -> HexCoord { let c_pos = self.to_chunk_pos(); + let off = self.to_offset(); return HexCoord::from_offset( ( - self.hex.x - (c_pos.x * Chunk::SIZE as i32), - self.hex.y - (c_pos.y * Chunk::SIZE as i32), + off.x - (c_pos.x * Chunk::SIZE as i32), + off.y - (c_pos.y * Chunk::SIZE as i32), ) .into(), ); } pub fn to_world(&self, height: f32) -> Vec3 { - return offset_to_world(self.hex.xy(), height); + return offset_to_world(self.to_offset(), height); } pub fn to_offset(&self) -> IVec2 { - return self.hex.xy(); + return IVec2::new(self.hex.x + (self.hex.y / 2), self.hex.y); } pub fn to_index(&self, width: usize) -> i32 { - return self.hex.x + self.hex.y * width as i32 + self.hex.y / 2; + return (self.hex.x + self.hex.y * width as i32) + (self.hex.y / 2); } pub fn to_chunk_index(&self, width: usize) -> i32 { let pos = self.to_chunk_pos(); @@ -150,7 +164,7 @@ impl HexCoord { pc = Self::slide_left(pc); } } - return HexCoord::from_offset(pc.xy() + center.hex.xy()); + return HexCoord::from_hex(pc.xy() + center.hex.xy()); } fn slide_left(hex: IVec3) -> IVec3 { @@ -163,12 +177,12 @@ impl HexCoord { pub fn scale(&self, dir: i32, radius: usize) -> HexCoord { let s = Self::DIRECTIONS[(dir % 6) as usize] * radius as i32; - return Self::from_offset(self.hex.xy() + s.xy()); + return Self::from_hex(self.hex.xy() + s.xy()); } pub fn get_neighbor(&self, dir: usize) -> HexCoord { let d = Self::DIRECTIONS[dir % 6]; - return Self::from_offset(self.hex.xy() + d.xy()); + return Self::from_hex(self.hex.xy() + d.xy()); } pub fn get_neighbors(&self) -> [HexCoord; 6] { diff --git a/engine/world_generation/src/lib.rs b/engine/world_generation/src/lib.rs index 70cff2d..826d56b 100644 --- a/engine/world_generation/src/lib.rs +++ b/engine/world_generation/src/lib.rs @@ -21,7 +21,7 @@ pub mod prelude { pub first_layer_mask: bool, } pub struct Chunk { - pub points: Vec, + pub points: [f32; Chunk::SIZE * Chunk::SIZE], pub chunk_offset: IVec2, } @@ -39,16 +39,18 @@ pub mod prelude { impl Map { pub fn get_neighbors(&self, pos: &HexCoord) -> [Option; 6] { let mut results: [Option; 6] = [None; 6]; + let w = self.width * Chunk::SIZE; + let h = self.height * Chunk::SIZE; let n_tiles = pos.get_neighbors(); for i in 0..6 { let n_tile = n_tiles[i]; - if !n_tile.is_in_bounds(self.height, self.width) { + if !n_tile.is_in_bounds(h, w) { continue; } let c_idx = n_tile.to_chunk_index(self.width); let chunk = &self.chunks[c_idx as usize]; let local = n_tile.to_chunk_local_index(); - results[i] = (Some(chunk.points[local as usize])); + results[i] = Some(chunk.points[local as usize]); } return results; } diff --git a/engine/world_generation/src/mesh_generator.rs b/engine/world_generation/src/mesh_generator.rs index 440252d..235cf3c 100644 --- a/engine/world_generation/src/mesh_generator.rs +++ b/engine/world_generation/src/mesh_generator.rs @@ -21,30 +21,21 @@ const HEX_CORNERS: [Vec3; 6] = [ ]; pub fn generate_chunk_mesh(chunk: &Chunk, map: &Map) -> Mesh { - let vertex_count: usize = Chunk::SIZE * Chunk::SIZE; + let vertex_count: usize = Chunk::SIZE * Chunk::SIZE * 6; let mut verts = Vec::with_capacity(vertex_count); let mut uvs = Vec::with_capacity(vertex_count); - let mut normals = 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 coord = HexCoord::from_grid_pos(x, z); - let height = chunk.points[coord.to_index(Chunk::SIZE) as usize]; + let height = chunk.points[x + z * Chunk::SIZE]; let off_pos = Vec3::new(x as f32, height, z as f32); - let grid_pos = offset3d_to_world(off_pos); - let n = map.get_neighbors(&HexCoord::from_offset( - coord.to_offset() + chunk.chunk_offset, - )); - create_tile( - grid_pos, - &n, - &mut verts, - &mut uvs, - &mut normals, - &mut indices, - 0, + 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); + create_tile(tile_pos, &n, &mut verts, &mut uvs, &mut indices, 0); } } @@ -54,7 +45,6 @@ pub fn generate_chunk_mesh(chunk: &Chunk, map: &Map) -> Mesh { ) .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, verts) .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs) - // .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals) .with_inserted_indices(Indices::U32(indices)) .with_duplicated_vertices() .with_computed_flat_normals(); @@ -67,20 +57,16 @@ fn create_tile( neighbors: &[Option; 6], verts: &mut Vec, uvs: &mut Vec, - normals: &mut Vec, indices: &mut Vec, texture_index: u32, ) { let idx = verts.len() as u32; - let center = Vec3::new(pos.x, 0., pos.z); - normals.push(Vec3::Y); uvs.push(pos.xz()); verts.push(pos); for i in 0..6 { let p = pos + HEX_CORNERS[i]; verts.push(p); uvs.push(p.xz()); - normals.push((p - center).normalize()); indices.push(idx); indices.push(idx + 1 + i as u32); indices.push(idx + 1 + ((i as u32 + 1) % 6)); @@ -90,17 +76,8 @@ fn create_tile( let cur_n = neighbors[i]; match cur_n { Some(n_height) => { - if true { - create_tile_wall( - pos, - i, - pos.y + 1., - verts, - uvs, - normals, - indices, - texture_index, - ); + if n_height < pos.y { + create_tile_wall(pos, i, n_height, verts, uvs, indices, texture_index); } } _ => {} @@ -114,18 +91,14 @@ fn create_tile_wall( height: f32, verts: &mut Vec, uvs: &mut Vec, - normals: &mut Vec, indices: &mut Vec, _texture_index: u32, ) { - println!("{dir}"); - let p1 = HEX_CORNERS[(dir + 1) % 6] + pos; - let p2 = HEX_CORNERS[(dir + 2) % 6] + pos; + let p1 = HEX_CORNERS[(dir) % 6] + pos; + let p2 = HEX_CORNERS[(dir + 1) % 6] + pos; let p3 = Vec3::new(p1.x, height, p1.z); let p4 = Vec3::new(p2.x, height, p2.z); - let normal = Vec3::Y; - let idx = verts.len() as u32; verts.push(p1); @@ -133,11 +106,6 @@ fn create_tile_wall( verts.push(p3); verts.push(p4); - normals.push(normal); - normals.push(normal); - normals.push(normal); - normals.push(normal); - indices.push(idx); indices.push(idx + 2); indices.push(idx + 1); diff --git a/game/camera_system/src/lib.rs b/game/camera_system/src/lib.rs index 72594ab..cdf753e 100644 --- a/game/camera_system/src/lib.rs +++ b/game/camera_system/src/lib.rs @@ -83,7 +83,6 @@ fn update_camera_mouse( return; } let mut transform = cam_query.single_mut(); - let window_scale = window.height().min(window.width()); for ev in mouse_move.read() { let (mut yaw, mut pitch, _) = transform.rotation.to_euler(EulerRot::YXZ); diff --git a/game/main/src/main.rs b/game/main/src/main.rs index 0beba06..20cd3c3 100644 --- a/game/main/src/main.rs +++ b/game/main/src/main.rs @@ -1,4 +1,4 @@ -use bevy::{pbr::wireframe::WireframePlugin, prelude::*}; +use bevy::prelude::*; use bevy_inspector_egui::quick::WorldInspectorPlugin; mod phos; use phos::PhosGamePlugin; diff --git a/game/main/src/phos.rs b/game/main/src/phos.rs index 4ba9abe..2777c21 100644 --- a/game/main/src/phos.rs +++ b/game/main/src/phos.rs @@ -1,12 +1,9 @@ -use bevy::asset::io::memory::Value::Vec; -use bevy::pbr::wireframe::{WireframeConfig, WireframePlugin}; use bevy::{pbr::CascadeShadowConfig, prelude::*}; use camera_system::PhosCameraPlugin; use iyes_perf_ui::prelude::*; use world_generation::hex_utils::{offset_to_world, HexCoord}; use world_generation::{ - heightmap::generate_heightmap, hex_utils::offset3d_to_world, - mesh_generator::generate_chunk_mesh, prelude::*, + heightmap::generate_heightmap, mesh_generator::generate_chunk_mesh, prelude::*, }; pub struct PhosGamePlugin; @@ -15,17 +12,11 @@ impl Plugin for PhosGamePlugin { fn build(&self, app: &mut App) { app.add_plugins(PhosCameraPlugin); app.add_systems(Startup, init_game) - .add_systems(Startup, create_map) - .add_systems(Update, draw_gizmos); + .add_systems(Startup, create_map); app.add_plugins(bevy::diagnostic::FrameTimeDiagnosticsPlugin) .add_plugins(bevy::diagnostic::EntityCountDiagnosticsPlugin) .add_plugins(bevy::diagnostic::SystemInformationDiagnosticsPlugin) .add_plugins(PerfUiPlugin); - app.add_plugins(WireframePlugin); - // app.insert_resource(WireframeConfig { - // global: true, - // default_color: Color::CYAN, - // }); } } @@ -33,7 +24,9 @@ fn init_game(mut commands: Commands) { commands.spawn(( PerfUiRoot::default(), PerfUiEntryFPS::default(), - PerfUiEntryClock::default(), + PerfUiEntryFPSWorst::default(), + PerfUiEntryFrameTime::default(), + PerfUiEntryFrameTimeWorst::default(), )); commands.spawn(DirectionalLightBundle { @@ -42,7 +35,7 @@ fn init_game(mut commands: Commands) { ..default() }, cascade_shadow_config: CascadeShadowConfig { - bounds: vec![500., 1000., 5000., 10000.], + bounds: vec![500., 1000., 2000., 5000.], ..default() }, transform: Transform::from_xyz(500., 160.0, 500.).looking_at(Vec3::ZERO, Vec3::Y), @@ -55,8 +48,8 @@ fn draw_gizmos(mut gizmos: Gizmos, hm: Res) { gizmos.arrow(Vec3::ZERO, Vec3::Z * 1.5, Color::BLUE); gizmos.arrow(Vec3::ZERO, Vec3::X * 1.5, Color::RED); - let ch = &hm.chunks[0]; - let coord = HexCoord::new(16, 16); + let coord = HexCoord::from_grid_pos(64, 14); + let ch = &hm.chunks[coord.to_chunk_index(hm.width) as usize]; let h = ch.points[coord.to_chunk_local_index() as usize]; gizmos.ray(coord.to_world(h), Vec3::Y, Color::RED); gizmos.ray(coord.to_world(h), Vec3::Z * 1.5, Color::BLUE); @@ -65,10 +58,18 @@ fn draw_gizmos(mut gizmos: Gizmos, hm: Res) { // let h = ch.points[t.to_chunk_local_index() as usize]; // gizmos.ray(t.to_world(h), Vec3::Y * 1., Color::PINK); let n = coord.get_neighbors(); + let nh = hm.get_neighbors(&coord); for i in 0..6 { let t = n[i]; - let h = ch.points[t.to_chunk_local_index() as usize]; - gizmos.ray(t.to_world(h), Vec3::Y * (i + 1) as f32, Color::CYAN); + let h = nh[i]; + if h.is_none() { + continue; + } + gizmos.ray( + t.to_world(h.unwrap()), + Vec3::Y * (i + 1) as f32, + Color::CYAN, + ); } } @@ -78,8 +79,8 @@ fn create_map( mut meshes: ResMut>, ) { let heightmap = generate_heightmap( - 1, - 1, + 32, + 32, &GenerationConfig { layers: vec![ GeneratorLayer {