From e9993182bf5cdaccd52ed30a9669677ae5e33ac9 Mon Sep 17 00:00:00 2001 From: numzero Date: Sat, 14 Sep 2024 23:24:37 +0300 Subject: [PATCH] Split ray tracing and trace display --- src/bin/flat/main.rs | 74 ++++++++-------------------------------- src/bin/flat/tube/mod.rs | 53 +++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 61 deletions(-) diff --git a/src/bin/flat/main.rs b/src/bin/flat/main.rs index abfe156..c5f4f56 100644 --- a/src/bin/flat/main.rs +++ b/src/bin/flat/main.rs @@ -4,6 +4,7 @@ use flo_canvas::*; use flo_draw::*; use glam::*; +use crate::ifaces::DebugTraceable; use crate::types::FlatTraceResult; use refraction::mathx::MatExt; use riemann::{trace_iter, Metric}; @@ -196,74 +197,27 @@ fn draw_cross(gc: &mut Vec, pos: Vec2, r: f32) { gc.line_to(pos.x + r, pos.y - r); } -fn draw_ray_2(gc: &mut Vec, space: &Space, base: Vec2, dir: Vec2) { - fn trace_to_flat(gc: &mut Vec, space: &Space, ray: Ray) -> (Ray, FlatTraceResult) { - for ray in space.trace_iter(ray).skip(1) { - gc.line_to(ray.pos.x, ray.pos.y); - match space.which_subspace(ray.pos) { - Inner => return (ray, space.trace_inner(ray)), - Outer => return (ray, space.trace_outer(ray)), - Boundary => continue, - }; - } - unreachable!("Space::trace_iter terminated!") - } +fn draw_ray_2(gc: &mut Vec, space: &Space, camera: Location, dir: Vec2) { + let pos = vec2(0., 0.); + let (hits, path) = space.trace_dbg(camera, Ray { pos, dir }); - let mut hits = Vec::::new(); gc.new_path(); - gc.move_to(base.x, base.y); - let mut ray = Ray { - pos: base, - dir: space.tube.normalize_vec_at(base, dir) * DT, - }; - for _ in 0..100 { - let ret; - (ray, ret) = trace_to_flat(gc, space, ray); - gc.stroke(); - gc.new_dash_pattern(); - // gc.dash_length(6.0); - gc.new_path(); - gc.move_to(ray.pos.x, ray.pos.y); - for hit in ret.objects { - let obj = space.objs[hit.id as usize]; - let apx_hit_pos = rel_to_abs(&space.tube, &obj.loc, hit.rel.pos, 128); - // assert_abs_diff_eq!(apx_hit_pos, hit.pos, epsilon=1.0); - let Ray { pos: rel, dir } = hit.rel; - let diff = rel.dot(dir).powi(2) - - dir.length_squared() * (rel.length_squared() - obj.r.powi(2)); - assert!(diff >= 0.0); - let t = (-rel.dot(dir) + diff.sqrt()) / dir.length_squared(); - let rel2 = hit.rel.forward(t).pos; - let pos2 = rel_to_abs(&space.tube, &obj.loc, rel2, 128); - draw_cross(&mut hits, pos2, 1.0); - } - let a = ray.pos; - if let Some(r) = ret.end { - ray = r - } else { - ray = ray.forward(1000.0 / DT); - gc.line_to(ray.pos.x, ray.pos.y); - break; - } - for p in space.line(a, ray.pos, 10.0) { - gc.line_to(p.x, p.y); - } - gc.stroke(); - gc.new_dash_pattern(); - gc.new_path(); - gc.move_to(ray.pos.x, ray.pos.y); + gc.move_to(pos.x, pos.y); + for pt in &path.points[1..] { + gc.line_to(pt.x, pt.y); } - gc.stroke(); - gc.new_path(); - gc.new_dash_pattern(); - gc.append(&mut hits); + let end_pos = *path + .points + .last() + .expect("the starting point is always in the path"); + let dir_pos = end_pos + 1000.0 * path.end_dir; + gc.line_to(dir_pos.x, dir_pos.y); gc.stroke(); } fn draw_fan_2(gc: &mut Vec, space: &Space, camera: Location, spread: f32) { for y in itertools_num::linspace(-spread, spread, 101) { - let ray_dir = vec2(1., y); - draw_ray_2(gc, space, camera.pos, camera.rot * ray_dir); + draw_ray_2(gc, space, camera, vec2(1., y)); } } diff --git a/src/bin/flat/tube/mod.rs b/src/bin/flat/tube/mod.rs index 29bb9b5..3c36a87 100644 --- a/src/bin/flat/tube/mod.rs +++ b/src/bin/flat/tube/mod.rs @@ -1,12 +1,14 @@ use glam::{bool, f32, vec2, Mat2, Vec2}; +use crate::ifaces::{DebugTraceable, RayPath, Traceable}; use coords::{FlatCoordinateSystem, InnerCS, OuterCS}; use metric::Tube; use Subspace::{Boundary, Inner, Outer}; -use crate::riemann; +use crate::riemann::Metric; use crate::tube::coords::FlatRegion; use crate::types::{FlatTraceResult, Hit, Location, Object, Ray}; +use crate::{riemann, DT}; mod coords; pub mod metric; @@ -153,6 +155,55 @@ impl Space { } } +impl Traceable for Space { + fn trace(&self, camera: Location, ray: Ray) -> Vec { + self.trace_dbg(camera, ray).0 + } +} + +impl DebugTraceable for Space { + fn trace_dbg(&self, camera: Location, ray: Ray) -> (Vec, RayPath) { + let mut points = vec![]; + let mut hits = vec![]; + let mut ray = Ray { + pos: camera.pos, + dir: camera.rot * ray.dir, + }; // TODO account for ray.pos + ray.dir = self.tube.normalize_vec_at(ray.pos, ray.dir) * DT; + + let trace_to_flat = |points: &mut Vec, ray| { + for ray in self.trace_iter(ray).skip(1) { + points.push(ray.pos); + let hitter = match self.which_subspace(ray.pos) { + Inner => Self::trace_inner, + Outer => Self::trace_outer, + Boundary => continue, + }; + return (ray, hitter(self, ray)); + } + unreachable!("Space::trace_iter terminated!") + }; + + points.push(ray.pos); + for _ in 0..100 { + let (ray_into_flat, ret) = trace_to_flat(&mut points, ray); + hits.extend(ret.objects); // TODO fix distance + let Some(ray_outta_flat) = ret.end else { + return ( + hits, + RayPath { + points, + end_dir: ray_into_flat.dir.normalize(), + }, + ); + }; + points.extend(self.line(ray_into_flat.pos, ray_outta_flat.pos, 10.0)); + ray = ray_outta_flat; + } + panic!("tracing didn't terminate"); + } +} + struct Rect { pub size: Vec2, }