From 41805ca05bc36527a8e8477d79e2921e9a650c68 Mon Sep 17 00:00:00 2001 From: numzero Date: Fri, 14 Nov 2025 03:34:28 +0300 Subject: [PATCH] mark a source --- src/main.rs | 44 +++++++++++++++++++++++++++++++++++++++++ src/trace.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 src/trace.rs diff --git a/src/main.rs b/src/main.rs index c23ba1a..1b1fb42 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![feature(gen_blocks)] + use std::{error::Error, f32::consts::PI, sync::Arc}; use glam::{Mat4, vec3}; @@ -11,10 +13,12 @@ use winit::{ use crate::{ camera::OrbitalCamera, render::lines::{LookParams, Mesh, Pipeline, Vertex}, + trace::Source, }; mod camera; mod render; +mod trace; const TITLE: &str = "WGPU example"; const OUTPUT_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Bgra8UnormSrgb; @@ -44,6 +48,23 @@ pub fn new_tripod(device: &wgpu::Device) -> Mesh { ) } +fn loop_list( + iter: impl IntoIterator, + mut fa: impl FnMut(T) -> U, + mut fb: impl FnMut(T) -> U, +) -> impl Iterator { + gen move { + let mut iter = iter.into_iter(); + let Some(first) = iter.next() else { return }; + yield fa(first.clone()); + for item in iter { + yield fb(item.clone()); + yield fa(item); + } + yield fb(first); + } +} + impl MainWindow { fn new(event_loop: &ActiveEventLoop) -> Self { let handle = event_loop @@ -111,6 +132,29 @@ impl MainWindow { ..Default::default() }); self.pipeline.render(&mut pass, [&self.tripod]); + + let source = Source { + position_yaw: 0.0, + position_pitch: PI / 3., + distance: 1.0, + diameter: 0.25, + }; + let contour = source.contour(17); + let contour: Vec = loop_list( + contour, + |pos| Vertex { + pos, + color: vec3(1., 1., 0.), + }, + |pos| Vertex { + pos, + color: vec3(1., 1., 1.), + }, + ) + .collect(); + self.pipeline + .render(&mut pass, [&Mesh::new(&self.device, &contour)]); + drop(pass); self.queue.submit(std::iter::once(encoder.finish())); } diff --git a/src/trace.rs b/src/trace.rs new file mode 100644 index 0000000..dc33510 --- /dev/null +++ b/src/trace.rs @@ -0,0 +1,55 @@ +use std::f32::consts::PI; + +use glam::{Mat4, Vec3, vec3}; + +use crate::camera::OrbitalCamera; + +#[derive(Debug, Clone)] +pub struct Source { + /// Horizontal position (angle), in radians from +X towards +Y. + pub position_yaw: f32, + + /// Vertical position (angle), in radians from XY plane towards +Z. + pub position_pitch: f32, + + /// Distance from the origin. + pub distance: f32, + + /// Disc diameter. + pub diameter: f32, +} + +impl Source { + fn orbital(&self) -> OrbitalCamera { + let &Self { + position_yaw, + position_pitch, + distance, + .. + } = self; + OrbitalCamera { + position_yaw, + position_pitch, + distance, + } + } + + pub fn position(&self) -> Vec3 { + self.orbital().position() + } + + pub fn transform(&self) -> Mat4 { + self.orbital().transform().inverse() + } + + pub fn contour(&self, n: usize) -> impl Iterator { + let step = 2. * PI / n as f32; + let r = 0.5 * self.diameter; + let m = self.transform(); + (0..n).map(move |k| { + let angle = (k as f32) * step; + let (x, y) = angle.sin_cos(); + m.transform_point3(r * vec3(x, y, 0.)) + }) + } +}