From bba34ea9e7c42a18e4a91f56688e21090e2fe5dc Mon Sep 17 00:00:00 2001 From: klangner Date: Fri, 26 Jul 2024 14:23:26 +0200 Subject: [PATCH] use glam Vec2 instead of custom implementaion --- Cargo.toml | 1 + src/cave/drunkard.rs | 4 ++-- src/cave/tile_map.rs | 25 ++++++++++++-------- src/cave/voronoi.rs | 10 ++++---- src/geometry.rs | 42 ++++------------------------------ src/layer.rs | 6 ++--- src/metric.rs | 13 +++++++---- src/path/dijkstra.rs | 14 ++++++------ src/poi/cull_unreachable.rs | 11 +++++---- src/poi/distant_exit.rs | 13 +++++++---- src/poi/starting_point.rs | 19 +++++++++------ src/rooms/bsp_interior.rs | 5 ++-- src/rooms/corridors_nearest.rs | 2 +- src/rooms/tile_map.rs | 13 +++++------ 14 files changed, 83 insertions(+), 95 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ba13c53..7811a67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ edition = "2021" [dependencies] fastrand = "2.1" +glam = "0.28" [workspace] members = ["demo"] \ No newline at end of file diff --git a/src/cave/drunkard.rs b/src/cave/drunkard.rs index caec28e..cf96b7f 100644 --- a/src/cave/drunkard.rs +++ b/src/cave/drunkard.rs @@ -14,8 +14,8 @@ //! use fastrand::Rng; +use glam::UVec2; -use crate::geometry::Vec2u; use crate::MapFilter; use super::tile_map::Symmetry; @@ -81,7 +81,7 @@ impl DrunkardsWalk { fn build(&self, rng: &mut Rng, map: &CaveMap) -> CaveMap { let mut new_map = map.clone(); // Set a central starting point - let starting_position = Vec2u::new(new_map.width / 2, new_map.height / 2); + let starting_position = UVec2::new(new_map.width / 2, new_map.height / 2); new_map.set_walkable(starting_position.x, starting_position.y, true); let total_tiles = new_map.width * new_map.height; diff --git a/src/cave/tile_map.rs b/src/cave/tile_map.rs index 7b625c5..2d9a020 100644 --- a/src/cave/tile_map.rs +++ b/src/cave/tile_map.rs @@ -7,10 +7,9 @@ //! The MapBuilder builds from this data the Map structure which is more suites for it. //! -use crate::{ - geometry::{diff_abs, Vec2u}, - layer::WalkableLayer, -}; +use glam::UVec2; + +use crate::layer::WalkableLayer; use std::fmt; #[derive(PartialEq, Copy, Clone)] @@ -27,8 +26,8 @@ pub struct CaveMap { pub walkable_layer: WalkableLayer, pub width: u32, pub height: u32, - pub starting_point: Option, - pub exit_point: Option, + pub starting_point: Option, + pub exit_point: Option, } impl CaveMap { @@ -75,8 +74,8 @@ impl CaveMap { self.walkable_layer.xy_idx(x, y) } - pub fn idx_point(&self, idx: usize) -> Vec2u { - Vec2u { + pub fn idx_point(&self, idx: usize) -> UVec2 { + UVec2 { x: idx as u32 % self.width, y: idx as u32 / self.width, } @@ -158,6 +157,14 @@ impl fmt::Display for CaveMap { } } +fn diff_abs(x: u32, y: u32) -> u32 { + if x >= y { + x - y + } else { + y - x + } +} + /// ------------------------------------------------------------------------------------------------ /// Module unit tests /// ------------------------------------------------------------------------------------------------ @@ -206,7 +213,7 @@ mod tests { let idx = map.xy_idx(x, y); - let Vec2u { x: x2, y: y2 } = map.idx_point(idx); + let UVec2 { x: x2, y: y2 } = map.idx_point(idx); assert_eq!(x, x2); assert_eq!(y, y2); diff --git a/src/cave/voronoi.rs b/src/cave/voronoi.rs index b45921d..6522e27 100644 --- a/src/cave/voronoi.rs +++ b/src/cave/voronoi.rs @@ -14,8 +14,8 @@ //! use fastrand::Rng; +use glam::UVec2; -use crate::geometry::Vec2u; use crate::MapFilter; use super::CaveMap; @@ -43,7 +43,7 @@ impl VoronoiHive { let mut voronoi_membership: Vec = vec![0; (map.width * map.height) as usize]; for (i, vid) in voronoi_membership.iter_mut().enumerate() { for (seed, pos) in seeds.iter().enumerate() { - let distance = pos.distance_to(&map.idx_point(i)); + let distance = (pos.as_vec2() - map.idx_point(i).as_vec2()).length(); voronoi_distance[seed] = (seed, distance); } @@ -80,13 +80,13 @@ impl VoronoiHive { } /// Generate random seeds - fn generate_seeds(&self, rng: &mut Rng, width: u32, height: u32) -> Vec { - let mut seeds: Vec = Vec::new(); + fn generate_seeds(&self, rng: &mut Rng, width: u32, height: u32) -> Vec { + let mut seeds: Vec = Vec::new(); while (seeds.len() as u32) < self.n_seeds { let vx = rng.u32(1..width); let vy = rng.u32(1..height); - let candidate = Vec2u::new(vx, vy); + let candidate = UVec2::new(vx, vy); if !seeds.contains(&candidate) { seeds.push(candidate); } diff --git a/src/geometry.rs b/src/geometry.rs index cf4c514..d4fc13b 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -1,26 +1,7 @@ -//! Support function for 2D geometry +//! Support function for 2D/3D geometry //! -/// Position on the map -#[derive(Default, PartialEq, Copy, Clone, Debug, Eq, Hash)] -pub struct Vec2u { - pub x: u32, - pub y: u32, -} - -impl Vec2u { - /// Create new point - pub fn new(x: u32, y: u32) -> Vec2u { - Vec2u { x, y } - } - - /// Euclidean distance to a given point - pub fn distance_to(self, point: &Vec2u) -> f32 { - let a = (self.x as f32 - point.x as f32).powf(2.0); - let b = (self.y as f32 - point.y as f32).powf(2.0); - (a + b).sqrt() - } -} +use glam::UVec2; /// Rectangle region on the map #[derive(PartialEq, Copy, Clone, Debug)] @@ -46,8 +27,8 @@ impl Rect { self.x1 <= other.x2 && self.x2 >= other.x1 && self.y1 <= other.y2 && self.y2 >= other.y1 } - pub fn center(&self) -> Vec2u { - Vec2u::new((self.x1 + self.x2) / 2, (self.y1 + self.y2) / 2) + pub fn center(&self) -> UVec2 { + UVec2::new((self.x1 + self.x2) / 2, (self.y1 + self.y2) / 2) } pub fn width(&self) -> u32 { @@ -75,13 +56,6 @@ impl Rect { /// assert_eq!(diff_abs(5, 3), 2); /// assert_eq!(diff_abs(3, 5), 2); /// ``` -pub fn diff_abs(x: u32, y: u32) -> u32 { - if x >= y { - x - y - } else { - y - x - } -} /// ------------------------------------------------------------------------------------------------ /// Module unit tests @@ -90,14 +64,6 @@ pub fn diff_abs(x: u32, y: u32) -> u32 { mod tests { use super::*; - #[test] - fn test_distance() { - let p1 = Vec2u::new(10, 10); - let p2 = Vec2u::new(14, 7); - let distance = p1.distance_to(&p2); - assert_eq!(distance, 5.0); - } - #[test] fn test_intersect() { let rect1 = Rect::new(10, 10, 40, 40); diff --git a/src/layer.rs b/src/layer.rs index 3cbe990..b5b1db6 100644 --- a/src/layer.rs +++ b/src/layer.rs @@ -3,7 +3,7 @@ use std::fmt; -use crate::geometry::Vec2u; +use glam::UVec2; #[derive(Default, Debug, Clone, PartialEq)] pub struct WalkableLayer { @@ -80,8 +80,8 @@ impl WalkableLayer { map } - pub fn idx_point(&self, idx: usize) -> Vec2u { - Vec2u { + pub fn idx_point(&self, idx: usize) -> UVec2 { + UVec2 { x: idx as u32 % self.width, y: idx as u32 / self.width, } diff --git a/src/metric.rs b/src/metric.rs index 9e13c4e..cd51458 100644 --- a/src/metric.rs +++ b/src/metric.rs @@ -4,7 +4,9 @@ //! and the provide generator score as an average. //! -use crate::{geometry::Vec2u, layer::WalkableLayer, path::DijkstraMap}; +use glam::UVec2; + +use crate::{layer::WalkableLayer, path::DijkstraMap}; /// This metric calculates the percentage of walkable cells (Floor). /// If this number is very low (like < 10%) then it means that the map @@ -17,7 +19,7 @@ pub fn density(walkable_layer: &WalkableLayer) -> f32 { /// Calculate the length of the shortes path from the starting point /// to the exit. /// If this path is very short, then the map is probably degenerated. -pub fn path_length(map: &WalkableLayer, starting_point: &Vec2u, exit_point: &Vec2u) -> f32 { +pub fn path_length(map: &WalkableLayer, starting_point: &UVec2, exit_point: &UVec2) -> f32 { let dijkstra = DijkstraMap::new(map, starting_point); dijkstra.tiles[map.xy_idx(exit_point.x, exit_point.y)] } @@ -27,8 +29,9 @@ pub fn path_length(map: &WalkableLayer, starting_point: &Vec2u, exit_point: &Vec /// ------------------------------------------------------------------------------------------------ #[cfg(test)] mod tests { + use glam::UVec2; + use super::*; - use crate::geometry::Vec2u; #[test] fn test_density_no_floor() { @@ -58,8 +61,8 @@ mod tests { ########## "; let map = WalkableLayer::from_string(map_str); - let starting_point = Vec2u::new(1, 1); - let exit_point = Vec2u::new(8, 1); + let starting_point = UVec2::new(1, 1); + let exit_point = UVec2::new(8, 1); let score = path_length(&map, &starting_point, &exit_point); assert!(f32::abs(score - 7.9) <= 0.01); diff --git a/src/path/dijkstra.rs b/src/path/dijkstra.rs index 084c52b..52490bf 100644 --- a/src/path/dijkstra.rs +++ b/src/path/dijkstra.rs @@ -27,7 +27,8 @@ use std::collections::VecDeque; -use crate::geometry::Vec2u; +use glam::UVec2; + use crate::layer::WalkableLayer; /// Representation of a Dijkstra flow map. @@ -43,7 +44,7 @@ pub struct DijkstraMap { impl DijkstraMap { //! Construct a new Dijkstra map, ready to run. - pub fn new(map: &WalkableLayer, starting_point: &Vec2u) -> DijkstraMap { + pub fn new(map: &WalkableLayer, starting_point: &UVec2) -> DijkstraMap { let len = (map.width * map.height) as usize; let tiles = vec![f32::MAX; len]; let mut d = DijkstraMap { @@ -61,7 +62,7 @@ impl DijkstraMap { /// depth is further than the current depth. /// WARNING: Will give incorrect results when used with non-uniform exit costs. Much slower /// algorithm required to support that. - fn build(&mut self, map: &WalkableLayer, starting_point: &Vec2u) { + fn build(&mut self, map: &WalkableLayer, starting_point: &UVec2) { let mapsize = self.size_x * self.size_y; let mut open_list: VecDeque<((u32, u32), f32)> = VecDeque::with_capacity(mapsize as usize); @@ -98,7 +99,6 @@ impl DijkstraMap { #[cfg(test)] mod tests { use super::*; - use crate::geometry::Vec2u; #[test] fn test_culling() { @@ -108,7 +108,7 @@ mod tests { ########## "; let map = WalkableLayer::from_string(map_str); - let dm = DijkstraMap::new(&map, &Vec2u::new(8, 1)); + let dm = DijkstraMap::new(&map, &UVec2::new(8, 1)); println!( "{:?}", @@ -141,7 +141,7 @@ mod tests { #### "; let map = WalkableLayer::from_string(map_str); - let starting_point = Vec2u::new(2, 2); + let starting_point = UVec2::new(2, 2); let dm = DijkstraMap::new(&map, &starting_point); let expected = [ f32::MAX, @@ -174,7 +174,7 @@ mod tests { ########## "; let map = WalkableLayer::from_string(map_str); - let starting_point = Vec2u::new(8, 2); + let starting_point = UVec2::new(8, 2); let dm = DijkstraMap::new(&map, &starting_point); let expected = [ f32::MAX, diff --git a/src/poi/cull_unreachable.rs b/src/poi/cull_unreachable.rs index 2da3f20..831b0cd 100644 --- a/src/poi/cull_unreachable.rs +++ b/src/poi/cull_unreachable.rs @@ -2,7 +2,8 @@ //! It will add wall on every tile which is not accessible from the starting point. //! -use crate::geometry::Vec2u; +use glam::UVec2; + use crate::layer::WalkableLayer; use crate::path::DijkstraMap; @@ -14,7 +15,7 @@ impl CullUnreachable { Box::new(CullUnreachable {}) } - pub fn remove_walkable_tiles(starting_point: &Vec2u, map: &WalkableLayer) -> WalkableLayer { + pub fn remove_walkable_tiles(starting_point: &UVec2, map: &WalkableLayer) -> WalkableLayer { let mut new_map = map.clone(); let dijkstra_map = DijkstraMap::new(map, starting_point); @@ -36,7 +37,9 @@ impl CullUnreachable { /// ------------------------------------------------------------------------------------------------ #[cfg(test)] mod tests { - use crate::{geometry::Vec2u, layer::WalkableLayer, poi::CullUnreachable}; + use glam::UVec2; + + use crate::{layer::WalkableLayer, poi::CullUnreachable}; #[test] fn test_culling() { @@ -46,7 +49,7 @@ mod tests { ########## "; let map = WalkableLayer::from_string(map_str); - let starting_point = Vec2u::new(9, 1); + let starting_point = UVec2::new(9, 1); let expected_map_str = " ########## #### # diff --git a/src/poi/distant_exit.rs b/src/poi/distant_exit.rs index a058a2e..3fdbd0c 100644 --- a/src/poi/distant_exit.rs +++ b/src/poi/distant_exit.rs @@ -3,7 +3,8 @@ //! This module will try to add exit point as far as possible from the starting point. //! -use crate::geometry::Vec2u; +use glam::UVec2; + use crate::layer::WalkableLayer; use crate::path::DijkstraMap; use std::f32; @@ -11,7 +12,7 @@ use std::f32; pub struct DistantExit; impl DistantExit { - pub fn find(starting_point: &Vec2u, map: &WalkableLayer) -> Vec2u { + pub fn find(starting_point: &UVec2, map: &WalkableLayer) -> UVec2 { let mut best_idx = 0; let mut best_value = 0.0; let dijkstra_map = DijkstraMap::new(map, starting_point); @@ -30,7 +31,9 @@ impl DistantExit { /// ------------------------------------------------------------------------------------------------ #[cfg(test)] mod tests { - use crate::{geometry::Vec2u, layer::WalkableLayer, poi::DistantExit}; + use glam::UVec2; + + use crate::{layer::WalkableLayer, poi::DistantExit}; #[test] fn test_exit() { @@ -41,9 +44,9 @@ mod tests { ########## "; let map = WalkableLayer::from_string(map_str); - let starting_point = Vec2u::new(9, 2); + let starting_point = UVec2::new(9, 2); let exit_point = DistantExit::find(&starting_point, &map); - assert_eq!(exit_point, Vec2u::new(1, 2)); + assert_eq!(exit_point, UVec2::new(1, 2)); } } diff --git a/src/poi/starting_point.rs b/src/poi/starting_point.rs index 8b1388a..57d901c 100644 --- a/src/poi/starting_point.rs +++ b/src/poi/starting_point.rs @@ -2,17 +2,19 @@ //! //! Example modifier usage: //! ``` -//! use mapgen::{geometry::Vec2u, layer::WalkableLayer, poi::*}; +//! use mapgen::{layer::WalkableLayer, poi::*}; +//! use glam::UVec2; //! //! let mut map = WalkableLayer::new(80, 50); //! map.set_walkable(10, 10, true); //! let point = AreaStartingPosition::find(XStart::LEFT, YStart::TOP, &map); //! -//! assert_eq!(point, Vec2u::new(10, 10)); +//! assert_eq!(point, UVec2::new(10, 10)); //! ``` //! -use crate::geometry::Vec2u; +use glam::{UVec2, Vec2}; + use crate::layer::WalkableLayer; /// Initial x region position @@ -34,7 +36,7 @@ pub struct AreaStartingPosition; impl AreaStartingPosition { /// Create new modifier with given region - pub fn find(x_start: XStart, y_start: YStart, map: &WalkableLayer) -> Vec2u { + pub fn find(x_start: XStart, y_start: YStart, map: &WalkableLayer) -> UVec2 { let seed_x = match x_start { XStart::LEFT => 1, XStart::CENTER => map.width / 2, @@ -52,7 +54,8 @@ impl AreaStartingPosition { if w { available_floors.push(( idx, - map.idx_point(idx).distance_to(&Vec2u::new(seed_x, seed_y)), + (map.idx_point(idx).as_vec2() - Vec2::new(seed_x as f32, seed_y as f32)) + .length(), )); } } @@ -71,7 +74,9 @@ impl AreaStartingPosition { /// ------------------------------------------------------------------------------------------------ #[cfg(test)] mod tests { - use crate::{geometry::Vec2u, layer::WalkableLayer, poi::*}; + use glam::UVec2; + + use crate::{layer::WalkableLayer, poi::*}; #[test] fn test_exit() { @@ -84,6 +89,6 @@ mod tests { let map = WalkableLayer::from_string(map_str); let starting_point = AreaStartingPosition::find(XStart::CENTER, YStart::TOP, &map); - assert_eq!(starting_point, Vec2u::new(6, 1)); + assert_eq!(starting_point, UVec2::new(6, 1)); } } diff --git a/src/rooms/bsp_interior.rs b/src/rooms/bsp_interior.rs index 38f617b..6ac9d6f 100644 --- a/src/rooms/bsp_interior.rs +++ b/src/rooms/bsp_interior.rs @@ -18,8 +18,9 @@ //! use fastrand::Rng; +use glam::UVec2; -use crate::geometry::{Rect, Vec2u}; +use crate::geometry::Rect; use super::RoomsMap; @@ -54,7 +55,7 @@ impl BspInterior { let start_y = rng.choice(room.y1..room.y2).unwrap(); let end_x = rng.choice(next_room.x1..next_room.x2).unwrap(); let end_y = rng.choice(next_room.y1..next_room.y2).unwrap(); - map.add_corridor(Vec2u::new(start_x, start_y), Vec2u::new(end_x, end_y)); + map.add_corridor(UVec2::new(start_x, start_y), UVec2::new(end_x, end_y)); } map diff --git a/src/rooms/corridors_nearest.rs b/src/rooms/corridors_nearest.rs index fe13e9f..1711e2f 100644 --- a/src/rooms/corridors_nearest.rs +++ b/src/rooms/corridors_nearest.rs @@ -26,7 +26,7 @@ impl NearestCorridors { for (j, other_room) in map.rooms.iter().enumerate() { if i != j && !connected.contains(&j) { let other_center = other_room.center(); - let distance = room_center.distance_to(&other_center); + let distance = (room_center.as_vec2() - other_center.as_vec2()).length(); room_distance.push((j, distance)); } } diff --git a/src/rooms/tile_map.rs b/src/rooms/tile_map.rs index bfcb27f..9a949c0 100644 --- a/src/rooms/tile_map.rs +++ b/src/rooms/tile_map.rs @@ -3,17 +3,16 @@ use std::fmt; -use crate::{ - geometry::{Rect, Vec2u}, - layer::WalkableLayer, -}; +use glam::UVec2; + +use crate::{geometry::Rect, layer::WalkableLayer}; #[derive(Default, Clone)] pub struct RoomsMap { pub width: u32, pub height: u32, pub rooms: Vec, - pub corridors: Vec>, + pub corridors: Vec>, pub walkable_layer: WalkableLayer, } @@ -39,7 +38,7 @@ impl RoomsMap { } } - pub fn add_corridor(&mut self, from: Vec2u, to: Vec2u) { + pub fn add_corridor(&mut self, from: UVec2, to: UVec2) { let mut corridor = Vec::new(); let mut x = from.x; let mut y = from.y; @@ -55,7 +54,7 @@ impl RoomsMap { y -= 1; } - corridor.push(Vec2u::new(x, y)); + corridor.push(UVec2::new(x, y)); self.walkable_layer.set_walkable(x, y, true); } }