summaryrefslogtreecommitdiff
path: root/src/sim/lib/ray.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim/lib/ray.rs')
-rw-r--r--src/sim/lib/ray.rs63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/sim/lib/ray.rs b/src/sim/lib/ray.rs
new file mode 100644
index 0000000..52d5ba9
--- /dev/null
+++ b/src/sim/lib/ray.rs
@@ -0,0 +1,63 @@
+use glam::{IVec2, Vec2};
+
+// Amanatides and Woo's fast Voxel Traversal
+pub struct AwDda {
+ next: IVec2,
+ step_sign: IVec2,
+ step_delta: Vec2,
+ t_max: Vec2,
+}
+
+impl AwDda {
+ pub fn new(from: Vec2, to: Vec2) -> Self {
+ let first = from.round().as_ivec2();
+ // direction we step for each component on each iteration
+ let from_to_delta = to - from;
+ let step_sign = from_to_delta.signum().as_ivec2();
+
+ let step_delta = 1.0 / from_to_delta.abs();
+
+ let frac = Vec2::new(
+ if step_sign.x > 0 {
+ (first.x as f32 + 0.5) - from.x
+ } else {
+ from.x - (first.x as f32 - 0.5)
+ },
+ if step_sign.y > 0 {
+ (first.y as f32 + 0.5) - from.y
+ } else {
+ from.y - (first.y as f32 - 0.5)
+ },
+ );
+
+ let t_max = frac * step_delta;
+
+ AwDda {
+ next: first,
+ step_sign,
+ step_delta,
+ t_max,
+ }
+ }
+}
+
+impl Iterator for AwDda {
+ type Item = IVec2;
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.t_max.min_element() >= 1.0 {
+ return None;
+ }
+
+ let cur = self.next;
+
+ if self.t_max.x < self.t_max.y {
+ self.next.x += self.step_sign.x;
+ self.t_max.x += self.step_delta.x;
+ } else {
+ self.next.y += self.step_sign.y;
+ self.t_max.y += self.step_delta.y;
+ }
+
+ Some(cur)
+ }
+}