refraction/src/bin/wireframe/scene.rs
2024-09-23 00:04:16 +03:00

130 lines
3.0 KiB
Rust

use glam::*;
use refraction::ifaces::{DebugTraceable, Traceable};
use refraction::tube::metric::Tube;
use refraction::tube::Space;
use refraction::types::{Location, Object, Ray};
use refraction::utils::put_object;
pub enum Line {
Lines(Vec<(Vec3, Vec3)>),
Strip(Vec<Vec3>),
Loop(Vec<Vec3>),
}
pub struct FancyLine {
pub color: Vec3,
pub line: Line,
}
fn paint(onto: &mut Vec<FancyLine>, color: Vec3, lines: Vec<Line>) {
onto.extend(lines.into_iter().map(move |line| FancyLine { color, line }))
}
fn draw_rect(center: Vec3, u: Vec3, v: Vec3) -> Line {
Line::Loop(vec![
center - u - v,
center + u - v,
center + u + v,
center - u + v,
])
}
pub fn build() -> Vec<FancyLine> {
let tube = Tube {
inner_radius: 30.0,
outer_radius: 50.0,
internal_halflength: 100.0,
external_halflength: 300.0,
};
let objs: Vec<_> = [-1.25, -1.00, -0.85, -0.50, 0.00, 0.40, 0.70, 0.95, 1.05]
.iter()
.enumerate()
.map(|(k, &y)| Object {
id: k as i32,
loc: put_object(
&tube,
vec3(0.0, y * tube.external_halflength, 0.0),
Mat3::from_mat2(Mat2::from_angle(y)),
),
r: 20.0,
})
.collect();
let space = Space { tube, objs };
let cam1 = put_object(&space.tube, vec3(-500., 0., 0.), Mat3::IDENTITY);
let cam2 = put_object(
&space.tube,
vec3(
-2.5 * tube.outer_radius,
1.25 * tube.external_halflength,
0.,
),
mat3(vec3(1., -1., 0.), vec3(1., 1., 0.), vec3(0., 0., 1.)),
);
let cam3 = put_object(
&space.tube,
vec3(
0.25 * tube.inner_radius,
0.25 * tube.external_halflength,
0.,
),
mat3(vec3(0., -1., 0.), vec3(1., 0., 0.), vec3(0., 0., 1.)),
);
let mut gc = vec![];
paint(&mut gc, vec3(0.8, 0.8, 0.8), tube.render());
paint(&mut gc, vec3(0.0, 0.8, 1.0), draw_fan_2(&space, cam3, 1.0));
paint(&mut gc, vec3(0.5, 1.0, 0.0), draw_fan_2(&space, cam2, 1.0));
paint(&mut gc, vec3(1.0, 0.5, 0.0), draw_fan_2(&space, cam1, 1.0));
gc
}
fn draw_ray_2(gc: &mut Vec<Line>, space: &Space, camera: Location, dir: Vec3) {
let pos = vec3(0., 0., 0.);
let (hits, path) = space.trace_dbg(camera, Ray { pos, dir });
let hits2 = space.trace(camera, Ray { pos, dir });
for (a, b) in hits.into_iter().zip(hits2.into_iter()) {
assert_eq!(a.id, b.id);
assert_eq!(a.pos, b.pos);
assert_eq!(a.rel, b.rel);
}
let mut pts = path.points;
let end_pos = *pts
.last()
.expect("the starting point is always in the path");
let dir_pos = end_pos + 10000.0 * path.end_dir;
pts.push(dir_pos);
gc.push(Line::Strip(pts));
}
fn draw_fan_2(space: &Space, camera: Location, spread: f32) -> Vec<Line> {
let mut gc = vec![];
for y in itertools_num::linspace(-spread, spread, 101) {
draw_ray_2(&mut gc, space, camera, vec3(1., y, 0.));
}
gc
}
trait Renderable {
fn render(&self) -> Vec<Line>;
}
impl Renderable for Tube {
fn render(&self) -> Vec<Line> {
vec![
draw_rect(
vec3(0., 0., 0.),
vec3(self.outer_radius, 0., 0.),
vec3(0., self.external_halflength, 0.),
),
draw_rect(
vec3(0., 0., 0.),
vec3(self.inner_radius, 0., 0.),
vec3(0., self.external_halflength, 0.),
),
]
}
}