From c31c2fb908bcdd5d56d564dc05e43ad8b58f4820 Mon Sep 17 00:00:00 2001 From: Amatsugu Date: Tue, 4 Jun 2024 09:18:31 -0400 Subject: [PATCH] organization and buidings db --- Cargo.lock | 9 + Cargo.toml | 5 +- engine/world_generation/src/consts.rs | 34 ++ .../src/{ => generators}/chunk_colliders.rs | 0 .../src/{ => generators}/mesh_generator.rs | 0 engine/world_generation/src/generators/mod.rs | 3 + .../{ => generators}/packed_mesh_generator.rs | 0 engine/world_generation/src/lib.rs | 332 +----------------- engine/world_generation/src/map/chunk.rs | 74 ++++ engine/world_generation/src/map/config.rs | 37 ++ engine/world_generation/src/map/map.rs | 167 +++++++++ engine/world_generation/src/map/mesh_chunk.rs | 24 ++ engine/world_generation/src/map/mod.rs | 4 + engine/world_generation/src/prelude.rs | 5 + game/buildings/Cargo.toml | 13 + game/buildings/src/buildings_database.rs | 65 ++++ game/buildings/src/lib.rs | 1 + game/main/Cargo.toml | 4 +- game/main/src/utlis/chunk_utils.rs | 5 +- game/main/src/utlis/render_distance_system.rs | 13 +- rustfmt.toml | 6 +- 21 files changed, 453 insertions(+), 348 deletions(-) create mode 100644 engine/world_generation/src/consts.rs rename engine/world_generation/src/{ => generators}/chunk_colliders.rs (100%) rename engine/world_generation/src/{ => generators}/mesh_generator.rs (100%) create mode 100644 engine/world_generation/src/generators/mod.rs rename engine/world_generation/src/{ => generators}/packed_mesh_generator.rs (100%) create mode 100644 engine/world_generation/src/map/chunk.rs create mode 100644 engine/world_generation/src/map/config.rs create mode 100644 engine/world_generation/src/map/map.rs create mode 100644 engine/world_generation/src/map/mesh_chunk.rs create mode 100644 engine/world_generation/src/map/mod.rs create mode 100644 engine/world_generation/src/prelude.rs create mode 100644 game/buildings/Cargo.toml create mode 100644 game/buildings/src/buildings_database.rs create mode 100644 game/buildings/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 9ad4cfa..76a9aff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1321,6 +1321,14 @@ dependencies = [ "tracing", ] +[[package]] +name = "buildings" +version = "0.1.0" +dependencies = [ + "bevy", + "world_generation", +] + [[package]] name = "bumpalo" version = "3.15.4" @@ -3246,6 +3254,7 @@ dependencies = [ "bevy", "bevy-inspector-egui 0.23.4", "bevy_rapier3d", + "buildings", "iyes_perf_ui", "noise 0.8.2", "rayon", diff --git a/Cargo.toml b/Cargo.toml index 06bfffe..585fbbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,8 +2,9 @@ resolver = "2" members = [ "game/main", + "game/buildings", "engine/world_generation", - "engine/asset_loader"] + "engine/asset_loader", "game/buildings"] # Enable a small amount of optimization in debug mode [profile.dev] @@ -14,4 +15,4 @@ opt-level = 1 opt-level = 3 [profile.release] -codegen-units = 1 \ No newline at end of file +codegen-units = 1 diff --git a/engine/world_generation/src/consts.rs b/engine/world_generation/src/consts.rs new file mode 100644 index 0000000..b54011a --- /dev/null +++ b/engine/world_generation/src/consts.rs @@ -0,0 +1,34 @@ +use bevy::{ + prelude::*, + render::{mesh::MeshVertexAttribute, render_resource::VertexFormat}, +}; + +use crate::hex_utils::{INNER_RADIUS, OUTER_RADIUS}; + +pub const TEX_MULTI: Vec2 = Vec2::new(1000., 1.); + +pub const HEX_CORNERS: [Vec3; 6] = [ + Vec3::new(0., 0., OUTER_RADIUS), + Vec3::new(INNER_RADIUS, 0., 0.5 * OUTER_RADIUS), + Vec3::new(INNER_RADIUS, 0., -0.5 * OUTER_RADIUS), + Vec3::new(0., 0., -OUTER_RADIUS), + Vec3::new(-INNER_RADIUS, 0., -0.5 * OUTER_RADIUS), + Vec3::new(-INNER_RADIUS, 0., 0.5 * OUTER_RADIUS), +]; + +pub const HEX_NORMALS: [Vec3; 6] = [ + Vec3::new(INNER_RADIUS / 2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / 2.), + Vec3::Z, + Vec3::new(INNER_RADIUS / -2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / 2.), + Vec3::new(INNER_RADIUS / -2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / -2.), + Vec3::NEG_Z, + Vec3::new(INNER_RADIUS / 2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / -2.), +]; + +pub const ATTRIBUTE_PACKED_VERTEX_DATA: MeshVertexAttribute = + MeshVertexAttribute::new("PackedVertexData", 988540817, VertexFormat::Uint32); +pub const ATTRIBUTE_VERTEX_HEIGHT: MeshVertexAttribute = + MeshVertexAttribute::new("VertexHeight", 988540717, VertexFormat::Float32); + +pub const ATTRIBUTE_TEXTURE_INDEX: MeshVertexAttribute = + MeshVertexAttribute::new("TextureIndex", 988540917, VertexFormat::Uint32); diff --git a/engine/world_generation/src/chunk_colliders.rs b/engine/world_generation/src/generators/chunk_colliders.rs similarity index 100% rename from engine/world_generation/src/chunk_colliders.rs rename to engine/world_generation/src/generators/chunk_colliders.rs diff --git a/engine/world_generation/src/mesh_generator.rs b/engine/world_generation/src/generators/mesh_generator.rs similarity index 100% rename from engine/world_generation/src/mesh_generator.rs rename to engine/world_generation/src/generators/mesh_generator.rs diff --git a/engine/world_generation/src/generators/mod.rs b/engine/world_generation/src/generators/mod.rs new file mode 100644 index 0000000..fa61ee3 --- /dev/null +++ b/engine/world_generation/src/generators/mod.rs @@ -0,0 +1,3 @@ +pub mod chunk_colliders; +pub mod mesh_generator; +pub mod packed_mesh_generator; diff --git a/engine/world_generation/src/packed_mesh_generator.rs b/engine/world_generation/src/generators/packed_mesh_generator.rs similarity index 100% rename from engine/world_generation/src/packed_mesh_generator.rs rename to engine/world_generation/src/generators/packed_mesh_generator.rs diff --git a/engine/world_generation/src/lib.rs b/engine/world_generation/src/lib.rs index e2ee706..b044427 100644 --- a/engine/world_generation/src/lib.rs +++ b/engine/world_generation/src/lib.rs @@ -1,333 +1,9 @@ pub mod biome_painter; -pub mod chunk_colliders; +pub mod consts; +pub mod generators; pub mod heightmap; pub mod hex_utils; -pub mod mesh_generator; -pub mod packed_mesh_generator; +pub mod map; +pub mod prelude; pub mod tile_manager; pub mod tile_mapper; - -pub mod prelude { - use crate::hex_utils::{get_tile_count, HexCoord, INNER_RADIUS, OUTER_RADIUS, SHORT_DIAGONAL}; - use bevy::math::{IVec2, UVec2, Vec2, Vec3}; - use bevy::prelude::Resource; - use bevy::prelude::*; - use bevy::render::mesh::MeshVertexAttribute; - use bevy::render::render_resource::VertexFormat; - use bevy_inspector_egui::InspectorOptions; - use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator}; - pub const TEX_MULTI: Vec2 = Vec2::new(1000., 1.); - - pub const HEX_CORNERS: [Vec3; 6] = [ - Vec3::new(0., 0., OUTER_RADIUS), - Vec3::new(INNER_RADIUS, 0., 0.5 * OUTER_RADIUS), - Vec3::new(INNER_RADIUS, 0., -0.5 * OUTER_RADIUS), - Vec3::new(0., 0., -OUTER_RADIUS), - Vec3::new(-INNER_RADIUS, 0., -0.5 * OUTER_RADIUS), - Vec3::new(-INNER_RADIUS, 0., 0.5 * OUTER_RADIUS), - ]; - - pub const HEX_NORMALS: [Vec3; 6] = [ - Vec3::new(INNER_RADIUS / 2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / 2.), - Vec3::Z, - Vec3::new(INNER_RADIUS / -2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / 2.), - Vec3::new(INNER_RADIUS / -2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / -2.), - Vec3::NEG_Z, - Vec3::new(INNER_RADIUS / 2., 0., (OUTER_RADIUS + 0.5 * OUTER_RADIUS) / -2.), - ]; - - #[derive(Resource, Reflect, Default)] - #[reflect(Resource)] - pub struct GenerationConfig { - pub noise_scale: f64, - pub sea_level: f64, - pub border_size: f32, - pub size: UVec2, - pub layers: Vec, - } - - impl GenerationConfig { - pub fn get_total_width(&self) -> usize { - return self.size.x as usize * Chunk::SIZE; - } - pub fn get_total_height(&self) -> usize { - return self.size.y as usize * Chunk::SIZE; - } - } - - #[derive(Reflect, InspectorOptions)] - pub struct GeneratorLayer { - pub strength: f64, - pub min_value: f64, - pub base_roughness: f64, - pub roughness: f64, - pub persistence: f64, - pub is_rigid: bool, - pub weight: f64, - pub weight_multi: f64, - pub layers: usize, - pub first_layer_mask: bool, - } - - #[derive(Clone)] - pub struct Chunk { - pub heights: [f32; Chunk::AREA], - pub textures: [[u32; 2]; Chunk::AREA], - pub moisture: [f32; Chunk::AREA], - pub temperature: [f32; Chunk::AREA], - pub chunk_offset: IVec2, - } - - impl Default for Chunk { - fn default() -> Self { - Self { - heights: [0.; Chunk::AREA], - textures: [[0; 2]; Chunk::AREA], - moisture: [0.; Chunk::AREA], - temperature: [0.; Chunk::AREA], - chunk_offset: Default::default(), - } - } - } - - impl Chunk { - pub const SIZE: usize = 64; - pub const AREA: usize = Chunk::SIZE * Chunk::SIZE; - pub const WORLD_WIDTH: f32 = Chunk::SIZE as f32 * SHORT_DIAGONAL; - pub const WORLD_HEIGHT: f32 = Chunk::SIZE as f32 * 1.5; - pub const WORLD_SIZE: Vec2 = Vec2::new(Chunk::WORLD_WIDTH, Chunk::WORLD_HEIGHT); - - pub fn get_pos_z_edge(&self) -> [f32; Chunk::SIZE] { - let mut data = [0.; Chunk::SIZE]; - - for x in 0..Chunk::SIZE { - let idx = x + (Chunk::SIZE - 1) * Chunk::SIZE; - data[x] = self.heights[idx]; - } - - return data; - } - - pub fn get_neg_z_edge(&self) -> [f32; Chunk::SIZE] { - let mut data = [0.; Chunk::SIZE]; - - for x in 0..Chunk::SIZE { - data[x] = self.heights[x]; - } - - return data; - } - - pub fn get_pos_x_edge(&self) -> [f32; Chunk::SIZE] { - let mut data = [0.; Chunk::SIZE]; - - for z in 0..Chunk::SIZE { - let idx = (Chunk::SIZE - 1) + z * Chunk::SIZE; - data[z] = self.heights[idx]; - } - - return data; - } - - pub fn get_neg_x_edge(&self) -> [f32; Chunk::SIZE] { - let mut data = [0.; Chunk::SIZE]; - - for z in 0..Chunk::SIZE { - let idx = z * Chunk::SIZE; - data[z] = self.heights[idx]; - } - - return data; - } - } - - pub struct MeshChunkData { - pub heights: [f32; Chunk::AREA], - pub textures: [[u32; 2]; Chunk::AREA], - } - - impl MeshChunkData { - pub fn get_neighbors(&self, coord: &HexCoord) -> [f32; 6] { - let mut data = [0.; 6]; - let n_tiles = coord.get_neighbors(); - for i in 0..6 { - let n = n_tiles[i]; - if !n.is_in_bounds(Chunk::SIZE, Chunk::SIZE) { - continue; - } - data[i] = self.heights[n.to_index(Chunk::SIZE)]; - } - - return data; - } - } - - #[derive(Resource, Clone)] - pub struct Map { - pub chunks: Vec, - pub height: usize, - pub width: usize, - pub sea_level: f32, - } - - impl Map { - pub fn get_chunk_mesh_data(&self, chunk_index: usize) -> MeshChunkData { - #[cfg(feature = "tracing")] - let _spawn_span = info_span!("Chunk Mesh Data").entered(); - let chunk = &self.chunks[chunk_index]; - - return MeshChunkData { - heights: chunk.heights.clone(), - textures: chunk.textures.clone(), - }; - } - - 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(h, w) { - continue; - } - let c_idx = n_tile.to_chunk_index(self.width); - let chunk = &self.chunks[c_idx]; - let local = n_tile.to_chunk_local_index(); - results[i] = Some(chunk.heights[local]); - } - return results; - } - - pub fn sample_height(&self, pos: &HexCoord) -> f32 { - let chunk = &self.chunks[pos.to_chunk_index(self.width)]; - return chunk.heights[pos.to_chunk_local_index()]; - } - - pub fn sample_height_mut(&mut self, pos: &HexCoord) -> &mut f32 { - let chunk = &mut self.chunks[pos.to_chunk_index(self.width)]; - return &mut chunk.heights[pos.to_chunk_local_index()]; - } - - pub fn is_in_bounds(&self, pos: &HexCoord) -> bool { - return pos.is_in_bounds(self.height * Chunk::SIZE, self.width * Chunk::SIZE); - } - - pub fn get_moisture(&self, pos: &HexCoord) -> f32 { - let chunk = &self.chunks[pos.to_chunk_index(self.width)]; - return chunk.moisture[pos.to_chunk_local_index()]; - } - - pub fn get_tempurature(&self, pos: &HexCoord) -> f32 { - let chunk = &self.chunks[pos.to_chunk_index(self.width)]; - return chunk.temperature[pos.to_chunk_local_index()]; - } - - pub fn get_center(&self) -> Vec3 { - let w = self.get_world_width(); - let h = self.get_world_height(); - return Vec3::new(w / 2., self.sea_level, h / 2.); - } - - pub fn get_world_width(&self) -> f32 { - return (self.width * Chunk::SIZE) as f32 * SHORT_DIAGONAL; - } - pub fn get_world_height(&self) -> f32 { - return (self.height * Chunk::SIZE) as f32 * 1.5; - } - - pub fn get_world_size(&self) -> Vec2 { - return Vec2::new(self.get_world_width(), self.get_world_height()); - } - - pub fn set_height(&mut self, pos: &HexCoord, height: f32) { - self.chunks[pos.to_chunk_index(self.width)].heights[pos.to_chunk_local_index()] = height; - } - - pub fn create_crater(&mut self, pos: &HexCoord, radius: usize, depth: f32) -> Vec { - assert!(radius != 0, "Radius cannot be zero"); - let width = self.width; - - let mut chunks = self.hex_select_mut(pos, radius, true, |p, h, r| { - let d = (r as f32) / (radius as f32); - let cur = *h; - let h2 = cur - depth; - *h = h2.lerp(cur, d * d); - - return p.to_chunk_index(width); - }); - - chunks.dedup(); - - return chunks; - } - - pub fn hex_select(&self, center: &HexCoord, radius: usize, include_center: bool, op: OP) -> Vec - where - OP: Fn(&HexCoord, f32, usize) -> Ret + Sync + Send, - { - assert!(radius != 0, "Radius cannot be zero"); - - if include_center { - let h = self.sample_height(¢er); - (op)(¢er, h, 0); - } - - let mut result = Vec::with_capacity(get_tile_count(radius)); - - for k in 0..(radius + 1) { - let mut p = center.scale(4, k); - for i in 0..6 { - for _j in 0..k { - p = p.get_neighbor(i); - let h = self.sample_height(&p); - result.push((op)(&p, h, k)); - } - } - } - - return result; - } - - pub fn hex_select_mut( - &mut self, - center: &HexCoord, - radius: usize, - include_center: bool, - op: OP, - ) -> Vec - where - OP: Fn(&HexCoord, &mut f32, usize) -> Ret + Sync + Send, - { - assert!(radius != 0, "Radius cannot be zero"); - - if include_center { - let h = self.sample_height_mut(¢er); - (op)(¢er, h, 0); - } - - let mut result = Vec::with_capacity(get_tile_count(radius)); - - for k in 0..(radius + 1) { - let mut p = center.scale(4, k); - for i in 0..6 { - for _j in 0..k { - p = p.get_neighbor(i); - let h = self.sample_height_mut(&p); - result.push((op)(&p, h, k)); - } - } - } - - return result; - } - } - pub const ATTRIBUTE_PACKED_VERTEX_DATA: MeshVertexAttribute = - MeshVertexAttribute::new("PackedVertexData", 988540817, VertexFormat::Uint32); - pub const ATTRIBUTE_VERTEX_HEIGHT: MeshVertexAttribute = - MeshVertexAttribute::new("VertexHeight", 988540717, VertexFormat::Float32); - - pub const ATTRIBUTE_TEXTURE_INDEX: MeshVertexAttribute = - MeshVertexAttribute::new("TextureIndex", 988540917, VertexFormat::Uint32); -} diff --git a/engine/world_generation/src/map/chunk.rs b/engine/world_generation/src/map/chunk.rs new file mode 100644 index 0000000..316855a --- /dev/null +++ b/engine/world_generation/src/map/chunk.rs @@ -0,0 +1,74 @@ +use crate::hex_utils::SHORT_DIAGONAL; +use bevy::prelude::*; + +#[derive(Clone)] +pub struct Chunk { + pub heights: [f32; Chunk::AREA], + pub textures: [[u32; 2]; Chunk::AREA], + pub moisture: [f32; Chunk::AREA], + pub temperature: [f32; Chunk::AREA], + pub chunk_offset: IVec2, +} + +impl Default for Chunk { + fn default() -> Self { + Self { + heights: [0.; Chunk::AREA], + textures: [[0; 2]; Chunk::AREA], + moisture: [0.; Chunk::AREA], + temperature: [0.; Chunk::AREA], + chunk_offset: Default::default(), + } + } +} + +impl Chunk { + pub const SIZE: usize = 64; + pub const AREA: usize = Chunk::SIZE * Chunk::SIZE; + pub const WORLD_WIDTH: f32 = Chunk::SIZE as f32 * SHORT_DIAGONAL; + pub const WORLD_HEIGHT: f32 = Chunk::SIZE as f32 * 1.5; + pub const WORLD_SIZE: Vec2 = Vec2::new(Chunk::WORLD_WIDTH, Chunk::WORLD_HEIGHT); + + pub fn get_pos_z_edge(&self) -> [f32; Chunk::SIZE] { + let mut data = [0.; Chunk::SIZE]; + + for x in 0..Chunk::SIZE { + let idx = x + (Chunk::SIZE - 1) * Chunk::SIZE; + data[x] = self.heights[idx]; + } + + return data; + } + + pub fn get_neg_z_edge(&self) -> [f32; Chunk::SIZE] { + let mut data = [0.; Chunk::SIZE]; + + for x in 0..Chunk::SIZE { + data[x] = self.heights[x]; + } + + return data; + } + + pub fn get_pos_x_edge(&self) -> [f32; Chunk::SIZE] { + let mut data = [0.; Chunk::SIZE]; + + for z in 0..Chunk::SIZE { + let idx = (Chunk::SIZE - 1) + z * Chunk::SIZE; + data[z] = self.heights[idx]; + } + + return data; + } + + pub fn get_neg_x_edge(&self) -> [f32; Chunk::SIZE] { + let mut data = [0.; Chunk::SIZE]; + + for z in 0..Chunk::SIZE { + let idx = z * Chunk::SIZE; + data[z] = self.heights[idx]; + } + + return data; + } +} diff --git a/engine/world_generation/src/map/config.rs b/engine/world_generation/src/map/config.rs new file mode 100644 index 0000000..4ae9214 --- /dev/null +++ b/engine/world_generation/src/map/config.rs @@ -0,0 +1,37 @@ +use bevy::prelude::*; +use bevy_inspector_egui::InspectorOptions; + +use super::chunk::Chunk; + +#[derive(Resource, Reflect, Default)] +#[reflect(Resource)] +pub struct GenerationConfig { + pub noise_scale: f64, + pub sea_level: f64, + pub border_size: f32, + pub size: UVec2, + pub layers: Vec, +} + +impl GenerationConfig { + pub fn get_total_width(&self) -> usize { + return self.size.x as usize * Chunk::SIZE; + } + pub fn get_total_height(&self) -> usize { + return self.size.y as usize * Chunk::SIZE; + } +} + +#[derive(Reflect, InspectorOptions)] +pub struct GeneratorLayer { + pub strength: f64, + pub min_value: f64, + pub base_roughness: f64, + pub roughness: f64, + pub persistence: f64, + pub is_rigid: bool, + pub weight: f64, + pub weight_multi: f64, + pub layers: usize, + pub first_layer_mask: bool, +} diff --git a/engine/world_generation/src/map/map.rs b/engine/world_generation/src/map/map.rs new file mode 100644 index 0000000..ce7874e --- /dev/null +++ b/engine/world_generation/src/map/map.rs @@ -0,0 +1,167 @@ +use bevy::prelude::*; + +use crate::hex_utils::*; + +use super::{chunk::Chunk, mesh_chunk::MeshChunkData}; + +#[derive(Resource, Clone)] +pub struct Map { + pub chunks: Vec, + pub height: usize, + pub width: usize, + pub sea_level: f32, +} + +impl Map { + pub fn get_chunk_mesh_data(&self, chunk_index: usize) -> MeshChunkData { + #[cfg(feature = "tracing")] + let _spawn_span = info_span!("Chunk Mesh Data").entered(); + let chunk = &self.chunks[chunk_index]; + + return MeshChunkData { + heights: chunk.heights.clone(), + textures: chunk.textures.clone(), + }; + } + + 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(h, w) { + continue; + } + let c_idx = n_tile.to_chunk_index(self.width); + let chunk = &self.chunks[c_idx]; + let local = n_tile.to_chunk_local_index(); + results[i] = Some(chunk.heights[local]); + } + return results; + } + + pub fn sample_height(&self, pos: &HexCoord) -> f32 { + let chunk = &self.chunks[pos.to_chunk_index(self.width)]; + return chunk.heights[pos.to_chunk_local_index()]; + } + + pub fn sample_height_mut(&mut self, pos: &HexCoord) -> &mut f32 { + let chunk = &mut self.chunks[pos.to_chunk_index(self.width)]; + return &mut chunk.heights[pos.to_chunk_local_index()]; + } + + pub fn is_in_bounds(&self, pos: &HexCoord) -> bool { + return pos.is_in_bounds(self.height * Chunk::SIZE, self.width * Chunk::SIZE); + } + + pub fn get_moisture(&self, pos: &HexCoord) -> f32 { + let chunk = &self.chunks[pos.to_chunk_index(self.width)]; + return chunk.moisture[pos.to_chunk_local_index()]; + } + + pub fn get_tempurature(&self, pos: &HexCoord) -> f32 { + let chunk = &self.chunks[pos.to_chunk_index(self.width)]; + return chunk.temperature[pos.to_chunk_local_index()]; + } + + pub fn get_center(&self) -> Vec3 { + let w = self.get_world_width(); + let h = self.get_world_height(); + return Vec3::new(w / 2., self.sea_level, h / 2.); + } + + pub fn get_world_width(&self) -> f32 { + return (self.width * Chunk::SIZE) as f32 * SHORT_DIAGONAL; + } + pub fn get_world_height(&self) -> f32 { + return (self.height * Chunk::SIZE) as f32 * 1.5; + } + + pub fn get_world_size(&self) -> Vec2 { + return Vec2::new(self.get_world_width(), self.get_world_height()); + } + + pub fn set_height(&mut self, pos: &HexCoord, height: f32) { + self.chunks[pos.to_chunk_index(self.width)].heights[pos.to_chunk_local_index()] = height; + } + + pub fn create_crater(&mut self, pos: &HexCoord, radius: usize, depth: f32) -> Vec { + assert!(radius != 0, "Radius cannot be zero"); + let width = self.width; + + let mut chunks = self.hex_select_mut(pos, radius, true, |p, h, r| { + let d = (r as f32) / (radius as f32); + let cur = *h; + let h2 = cur - depth; + *h = h2.lerp(cur, d * d); + + return p.to_chunk_index(width); + }); + + chunks.dedup(); + + return chunks; + } + + pub fn hex_select(&self, center: &HexCoord, radius: usize, include_center: bool, op: OP) -> Vec + where + OP: Fn(&HexCoord, f32, usize) -> Ret + Sync + Send, + { + assert!(radius != 0, "Radius cannot be zero"); + + if include_center { + let h = self.sample_height(¢er); + (op)(¢er, h, 0); + } + + let mut result = Vec::with_capacity(get_tile_count(radius)); + + for k in 0..(radius + 1) { + let mut p = center.scale(4, k); + for i in 0..6 { + for _j in 0..k { + p = p.get_neighbor(i); + let h = self.sample_height(&p); + result.push((op)(&p, h, k)); + } + } + } + + return result; + } + + pub fn hex_select_mut( + &mut self, + center: &HexCoord, + radius: usize, + include_center: bool, + op: OP, + ) -> Vec + where + OP: Fn(&HexCoord, &mut f32, usize) -> Ret + Sync + Send, + { + assert!(radius != 0, "Radius cannot be zero"); + + if include_center { + let h = self.sample_height_mut(¢er); + (op)(¢er, h, 0); + } + + let mut result = Vec::with_capacity(get_tile_count(radius)); + + for k in 0..(radius + 1) { + let mut p = center.scale(4, k); + for i in 0..6 { + for _j in 0..k { + p = p.get_neighbor(i); + let h = self.sample_height_mut(&p); + result.push((op)(&p, h, k)); + } + } + } + + return result; + } +} diff --git a/engine/world_generation/src/map/mesh_chunk.rs b/engine/world_generation/src/map/mesh_chunk.rs new file mode 100644 index 0000000..3a09423 --- /dev/null +++ b/engine/world_generation/src/map/mesh_chunk.rs @@ -0,0 +1,24 @@ +use crate::hex_utils::HexCoord; + +use super::chunk::Chunk; + +pub struct MeshChunkData { + pub heights: [f32; Chunk::AREA], + pub textures: [[u32; 2]; Chunk::AREA], +} + +impl MeshChunkData { + pub fn get_neighbors(&self, coord: &HexCoord) -> [f32; 6] { + let mut data = [0.; 6]; + let n_tiles = coord.get_neighbors(); + for i in 0..6 { + let n = n_tiles[i]; + if !n.is_in_bounds(Chunk::SIZE, Chunk::SIZE) { + continue; + } + data[i] = self.heights[n.to_index(Chunk::SIZE)]; + } + + return data; + } +} diff --git a/engine/world_generation/src/map/mod.rs b/engine/world_generation/src/map/mod.rs new file mode 100644 index 0000000..6e29e3e --- /dev/null +++ b/engine/world_generation/src/map/mod.rs @@ -0,0 +1,4 @@ +pub mod chunk; +pub mod mesh_chunk; +pub mod config; +pub mod map; \ No newline at end of file diff --git a/engine/world_generation/src/prelude.rs b/engine/world_generation/src/prelude.rs new file mode 100644 index 0000000..1c85b04 --- /dev/null +++ b/engine/world_generation/src/prelude.rs @@ -0,0 +1,5 @@ +pub use crate::consts::*; +pub use crate::map::chunk::*; +pub use crate::map::config::*; +pub use crate::map::map::*; +pub use crate::map::mesh_chunk::*; diff --git a/game/buildings/Cargo.toml b/game/buildings/Cargo.toml new file mode 100644 index 0000000..f6cadfd --- /dev/null +++ b/game/buildings/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "buildings" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +bevy = "0.13.2" +world_generation = {path = "../../engine/world_generation"} + +[features] +tracing = [] diff --git a/game/buildings/src/buildings_database.rs b/game/buildings/src/buildings_database.rs new file mode 100644 index 0000000..2f584b2 --- /dev/null +++ b/game/buildings/src/buildings_database.rs @@ -0,0 +1,65 @@ +use bevy::prelude::*; +use world_generation::hex_utils::HexCoord; + +#[derive(Resource)] +pub struct BuildingDatabase { + pub chunks: Vec, +} + +impl BuildingDatabase { + pub fn new(size: UVec2) -> Self { + let mut db = BuildingDatabase { + chunks: Vec::with_capacity(size.length_squared() as usize), + }; + + for y in 0..size.y as i32 { + for x in 0..size.x as i32 { + let offset = IVec2::new(x, y); + let index = (x + y * size.x as i32) as usize; + db.chunks.push(BuildingChunk::new(offset, index)); + } + } + + return db; + } + + pub fn get_buildings_in_range(&self, coord: &HexCoord, radius: usize) -> Option> { + assert!(radius != 0, "Radius cannot be zero"); + todo!(); + } + + pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry> { + todo!(); + } +} + +pub struct BuildingChunk { + pub entries: Vec, + pub index: usize, + pub offset: IVec2, +} + +impl BuildingChunk { + pub fn new(offset: IVec2, index: usize) -> Self { + return BuildingChunk { + entries: Vec::new(), + index, + offset, + }; + } + + pub fn get_building(&self, coord: &HexCoord) -> Option<&BuildingEntry> { + todo!(); + } +} + +pub struct BuildingEntry { + pub coord: HexCoord, + pub entity: Entity, +} + +impl BuildingEntry { + pub fn new(coord: HexCoord, entity: Entity) -> Self { + return BuildingEntry { coord, entity }; + } +} diff --git a/game/buildings/src/lib.rs b/game/buildings/src/lib.rs new file mode 100644 index 0000000..0e98d5c --- /dev/null +++ b/game/buildings/src/lib.rs @@ -0,0 +1 @@ +pub mod buildings_database; diff --git a/game/main/Cargo.toml b/game/main/Cargo.toml index 9fd824e..2fe4c00 100644 --- a/game/main/Cargo.toml +++ b/game/main/Cargo.toml @@ -14,7 +14,7 @@ noise = "0.8.2" world_generation ={path="../../engine/world_generation"} bevy_rapier3d = { version = "0.25.0", features = [ "simd-stable","parallel" ] } rayon = "1.10.0" - +buildings = {path="../buildings"} [features] -tracing = ["bevy/trace_tracy", "world_generation/tracing"] \ No newline at end of file +tracing = ["bevy/trace_tracy", "world_generation/tracing", "buildings/tracing"] \ No newline at end of file diff --git a/game/main/src/utlis/chunk_utils.rs b/game/main/src/utlis/chunk_utils.rs index 1a783bb..4e767f3 100644 --- a/game/main/src/utlis/chunk_utils.rs +++ b/game/main/src/utlis/chunk_utils.rs @@ -10,9 +10,8 @@ use bevy_rapier3d::geometry::{Collider, TriMeshFlags}; use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator}; use world_generation::{ biome_painter::BiomePainterAsset, - chunk_colliders::generate_chunk_collider, - hex_utils::{offset_to_index, offset_to_world}, - mesh_generator::generate_chunk_mesh, + generators::{chunk_colliders::generate_chunk_collider, mesh_generator::generate_chunk_mesh}, + hex_utils::offset_to_world, prelude::{Chunk, Map, MeshChunkData}, tile_manager::TileAsset, tile_mapper::TileMapperAsset, diff --git a/game/main/src/utlis/render_distance_system.rs b/game/main/src/utlis/render_distance_system.rs index 9c66658..13f6286 100644 --- a/game/main/src/utlis/render_distance_system.rs +++ b/game/main/src/utlis/render_distance_system.rs @@ -34,7 +34,6 @@ impl Default for RenderDistanceSettings { #[derive(Component)] pub struct RenderDistanceVisibility { - pub distance_multiplier: f32, pub offset: Vec3, } @@ -43,19 +42,11 @@ impl RenderDistanceVisibility { self.offset = offset; return self; } - - pub fn with_multiplier(mut self, distance_multiplier: f32) -> Self { - self.distance_multiplier = distance_multiplier; - return self; - } } impl Default for RenderDistanceVisibility { fn default() -> Self { - Self { - distance_multiplier: 1., - offset: Vec3::ZERO, - } + Self { offset: Vec3::ZERO } } } @@ -66,7 +57,7 @@ fn render_distance_system( ) { let camera = camera_query.single(); for (t, mut vis, r) in objects.iter_mut() { - let dist = (camera.translation - (t.translation + r.offset)).length() * r.distance_multiplier; + let dist = (camera.translation - (t.translation + r.offset)).length(); if settings.render_distance < dist { *vis = Visibility::Hidden; } else { diff --git a/rustfmt.toml b/rustfmt.toml index 8c948b9..cca1e7a 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,2 +1,4 @@ -hard_tabs=true -max_width=120 \ No newline at end of file +hard_tabs = true +max_width = 120 +brace_style = "AlwaysNextLine" +control_brace_style = "AlwaysNextLine" \ No newline at end of file