diff --git a/src/bin/wireframe/main.rs b/src/bin/wireframe/main.rs index fcd2abd..ef0d96d 100644 --- a/src/bin/wireframe/main.rs +++ b/src/bin/wireframe/main.rs @@ -1,12 +1,11 @@ -use std::{ - collections::HashSet, - time::{Instant, SystemTime}, -}; +use std::{collections::HashSet, time::Instant}; use glam::{mat4, vec2, vec3, vec4, Mat4, Quat, Vec2, Vec3}; use glium::{ - backend::glutin::SimpleWindowBuilder, - implement_vertex, uniform, + backend::{glutin::SimpleWindowBuilder, Facade}, + implement_vertex, + index::PrimitiveType, + uniform, winit::event::{Event, WindowEvent}, Program, Surface, VertexBuffer, }; @@ -16,6 +15,8 @@ use winit::{ keyboard::{KeyCode, PhysicalKey}, }; +mod scene; + #[derive(Copy, Clone)] struct Vertex { position: [f32; 3], @@ -56,6 +57,46 @@ impl DragCtl { } } +struct Wireframe { + color: Vec3, + mode: PrimitiveType, + data: VertexBuffer, +} + +fn prepare_scene(display: &impl Facade) -> Vec { + scene::build() + .into_iter() + .map(|line| { + let color = line.color; + let mode; + let data: Vec; + match line.line { + scene::Line::Lines(_) => todo!(), + scene::Line::Strip(pts) => { + mode = PrimitiveType::LineStrip; + data = pts + .into_iter() + .map(|p| Vertex { + position: p.to_array(), + }) + .collect(); + } + scene::Line::Loop(pts) => { + mode = PrimitiveType::LineLoop; + data = pts + .into_iter() + .map(|p| Vertex { + position: p.to_array(), + }) + .collect(); + } + }; + let data = VertexBuffer::new(display, &data).unwrap(); + Wireframe { color, mode, data } + }) + .collect() +} + fn main() { let event_loop = EventLoop::builder().build().unwrap(); let (window, display) = SimpleWindowBuilder::new() @@ -91,6 +132,8 @@ fn main() { ]; let vertex_buffer = VertexBuffer::new(&display, &shape).unwrap(); + let scene = prepare_scene(&display); + let rot = Quat::from_euler(glam::EulerRot::YXZ, std::f32::consts::FRAC_PI_4, 0., 0.); let mut cur_pos = vec2(0., 0.); let mut cam_pos = rot * vec3(0., 1., -4.); @@ -151,6 +194,22 @@ fn main() { &Default::default(), ) .unwrap(); + for mesh in &scene { + let uniforms = uniform! { + mvp: mvp.to_cols_array_2d(), + color: mesh.color.to_array(), + }; + let indices = glium::index::NoIndices(mesh.mode); + target + .draw( + &mesh.data, + &indices, + &program, + &uniforms, + &Default::default(), + ) + .unwrap(); + } target.finish().unwrap(); } diff --git a/src/bin/wireframe/ray.v.glsl b/src/bin/wireframe/ray.v.glsl index c51e18d..947c66a 100644 --- a/src/bin/wireframe/ray.v.glsl +++ b/src/bin/wireframe/ray.v.glsl @@ -8,6 +8,6 @@ in vec3 position; out vec3 vertex_color; void main() { - vertex_color = position; + vertex_color = color; gl_Position = mvp * vec4(position, 1.0); } diff --git a/src/bin/wireframe/scene.rs b/src/bin/wireframe/scene.rs new file mode 100644 index 0000000..20d5dd4 --- /dev/null +++ b/src/bin/wireframe/scene.rs @@ -0,0 +1,129 @@ +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), + Loop(Vec), +} + +pub struct FancyLine { + pub color: Vec3, + pub line: Line, +} + +fn paint(onto: &mut Vec, color: Vec3, lines: Vec) { + 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 { + 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, 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 + 1000.0 * path.end_dir; + pts.push(dir_pos); + gc.push(Line::Strip(pts)); +} + +fn draw_fan_2(space: &Space, camera: Location, spread: f32) -> Vec { + 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; +} + +impl Renderable for Tube { + fn render(&self) -> Vec { + 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.), + ), + ] + } +}