fixed hex coords, added tile walls

This commit is contained in:
2024-03-31 01:37:25 -04:00
parent b7853beb88
commit 45d4e8cfa0
7 changed files with 74 additions and 89 deletions

View File

@@ -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 { pub fn generate_chunk(chunk_x: f64, chunk_z: f64, cfg: &GenerationConfig, seed: u32) -> Chunk {
let mut result: Vec<f32> = 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); let noise = SuperSimplex::new(seed);
for z in 0..Chunk::SIZE { for z in 0..Chunk::SIZE {
for x 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, x as f64 + chunk_x * Chunk::SIZE as f64,
z as f64 + chunk_z * Chunk::SIZE as f64, z as f64 + chunk_z * Chunk::SIZE as f64,
&cfg, &cfg,
&noise, &noise,
)); );
result[x + z * Chunk::SIZE] = sample;
} }
} }
return Chunk { return Chunk {

View File

@@ -16,11 +16,13 @@ pub fn offset_to_world(offset: IVec2, height: f32) -> Vec3 {
} }
pub fn offset_to_hex(offset: IVec2) -> IVec3 { pub fn offset_to_hex(offset: IVec2) -> IVec3 {
return IVec3 { let mut v = IVec3 {
x: offset.x, x: offset.x - (offset.y / 2),
y: offset.y, 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 { pub fn snap_to_hex_grid(world_pos: Vec3) -> Vec3 {
@@ -54,21 +56,29 @@ pub struct HexCoord {
impl HexCoord { impl HexCoord {
pub const DIRECTIONS: [IVec3; 6] = [ pub const DIRECTIONS: [IVec3; 6] = [
IVec3::new(1, 1, 0), IVec3::new(0, 1, -1),
IVec3::new(1, 0, -1), IVec3::new(1, 0, -1),
IVec3::new(1, -1, 0), IVec3::new(1, -1, 0),
IVec3::new(0, -1, 1), IVec3::new(0, -1, 1),
IVec3::new(-1, 0, 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 const ZERO: HexCoord = HexCoord { hex: IVec3::ZERO };
pub fn new(x: i32, z: i32) -> Self { 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 { 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 { pub fn from_offset(offset_pos: IVec2) -> Self {
return HexCoord { return HexCoord {
@@ -77,11 +87,12 @@ impl HexCoord {
} }
pub fn is_in_bounds(&self, map_height: usize, map_width: usize) -> bool { 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; 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; return false;
} }
@@ -89,33 +100,36 @@ impl HexCoord {
} }
pub fn to_chunk_pos(&self) -> IVec2 { pub fn to_chunk_pos(&self) -> IVec2 {
let off = self.to_offset();
return IVec2 { return IVec2 {
x: (self.hex.x as f32 / Chunk::SIZE as f32).floor() as i32, x: (off.x as f32 / Chunk::SIZE as f32).floor() as i32,
y: (self.hex.y 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 { pub fn to_chunk(&self) -> HexCoord {
let c_pos = self.to_chunk_pos(); let c_pos = self.to_chunk_pos();
let off = self.to_offset();
return HexCoord::from_offset( return HexCoord::from_offset(
( (
self.hex.x - (c_pos.x * Chunk::SIZE as i32), off.x - (c_pos.x * Chunk::SIZE as i32),
self.hex.y - (c_pos.y * Chunk::SIZE as i32), off.y - (c_pos.y * Chunk::SIZE as i32),
) )
.into(), .into(),
); );
} }
pub fn to_world(&self, height: f32) -> Vec3 { 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 { 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 { 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 { pub fn to_chunk_index(&self, width: usize) -> i32 {
let pos = self.to_chunk_pos(); let pos = self.to_chunk_pos();
@@ -150,7 +164,7 @@ impl HexCoord {
pc = Self::slide_left(pc); 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 { fn slide_left(hex: IVec3) -> IVec3 {
@@ -163,12 +177,12 @@ impl HexCoord {
pub fn scale(&self, dir: i32, radius: usize) -> HexCoord { pub fn scale(&self, dir: i32, radius: usize) -> HexCoord {
let s = Self::DIRECTIONS[(dir % 6) as usize] * radius as i32; 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 { pub fn get_neighbor(&self, dir: usize) -> HexCoord {
let d = Self::DIRECTIONS[dir % 6]; 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] { pub fn get_neighbors(&self) -> [HexCoord; 6] {

View File

@@ -21,7 +21,7 @@ pub mod prelude {
pub first_layer_mask: bool, pub first_layer_mask: bool,
} }
pub struct Chunk { pub struct Chunk {
pub points: Vec<f32>, pub points: [f32; Chunk::SIZE * Chunk::SIZE],
pub chunk_offset: IVec2, pub chunk_offset: IVec2,
} }
@@ -39,16 +39,18 @@ pub mod prelude {
impl Map { impl Map {
pub fn get_neighbors(&self, pos: &HexCoord) -> [Option<f32>; 6] { pub fn get_neighbors(&self, pos: &HexCoord) -> [Option<f32>; 6] {
let mut results: [Option<f32>; 6] = [None; 6]; let mut results: [Option<f32>; 6] = [None; 6];
let w = self.width * Chunk::SIZE;
let h = self.height * Chunk::SIZE;
let n_tiles = pos.get_neighbors(); let n_tiles = pos.get_neighbors();
for i in 0..6 { for i in 0..6 {
let n_tile = n_tiles[i]; 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; continue;
} }
let c_idx = n_tile.to_chunk_index(self.width); let c_idx = n_tile.to_chunk_index(self.width);
let chunk = &self.chunks[c_idx as usize]; let chunk = &self.chunks[c_idx as usize];
let local = n_tile.to_chunk_local_index(); 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; return results;
} }

View File

@@ -21,30 +21,21 @@ const HEX_CORNERS: [Vec3; 6] = [
]; ];
pub fn generate_chunk_mesh(chunk: &Chunk, map: &Map) -> Mesh { 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 verts = Vec::with_capacity(vertex_count);
let mut uvs = 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); let mut indices = Vec::with_capacity(vertex_count);
for z in 0..Chunk::SIZE { for z in 0..Chunk::SIZE {
for x in 0..Chunk::SIZE { for x in 0..Chunk::SIZE {
let coord = HexCoord::from_grid_pos(x, z); let height = chunk.points[x + z * Chunk::SIZE];
let height = chunk.points[coord.to_index(Chunk::SIZE) as usize];
let off_pos = Vec3::new(x as f32, height, z as f32); let off_pos = Vec3::new(x as f32, height, z as f32);
let grid_pos = offset3d_to_world(off_pos); let tile_pos = offset3d_to_world(off_pos);
let n = map.get_neighbors(&HexCoord::from_offset( let coord = HexCoord::from_offset(
coord.to_offset() + chunk.chunk_offset, IVec2::new(x as i32, z as i32) + (chunk.chunk_offset * Chunk::SIZE as i32),
));
create_tile(
grid_pos,
&n,
&mut verts,
&mut uvs,
&mut normals,
&mut indices,
0,
); );
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_POSITION, verts)
.with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs) .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
// .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
.with_inserted_indices(Indices::U32(indices)) .with_inserted_indices(Indices::U32(indices))
.with_duplicated_vertices() .with_duplicated_vertices()
.with_computed_flat_normals(); .with_computed_flat_normals();
@@ -67,20 +57,16 @@ fn create_tile(
neighbors: &[Option<f32>; 6], neighbors: &[Option<f32>; 6],
verts: &mut Vec<Vec3>, verts: &mut Vec<Vec3>,
uvs: &mut Vec<Vec2>, uvs: &mut Vec<Vec2>,
normals: &mut Vec<Vec3>,
indices: &mut Vec<u32>, indices: &mut Vec<u32>,
texture_index: u32, texture_index: u32,
) { ) {
let idx = verts.len() as u32; let idx = verts.len() as u32;
let center = Vec3::new(pos.x, 0., pos.z);
normals.push(Vec3::Y);
uvs.push(pos.xz()); uvs.push(pos.xz());
verts.push(pos); verts.push(pos);
for i in 0..6 { for i in 0..6 {
let p = pos + HEX_CORNERS[i]; let p = pos + HEX_CORNERS[i];
verts.push(p); verts.push(p);
uvs.push(p.xz()); uvs.push(p.xz());
normals.push((p - center).normalize());
indices.push(idx); indices.push(idx);
indices.push(idx + 1 + i as u32); indices.push(idx + 1 + i as u32);
indices.push(idx + 1 + ((i as u32 + 1) % 6)); indices.push(idx + 1 + ((i as u32 + 1) % 6));
@@ -90,17 +76,8 @@ fn create_tile(
let cur_n = neighbors[i]; let cur_n = neighbors[i];
match cur_n { match cur_n {
Some(n_height) => { Some(n_height) => {
if true { if n_height < pos.y {
create_tile_wall( create_tile_wall(pos, i, n_height, verts, uvs, indices, texture_index);
pos,
i,
pos.y + 1.,
verts,
uvs,
normals,
indices,
texture_index,
);
} }
} }
_ => {} _ => {}
@@ -114,18 +91,14 @@ fn create_tile_wall(
height: f32, height: f32,
verts: &mut Vec<Vec3>, verts: &mut Vec<Vec3>,
uvs: &mut Vec<Vec2>, uvs: &mut Vec<Vec2>,
normals: &mut Vec<Vec3>,
indices: &mut Vec<u32>, indices: &mut Vec<u32>,
_texture_index: u32, _texture_index: u32,
) { ) {
println!("{dir}"); let p1 = HEX_CORNERS[(dir) % 6] + pos;
let p1 = HEX_CORNERS[(dir + 1) % 6] + pos; let p2 = HEX_CORNERS[(dir + 1) % 6] + pos;
let p2 = HEX_CORNERS[(dir + 2) % 6] + pos;
let p3 = Vec3::new(p1.x, height, p1.z); let p3 = Vec3::new(p1.x, height, p1.z);
let p4 = Vec3::new(p2.x, height, p2.z); let p4 = Vec3::new(p2.x, height, p2.z);
let normal = Vec3::Y;
let idx = verts.len() as u32; let idx = verts.len() as u32;
verts.push(p1); verts.push(p1);
@@ -133,11 +106,6 @@ fn create_tile_wall(
verts.push(p3); verts.push(p3);
verts.push(p4); verts.push(p4);
normals.push(normal);
normals.push(normal);
normals.push(normal);
normals.push(normal);
indices.push(idx); indices.push(idx);
indices.push(idx + 2); indices.push(idx + 2);
indices.push(idx + 1); indices.push(idx + 1);

View File

@@ -83,7 +83,6 @@ fn update_camera_mouse(
return; return;
} }
let mut transform = cam_query.single_mut(); let mut transform = cam_query.single_mut();
let window_scale = window.height().min(window.width());
for ev in mouse_move.read() { for ev in mouse_move.read() {
let (mut yaw, mut pitch, _) = transform.rotation.to_euler(EulerRot::YXZ); let (mut yaw, mut pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);

View File

@@ -1,4 +1,4 @@
use bevy::{pbr::wireframe::WireframePlugin, prelude::*}; use bevy::prelude::*;
use bevy_inspector_egui::quick::WorldInspectorPlugin; use bevy_inspector_egui::quick::WorldInspectorPlugin;
mod phos; mod phos;
use phos::PhosGamePlugin; use phos::PhosGamePlugin;

View File

@@ -1,12 +1,9 @@
use bevy::asset::io::memory::Value::Vec;
use bevy::pbr::wireframe::{WireframeConfig, WireframePlugin};
use bevy::{pbr::CascadeShadowConfig, prelude::*}; use bevy::{pbr::CascadeShadowConfig, prelude::*};
use camera_system::PhosCameraPlugin; use camera_system::PhosCameraPlugin;
use iyes_perf_ui::prelude::*; use iyes_perf_ui::prelude::*;
use world_generation::hex_utils::{offset_to_world, HexCoord}; use world_generation::hex_utils::{offset_to_world, HexCoord};
use world_generation::{ use world_generation::{
heightmap::generate_heightmap, hex_utils::offset3d_to_world, heightmap::generate_heightmap, mesh_generator::generate_chunk_mesh, prelude::*,
mesh_generator::generate_chunk_mesh, prelude::*,
}; };
pub struct PhosGamePlugin; pub struct PhosGamePlugin;
@@ -15,17 +12,11 @@ impl Plugin for PhosGamePlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_plugins(PhosCameraPlugin); app.add_plugins(PhosCameraPlugin);
app.add_systems(Startup, init_game) app.add_systems(Startup, init_game)
.add_systems(Startup, create_map) .add_systems(Startup, create_map);
.add_systems(Update, draw_gizmos);
app.add_plugins(bevy::diagnostic::FrameTimeDiagnosticsPlugin) app.add_plugins(bevy::diagnostic::FrameTimeDiagnosticsPlugin)
.add_plugins(bevy::diagnostic::EntityCountDiagnosticsPlugin) .add_plugins(bevy::diagnostic::EntityCountDiagnosticsPlugin)
.add_plugins(bevy::diagnostic::SystemInformationDiagnosticsPlugin) .add_plugins(bevy::diagnostic::SystemInformationDiagnosticsPlugin)
.add_plugins(PerfUiPlugin); .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(( commands.spawn((
PerfUiRoot::default(), PerfUiRoot::default(),
PerfUiEntryFPS::default(), PerfUiEntryFPS::default(),
PerfUiEntryClock::default(), PerfUiEntryFPSWorst::default(),
PerfUiEntryFrameTime::default(),
PerfUiEntryFrameTimeWorst::default(),
)); ));
commands.spawn(DirectionalLightBundle { commands.spawn(DirectionalLightBundle {
@@ -42,7 +35,7 @@ fn init_game(mut commands: Commands) {
..default() ..default()
}, },
cascade_shadow_config: CascadeShadowConfig { cascade_shadow_config: CascadeShadowConfig {
bounds: vec![500., 1000., 5000., 10000.], bounds: vec![500., 1000., 2000., 5000.],
..default() ..default()
}, },
transform: Transform::from_xyz(500., 160.0, 500.).looking_at(Vec3::ZERO, Vec3::Y), 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<Map>) {
gizmos.arrow(Vec3::ZERO, Vec3::Z * 1.5, Color::BLUE); gizmos.arrow(Vec3::ZERO, Vec3::Z * 1.5, Color::BLUE);
gizmos.arrow(Vec3::ZERO, Vec3::X * 1.5, Color::RED); gizmos.arrow(Vec3::ZERO, Vec3::X * 1.5, Color::RED);
let ch = &hm.chunks[0]; let coord = HexCoord::from_grid_pos(64, 14);
let coord = HexCoord::new(16, 16); let ch = &hm.chunks[coord.to_chunk_index(hm.width) as usize];
let h = ch.points[coord.to_chunk_local_index() 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::Y, Color::RED);
gizmos.ray(coord.to_world(h), Vec3::Z * 1.5, Color::BLUE); gizmos.ray(coord.to_world(h), Vec3::Z * 1.5, Color::BLUE);
@@ -65,10 +58,18 @@ fn draw_gizmos(mut gizmos: Gizmos, hm: Res<Map>) {
// let h = ch.points[t.to_chunk_local_index() as usize]; // let h = ch.points[t.to_chunk_local_index() as usize];
// gizmos.ray(t.to_world(h), Vec3::Y * 1., Color::PINK); // gizmos.ray(t.to_world(h), Vec3::Y * 1., Color::PINK);
let n = coord.get_neighbors(); let n = coord.get_neighbors();
let nh = hm.get_neighbors(&coord);
for i in 0..6 { for i in 0..6 {
let t = n[i]; let t = n[i];
let h = ch.points[t.to_chunk_local_index() as usize]; let h = nh[i];
gizmos.ray(t.to_world(h), Vec3::Y * (i + 1) as f32, Color::CYAN); 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<Assets<Mesh>>, mut meshes: ResMut<Assets<Mesh>>,
) { ) {
let heightmap = generate_heightmap( let heightmap = generate_heightmap(
1, 32,
1, 32,
&GenerationConfig { &GenerationConfig {
layers: vec![ layers: vec![
GeneratorLayer { GeneratorLayer {