everything is broken

This commit is contained in:
2024-03-30 21:32:12 -04:00
parent 402b8eb93c
commit b7853beb88
7 changed files with 359 additions and 201 deletions

View File

@@ -5,151 +5,173 @@ pub const OUTER_RADIUS: f32 = 1.;
pub const INNER_RADIUS: f32 = OUTER_RADIUS * 0.866025404;
pub fn offset3d_to_world(offset: Vec3) -> Vec3 {
let x = (offset.x + offset.z * 0.5 - (offset.z / 2.).floor()) * (INNER_RADIUS * 2.);
return Vec3::new(x, offset.y, offset.z * OUTER_RADIUS * 1.5);
let x = (offset.x + (offset.z * 0.5) - (offset.z / 2.).floor()) * (INNER_RADIUS * 2.);
return Vec3::new(x, offset.y, offset.z * OUTER_RADIUS * 1.5);
}
pub fn offset_to_world(offset: IVec2) -> Vec3 {
let x = (offset.x as f32 + offset.y as f32 * 0.5 - (offset.y as f32 / 2.).floor())
* (INNER_RADIUS * 2.);
return Vec3::new(x, 0., offset.y as f32 * OUTER_RADIUS * 1.5);
pub fn offset_to_world(offset: IVec2, height: f32) -> Vec3 {
let off = offset.as_vec2();
let x = (off.x + (off.y * 0.5) - (off.y / 2.).floor()) * (INNER_RADIUS * 2.);
return Vec3::new(x, height, off.y * OUTER_RADIUS * 1.5);
}
pub fn offset_to_hex(offset: IVec2) -> IVec3 {
return IVec3 {
x: offset.x,
y: offset.y,
z: -offset.x - offset.y,
};
return IVec3 {
x: offset.x,
y: offset.y,
z: -offset.x - offset.y,
};
}
pub fn snap_to_hex_grid(world_pos: Vec3) -> Vec3 {
return offset_to_world(world_to_offset_pos(world_pos));
return offset_to_world(world_to_offset_pos(world_pos), world_pos.y);
}
pub fn world_to_offset_pos(world_pos: Vec3) -> IVec2 {
let offset = world_pos.z / (OUTER_RADIUS * 3.);
let x = (world_pos.x / (INNER_RADIUS * 2.)) - offset;
let z = -world_pos.x - offset;
let offset = world_pos.z / (OUTER_RADIUS * 3.);
let x = (world_pos.x / (INNER_RADIUS * 2.)) - offset;
let z = -world_pos.x - offset;
let ix = x.round() as i32;
let iz = z.round() as i32;
let ox = ix + iz / 2;
let oz = iz;
return IVec2::new(ox, oz);
let ix = x.round() as i32;
let iz = z.round() as i32;
let ox = ix + iz / 2;
let oz = iz;
return IVec2::new(ox, oz);
}
pub fn tile_to_world_distance(dist: i32) -> f32 {
return dist as f32 * (2. * INNER_RADIUS);
return dist as f32 * (2. * INNER_RADIUS);
}
pub fn get_tile_count(radius: i32)->i32{
pub fn get_tile_count(radius: i32) -> i32 {
return 1 + 3 * (radius + 1) * radius;
}
#[derive(Default, Clone, Copy)]
#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
pub struct HexCoord {
pub hex: IVec3,
pub offset: IVec2,
pub world: Vec3,
pub hex: IVec3,
}
impl PartialEq<Self> for HexCoord {
fn eq(&self, other: &Self) -> bool {
return self.offset == other.offset;
}
}
impl Eq for HexCoord {}
impl HexCoord {
pub const DIRECTIONS: [IVec3; 6] = [
IVec3::new(1, -1, 0),
IVec3::new(1, 0, -1),
IVec3::new(0, 1, -1),
IVec3::new(-1, 1, 0),
IVec3::new(-1, 0, 1),
IVec3::new(0, -1, 1),
];
pub const DIRECTIONS: [IVec3; 6] = [
IVec3::new(1, 1, 0),
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),
];
pub const ZERO: HexCoord = HexCoord {
offset: IVec2::ZERO,
hex: IVec3::ZERO,
world: Vec3::ZERO,
};
pub const ZERO: HexCoord = HexCoord { hex: IVec3::ZERO };
pub fn new(x: i32, z: i32) -> Self {
return Self::from_offset(IVec2::new(x, z));
}
pub fn from_grid_pos(x: usize, z: usize) -> Self {
return HexCoord::new(x as i32, z as i32);
}
pub fn from_offset(offset_pos: IVec2) -> Self {
return HexCoord {
offset: offset_pos,
hex: offset_to_hex(offset_pos),
world: offset3d_to_world(offset_pos.extend(0).xzy().as_vec3()),
};
}
pub fn new(x: i32, z: i32) -> Self {
return Self::from_offset(IVec2::new(x, z));
}
pub fn from_grid_pos(x: usize, z: usize) -> Self {
return HexCoord::new(x as i32, z as i32);
}
pub fn from_offset(offset_pos: IVec2) -> Self {
return HexCoord {
hex: offset_to_hex(offset_pos),
};
}
pub fn to_chunk_pos(&self) -> IVec2 {
return IVec2 {
x: (self.offset.x as f32 / Chunk::SIZE as f32).floor() as i32,
y: (self.offset.y as f32 / Chunk::SIZE as f32).floor() as i32,
};
}
pub fn is_in_bounds(&self, map_height: usize, map_width: usize) -> bool {
if self.hex.x < 0 || self.hex.y < 0 {
return false;
}
pub fn to_chunk_index(&self, width: usize) -> usize {
let pos = self.to_chunk_pos();
return pos.x as usize + pos.y as usize * width;
}
if self.hex.x >= map_width as i32 || self.hex.y >= map_height as i32 {
return false;
}
pub fn distance(&self, other: &HexCoord) -> i32 {
return (self.hex.x - other.hex.x).abs()
+ (self.hex.y - other.hex.y).abs()
+ (self.hex.z - other.hex.z).abs();
}
return true;
}
pub fn rotate_around(&self, center: &HexCoord, angle: i32) -> HexCoord {
if self == center || angle == 0 {
return self.clone();
}
pub fn to_chunk_pos(&self) -> IVec2 {
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,
};
}
let mut a = angle % 6;
let mut pc = self.hex - center.hex;
pub fn to_chunk(&self) -> HexCoord {
let c_pos = self.to_chunk_pos();
return HexCoord::from_offset(
(
self.hex.x - (c_pos.x * Chunk::SIZE as i32),
self.hex.y - (c_pos.y * Chunk::SIZE as i32),
)
.into(),
);
}
if a > 0 {
for _ in 0..a {
pc = Self::slide_right(pc);
}
} else {
a = a.abs();
for _ in 0..a {
pc = Self::slide_left(pc);
}
}
return HexCoord::from_offset(pc.xy() + center.hex.xy());
}
pub fn to_world(&self, height: f32) -> Vec3 {
return offset_to_world(self.hex.xy(), height);
}
fn slide_left(hex: IVec3) -> IVec3 {
return (hex * -1).yzx();
}
pub fn to_offset(&self) -> IVec2 {
return self.hex.xy();
}
fn slide_right(hex: IVec3) -> IVec3 {
return (hex * -1).zxy();
}
pub fn to_index(&self, width: usize) -> i32 {
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();
return pos.x + pos.y * width as i32;
}
pub fn scale(&self, dir: i32, radius: usize)-> HexCoord{
pub fn to_chunk_local_index(&self) -> i32 {
return self.to_chunk().to_index(Chunk::SIZE);
}
pub fn distance(&self, other: &HexCoord) -> i32 {
return (self.hex.x - other.hex.x).abs()
+ (self.hex.y - other.hex.y).abs()
+ (self.hex.z - other.hex.z).abs();
}
pub fn rotate_around(&self, center: &HexCoord, angle: i32) -> HexCoord {
if self == center || angle == 0 {
return self.clone();
}
let mut a = angle % 6;
let mut pc = self.hex - center.hex;
if a > 0 {
for _ in 0..a {
pc = Self::slide_right(pc);
}
} else {
a = a.abs();
for _ in 0..a {
pc = Self::slide_left(pc);
}
}
return HexCoord::from_offset(pc.xy() + center.hex.xy());
}
fn slide_left(hex: IVec3) -> IVec3 {
return (hex * -1).yzx();
}
fn slide_right(hex: IVec3) -> IVec3 {
return (hex * -1).zxy();
}
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());
}
pub fn get_neighbor(&self, dir: usize)-> HexCoord{
pub fn get_neighbor(&self, dir: usize) -> HexCoord {
let d = Self::DIRECTIONS[dir % 6];
return Self::from_offset(self.hex.xy() + d.xy());
}
pub fn get_neighbors(&self) -> [HexCoord; 6]{
pub fn get_neighbors(&self) -> [HexCoord; 6] {
return [
self.get_neighbor(0),
self.get_neighbor(1),
@@ -157,6 +179,6 @@ impl HexCoord {
self.get_neighbor(3),
self.get_neighbor(4),
self.get_neighbor(5),
]
];
}
}

View File

@@ -1,5 +1,7 @@
pub mod prelude {
use crate::hex_utils::HexCoord;
use bevy::math::IVec2;
use bevy::prelude::Resource;
pub struct GenerationConfig {
pub noise_scale: f64,
@@ -26,24 +28,33 @@ pub mod prelude {
impl Chunk {
pub const SIZE: usize = 32;
}
#[derive(Resource)]
pub struct Map {
pub chunks: Vec<Chunk>,
pub height: usize,
pub width: usize,
}
impl Map {
pub fn get_neighbors(&self, pos: &HexCoord) -> [Option<f32>; 6] {
let mut results: [Option<f32>; 6] = [None; 6];
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) {
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]));
}
return results;
}
}
}
pub mod heightmap;
pub mod hex_utils;
pub mod mesh_generator;
#[cfg(test)]
mod tests {
use super::*;
// #[test]
// fn it_works() {
// let result = add(2, 2);
// assert_eq!(result, 4);
// }
}

