diff options
| author | Kai Stevenson <kai@kaistevenson.com> | 2026-08-22 00:39:39 -0700 |
|---|---|---|
| committer | Kai Stevenson <kai@kaistevenson.com> | 2026-08-22 00:39:39 -0700 |
| commit | 21f6ee0be48f83db3a0052269cfc47ac73dc64f9 (patch) | |
| tree | c9d90a898a7cf56880a4b48ce3c6fe7c6918886c /src/sim/lib/ray.rs | |
| parent | b13e8cc52ca3d9e80339fd6acc10159c5ffc2903 (diff) | |
refactor dda
Diffstat (limited to 'src/sim/lib/ray.rs')
| -rw-r--r-- | src/sim/lib/ray.rs | 63 |
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) + } +} |
