From 1e981dd1ff6b9f90e229cd4e2b89d4fbd302f981 Mon Sep 17 00:00:00 2001 From: Amatsugu Date: Sun, 20 Oct 2024 17:22:16 -0400 Subject: [PATCH] fixes for water shoreline --- engine/world_generation/src/consts.rs | 15 ++++ .../src/generators/mesh_generator.rs | 72 ++++++++++++++++--- engine/world_generation/src/map/mesh_chunk.rs | 11 +-- game/main/assets | 2 +- game/main/src/utlis/debug_plugin.rs | 19 ++++- 5 files changed, 104 insertions(+), 15 deletions(-) diff --git a/engine/world_generation/src/consts.rs b/engine/world_generation/src/consts.rs index b54011a..8b1f737 100644 --- a/engine/world_generation/src/consts.rs +++ b/engine/world_generation/src/consts.rs @@ -16,6 +16,21 @@ pub const HEX_CORNERS: [Vec3; 6] = [ Vec3::new(-INNER_RADIUS, 0., 0.5 * OUTER_RADIUS), ]; +pub const WATER_HEX_CORNERS: [Vec3; 12] = [ + Vec3::new(0., 0., OUTER_RADIUS), + Vec3::new(INNER_RADIUS / 2.0, 0., 0.75 * OUTER_RADIUS), + Vec3::new(INNER_RADIUS, 0., 0.5 * OUTER_RADIUS), + Vec3::new(INNER_RADIUS, 0., 0.), + Vec3::new(INNER_RADIUS, 0., -0.5 * OUTER_RADIUS), + Vec3::new(INNER_RADIUS / 2.0, 0., -0.75 * OUTER_RADIUS), + Vec3::new(0., 0., -OUTER_RADIUS), + Vec3::new(-INNER_RADIUS / 2.0, 0., -0.75 * OUTER_RADIUS), + Vec3::new(-INNER_RADIUS, 0., -0.5 * OUTER_RADIUS), + Vec3::new(-INNER_RADIUS, 0., 0.), + Vec3::new(-INNER_RADIUS, 0., 0.5 * OUTER_RADIUS), + Vec3::new(-INNER_RADIUS / 2.0, 0., 0.75 * OUTER_RADIUS), +]; + pub const HEX_NORMALS: [Vec3; 6] = [ Vec3::new(INNER_RADIUS / 2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / 2.), Vec3::Z, diff --git a/engine/world_generation/src/generators/mesh_generator.rs b/engine/world_generation/src/generators/mesh_generator.rs index d58881a..e42cb92 100644 --- a/engine/world_generation/src/generators/mesh_generator.rs +++ b/engine/world_generation/src/generators/mesh_generator.rs @@ -1,4 +1,4 @@ -use crate::hex_utils::HexCoord; +use crate::hex_utils::{HexCoord, INNER_RADIUS}; use crate::{hex_utils::offset3d_to_world, prelude::*}; #[cfg(feature = "tracing")] use bevy::log::*; @@ -114,9 +114,17 @@ pub fn generate_chunk_water_mesh(chunk: &MeshChunkData, sealevel: f32, map_width let off_pos = Vec3::new(x as f32, sealevel, z as f32); let tile_pos = offset3d_to_world(off_pos); let coord = HexCoord::from_grid_pos(x, z); - let n = chunk.get_neighbors(&coord); + let (n, neighbor_has_land) = chunk.get_neighbors_with_water_info(&coord); - create_tile_water_surface(tile_pos, &n, &mut verts, &mut uvs, &mut indices, &mut normals); + create_tile_water_surface( + tile_pos, + &n, + neighbor_has_land, + &mut verts, + &mut uvs, + &mut indices, + &mut normals, + ); } } let mesh = Mesh::new( @@ -131,6 +139,48 @@ pub fn generate_chunk_water_mesh(chunk: &MeshChunkData, sealevel: f32, map_width } fn create_tile_water_surface( + pos: Vec3, + neighbors: &[f32; 6], + neighbor_has_land: bool, + verts: &mut Vec, + uvs: &mut Vec, + indices: &mut Vec, + normals: &mut Vec, +) { + if !neighbor_has_land { + crate_tile_water_inner_surface(pos, verts, uvs, indices, normals); + return; + } + crate_tile_water_shore_surface(pos, neighbors, verts, uvs, indices, normals); +} + +fn crate_tile_water_inner_surface( + pos: Vec3, + verts: &mut Vec, + uvs: &mut Vec, + indices: &mut Vec, + normals: &mut Vec, +) { + //todo: share verts + let idx = verts.len() as u32; + for i in 0..6 { + let p = pos + HEX_CORNERS[i]; + verts.push(p); + uvs.push(Vec2::ZERO); + normals.push(Vec3::Y); + } + for i in 0..3 { + let off = i * 2; + indices.push(off + idx); + indices.push(((off + 1) % 6) + idx); + indices.push(((off + 2) % 6) + idx); + } + indices.push(idx); + indices.push(idx + 2); + indices.push(idx + 4); +} + +fn crate_tile_water_shore_surface( pos: Vec3, neighbors: &[f32; 6], verts: &mut Vec, @@ -143,20 +193,26 @@ fn create_tile_water_surface( verts.push(pos); uvs.push(Vec2::ZERO); normals.push(Vec3::Y); - for i in 0..6 { - let p = pos + HEX_CORNERS[i]; + for i in 0..12 { + let p = pos + WATER_HEX_CORNERS[i]; verts.push(p); let mut uv = Vec2::ZERO; - let n = neighbors[i]; - let nn = neighbors[(i + 5) % 6]; + let ni = i / 2; + let n = neighbors[ni]; + let nn = neighbors[(ni + 5) % 6]; if nn > pos.y || n > pos.y { uv = Vec2::ONE; } + if ni * 2 != i { + if n <= pos.y { + uv = Vec2::ZERO; + } + } indices.push(idx); indices.push(idx + 1 + i as u32); - indices.push(idx + 1 + ((i as u32 + 1) % 6)); + indices.push(idx + 1 + ((i as u32 + 1) % 12)); uvs.push(uv); normals.push(Vec3::Y); diff --git a/engine/world_generation/src/map/mesh_chunk.rs b/engine/world_generation/src/map/mesh_chunk.rs index f0f07ed..5ec50d3 100644 --- a/engine/world_generation/src/map/mesh_chunk.rs +++ b/engine/world_generation/src/map/mesh_chunk.rs @@ -24,17 +24,20 @@ impl MeshChunkData { return data; } - pub fn get_neighbors_map_bounded(&self, coord: &HexCoord, width: usize, height: usize) -> [f32; 6] { + pub fn get_neighbors_with_water_info(&self, coord: &HexCoord) -> ([f32; 6], bool) { + let mut has_land = false; let mut data = [self.min_height; 6]; let n_tiles = coord.get_neighbors(); for i in 0..6 { let n = n_tiles[i]; - if !n.is_in_bounds(Chunk::SIZE * width, Chunk::SIZE * height) { + if !n.is_in_bounds(Chunk::SIZE, Chunk::SIZE) { continue; } data[i] = self.heights[n.to_index(Chunk::SIZE)]; + if data[i] > self.sealevel { + has_land = true; + } } - - return data; + return (data, has_land); } } diff --git a/game/main/assets b/game/main/assets index 1e174e7..c2625f8 160000 --- a/game/main/assets +++ b/game/main/assets @@ -1 +1 @@ -Subproject commit 1e174e70543ea2eb4a7b19dd1f16ad5856bdcba8 +Subproject commit c2625f8951762a99591d1f9214da4a11e20f49fc diff --git a/game/main/src/utlis/debug_plugin.rs b/game/main/src/utlis/debug_plugin.rs index 8c43248..a9c1176 100644 --- a/game/main/src/utlis/debug_plugin.rs +++ b/game/main/src/utlis/debug_plugin.rs @@ -1,7 +1,11 @@ -use bevy::prelude::*; +use bevy::{gizmos::gizmos, prelude::*}; use shared::resources::TileUnderCursor; use shared::states::GameplayState; -use world_generation::{consts::HEX_CORNERS, prelude::Map, states::GeneratorState}; +use world_generation::{ + consts::{HEX_CORNERS, WATER_HEX_CORNERS}, + prelude::Map, + states::GeneratorState, +}; pub struct DebugPlugin; @@ -71,6 +75,17 @@ fn show_tile_heights(map: Res, mut gizmos: Gizmos, shape: Res, tile_ gizmos.line(contact.point, contact.point + Vec3::X, LinearRgba::RED); gizmos.line(contact.point, contact.point + Vec3::Y, LinearRgba::GREEN); gizmos.line(contact.point, contact.point + Vec3::Z, LinearRgba::BLUE); + + // show_water_corners(contact.tile.to_world(height + 1.0), &mut gizmos); + } +} + +fn show_water_corners(pos: Vec3, gizmos: &mut Gizmos) { + for i in 0..WATER_HEX_CORNERS.len() { + let p = pos + WATER_HEX_CORNERS[i]; + let p2 = pos + WATER_HEX_CORNERS[(i + 1) % WATER_HEX_CORNERS.len()]; + + gizmos.line(p, p2, LinearRgba::RED); } }