everything is broken
This commit is contained in:
12
Cargo.toml
12
Cargo.toml
@@ -1,14 +1,14 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
|
|
||||||
members = [
|
members = [
|
||||||
"game/main",
|
"game/main",
|
||||||
"engine/world_generation"
|
"engine/world_generation"
|
||||||
, "game/camera_system"]
|
, "game/camera_system"]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
# Enable a small amount of optimization in debug mode
|
# Enable a small amount of optimization in debug mode
|
||||||
[profile.dev]
|
#[profile.dev]
|
||||||
opt-level = 1
|
#opt-level = 1
|
||||||
|
|
||||||
# Enable high optimizations for dependencies (incl. Bevy), but not for our code:
|
# Enable high optimizations for dependencies (incl. Bevy), but not for our code:
|
||||||
[profile.dev.package."*"]
|
[profile.dev.package."*"]
|
||||||
|
|||||||
@@ -5,151 +5,173 @@ pub const OUTER_RADIUS: f32 = 1.;
|
|||||||
pub const INNER_RADIUS: f32 = OUTER_RADIUS * 0.866025404;
|
pub const INNER_RADIUS: f32 = OUTER_RADIUS * 0.866025404;
|
||||||
|
|
||||||
pub fn offset3d_to_world(offset: Vec3) -> Vec3 {
|
pub fn offset3d_to_world(offset: Vec3) -> Vec3 {
|
||||||
let x = (offset.x + offset.z * 0.5 - (offset.z / 2.).floor()) * (INNER_RADIUS * 2.);
|
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);
|
return Vec3::new(x, offset.y, offset.z * OUTER_RADIUS * 1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset_to_world(offset: IVec2) -> Vec3 {
|
pub fn offset_to_world(offset: IVec2, height: f32) -> Vec3 {
|
||||||
let x = (offset.x as f32 + offset.y as f32 * 0.5 - (offset.y as f32 / 2.).floor())
|
let off = offset.as_vec2();
|
||||||
* (INNER_RADIUS * 2.);
|
let x = (off.x + (off.y * 0.5) - (off.y / 2.).floor()) * (INNER_RADIUS * 2.);
|
||||||
return Vec3::new(x, 0., offset.y as f32 * OUTER_RADIUS * 1.5);
|
return Vec3::new(x, height, off.y * OUTER_RADIUS * 1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset_to_hex(offset: IVec2) -> IVec3 {
|
pub fn offset_to_hex(offset: IVec2) -> IVec3 {
|
||||||
return IVec3 {
|
return IVec3 {
|
||||||
x: offset.x,
|
x: offset.x,
|
||||||
y: offset.y,
|
y: offset.y,
|
||||||
z: -offset.x - offset.y,
|
z: -offset.x - offset.y,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn snap_to_hex_grid(world_pos: Vec3) -> Vec3 {
|
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 {
|
pub fn world_to_offset_pos(world_pos: Vec3) -> IVec2 {
|
||||||
let offset = world_pos.z / (OUTER_RADIUS * 3.);
|
let offset = world_pos.z / (OUTER_RADIUS * 3.);
|
||||||
let x = (world_pos.x / (INNER_RADIUS * 2.)) - offset;
|
let x = (world_pos.x / (INNER_RADIUS * 2.)) - offset;
|
||||||
let z = -world_pos.x - offset;
|
let z = -world_pos.x - offset;
|
||||||
|
|
||||||
let ix = x.round() as i32;
|
let ix = x.round() as i32;
|
||||||
let iz = z.round() as i32;
|
let iz = z.round() as i32;
|
||||||
let ox = ix + iz / 2;
|
let ox = ix + iz / 2;
|
||||||
let oz = iz;
|
let oz = iz;
|
||||||
return IVec2::new(ox, oz);
|
return IVec2::new(ox, oz);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tile_to_world_distance(dist: i32) -> f32 {
|
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;
|
return 1 + 3 * (radius + 1) * radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
pub struct HexCoord {
|
pub struct HexCoord {
|
||||||
pub hex: IVec3,
|
pub hex: IVec3,
|
||||||
pub offset: IVec2,
|
|
||||||
pub world: Vec3,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq<Self> for HexCoord {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
return self.offset == other.offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for HexCoord {}
|
|
||||||
|
|
||||||
impl HexCoord {
|
impl HexCoord {
|
||||||
pub const DIRECTIONS: [IVec3; 6] = [
|
pub const DIRECTIONS: [IVec3; 6] = [
|
||||||
IVec3::new(1, -1, 0),
|
IVec3::new(1, 1, 0),
|
||||||
IVec3::new(1, 0, -1),
|
IVec3::new(1, 0, -1),
|
||||||
IVec3::new(0, 1, -1),
|
IVec3::new(1, -1, 0),
|
||||||
IVec3::new(-1, 1, 0),
|
IVec3::new(0, -1, 1),
|
||||||
IVec3::new(-1, 0, 1),
|
IVec3::new(-1, 0, 1),
|
||||||
IVec3::new(0, -1, 1),
|
IVec3::new(0, 1, -1),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const ZERO: HexCoord = HexCoord {
|
pub const ZERO: HexCoord = HexCoord { hex: IVec3::ZERO };
|
||||||
offset: IVec2::ZERO,
|
|
||||||
hex: IVec3::ZERO,
|
|
||||||
world: Vec3::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 Self::from_offset(IVec2::new(x, z));
|
||||||
}
|
}
|
||||||
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);
|
||||||
}
|
}
|
||||||
pub fn from_offset(offset_pos: IVec2) -> Self {
|
pub fn from_offset(offset_pos: IVec2) -> Self {
|
||||||
return HexCoord {
|
return HexCoord {
|
||||||
offset: offset_pos,
|
hex: offset_to_hex(offset_pos),
|
||||||
hex: offset_to_hex(offset_pos),
|
};
|
||||||
world: offset3d_to_world(offset_pos.extend(0).xzy().as_vec3()),
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_chunk_pos(&self) -> IVec2 {
|
pub fn is_in_bounds(&self, map_height: usize, map_width: usize) -> bool {
|
||||||
return IVec2 {
|
if self.hex.x < 0 || self.hex.y < 0 {
|
||||||
x: (self.offset.x as f32 / Chunk::SIZE as f32).floor() as i32,
|
return false;
|
||||||
y: (self.offset.y as f32 / Chunk::SIZE as f32).floor() as i32,
|
}
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_chunk_index(&self, width: usize) -> usize {
|
if self.hex.x >= map_width as i32 || self.hex.y >= map_height as i32 {
|
||||||
let pos = self.to_chunk_pos();
|
return false;
|
||||||
return pos.x as usize + pos.y as usize * width;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn distance(&self, other: &HexCoord) -> i32 {
|
return true;
|
||||||
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 {
|
pub fn to_chunk_pos(&self) -> IVec2 {
|
||||||
if self == center || angle == 0 {
|
return IVec2 {
|
||||||
return self.clone();
|
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;
|
pub fn to_chunk(&self) -> HexCoord {
|
||||||
let mut pc = self.hex - center.hex;
|
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 {
|
pub fn to_world(&self, height: f32) -> Vec3 {
|
||||||
for _ in 0..a {
|
return offset_to_world(self.hex.xy(), height);
|
||||||
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 {
|
pub fn to_offset(&self) -> IVec2 {
|
||||||
return (hex * -1).yzx();
|
return self.hex.xy();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn slide_right(hex: IVec3) -> IVec3 {
|
pub fn to_index(&self, width: usize) -> i32 {
|
||||||
return (hex * -1).zxy();
|
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;
|
let s = Self::DIRECTIONS[(dir % 6) as usize] * radius as i32;
|
||||||
return Self::from_offset(self.hex.xy() + s.xy());
|
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];
|
let d = Self::DIRECTIONS[dir % 6];
|
||||||
return Self::from_offset(self.hex.xy() + d.xy());
|
return Self::from_offset(self.hex.xy() + d.xy());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_neighbors(&self) -> [HexCoord; 6]{
|
pub fn get_neighbors(&self) -> [HexCoord; 6] {
|
||||||
return [
|
return [
|
||||||
self.get_neighbor(0),
|
self.get_neighbor(0),
|
||||||
self.get_neighbor(1),
|
self.get_neighbor(1),
|
||||||
@@ -157,6 +179,6 @@ impl HexCoord {
|
|||||||
self.get_neighbor(3),
|
self.get_neighbor(3),
|
||||||
self.get_neighbor(4),
|
self.get_neighbor(4),
|
||||||
self.get_neighbor(5),
|
self.get_neighbor(5),
|
||||||
]
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
|
use crate::hex_utils::HexCoord;
|
||||||
use bevy::math::IVec2;
|
use bevy::math::IVec2;
|
||||||
|
use bevy::prelude::Resource;
|
||||||
|
|
||||||
pub struct GenerationConfig {
|
pub struct GenerationConfig {
|
||||||
pub noise_scale: f64,
|
pub noise_scale: f64,
|
||||||
@@ -26,24 +28,33 @@ pub mod prelude {
|
|||||||
impl Chunk {
|
impl Chunk {
|
||||||
pub const SIZE: usize = 32;
|
pub const SIZE: usize = 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Resource)]
|
||||||
pub struct Map {
|
pub struct Map {
|
||||||
pub chunks: Vec<Chunk>,
|
pub chunks: Vec<Chunk>,
|
||||||
pub height: usize,
|
pub height: usize,
|
||||||
pub width: 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 heightmap;
|
||||||
pub mod hex_utils;
|
pub mod hex_utils;
|
||||||
pub mod mesh_generator;
|
pub mod mesh_generator;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn it_works() {
|
|
||||||
// let result = add(2, 2);
|
|
||||||
// assert_eq!(result, 4);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::hex_utils::HexCoord;
|
||||||
use crate::{
|
use crate::{
|
||||||
hex_utils::{offset3d_to_world, INNER_RADIUS, OUTER_RADIUS},
|
hex_utils::{offset3d_to_world, INNER_RADIUS, OUTER_RADIUS},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
@@ -19,7 +20,7 @@ const HEX_CORNERS: [Vec3; 6] = [
|
|||||||
Vec3::new(-INNER_RADIUS, 0., 0.5 * OUTER_RADIUS),
|
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 vertex_count: usize = Chunk::SIZE * Chunk::SIZE;
|
||||||
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);
|
||||||
@@ -28,10 +29,22 @@ pub fn generate_chunk_mesh(chunk: &Chunk) -> Mesh {
|
|||||||
|
|
||||||
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 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 off_pos = Vec3::new(x as f32, height, z as f32);
|
||||||
let grid_pos = offset3d_to_world(off_pos);
|
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
|
//TODO: figure out texture index
|
||||||
fn create_tile(
|
fn create_tile(
|
||||||
pos: Vec3,
|
pos: Vec3,
|
||||||
|
neighbors: &[Option<f32>; 6],
|
||||||
verts: &mut Vec<Vec3>,
|
verts: &mut Vec<Vec3>,
|
||||||
uvs: &mut Vec<Vec2>,
|
uvs: &mut Vec<Vec2>,
|
||||||
normals: &mut Vec<Vec3>,
|
normals: &mut Vec<Vec3>,
|
||||||
indices: &mut Vec<u32>,
|
indices: &mut Vec<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);
|
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);
|
||||||
indices.push(idx + 1 + ((i as u32 + 1) % 6));
|
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.));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,20 +18,22 @@ pub struct PhosCameraPlugin;
|
|||||||
|
|
||||||
impl Plugin for PhosCameraPlugin {
|
impl Plugin for PhosCameraPlugin {
|
||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.add_systems(Startup, setup)
|
app.add_systems(Startup, setup).add_systems(
|
||||||
.add_systems(Update, (update_camera, grab_mouse, update_camera_mouse));
|
Update,
|
||||||
|
(grab_mouse, (update_camera, update_camera_mouse).chain()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(mut commands: Commands) {
|
fn setup(mut commands: Commands) {
|
||||||
commands.spawn((
|
commands.spawn((
|
||||||
Camera3dBundle {
|
Camera3dBundle {
|
||||||
transform: Transform::from_xyz(-200., 300., -200.)
|
transform: Transform::from_xyz(0., 30., 0.)
|
||||||
.looking_at(Vec3::new(1000., 0., 1000.), Vec3::Y),
|
.looking_at(Vec3::new(1000., 0., 1000.), Vec3::Y),
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
PhosCamera {
|
PhosCamera {
|
||||||
speed: 100.,
|
speed: 50.,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
@@ -56,17 +58,18 @@ fn update_camera(
|
|||||||
if keyboard_input.pressed(KeyCode::KeyS) {
|
if keyboard_input.pressed(KeyCode::KeyS) {
|
||||||
move_vec += Vec3::Z;
|
move_vec += Vec3::Z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let rot = transform.rotation;
|
||||||
|
move_vec = (rot * move_vec.normalize_or_zero()) * cam.speed * time.delta_seconds();
|
||||||
|
|
||||||
if keyboard_input.pressed(KeyCode::ShiftLeft) {
|
if keyboard_input.pressed(KeyCode::ShiftLeft) {
|
||||||
move_vec += Vec3::NEG_Y;
|
move_vec += Vec3::from(transform.down());
|
||||||
}
|
}
|
||||||
if keyboard_input.pressed(KeyCode::Space) {
|
if keyboard_input.pressed(KeyCode::Space) {
|
||||||
move_vec += Vec3::Y;
|
move_vec += Vec3::from(transform.up());
|
||||||
}
|
}
|
||||||
if move_vec.length_squared() == 0. {
|
|
||||||
return;
|
transform.translation += move_vec.normalize_or_zero() * cam.speed * time.delta_seconds();
|
||||||
}
|
|
||||||
let rot = transform.rotation;
|
|
||||||
transform.translation += (rot * move_vec.normalize()) * cam.speed * time.delta_seconds();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_camera_mouse(
|
fn update_camera_mouse(
|
||||||
@@ -80,19 +83,25 @@ fn update_camera_mouse(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let mut transform = cam_query.single_mut();
|
let mut transform = cam_query.single_mut();
|
||||||
let cam_rot = mouse_move.read().map(|event| event.delta).sum::<Vec2>() * time.delta_seconds();
|
let window_scale = window.height().min(window.width());
|
||||||
|
|
||||||
let (mut pitch, mut yaw, _) = transform.rotation.to_euler(EulerRot::XYZ);
|
for ev in mouse_move.read() {
|
||||||
|
let (mut yaw, mut pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);
|
||||||
|
match window.cursor.grab_mode {
|
||||||
|
CursorGrabMode::None => (),
|
||||||
|
_ => {
|
||||||
|
// Using smallest of height or width ensures equal vertical and horizontal sensitivity
|
||||||
|
pitch -= (ev.delta.y * time.delta_seconds() * 5.).to_radians();
|
||||||
|
yaw -= (ev.delta.x * time.delta_seconds() * 5.).to_radians();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pitch -= cam_rot.y.to_radians();
|
pitch = pitch.clamp(-1.54, 1.54);
|
||||||
yaw -= cam_rot.x.to_radians();
|
|
||||||
pitch = pitch.clamp(-1.54, 1.54);
|
|
||||||
// if rot_x > PI && cam_rot.x < 2. * PI {
|
|
||||||
// rot_x = PI;
|
|
||||||
// }
|
|
||||||
|
|
||||||
transform.rotation =
|
// Order is important to prevent unintended roll
|
||||||
Quat::from_axis_angle(Vec3::Y, yaw) * Quat::from_axis_angle(Vec3::X, pitch);
|
transform.rotation =
|
||||||
|
Quat::from_axis_angle(Vec3::Y, yaw) * Quat::from_axis_angle(Vec3::X, pitch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn grab_mouse(
|
fn grab_mouse(
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ fn main() {
|
|||||||
}),
|
}),
|
||||||
..default()
|
..default()
|
||||||
}),
|
}),
|
||||||
WireframePlugin,
|
|
||||||
WorldInspectorPlugin::new(),
|
WorldInspectorPlugin::new(),
|
||||||
PhosGamePlugin,
|
PhosGamePlugin,
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -1,7 +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;
|
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, hex_utils::offset3d_to_world,
|
||||||
mesh_generator::generate_chunk_mesh, prelude::*,
|
mesh_generator::generate_chunk_mesh, prelude::*,
|
||||||
@@ -13,11 +15,17 @@ 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,
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,76 +38,103 @@ fn init_game(mut commands: Commands) {
|
|||||||
|
|
||||||
commands.spawn(DirectionalLightBundle {
|
commands.spawn(DirectionalLightBundle {
|
||||||
directional_light: DirectionalLight {
|
directional_light: DirectionalLight {
|
||||||
shadows_enabled: false,
|
shadows_enabled: true,
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
cascade_shadow_config: CascadeShadowConfig {
|
cascade_shadow_config: CascadeShadowConfig {
|
||||||
bounds: vec![20., 40., 80., 1000., 5000., 19000., 20000.],
|
bounds: vec![500., 1000., 5000., 10000.],
|
||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
transform: Transform::from_xyz(0.0, 16.0, 5.).looking_at(Vec3::ZERO, Vec3::Y),
|
transform: Transform::from_xyz(500., 160.0, 500.).looking_at(Vec3::ZERO, Vec3::Y),
|
||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn draw_gizmos(mut gizmos: Gizmos, hm: Res<Map>) {
|
||||||
|
gizmos.arrow(Vec3::ZERO, Vec3::Y * 1.5, Color::GREEN);
|
||||||
|
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 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);
|
||||||
|
|
||||||
|
// let t = coord.get_neighbor(5);
|
||||||
|
// 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();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn create_map(
|
fn create_map(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
) {
|
) {
|
||||||
let heightmap = generate_heightmap(
|
let heightmap = generate_heightmap(
|
||||||
32,
|
1,
|
||||||
32,
|
1,
|
||||||
&GenerationConfig {
|
&GenerationConfig {
|
||||||
layers: vec![GeneratorLayer {
|
layers: vec![
|
||||||
base_roughness: 2.14,
|
GeneratorLayer {
|
||||||
roughness: 0.87,
|
base_roughness: 2.14,
|
||||||
strength: 2.93,
|
roughness: 0.87,
|
||||||
min_value: -0.2,
|
strength: 2.93,
|
||||||
persistence: 0.77,
|
min_value: -0.2,
|
||||||
is_rigid: false,
|
persistence: 0.77,
|
||||||
weight: 0.,
|
is_rigid: false,
|
||||||
weight_multi: 0.,
|
weight: 0.,
|
||||||
layers: 4,
|
weight_multi: 0.,
|
||||||
first_layer_mask: false,
|
layers: 4,
|
||||||
},GeneratorLayer {
|
first_layer_mask: false,
|
||||||
base_roughness: 2.85,
|
},
|
||||||
roughness: 2.,
|
GeneratorLayer {
|
||||||
strength: -0.23,
|
base_roughness: 2.85,
|
||||||
min_value: -0.,
|
roughness: 2.,
|
||||||
persistence: 1.,
|
strength: -0.23,
|
||||||
is_rigid: false,
|
min_value: -0.,
|
||||||
weight: 0.,
|
persistence: 1.,
|
||||||
weight_multi: 0.,
|
is_rigid: false,
|
||||||
layers: 4,
|
weight: 0.,
|
||||||
first_layer_mask: false,
|
weight_multi: 0.,
|
||||||
},GeneratorLayer {
|
layers: 4,
|
||||||
base_roughness: 2.6,
|
first_layer_mask: false,
|
||||||
roughness: 4.,
|
},
|
||||||
strength: 10.44,
|
GeneratorLayer {
|
||||||
min_value: 0.,
|
base_roughness: 2.6,
|
||||||
persistence: 1.57,
|
roughness: 4.,
|
||||||
is_rigid: true,
|
strength: 10.44,
|
||||||
weight: 1.,
|
min_value: 0.,
|
||||||
weight_multi: 0.35,
|
persistence: 1.57,
|
||||||
layers: 4,
|
is_rigid: true,
|
||||||
first_layer_mask: true,
|
weight: 1.,
|
||||||
},GeneratorLayer {
|
weight_multi: 0.35,
|
||||||
base_roughness: 3.87,
|
layers: 4,
|
||||||
roughness: 5.8,
|
first_layer_mask: true,
|
||||||
strength: -1.,
|
},
|
||||||
min_value: 0.,
|
GeneratorLayer {
|
||||||
persistence: 0.,
|
base_roughness: 3.87,
|
||||||
is_rigid: true,
|
roughness: 5.8,
|
||||||
weight: 1.,
|
strength: -1.,
|
||||||
weight_multi: 4.57,
|
min_value: 0.,
|
||||||
layers: 3,
|
persistence: 0.,
|
||||||
first_layer_mask: true,
|
is_rigid: true,
|
||||||
}],
|
weight: 1.,
|
||||||
|
weight_multi: 4.57,
|
||||||
|
layers: 3,
|
||||||
|
first_layer_mask: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
noise_scale: 350.,
|
noise_scale: 350.,
|
||||||
sea_level: 4.,
|
sea_level: 4.,
|
||||||
},
|
},
|
||||||
1,
|
2,
|
||||||
);
|
);
|
||||||
|
|
||||||
let debug_material = materials.add(StandardMaterial {
|
let debug_material = materials.add(StandardMaterial {
|
||||||
@@ -107,9 +142,9 @@ fn create_map(
|
|||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
|
|
||||||
for chunk in heightmap.chunks {
|
for chunk in &heightmap.chunks {
|
||||||
let mesh = generate_chunk_mesh(&chunk);
|
let mesh = generate_chunk_mesh(&chunk, &heightmap);
|
||||||
let pos = offset_to_world(chunk.chunk_offset * Chunk::SIZE as i32);
|
let pos = offset_to_world(chunk.chunk_offset * Chunk::SIZE as i32, 0.);
|
||||||
commands.spawn(PbrBundle {
|
commands.spawn(PbrBundle {
|
||||||
mesh: meshes.add(mesh),
|
mesh: meshes.add(mesh),
|
||||||
material: debug_material.clone(),
|
material: debug_material.clone(),
|
||||||
@@ -117,4 +152,6 @@ fn create_map(
|
|||||||
..default()
|
..default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
commands.insert_resource(heightmap);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user