veloren/common/src/hierarchical.rs

140 lines
4.3 KiB
Rust
Raw Normal View History

2019-12-29 20:58:21 +00:00
use crate::{
astar::astar,
pathfinding::WorldPath,
vol::{ReadVol, RectRasterableVol},
volumes::vol_grid_2d::VolGrid2d,
};
use std::fmt::Debug;
use vek::*;
#[derive(Clone, Debug, Default)]
pub struct ChunkPath {
pub from: Vec3<f32>,
pub dest: Vec3<f32>,
pub chunk_path: Option<Vec<Vec2<i32>>>,
}
impl ChunkPath {
pub fn new<V: RectRasterableVol + ReadVol + Debug>(
vol: &VolGrid2d<V>,
from: Vec3<f32>,
dest: Vec3<f32>,
) -> Self {
let ifrom: Vec3<i32> = Vec3::from(from.map(|e| e.floor() as i32));
let idest: Vec3<i32> = Vec3::from(dest.map(|e| e.floor() as i32));
let start_chunk = vol.pos_key(ifrom);
let end_chunk = vol.pos_key(idest);
let chunk_path = astar(
start_chunk,
end_chunk,
chunk_euclidean_distance,
|pos| ChunkPath::chunk_get_neighbors(vol, pos),
chunk_transition_cost,
);
Self {
from,
dest,
chunk_path,
}
}
pub fn chunk_get_neighbors<V: RectRasterableVol + ReadVol + Debug>(
_vol: &VolGrid2d<V>,
pos: &Vec2<i32>,
) -> impl Iterator<Item = Vec2<i32>> {
2019-12-29 20:58:21 +00:00
let directions = vec![
Vec2::new(1, 0), // Right chunk
Vec2::new(-1, 0), // Left chunk
Vec2::new(0, 1), // Top chunk
Vec2::new(0, -1), // Bottom chunk
];
let mut neighbors = Vec::new();
for x in -2..3 {
for y in -2..3 {
neighbors.push(pos + Vec2::new(x, y));
}
}
//let neighbors: Vec<Vec2<i32>> = directions.into_iter().map(|dir| dir +
// pos).collect();
2019-12-29 20:58:21 +00:00
neighbors.into_iter()
}
2019-12-29 20:58:21 +00:00
pub fn worldpath_get_neighbors<V: RectRasterableVol + ReadVol + Debug>(
&mut self,
vol: &VolGrid2d<V>,
pos: Vec3<i32>,
) -> impl Iterator<Item = Vec3<i32>> {
2019-12-29 20:58:21 +00:00
let directions = vec![
Vec3::new(0, 1, 0), // Forward
Vec3::new(0, 1, 1), // Forward upward
Vec3::new(0, 1, 2), // Forward Upwardx2
Vec3::new(0, 1, -1), // Forward downward
Vec3::new(1, 0, 0), // Right
Vec3::new(1, 0, 1), // Right upward
Vec3::new(1, 0, 2), // Right Upwardx2
Vec3::new(1, 0, -1), // Right downward
Vec3::new(0, -1, 0), // Backwards
Vec3::new(0, -1, 1), // Backward Upward
Vec3::new(0, -1, 2), // Backward Upwardx2
Vec3::new(0, -1, -1), // Backward downward
Vec3::new(-1, 0, 0), // Left
Vec3::new(-1, 0, 1), // Left upward
Vec3::new(-1, 0, 2), // Left Upwardx2
Vec3::new(-1, 0, -1), // Left downward
];
let neighbors: Vec<Vec3<i32>> = directions
.into_iter()
.map(|dir| dir + pos)
.filter(|new_pos| self.is_valid_space(vol, *new_pos))
.collect();
neighbors.into_iter()
}
2019-12-29 20:58:21 +00:00
pub fn is_valid_space<V: RectRasterableVol + ReadVol + Debug>(
&mut self,
vol: &VolGrid2d<V>,
pos: Vec3<i32>,
) -> bool {
let is_walkable_position = WorldPath::is_walkable_space(vol, pos);
let mut is_within_chunk = false;
match self.chunk_path.clone() {
Some(chunk_path) => {
is_within_chunk = chunk_path
.iter()
.any(|new_pos| new_pos.cmpeq(&vol.pos_key(pos)).iter().all(|e| *e));
},
2019-12-29 20:58:21 +00:00
_ => {
//println!("No chunk path");
},
2019-12-29 20:58:21 +00:00
}
return is_walkable_position && is_within_chunk;
}
2019-12-29 20:58:21 +00:00
pub fn get_worldpath<V: RectRasterableVol + ReadVol + Debug>(
&mut self,
vol: &VolGrid2d<V>,
) -> Result<WorldPath, ()> {
2019-12-29 20:58:21 +00:00
let wp = WorldPath::new(vol, self.from, self.dest, |vol, pos| {
self.worldpath_get_neighbors(vol, pos)
2019-12-29 20:58:21 +00:00
});
//println!("Fetching world path from hierarchical path: {:?}", wp);
2019-12-29 20:58:21 +00:00
wp
}
}
pub fn chunk_euclidean_distance(start: &Vec2<i32>, end: &Vec2<i32>) -> f32 {
let istart = start.map(|e| e as f32);
let iend = end.map(|e| e as f32);
istart.distance(iend)
}
pub fn chunk_transition_cost(_start: &Vec2<i32>, _end: &Vec2<i32>) -> f32 { 1.0f32 }