Wip layers
This commit is contained in:
parent
905a3faa0c
commit
fac5bda2f5
6 changed files with 214 additions and 90 deletions
|
@ -133,7 +133,7 @@ fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){
|
||||||
// false => trap::shapes::ARE_YOU_SURE,
|
// false => trap::shapes::ARE_YOU_SURE,
|
||||||
// };
|
// };
|
||||||
|
|
||||||
let points = model.current_lines.clone();
|
let points = model.current_layers.clone();
|
||||||
|
|
||||||
let mut new_points = Vec::new();
|
let mut new_points = Vec::new();
|
||||||
for point in points.into_iter() {
|
for point in points.into_iter() {
|
||||||
|
|
177
src/main.rs
177
src/main.rs
|
@ -2,7 +2,6 @@
|
||||||
//! A clone of the `laser_frame_stream.rs` example that allows for configuring laser settings via a
|
//! A clone of the `laser_frame_stream.rs` example that allows for configuring laser settings via a
|
||||||
//! UI.
|
//! UI.
|
||||||
|
|
||||||
use bevy::scene::ron::Map;
|
|
||||||
// use bevy_nannou::prelude::DARK_GRAY;
|
// use bevy_nannou::prelude::DARK_GRAY;
|
||||||
// use nannou::lyon::geom::euclid::Transform2D;
|
// use nannou::lyon::geom::euclid::Transform2D;
|
||||||
use nannou::{geom::Rect, math::map_range as nannou_map_range};
|
use nannou::{geom::Rect, math::map_range as nannou_map_range};
|
||||||
|
@ -15,7 +14,7 @@ use nannou_laser::{self as laser};
|
||||||
use serde_json::Result;
|
use serde_json::Result;
|
||||||
use laserspace::trap::filters::{MappedPoint, PointFilters};
|
use laserspace::trap::filters::{MappedPoint, PointFilters};
|
||||||
use laserspace::trap::laser::{shape_rect, LaserPoints, LaserSpace, StreamSource, STREAM_SOURCES, TMP_DESK_CLUBMAX, Corner};
|
use laserspace::trap::laser::{shape_rect, LaserPoints, LaserSpace, StreamSource, STREAM_SOURCES, TMP_DESK_CLUBMAX, Corner};
|
||||||
use laserspace::trap::tracks::CoordinateSpace;
|
use laserspace::trap::tracks::{CoordinateSpace, RenderableLayers};
|
||||||
use laserspace::trap::utils::{closest_edge, split_on_blank};
|
use laserspace::trap::utils::{closest_edge, split_on_blank};
|
||||||
use laserspace::trap::{laser::{python_cv_h_into_mat3, LaserModel, TMP_PYTHON_LASER_H, DacConfig}, tracks::{RenderableLines}};
|
use laserspace::trap::{laser::{python_cv_h_into_mat3, LaserModel, TMP_PYTHON_LASER_H, DacConfig}, tracks::{RenderableLines}};
|
||||||
use zmq::Socket;
|
use zmq::Socket;
|
||||||
|
@ -72,7 +71,7 @@ struct GuiModel {
|
||||||
egui: Egui,
|
egui: Egui,
|
||||||
// socket for receiving points
|
// socket for receiving points
|
||||||
zmq: Socket,
|
zmq: Socket,
|
||||||
current_lines: RenderableLines, // a copy for the drawing renderer
|
current_layers: RenderableLayers, // a copy for the drawing renderer
|
||||||
last_update: Instant,
|
last_update: Instant,
|
||||||
// dimming_factor: f32,
|
// dimming_factor: f32,
|
||||||
lost_alpha: f32,
|
lost_alpha: f32,
|
||||||
|
@ -155,23 +154,23 @@ fn zmq_receive(model: &mut GuiModel) {
|
||||||
];
|
];
|
||||||
let _nr = zmq::poll(&mut items, 0).unwrap();
|
let _nr = zmq::poll(&mut items, 0).unwrap();
|
||||||
|
|
||||||
let lines: RenderableLines;
|
let layers: RenderableLayers;
|
||||||
if items[0].is_readable() {
|
if items[0].is_readable() {
|
||||||
let json = subscriber.recv_string(0).unwrap().unwrap();
|
let json = subscriber.recv_string(0).unwrap().unwrap();
|
||||||
// dbg!(&json[4..]);
|
// dbg!(&json[4..]);
|
||||||
|
|
||||||
// let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?");
|
// let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?");
|
||||||
let res: Result<RenderableLines> = serde_json::from_str(&json);
|
let res: Result<RenderableLayers> = serde_json::from_str(&json);
|
||||||
model.lost_alpha = 1.;
|
model.lost_alpha = 1.;
|
||||||
model.connected = true;
|
model.connected = true;
|
||||||
|
|
||||||
lines = match res {
|
layers = match res {
|
||||||
Ok(lines) => lines, // if Ok(255), set x to 255
|
Ok(layers) => layers, // if Ok(255), set x to 255
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
println!("No valid json?");
|
println!("No valid json?");
|
||||||
println!("{}", _e);
|
println!("{}", _e);
|
||||||
// empty if invalid
|
// empty if invalid
|
||||||
RenderableLines::new()
|
RenderableLayers::new()
|
||||||
}, // if Err("some message"), panic with error message "some message"
|
}, // if Err("some message"), panic with error message "some message"
|
||||||
};
|
};
|
||||||
} else if model.last_update < Instant::now() - Duration::from_millis(100){
|
} else if model.last_update < Instant::now() - Duration::from_millis(100){
|
||||||
|
@ -180,14 +179,14 @@ fn zmq_receive(model: &mut GuiModel) {
|
||||||
|
|
||||||
if model.lost_alpha > 0.{
|
if model.lost_alpha > 0.{
|
||||||
|
|
||||||
println!("No input, clear lines!!");
|
println!("No input, clear layers!!");
|
||||||
model.lost_alpha *= 0.80;
|
model.lost_alpha *= 0.80;
|
||||||
if model.lost_alpha < 0.1{
|
if model.lost_alpha < 0.1{
|
||||||
model.lost_alpha = 0.;
|
model.lost_alpha = 0.;
|
||||||
}
|
}
|
||||||
lines = model.current_lines.with_alpha(model.lost_alpha);
|
layers = model.current_layers.with_alpha(model.lost_alpha);
|
||||||
} else {
|
} else {
|
||||||
lines = RenderableLines::new()
|
layers = RenderableLayers::new()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No new lines, break
|
// No new lines, break
|
||||||
|
@ -198,17 +197,17 @@ fn zmq_receive(model: &mut GuiModel) {
|
||||||
|
|
||||||
for (_dac, stream) in (&model.laser_streams).into_iter() {
|
for (_dac, stream) in (&model.laser_streams).into_iter() {
|
||||||
// let lines = get_laser_lines(version);
|
// let lines = get_laser_lines(version);
|
||||||
let lines_for_laser: RenderableLines = lines.clone();
|
let layers_for_laser: RenderableLayers = layers.clone();
|
||||||
let sending = stream.send(move |laser_model: &mut LaserModel| {
|
let sending = stream.send(move |laser_model: &mut LaserModel| {
|
||||||
let laser_lines: RenderableLines = lines_for_laser;
|
let laser_layers: RenderableLayers = layers_for_laser;
|
||||||
laser_model.current_lines = laser_lines;
|
laser_model.current_layers = laser_layers;
|
||||||
});
|
});
|
||||||
if let Err(e) = sending {
|
if let Err(e) = sending {
|
||||||
println!("Error sending to laser! {e:?}");
|
println!("Error sending to laser! {e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
model.current_lines = lines;
|
model.current_layers = layers;
|
||||||
model.last_update = Instant::now();
|
model.last_update = Instant::now();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -393,7 +392,7 @@ fn model(app: &App) -> GuiModel {
|
||||||
let egui_ctx = egui.ctx();
|
let egui_ctx = egui.ctx();
|
||||||
egui_ctx.set_style(style());
|
egui_ctx.set_style(style());
|
||||||
|
|
||||||
let current_lines = RenderableLines::new(); //Vec::new();
|
let current_layers = RenderableLayers::new(); //Vec::new();
|
||||||
|
|
||||||
GuiModel {
|
GuiModel {
|
||||||
laser_api,
|
laser_api,
|
||||||
|
@ -403,7 +402,7 @@ fn model(app: &App) -> GuiModel {
|
||||||
dac_rx,
|
dac_rx,
|
||||||
egui,
|
egui,
|
||||||
zmq,
|
zmq,
|
||||||
current_lines: current_lines,
|
current_layers: current_layers,
|
||||||
last_update: Instant::now(),
|
last_update: Instant::now(),
|
||||||
lost_alpha: 1.,
|
lost_alpha: 1.,
|
||||||
connected: true,
|
connected: true,
|
||||||
|
@ -420,34 +419,35 @@ fn model(app: &App) -> GuiModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn layers_to_points_for_config(current_layers: &RenderableLayers, config: &DacConfig ) -> Vec<Vec<laser::Point>> {
|
||||||
|
let mut new_laser_points: Vec<laser::Point> = Vec::new();
|
||||||
|
for (layer_nr, layer) in current_layers.0.iter() {
|
||||||
|
let mask = 1 << layer_nr;
|
||||||
|
if (mask & config.layers_enabled) != 0 {
|
||||||
|
let current_points: LaserPoints = layer.into();
|
||||||
|
|
||||||
|
// check which source should be used, and get points accordingly.
|
||||||
|
// potentially ignoring the points coming from the stream
|
||||||
|
let points = config.source.get_shape(current_points, config);
|
||||||
|
|
||||||
|
// let pointno = points.points.len();
|
||||||
|
|
||||||
|
let new_points = match points.space {
|
||||||
|
CoordinateSpace::RawLaser => points,
|
||||||
|
_ => config.filters.apply(&points)
|
||||||
|
};
|
||||||
|
// let new_laser_points = new_points.points;
|
||||||
|
new_laser_points.extend(new_points.points);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
split_on_blank(new_laser_points)
|
||||||
|
}
|
||||||
|
|
||||||
fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){
|
fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){
|
||||||
|
let lines = layers_to_points_for_config(&model.current_layers, &model.config);
|
||||||
let current_points: LaserPoints = (&model.current_lines).into();
|
|
||||||
// let space = &model.current_lines.space;
|
|
||||||
|
|
||||||
// check which source should be used, and get points accordingly.
|
|
||||||
// potentially ignoring the points coming from the stream
|
|
||||||
let points = model.config.source.get_shape(current_points, &model.config);
|
|
||||||
|
|
||||||
// let pointno = points.points.len();
|
|
||||||
|
|
||||||
let new_points = match points.space {
|
|
||||||
CoordinateSpace::RawLaser => points,
|
|
||||||
_ => model.config.filters.apply(&points)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
let new_laser_points = new_points.points;
|
|
||||||
// if new_laser_points.len() < pointno {
|
|
||||||
// println!("Cropped Points {} (was: {})", new_laser_points.len(), pointno);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// split by blanked points
|
|
||||||
let lines = split_on_blank(new_laser_points);
|
|
||||||
for line in lines {
|
for line in lines {
|
||||||
frame.add_lines(line);
|
frame.add_lines(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,7 +542,7 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
ref mut laser_settings,
|
ref mut laser_settings,
|
||||||
ref mut per_laser_config,
|
ref mut per_laser_config,
|
||||||
ref mut selected_stream,
|
ref mut selected_stream,
|
||||||
ref mut current_lines,
|
ref mut current_layers,
|
||||||
..
|
..
|
||||||
} = *model;
|
} = *model;
|
||||||
|
|
||||||
|
@ -566,9 +566,17 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
|
ui.columns(3, |cols| {
|
||||||
|
cols[0].label(format!("Layers {}", current_layers.0.len()));
|
||||||
|
cols[1].label(format!("Lines {}", current_layers.line_count()));
|
||||||
|
cols[2].label(format!("Points {}", current_layers.point_count()));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
ui.add(egui::Label::new(format!("Lines {}", current_lines.lines.len())));
|
// ui.add(egui::Label::new(format!("Layers {}", current_layers.0.len())));
|
||||||
ui.add(egui::Label::new(format!("Points {}", current_lines.point_count())));
|
// ui.add(egui::Label::new(format!("Lines {}", current_layers.line_count())));
|
||||||
|
// ui.add(egui::Label::new(format!("Points {}", current_layers.point_count())));
|
||||||
|
|
||||||
ui.heading("General settings");
|
ui.heading("General settings");
|
||||||
|
|
||||||
|
@ -731,6 +739,40 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
ui.horizontal_wrapped(|ui| {
|
||||||
|
for layer_nr in 1..=8 {
|
||||||
|
let mask = 1 << layer_nr;
|
||||||
|
let mut enabled_bool = mask & selected_config.layers_enabled != 0;
|
||||||
|
|
||||||
|
if ui
|
||||||
|
.add(egui::Checkbox::new(&mut enabled_bool,format!("{:?}", layer_nr)))
|
||||||
|
.changed()
|
||||||
|
{
|
||||||
|
selected_config.layers_enabled &= mask;
|
||||||
|
let layers_enabled = selected_config.layers_enabled;
|
||||||
|
if let Some(stream) = selected_laser_stream {
|
||||||
|
stream.send(move |laser_model: &mut LaserModel| {
|
||||||
|
laser_model.config.layers_enabled = layers_enabled;
|
||||||
|
}).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// if ui
|
||||||
|
// .add_enabled(laser_settings.enable_optimisations,
|
||||||
|
// egui::Checkbox::new(&mut laser_settings.enable_draw_reorder,"Reorder paths")
|
||||||
|
// )
|
||||||
|
// // .checkbox(&mut laser_settings.enable_draw_reorder, "Reorder paths")
|
||||||
|
// .changed()
|
||||||
|
// {
|
||||||
|
// for (_dac_id, stream) in laser_streams.iter() {
|
||||||
|
// stream
|
||||||
|
// .enable_draw_reorder(laser_settings.enable_draw_reorder)
|
||||||
|
// .ok();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if ui
|
if ui
|
||||||
.add(egui::Slider::new(&mut selected_config.filters.dim.intensity, 0.0..=1.).text("Dimming"))
|
.add(egui::Slider::new(&mut selected_config.filters.dim.intensity, 0.0..=1.).text("Dimming"))
|
||||||
|
@ -743,7 +785,7 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui
|
if ui
|
||||||
.add(egui::Slider::new(&mut selected_config.filters.dim.intensity, 0.0..=1.).text("Dimming"))
|
.add(egui::Slider::new(&mut selected_config.filters.dim.intensity, 0.0..=1.).text("Dimming"))
|
||||||
.changed()
|
.changed()
|
||||||
|
@ -867,12 +909,9 @@ fn view_line_canvas(app: &App, model: &GuiModel, frame: Frame) {
|
||||||
// LaserPoints supports a mode that sends points directly into the laser
|
// LaserPoints supports a mode that sends points directly into the laser
|
||||||
// if this mode is enabled by the sender, set background to blue
|
// if this mode is enabled by the sender, set background to blue
|
||||||
// Red if nothing is sending / not for too long.
|
// Red if nothing is sending / not for too long.
|
||||||
let bgcolor = match model.current_lines.space {
|
let bgcolor = match model.connected{
|
||||||
CoordinateSpace::Laser => MEDIUMSLATEBLUE,
|
|
||||||
_ => match model.connected{
|
|
||||||
true => DARKGRAY,
|
true => DARKGRAY,
|
||||||
false => LIGHTCORAL,
|
false => LIGHTCORAL,
|
||||||
},
|
|
||||||
};
|
};
|
||||||
draw.background().color(bgcolor);
|
draw.background().color(bgcolor);
|
||||||
|
|
||||||
|
@ -901,20 +940,23 @@ fn view_line_canvas(app: &App, model: &GuiModel, frame: Frame) {
|
||||||
|
|
||||||
|
|
||||||
// draw current laser lines
|
// draw current laser lines
|
||||||
for line in &model.current_lines.lines{
|
for (_, layer) in model.current_layers.0.iter() {
|
||||||
let vertices = line.points.iter().map(|p| {
|
|
||||||
let color = srgba(p.color.red, p.color.green, p.color.blue, p.color.alpha);
|
|
||||||
|
|
||||||
let pos = [p.position[0] * scale + translate_x, p.position[1] * -scale + translate_y];
|
|
||||||
(pos, color)
|
|
||||||
});
|
|
||||||
|
|
||||||
draw.polyline()
|
for line in &layer.lines{
|
||||||
|
let vertices = line.points.iter().map(|p| {
|
||||||
|
let color = srgba(p.color.red, p.color.green, p.color.blue, p.color.alpha);
|
||||||
|
|
||||||
|
let pos = [p.position[0] * scale + translate_x, p.position[1] * -scale + translate_y];
|
||||||
|
(pos, color)
|
||||||
|
});
|
||||||
|
|
||||||
|
draw.polyline()
|
||||||
.weight(thickness)
|
.weight(thickness)
|
||||||
.join_round()
|
.join_round()
|
||||||
.points_colored(vertices);
|
.points_colored(vertices);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// show each configured laser in the canvas. Highlight the selected.
|
// show each configured laser in the canvas. Highlight the selected.
|
||||||
for (dac_id, config) in model.per_laser_config.iter() {
|
for (dac_id, config) in model.per_laser_config.iter() {
|
||||||
let rect = shape_rect(LaserSpace::READY, 11);
|
let rect = shape_rect(LaserSpace::READY, 11);
|
||||||
|
@ -1014,7 +1056,7 @@ fn view_laser_preview(app: &App, model: &GuiModel, frame: Frame) {
|
||||||
// let stream = model.laser_streams.get(&dac_id); //.expect("Selected stream not found in configs");
|
// let stream = model.laser_streams.get(&dac_id); //.expect("Selected stream not found in configs");
|
||||||
|
|
||||||
// 1. get config for laser
|
// 1. get config for laser
|
||||||
let config = model.per_laser_config.get(&dac_id).expect("Selected stream not found in configs");
|
let config: &DacConfig = model.per_laser_config.get(&dac_id).expect("Selected stream not found in configs");
|
||||||
|
|
||||||
// 2. clipping mask + its anchor points
|
// 2. clipping mask + its anchor points
|
||||||
|
|
||||||
|
@ -1039,28 +1081,13 @@ fn view_laser_preview(app: &App, model: &GuiModel, frame: Frame) {
|
||||||
|
|
||||||
|
|
||||||
// 3. current shape of the laser
|
// 3. current shape of the laser
|
||||||
|
let lines = layers_to_points_for_config(&model.current_layers, &config);
|
||||||
|
|
||||||
let current_points: LaserPoints = (&model.current_lines).into();
|
|
||||||
|
|
||||||
// check which source should be used, and get points accordingly.
|
|
||||||
// potentially ignoring the points coming from the stream
|
|
||||||
let points = config.source.get_shape(current_points, config);
|
|
||||||
|
|
||||||
// let pointno = points.points.len();
|
|
||||||
|
|
||||||
let new_points = match points.space {
|
|
||||||
CoordinateSpace::RawLaser => points,
|
|
||||||
_ => config.filters.apply(&points)
|
|
||||||
};
|
|
||||||
|
|
||||||
let new_laser_points = new_points.points;
|
|
||||||
|
|
||||||
// draw as distinct lines (this is how it is send to post-processing)
|
// draw as distinct lines (this is how it is send to post-processing)
|
||||||
// TODO: alternatively, if the optimisation becomes an actual filter
|
// TODO: alternatively, if the optimisation becomes an actual filter
|
||||||
// this should be drawn as a single line, and we can have an option to
|
// this should be drawn as a single line, and we can have an option to
|
||||||
// visualise the intermediate lines to make the draw order apparent
|
// visualise the intermediate lines to make the draw order apparent
|
||||||
let lines = split_on_blank(new_laser_points);
|
|
||||||
for line in lines {
|
for line in lines {
|
||||||
// similar to map code:
|
// similar to map code:
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,11 @@ pub struct ScaleFilter {
|
||||||
pub factor: f32
|
pub factor: f32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct InterpolateFilter {
|
||||||
|
pub max_distance: f32
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct PincushionFilter {
|
pub struct PincushionFilter {
|
||||||
pub k_x: f32,
|
pub k_x: f32,
|
||||||
|
@ -69,6 +74,7 @@ pub struct PincushionFilter {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct PointFilters{
|
pub struct PointFilters{
|
||||||
|
pub interpolate: InterpolateFilter,
|
||||||
pub dim: DimFilter,
|
pub dim: DimFilter,
|
||||||
pub homography: HomographyFilter,
|
pub homography: HomographyFilter,
|
||||||
pub scale: ScaleFilter,
|
pub scale: ScaleFilter,
|
||||||
|
@ -91,9 +97,14 @@ pub struct PointFilters{
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
pub fn lerp(a: f32, b: f32, t: f32) -> f32{
|
||||||
|
return (1. - t) * a + t * b
|
||||||
|
}
|
||||||
|
|
||||||
impl PointFilters {
|
impl PointFilters {
|
||||||
pub fn apply(&self, points: &LaserPoints) -> LaserPoints{
|
pub fn apply(&self, points: &LaserPoints) -> LaserPoints{
|
||||||
let mut p = self.dim.apply(points);
|
let mut p = self.dim.apply(points);
|
||||||
|
// TODO: not implemented yet p = self.interpolate.apply(&p);
|
||||||
p = self.homography.apply(&p);
|
p = self.homography.apply(&p);
|
||||||
p = self.scale.apply(&p);
|
p = self.scale.apply(&p);
|
||||||
p = self.crop.apply(&p);
|
p = self.crop.apply(&p);
|
||||||
|
@ -141,6 +152,7 @@ impl Default for PointFilters {
|
||||||
// let crop_filter = CropFilter{};
|
// let crop_filter = CropFilter{};
|
||||||
Self {
|
Self {
|
||||||
homography: HomographyFilter::default(),
|
homography: HomographyFilter::default(),
|
||||||
|
interpolate: InterpolateFilter{max_distance: 0.2},
|
||||||
dim: DimFilter{intensity: 0.5},
|
dim: DimFilter{intensity: 0.5},
|
||||||
scale: ScaleFilter { factor: 1. },
|
scale: ScaleFilter { factor: 1. },
|
||||||
pincushion: PincushionFilter{k_x: 0.,k_x2: 0., k_y: 0., k_y2: 0.},
|
pincushion: PincushionFilter{k_x: 0.,k_x2: 0., k_y: 0., k_y2: 0.},
|
||||||
|
@ -571,6 +583,57 @@ impl Filter for DimFilter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Filter for InterpolateFilter {
|
||||||
|
fn apply(&self, points: &LaserPoints) -> LaserPoints {
|
||||||
|
// TODO: fix the code below
|
||||||
|
|
||||||
|
// let mut new_positions: Vec<[f32;2]> = Vec::new();
|
||||||
|
|
||||||
|
// // min distance between points before geometric filters
|
||||||
|
// let interpolated_edges = p.points.iter().zip(p.points.iter().skip(1)).map(|(p1, p2)|{
|
||||||
|
// let distance = f32::sqrt((p2.position[0] - p1.position[0]).powi(2) + (p2.position[1] - p1.position[1]).powi(2));
|
||||||
|
// let steps: i32 = (distance / required_distance).ceil() as i32;
|
||||||
|
// let mut interpolated_edge = Vec::new();
|
||||||
|
// for i in 0..steps {
|
||||||
|
// let t = (steps as f32) /(i as f32);
|
||||||
|
// interpolated_edge.push(
|
||||||
|
// laser::Point{
|
||||||
|
// position: [
|
||||||
|
// lerp(p1.position[0], p2.position[0], t),
|
||||||
|
// lerp(p1.position[1], p2.position[1], t)
|
||||||
|
// ],
|
||||||
|
// color: p1.color,
|
||||||
|
// weight: p1.weight,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// interpolated_edge
|
||||||
|
// });
|
||||||
|
|
||||||
|
// let mut interpolated_points: Vec<laser::Point> = interpolated_edges.flatten().collect();
|
||||||
|
// if let Some(last) = p.points.last() {
|
||||||
|
// interpolated_points.push(last.clone()); // add last one so we don't lose it
|
||||||
|
// }
|
||||||
|
|
||||||
|
// LaserPoints{
|
||||||
|
// points: interpolated_points,
|
||||||
|
// space: points.space,
|
||||||
|
// }
|
||||||
|
LaserPoints::default()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reverse(&self, points: &LaserPoints) -> LaserPoints{
|
||||||
|
// cannot easily be undone
|
||||||
|
LaserPoints{
|
||||||
|
points: points.points.clone(),
|
||||||
|
space: points.space,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn scale(points: &LaserPoints, factor: f32) -> LaserPoints{
|
fn scale(points: &LaserPoints, factor: f32) -> LaserPoints{
|
||||||
let new_points = points.points.iter().map(|point| {
|
let new_points = points.points.iter().map(|point| {
|
||||||
let mut position = point.position.clone();
|
let mut position = point.position.clone();
|
||||||
|
|
|
@ -2,7 +2,7 @@ use bevy::prelude::*;
|
||||||
use nannou_laser as laser;
|
use nannou_laser as laser;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use crate::trap::{filters::{PointFilters}, tracks::CoordinateSpace};
|
use crate::trap::{filters::PointFilters, tracks::{CoordinateSpace, RenderableLayers}};
|
||||||
|
|
||||||
use super::tracks::{RenderableLines};
|
use super::tracks::{RenderableLines};
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ pub fn apply_homography_matrix(h: Mat3, p: &[f32; 2]) -> [f32; 2]{
|
||||||
#[derive(Resource, Clone)]
|
#[derive(Resource, Clone)]
|
||||||
pub struct LaserModel{
|
pub struct LaserModel{
|
||||||
pub t: Instant, // register start time, so that animations can be moving
|
pub t: Instant, // register start time, so that animations can be moving
|
||||||
pub current_lines: RenderableLines,
|
pub current_layers: RenderableLayers,
|
||||||
// pub dimming: f32,
|
// pub dimming: f32,
|
||||||
pub config: DacConfig, // per dac configuration
|
pub config: DacConfig, // per dac configuration
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ impl LaserModel{
|
||||||
pub fn new() -> Self{
|
pub fn new() -> Self{
|
||||||
Self{
|
Self{
|
||||||
t: Instant::now(),
|
t: Instant::now(),
|
||||||
current_lines: RenderableLines::new(),
|
current_layers: RenderableLayers::new(),
|
||||||
// dimming: 0.3,
|
// dimming: 0.3,
|
||||||
config: DacConfig::default(),
|
config: DacConfig::default(),
|
||||||
}
|
}
|
||||||
|
@ -118,16 +118,18 @@ pub struct DacConfig{
|
||||||
// pub homography: Mat3,
|
// pub homography: Mat3,
|
||||||
pub source: StreamSource,
|
pub source: StreamSource,
|
||||||
pub filters: PointFilters,
|
pub filters: PointFilters,
|
||||||
|
pub layers_enabled: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||||
pub enum StreamSource {
|
pub enum StreamSource {
|
||||||
Disabled,
|
Disabled,
|
||||||
CurrentLines,
|
CurrentLayers,
|
||||||
Rectangle,
|
Rectangle,
|
||||||
GridY, // lines
|
GridY, // lines
|
||||||
WorldGrid, // grid in world space
|
WorldGrid, // grid in world space
|
||||||
Homography, // points for homography alignment
|
Homography, // points for homography alignment
|
||||||
|
// Layers ( layers: )
|
||||||
// Circle, // segments
|
// Circle, // segments
|
||||||
// Spiral,
|
// Spiral,
|
||||||
}
|
}
|
||||||
|
@ -135,7 +137,7 @@ pub enum StreamSource {
|
||||||
// usefull to create pull downs with an iterator
|
// usefull to create pull downs with an iterator
|
||||||
pub const STREAM_SOURCES: [StreamSource; 6] = [
|
pub const STREAM_SOURCES: [StreamSource; 6] = [
|
||||||
StreamSource::Disabled,
|
StreamSource::Disabled,
|
||||||
StreamSource::CurrentLines,
|
StreamSource::CurrentLayers,
|
||||||
StreamSource::Rectangle,
|
StreamSource::Rectangle,
|
||||||
StreamSource::GridY,
|
StreamSource::GridY,
|
||||||
StreamSource::WorldGrid,
|
StreamSource::WorldGrid,
|
||||||
|
@ -152,7 +154,7 @@ impl Default for DacConfig{
|
||||||
fn default() -> DacConfig{
|
fn default() -> DacConfig{
|
||||||
//DacConfig { name: "Unknown".into(), homography: Mat3::IDENTITY }
|
//DacConfig { name: "Unknown".into(), homography: Mat3::IDENTITY }
|
||||||
// DacConfig { name: "Unknown".into(), homography: LASER_H_CM }
|
// DacConfig { name: "Unknown".into(), homography: LASER_H_CM }
|
||||||
DacConfig { name: "Unknown".into(), source: StreamSource::CurrentLines, filters: PointFilters::default().with_homography(LASER_H) }
|
DacConfig { name: "Unknown".into(), source: StreamSource::CurrentLayers, filters: PointFilters::default().with_homography(LASER_H), layers_enabled: 0b1111_1111 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +216,7 @@ impl StreamSource{
|
||||||
pub fn get_shape(&self, current_points: LaserPoints, config: &DacConfig) -> LaserPoints {
|
pub fn get_shape(&self, current_points: LaserPoints, config: &DacConfig) -> LaserPoints {
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Self::CurrentLines => current_points,
|
Self::CurrentLayers => current_points,
|
||||||
Self::Rectangle => {
|
Self::Rectangle => {
|
||||||
shape_rect(LaserSpace::READY, 11)
|
shape_rect(LaserSpace::READY, 11)
|
||||||
},
|
},
|
||||||
|
|
|
@ -86,6 +86,36 @@ pub struct RenderableLines{
|
||||||
pub space: CoordinateSpace, // enum in python
|
pub space: CoordinateSpace, // enum in python
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
pub struct RenderableLayers(pub std::collections::HashMap<u8, RenderableLines>);
|
||||||
|
|
||||||
|
impl RenderableLayers{
|
||||||
|
pub fn new() -> Self{
|
||||||
|
Self (std::collections::HashMap::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_alpha(&self, alpha: f32) -> Self {
|
||||||
|
if alpha == 1. {
|
||||||
|
return self.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
Self ( self.0.iter().map(|(layer, lines)| { (*layer, lines.with_alpha(alpha))}).collect() )
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn line_count(&self) -> usize {
|
||||||
|
let s = self.0.values().map(|l| l.lines.len()).sum();
|
||||||
|
s
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn point_count(&self) -> usize {
|
||||||
|
let s = self.0.values().map(|l| l.point_count()).sum();
|
||||||
|
s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl RenderableLines{
|
impl RenderableLines{
|
||||||
pub fn new() -> Self{
|
pub fn new() -> Self{
|
||||||
RenderableLines { lines: Vec::new(), space: CoordinateSpace::World }
|
RenderableLines { lines: Vec::new(), space: CoordinateSpace::World }
|
||||||
|
|
|
@ -2,6 +2,8 @@ use zmq::Socket;
|
||||||
use serde_json::Result;
|
use serde_json::Result;
|
||||||
use bevy::{ecs::system::SystemState, prelude::*, render::Render};
|
use bevy::{ecs::system::SystemState, prelude::*, render::Render};
|
||||||
use std::num::NonZero;
|
use std::num::NonZero;
|
||||||
|
use crate::trap::tracks::RenderableLayers;
|
||||||
|
|
||||||
use super::{laser::{LaserApi, LaserTimer}, tracks::{Frame, RenderableLines, Track, TrackBundle}};
|
use super::{laser::{LaserApi, LaserTimer}, tracks::{Frame, RenderableLines, Track, TrackBundle}};
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,10 +62,10 @@ fn receive_zmq_lines(
|
||||||
dbg!(&json);
|
dbg!(&json);
|
||||||
|
|
||||||
// let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?");
|
// let msg: Frame = serde_json::from_str(&json[4..]).expect("No valid json?");
|
||||||
let res: Result<RenderableLines> = serde_json::from_str(&json);
|
let res: Result<RenderableLayers> = serde_json::from_str(&json);
|
||||||
|
|
||||||
let lines: RenderableLines = match res {
|
let layers: RenderableLayers = match res {
|
||||||
Ok(lines) => lines, // if Ok(255), set x to 255
|
Ok(layers) => layers, // if Ok(255), set x to 255
|
||||||
Err(_e) => {
|
Err(_e) => {
|
||||||
println!("No valid json? {json}");
|
println!("No valid json? {json}");
|
||||||
println!("{}", _e);
|
println!("{}", _e);
|
||||||
|
@ -73,15 +75,15 @@ fn receive_zmq_lines(
|
||||||
}, // if Err("some message"), panic with error message "some message"
|
}, // if Err("some message"), panic with error message "some message"
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("receive {}", lines.lines.len());
|
println!("receive {} lines", layers.line_count());
|
||||||
|
|
||||||
for (laser_api, mut laser_timer) in lasers.iter_mut() {
|
for (laser_api, mut laser_timer) in lasers.iter_mut() {
|
||||||
laser_timer.timer.tick(time.delta());
|
laser_timer.timer.tick(time.delta());
|
||||||
// let lines = get_laser_lines(version);
|
// let lines = get_laser_lines(version);
|
||||||
let lines: RenderableLines = lines.clone();
|
let lines: RenderableLayers = layers.clone();
|
||||||
laser_api.laser_stream.send(|laser| {
|
laser_api.laser_stream.send(|laser| {
|
||||||
let laser_lines: RenderableLines = lines;
|
let current_layers: RenderableLayers = lines;
|
||||||
laser.current_lines = laser_lines;
|
laser.current_layers = current_layers;
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue