Extract put_object into crate::utils

This commit is contained in:
numzero 2024-09-22 20:52:12 +03:00
parent ddccfd3a80
commit cf7f9c7f46
3 changed files with 92 additions and 79 deletions

View File

@ -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<Draw>, mut pts: impl Iterator<Item = Vec3>) {
@ -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<Draw>, pos: Vec2, r: f32) {
gc.move_to(pos.x - r, pos.y - r);
gc.line_to(pos.x + r, pos.y + r);

View File

@ -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;

90
src/utils.rs Normal file
View File

@ -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 = ε
);
}
}