diff --git a/src/bin/flat/main.rs b/src/bin/flat/main.rs index a5baffc..a9f8119 100644 --- a/src/bin/flat/main.rs +++ b/src/bin/flat/main.rs @@ -5,11 +5,10 @@ use flo_draw::*; use glam::*; use refraction::ifaces::{DebugTraceable, Traceable}; -use refraction::mathx::MatExt; -use refraction::riemann::{trace_iter, Metric}; use refraction::tube::metric::Tube; use refraction::tube::Space; use refraction::types::{Location, Object, Ray}; +use refraction::utils::put_object; use refraction::DT; fn draw_loop(gc: &mut Vec, mut pts: impl Iterator) { @@ -147,83 +146,6 @@ pub fn main() { }); } -fn rel_to_abs(space: &impl Metric, base: &Location, rel: Vec3, steps: usize) -> Vec3 { - let c = 1.0 / (steps as f32); - trace_iter(space, base.pos, base.rot * rel, c * rel.length()) - .nth(steps - 1) - .unwrap() -} - -/// Converts a position and a rotation to a [Location]. Only the X direction is preserved from `rot` to ensure the resulting Location describes an orthonormal coordinate system. -fn put_object(space: &impl Metric, pos: Vec3, rot: Mat3) -> Location { - let metric_sqrt = space.sqrt_at(pos); - let metric_inv_sqrt = space.sqrt_at(pos).inverse(); - let rot = metric_inv_sqrt * (metric_sqrt * rot).orthonormalize(); - Location { pos, rot } -} - -#[test] -fn test_put_object() { - use approx::assert_abs_diff_eq; - - let ε = 1e-5; - let m = refraction::riemann::samples::ScaledMetric { - scale: vec3(3., 4., 5.), - }; - - let loc = put_object( - &m, - vec3(1., 2., 0.), - mat3(vec3(1., 0., 0.), vec3(0., 1., 0.), vec3(0., 0., 1.)), - ); - assert_eq!(loc.pos, vec3(1., 2., 0.)); - assert_abs_diff_eq!( - loc.rot * vec3(1., 0., 0.), - vec3(1. / 3., 0., 0.), - epsilon = ε - ); - assert_abs_diff_eq!( - loc.rot * vec3(0., 1., 0.), - vec3(0., 1. / 4., 0.), - epsilon = ε - ); - - let loc = put_object( - &m, - vec3(1., 2., 0.), - mat3(vec3(0., 1., 0.), vec3(-1., 0., 0.), vec3(0., 0., 1.)), - ); - assert_eq!(loc.pos, vec3(1., 2., 0.)); - assert_abs_diff_eq!( - loc.rot * vec3(1., 0., 0.), - vec3(0., 1. / 4., 0.), - epsilon = ε - ); - assert_abs_diff_eq!( - loc.rot * vec3(0., 1., 0.), - vec3(-1. / 3., 0., 0.), - epsilon = ε - ); - - let c = 0.5 * std::f32::consts::SQRT_2; - let loc = put_object( - &m, - vec3(1., 2., 0.), - mat3(vec3(c, c, 0.), vec3(-c, c, 0.), vec3(0., 0., 1.)), - ); - assert_eq!(loc.pos, vec3(1., 2., 0.)); - assert_abs_diff_eq!( - loc.rot * vec3(1., 0., 0.), - vec3(1. / 5., 1. / 5., 0.), - epsilon = ε - ); - assert_abs_diff_eq!( - loc.rot * vec3(0., 1., 0.), - vec3(-4. / 15., 3. / 20., 0.), - epsilon = ε - ); -} - fn draw_cross(gc: &mut Vec, pos: Vec2, r: f32) { gc.move_to(pos.x - r, pos.y - r); gc.line_to(pos.x + r, pos.y + r); diff --git a/src/lib.rs b/src/lib.rs index af61334..15535c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,5 +6,6 @@ pub mod mesh_tracer; pub mod riemann; pub mod tube; pub mod types; +pub mod utils; pub const DT: f32 = 0.1; diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..5e7e33a --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,90 @@ +use crate::{ + mathx::MatExt as _, + riemann::{trace_iter, Metric}, + types::Location, +}; +use glam::{Mat3, Vec3}; + +pub fn rel_to_abs(space: &impl Metric, base: &Location, rel: Vec3, steps: usize) -> Vec3 { + let c = 1.0 / (steps as f32); + trace_iter(space, base.pos, base.rot * rel, c * rel.length()) + .nth(steps - 1) + .unwrap() +} + +/// Converts a position and a rotation to a [Location]. Only the X direction is preserved from `rot` to ensure the resulting Location describes an orthonormal coordinate system. +pub fn put_object(space: &impl Metric, pos: Vec3, rot: Mat3) -> Location { + let metric_sqrt = space.sqrt_at(pos); + let metric_inv_sqrt = space.sqrt_at(pos).inverse(); + let rot = metric_inv_sqrt * (metric_sqrt * rot).orthonormalize(); + Location { pos, rot } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::riemann::samples; + use glam::{mat3, vec3}; + + #[test] + fn test_put_object() { + use approx::assert_abs_diff_eq; + + let ε = 1e-5; + let m = samples::ScaledMetric { + scale: vec3(3., 4., 5.), + }; + + let loc = put_object( + &m, + vec3(1., 2., 0.), + mat3(vec3(1., 0., 0.), vec3(0., 1., 0.), vec3(0., 0., 1.)), + ); + assert_eq!(loc.pos, vec3(1., 2., 0.)); + assert_abs_diff_eq!( + loc.rot * vec3(1., 0., 0.), + vec3(1. / 3., 0., 0.), + epsilon = ε + ); + assert_abs_diff_eq!( + loc.rot * vec3(0., 1., 0.), + vec3(0., 1. / 4., 0.), + epsilon = ε + ); + + let loc = put_object( + &m, + vec3(1., 2., 0.), + mat3(vec3(0., 1., 0.), vec3(-1., 0., 0.), vec3(0., 0., 1.)), + ); + assert_eq!(loc.pos, vec3(1., 2., 0.)); + assert_abs_diff_eq!( + loc.rot * vec3(1., 0., 0.), + vec3(0., 1. / 4., 0.), + epsilon = ε + ); + assert_abs_diff_eq!( + loc.rot * vec3(0., 1., 0.), + vec3(-1. / 3., 0., 0.), + epsilon = ε + ); + + let c = 0.5 * std::f32::consts::SQRT_2; + let loc = put_object( + &m, + vec3(1., 2., 0.), + mat3(vec3(c, c, 0.), vec3(-c, c, 0.), vec3(0., 0., 1.)), + ); + assert_eq!(loc.pos, vec3(1., 2., 0.)); + assert_abs_diff_eq!( + loc.rot * vec3(1., 0., 0.), + vec3(1. / 5., 1. / 5., 0.), + epsilon = ε + ); + assert_abs_diff_eq!( + loc.rot * vec3(0., 1., 0.), + vec3(-4. / 15., 3. / 20., 0.), + epsilon = ε + ); + } +}