View File

@@ -1,3 +1,4 @@
use crate::hex_utils::HexCoord;
use crate::{
hex_utils::{offset3d_to_world, INNER_RADIUS, OUTER_RADIUS},
prelude::*,
@@ -19,7 +20,7 @@ const HEX_CORNERS: [Vec3; 6] = [
Vec3::new(-INNER_RADIUS, 0., 0.5 * OUTER_RADIUS),
];
pub fn generate_chunk_mesh(chunk: &Chunk) -> Mesh {
pub fn generate_chunk_mesh(chunk: &Chunk, map: &Map) -> Mesh {
let vertex_count: usize = Chunk::SIZE * Chunk::SIZE;
let mut verts = Vec::with_capacity(vertex_count);
let mut uvs = Vec::with_capacity(vertex_count);
@@ -28,10 +29,22 @@ pub fn generate_chunk_mesh(chunk: &Chunk) -> Mesh {
for z in 0..Chunk::SIZE {
for x in 0..Chunk::SIZE {
let height = chunk.points[x + z * Chunk::SIZE];
let coord = HexCoord::from_grid_pos(x, z);
let height = chunk.points[coord.to_index(Chunk::SIZE) as usize];
let off_pos = Vec3::new(x as f32, height, z as f32);
let grid_pos = offset3d_to_world(off_pos);
create_tile(grid_pos, &mut verts, &mut uvs, &mut normals, &mut indices);
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,
);
}
}
@@ -51,10 +64,12 @@ pub fn generate_chunk_mesh(chunk: &Chunk) -> Mesh {
//TODO: figure out texture index
fn create_tile(
pos: Vec3,
neighbors: &[Option<f32>; 6],
verts: &mut Vec<Vec3>,
uvs: &mut Vec<Vec2>,
normals: &mut Vec<Vec3>,
indices: &mut Vec<u32>,
texture_index: u32,
) {
let idx = verts.len() as u32;
let center = Vec3::new(pos.x, 0., pos.z);
@@ -70,4 +85,69 @@ fn create_tile(
indices.push(idx + 1 + i as u32);
indices.push(idx + 1 + ((i as u32 + 1) % 6));
}
for i in 0..neighbors.len() {
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,
);
}
}
_ => {}
}
}
}
fn create_tile_wall(
pos: Vec3,
dir: usize,
height: f32,
verts: &mut Vec<Vec3>,
uvs: &mut Vec<Vec2>,
normals: &mut Vec<Vec3>,
indices: &mut Vec<u32>,
_texture_index: u32,
) {
println!("{dir}");
let p1 = HEX_CORNERS[(dir + 1) % 6] + pos;
let p2 = HEX_CORNERS[(dir + 2) % 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);
verts.push(p2);
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);
indices.push(idx + 1);
indices.push(idx + 2);
indices.push(idx + 3);
uvs.push(Vec2::new(0., 0.));
uvs.push(Vec2::new(1., 0.));
uvs.push(Vec2::new(0., 1.));
uvs.push(Vec2::new(1., 1.));
}