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>,
|
2020-01-22 03:12:17 +00:00
|
|
|
) -> 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
|
|
|
|
];
|
|
|
|
|
2020-01-22 03:12:17 +00:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
pub fn worldpath_get_neighbors<V: RectRasterableVol + ReadVol + Debug>(
|
|
|
|
&mut self,
|
|
|
|
vol: &VolGrid2d<V>,
|
|
|
|
pos: Vec3<i32>,
|
2020-01-22 03:12:17 +00:00
|
|
|
) -> 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()
|
|
|
|
}
|
|
|
|
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));
|
|
|
|
}
|
|
|
|
_ => {
|
2020-01-22 03:12:17 +00:00
|
|
|
//println!("No chunk path");
|
2019-12-29 20:58:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return is_walkable_position && is_within_chunk;
|
|
|
|
}
|
|
|
|
pub fn get_worldpath<V: RectRasterableVol + ReadVol + Debug>(
|
|
|
|
&mut self,
|
|
|
|
vol: &VolGrid2d<V>,
|
2020-01-22 03:12:17 +00:00
|
|
|
) -> Result<WorldPath, ()> {
|
2019-12-29 20:58:21 +00:00
|
|
|
let wp = WorldPath::new(vol, self.from, self.dest, |vol, pos| {
|
2020-01-22 03:12:17 +00:00
|
|
|
self.worldpath_get_neighbors(vol, pos)
|
2019-12-29 20:58:21 +00:00
|
|
|
});
|
2020-01-22 03:12:17 +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
|
|
|
|
}
|