1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
use std::f32::consts::PI;
use serde::{Serialize, Deserialize};
use strum::EnumIter;
pub type Erm<T> = color_eyre::Result<T>;
pub fn erm<E, T>(e: E) -> Erm<T> where E: std::error::Error + std::marker::Send + std::marker::Sync + 'static {
Err(e.into())
}
pub struct ErrorHandler;
impl color_eyre::eyre::EyreHandler for ErrorHandler {
fn debug(
&self,
error: &(dyn std::error::Error + 'static),
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
if f.alternate() {
return core::fmt::Debug::fmt(error, f);
}
let mut first = true;
if let Some(s) = error.source() {
let errors: Vec<_> = std::iter::successors(Some(s), |e| (*e).source()).collect();
for err in errors.iter().rev() {
writeln!(f)?; write!(f, "{}{}", if first {""} else {" - "}, err)?;
first = false;
}
}
writeln!(f)?; write!(f, "{}{}", if first {""} else {" - "}, error)?;
Ok(())
}
}
pub fn install_error_handler() {
let (panic_hook, _) = color_eyre::config::HookBuilder::default().into_hooks();
panic_hook.install();
color_eyre::eyre::set_hook(Box::new(move |_| Box::new(ErrorHandler))).expect("failed to install error handler");
}
#[derive(Clone, Copy, Debug, EnumIter, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub enum Cardinal {
North,
South,
West,
East,
}
impl Cardinal {
pub fn to_string(&self) -> &'static str {
match self {
Self::North => "north",
Self::South => "south",
Self::West => "west",
Self::East => "east",
}
}
pub fn turn_cw(&self) -> Self {
match self {
Self::North => Self::East,
Self::South => Self::West,
Self::West => Self::North,
Self::East => Self::South,
}
}
pub fn turn_ccw(&self) -> Self {
match self {
Self::North => Self::West,
Self::South => Self::East,
Self::West => Self::South,
Self::East => Self::North,
}
}
pub fn dir(&self) -> glam::Vec3 {
match self {
Self::North => glam::Vec3::new(0.0, 1.0, 0.0),
Self::South => glam::Vec3::new(0.0, -1.0, 0.0),
Self::West => glam::Vec3::new(-1.0, 0.0, 0.0),
Self::East => glam::Vec3::new(1.0, 0.0, 0.0),
}
}
pub fn offsets(&self) -> (i32, i32) {
match self {
Self::North => (0, 1),
Self::South => (0, -1),
Self::West => (-1, 0),
Self::East => (1, 0),
}
}
pub fn angle(&self) -> f32 {
match self {
Self::North => 0.0,
Self::South => PI,
Self::West => PI / 2.0,
Self::East => 3.0 * PI / 2.0,
}
}
pub fn turn_by(&self, o: &Self) -> Self {
match o {
Self::North => self.clone(),
Self::South => self.turn_cw().turn_cw(),
Self::West => self.turn_cw(),
Self::East => self.turn_ccw(),
}
}
pub fn angle_between(&self, o: &Self) -> f32 {
if o == &self.turn_cw() { -PI / 2.0 }
else if o == &self.turn_ccw() { PI / 2.0 }
else if o == &self.turn_cw().turn_cw() { PI }
else { 0.0 }
}
}
pub fn lerp(a: f32, b: f32, t: f32) -> f32 {
a + t.clamp(0.0, 1.0) * (b - a)
}
pub fn dir_lerp(a: &glam::Vec3, b: glam::Vec3, t: f32) -> glam::Vec3 {
let dirrotaxis = a.cross(b).normalize();
let dirrotangle = a.angle_between(b);
let dirrotfull = glam::Quat::from_axis_angle(dirrotaxis, dirrotangle);
let dirrot = glam::Quat::IDENTITY.slerp(dirrotfull, t);
dirrot.mul_vec3(a.clone())
}
|