diff --git a/src/bin/wireframe/main.rs b/src/bin/wireframe/main.rs index 8b29463..b4ede44 100644 --- a/src/bin/wireframe/main.rs +++ b/src/bin/wireframe/main.rs @@ -20,6 +20,7 @@ mod scene; #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] struct Vertex { position: [f32; 3], + tangent: [f32; 3], } struct Wireframe { @@ -33,28 +34,14 @@ fn prepare_scene(device: &wgpu::Device) -> Vec { .into_iter() .map(|line| { let color = line.color; - let data: Vec; - match line.line { - scene::Line::Lines(_) => todo!(), - scene::Line::Strip(pts) => { - data = pts - .into_iter() - .map(|p| Vertex { - position: p.to_array(), - }) - .collect(); - } - scene::Line::Loop(pts) => { - let first = pts.first().copied(); - data = pts - .into_iter() - .chain(first) - .map(|p| Vertex { - position: p.to_array(), - }) - .collect(); - } - }; + let data: Vec = line + .pts + .into_iter() + .map(|r| Vertex { + position: r.pos.to_array(), + tangent: r.dir.to_array(), + }) + .collect(); let size = data.len() as u32; let data = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { label: Some("Vertex Buffer"), @@ -304,10 +291,21 @@ impl<'a> State<'a> { shader_location: 0, format: wgpu::VertexFormat::Float32x3, }, + wgpu::VertexAttribute { + offset: mem::offset_of!(Vertex, tangent) as u64, + shader_location: 1, + format: wgpu::VertexFormat::Float32x3, + }, wgpu::VertexAttribute { offset: (mem::size_of::() + mem::offset_of!(Vertex, position)) as u64, - shader_location: 1, + shader_location: 2, + format: wgpu::VertexFormat::Float32x3, + }, + wgpu::VertexAttribute { + offset: (mem::size_of::() + mem::offset_of!(Vertex, tangent)) + as u64, + shader_location: 3, format: wgpu::VertexFormat::Float32x3, }, ], diff --git a/src/bin/wireframe/ray.wgsl b/src/bin/wireframe/ray.wgsl index e837f01..2d9362d 100644 --- a/src/bin/wireframe/ray.wgsl +++ b/src/bin/wireframe/ray.wgsl @@ -13,7 +13,9 @@ var line: LineUniform; struct SegmentInput { @location(0) a: vec3, - @location(1) b: vec3, + @location(1) ad: vec3, + @location(2) b: vec3, + @location(3) bd: vec3, } struct OffsetInput { @builtin(vertex_index) idx: u32, @@ -28,18 +30,27 @@ struct VertexOutput { fn vs_main(seg: SegmentInput, off: OffsetInput) -> VertexOutput { var out: VertexOutput; out.vertex_color = line.color; - let a = camera.mvp * vec4(seg.a, 1.); - let b = camera.mvp * vec4(seg.b, 1.); - let dir = normalize(b.xy / b.w - a.xy / a.w); - let ortho = width * camera.scale * vec2(-dir.y, dir.x); - let d = vec4(ortho, 0., 0.); + var pt: vec3; + var dir: vec3; switch (off.idx) { - case 0u: { out.clip_position = a - d; } - case 1u: { out.clip_position = a + d; } - case 2u: { out.clip_position = b - d; } - case 3u: { out.clip_position = b + d; } + case 0u: { pt = seg.a; dir = seg.ad; } + case 1u: { pt = seg.a; dir = seg.ad; } + case 2u: { pt = seg.b; dir = seg.bd; } + case 3u: { pt = seg.b; dir = seg.bd; } default: {} } + var sgn: f32; + switch (off.idx) { + case 0u: { sgn = -1.; } + case 1u: { sgn = 1.; } + case 2u: { sgn = -1.; } + case 3u: { sgn = 1.; } + default: {} + } + let pt_cs = camera.mvp * vec4(pt, 1.); + let dir_cs = camera.mvp * vec4(dir, 0.); + let normal_cs = camera.scale * normalize(vec2(-dir_cs.y, dir_cs.x)); + out.clip_position = pt_cs + vec4(sgn * width * normal_cs, 0., 0.); return out; } diff --git a/src/bin/wireframe/scene.rs b/src/bin/wireframe/scene.rs index 56cdc32..6927ef5 100644 --- a/src/bin/wireframe/scene.rs +++ b/src/bin/wireframe/scene.rs @@ -1,5 +1,5 @@ use glam::*; -use itertools::{chain, iproduct, Itertools}; +use itertools::{chain, iproduct}; use refraction::ifaces::{DebugTraceable, Traceable}; use refraction::tube::metric::Tube; @@ -8,27 +8,44 @@ use refraction::types::{Location, Object, Ray}; use refraction::utils::put_object; pub enum Line { - Lines(Vec<(Vec3, Vec3)>), - Strip(Vec), - Loop(Vec), + Strip(Vec), + Loop(Vec), } pub struct FancyLine { pub color: Vec3, - pub line: Line, + pub pts: Vec, } fn paint(onto: &mut Vec, color: Vec3, lines: Vec) { - onto.extend(lines.into_iter().map(move |line| FancyLine { color, line })) + onto.extend(lines.into_iter().map(move |line| FancyLine { + color, + pts: match line { + Line::Strip(pts) => pts, + Line::Loop(mut pts) => { + pts.push(*pts.first().unwrap()); + pts + } + }, + })) } -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, - ]) +fn draw_line(a: Vec3, b: Vec3) -> Line { + let dir = (b - a).normalize(); + Line::Strip(vec![Ray { pos: a, dir }, Ray { pos: b, dir }]) +} + +fn draw_rect(center: Vec3, u: Vec3, v: Vec3) -> Vec { + let a = center - u - v; + let b = center + u - v; + let c = center + u + v; + let d = center - u + v; + vec![ + draw_line(a, b), + draw_line(b, c), + draw_line(c, d), + draw_line(d, a), + ] } fn draw_ellipse(center: Vec3, u: Vec3, v: Vec3) -> Line { @@ -38,7 +55,10 @@ fn draw_ellipse(center: Vec3, u: Vec3, v: Vec3) -> Line { (0..segments) .map(|k| k as f32 * step) .map(Vec2::from_angle) - .map(|d| center + d.x * u + d.y * v) + .map(|d| Ray { + pos: center + d.x * u + d.y * v, + dir: -d.y * u + d.x * v, + }) .collect(), ) } @@ -109,7 +129,7 @@ fn draw_ray_2(gc: &mut Vec, space: &Space, camera: Location, dir: Vec3) { .expect("the starting point is always in the path"); let dir_pos = end_pos.forward(10000.0); pts.push(dir_pos); - gc.push(Line::Strip(pts.into_iter().map(|r| r.pos).collect())); + gc.push(Line::Strip(pts)); } fn draw_fan_2(space: &Space, camera: Location, spread: f32) -> Vec { @@ -135,7 +155,7 @@ impl Renderable for Tube { .map(|k| k as f32 * step) .map(Vec2::from_angle) .map(|d| vec3(d.x, 0., d.y)) - .map(|d| draw_rect(r * d, w * d, l)); + .flat_map(|d| draw_rect(r * d, w * d, l)); let caps = iproduct!([self.inner_radius, self.outer_radius], [-l, l]) .map(|(r, l)| draw_ellipse(l, vec3(r, 0., 0.), vec3(0., 0., r))); chain!(along, caps).collect()