diff --git a/Cargo.toml b/Cargo.toml index ea9d5e6..6f5bb0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,11 +14,13 @@ serde_json = "1.0.140" zmq = "0.10.0" -[dev-dependencies] nannou = "0.19.0" nannou_egui = { version = "0.19.0", features = ["wayland"] } +[dev-dependencies] + + # Enable max optimizations for dependencies, but not for our code: # (tip from bevy examples for fast compilation/performance trade-off) [profile.dev.package."*"] diff --git a/src/bin/render_lines_gui.rs b/src/bin/render_lines_gui.rs index 5cba283..576deee 100644 --- a/src/bin/render_lines_gui.rs +++ b/src/bin/render_lines_gui.rs @@ -6,11 +6,12 @@ use bevy::math::Mat3; use nannou::geom::Rect; use nannou::prelude::*; use nannou_egui::{self, egui, Egui}; -use nannou_laser as laser; +use nannou_laser::{self as laser, util::map_range}; use serde_json::Result; use trap_rust::trap::{laser::{apply_homography_matrix, python_cv_h_into_mat3, LaserModel, TMP_PYTHON_LASER_H}, tracks::{LaserPoints, RenderableLines}}; use zmq::Socket; use std::sync::{mpsc, Arc}; +use std::time::{Instant, Duration}; fn main() { nannou::app(model).update(update).run(); @@ -32,6 +33,8 @@ struct Model { // socket for receiving points zmq: Socket, current_points: LaserPoints, // a copy for the drawing renderer + last_update: Instant, + // dimming_factor: f32, } struct LaserSettings { @@ -44,10 +47,6 @@ struct LaserSettings { radians_per_point: f32, } -#[derive(Clone, Copy)] -struct RgbProfile { - rgb: [f32; 3], -} impl Default for LaserSettings { @@ -69,11 +68,6 @@ impl Default for LaserSettings { } } -impl Default for RgbProfile { - fn default() -> Self { - RgbProfile { rgb: [1.0; 3] } - } -} fn setup_zmq() -> Socket{ let url = "tcp://100.109.175.82:99174"; @@ -96,6 +90,7 @@ fn zmq_receive(model: &mut Model) { ]; let _nr = zmq::poll(&mut items, 0).unwrap(); + let lines: RenderableLines; if items[0].is_readable() { let json = subscriber.recv_string(0).unwrap().unwrap(); // dbg!(&json[4..]); @@ -103,29 +98,42 @@ fn zmq_receive(model: &mut Model) { // let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?"); let res: Result = serde_json::from_str(&json); - let lines: RenderableLines = match res { + lines = match res { Ok(lines) => lines, // if Ok(255), set x to 255 Err(_e) => { println!("No valid json?"); println!("{}", _e); - return + // empty if invalid + RenderableLines{ + lines: Vec::new() + } }, // if Err("some message"), panic with error message "some message" }; - - // println!("receive {}", lines.lines.len()); - - for laser_stream in (&model.laser_streams).into_iter() { - // let lines = get_laser_lines(version); - let points: LaserPoints = (&lines).into(); - laser_stream.send(|laser| { - let laser_points: LaserPoints = points; - laser.current_points = laser_points; - }).unwrap(); + } else if model.last_update < Instant::now() - Duration::from_millis(100){ + // set lines empty, if no new input for > 100ms (10fps) + println!("No input, clear lines!!"); + lines = RenderableLines{ + lines: Vec::new() } - - model.current_points = (&lines).into(); - + } else { + // No new lines, break + return } + + // println!("receive {}", lines.lines.len()); + + for laser_stream in (&model.laser_streams).into_iter() { + // let lines = get_laser_lines(version); + let points: LaserPoints = (&lines).into(); + laser_stream.send(|laser| { + let laser_points: LaserPoints = points; + laser.current_points = laser_points; + }).unwrap(); + } + + model.current_points = (&lines).into(); + model.last_update = Instant::now(); + } fn model(app: &App) -> Model { @@ -208,6 +216,8 @@ fn model(app: &App) -> Model { egui, zmq, current_points, + last_update: Instant::now(), + // dimming_factor: 1., } } @@ -231,22 +241,46 @@ const LASER_H: Mat3 = python_cv_h_into_mat3(TMP_PYTHON_LASER_H); fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){ let points = model.current_points.clone(); + let pointno = points.len(); let mut new_points = Vec::new(); for point in points.into_iter() { let p = point.position; let new_position = apply_homography_matrix(LASER_H, &p); // let s = 1.; // when using TMP_PYTHON_LASER_H_FOR_NANNOU -- doesn't work? - let s = 0xFFF as f32; // when using TMP_PYTHON_LASER_H + let s = 0xFFF as f32 / 2.; // when using TMP_PYTHON_LASER_H + let position = [new_position[0]/s - 1., new_position[1]/s - 1.]; + // let position = [ + // map_range(new_position[0], 0. as f32, 0xFFF as f32, -1.0 , 1.0 ) as f32, + // map_range(new_position[1], 0. as f32, 0xFFF as f32, -1.0 , 1.0 ) as f32, + // ]; + + const LASER_MIN: f32 = -1.0; + const LASER_MAX: f32 = 1.0; + if position[0] < LASER_MIN || position[0] > LASER_MAX || position[1] < LASER_MIN || position[1] > LASER_MAX{ + continue; + } + + let mut color = point.color.clone(); + if model.dimming < 1.0 { + color[0] *= model.dimming; + color[1] *= model.dimming; + color[2] *= model.dimming; + } let new_point = laser::Point { - position: [new_position[0]/s, new_position[1]/s], + position, + color, .. point }; + new_points.push(new_point); } - // println!("Points {}", new_points.len()); + if new_points.len() < pointno { + println!("Cropped Points {} (was: {})", new_points.len(), pointno); + } + // println!("{:?}", new_points); frame.add_lines(new_points); } @@ -302,6 +336,7 @@ fn update(_app: &App, model: &mut Model, update: Update) { zmq_receive(model); + // Update the GUI. let Model { ref mut egui, @@ -332,7 +367,20 @@ fn update(_app: &App, model: &mut Model, update: Update) { ui.heading("Laser Settings"); if ui - .add(egui::Slider::new(&mut laser_settings.point_hz, 1_000..=10_000).text("DAC PPS")) + .add(egui::Slider::new(&mut model.laser_model.dimming, 0.0..=1.).text("Dimming")) + .changed() + { + for laser_stream in laser_streams { + let factor = model.laser_model.dimming; + // let lines = get_laser_lines(version); + laser_stream.send(move |laser| { + laser.dimming = factor; + }).unwrap(); + } + } + + if ui + .add(egui::Slider::new(&mut laser_settings.point_hz, 1_000..=50_000).text("DAC PPS")) .changed() { let hz = laser_settings.point_hz; diff --git a/src/trap/laser.rs b/src/trap/laser.rs index 4b8bb21..7cd2eb6 100644 --- a/src/trap/laser.rs +++ b/src/trap/laser.rs @@ -32,14 +32,16 @@ pub fn apply_homography_matrix(h: Mat3, p: &[f32; 2]) -> [f32; 2]{ #[derive(Resource, Clone)] pub struct LaserModel{ pub t: Instant, // register start time, so that animations can be moving - pub current_points: LaserPoints + pub current_points: LaserPoints, + pub dimming: f32, } impl LaserModel{ pub fn new() -> Self{ Self{ t: Instant::now(), - current_points: Vec::new() + current_points: Vec::new(), + dimming: 0.3 } } }