Compare commits
No commits in common. "e8fec78250f48bbf57f459eb110efda763b3afea" and "d989cdaa869ab85fd6e92cd34bf1ebfd11f174be" have entirely different histories.
e8fec78250
...
d989cdaa86
3 changed files with 93 additions and 303 deletions
|
@ -12,7 +12,7 @@ use nannou_laser::DacId;
|
||||||
use nannou_laser::{self as laser};
|
use nannou_laser::{self as laser};
|
||||||
use serde_json::Result;
|
use serde_json::Result;
|
||||||
use trap_rust::trap::filters::PointFilters;
|
use trap_rust::trap::filters::PointFilters;
|
||||||
use trap_rust::trap::laser::{LaserPoints, StreamSource, STREAM_SOURCES, TMP_DESK_CLUBMAX};
|
use trap_rust::trap::laser::{LaserPoints, TMP_DESK_CLUBMAX};
|
||||||
use trap_rust::trap::tracks::CoordinateSpace;
|
use trap_rust::trap::tracks::CoordinateSpace;
|
||||||
use trap_rust::trap::{laser::{python_cv_h_into_mat3, LaserModel, TMP_PYTHON_LASER_H, DacConfig}, tracks::{RenderableLines}};
|
use trap_rust::trap::{laser::{python_cv_h_into_mat3, LaserModel, TMP_PYTHON_LASER_H, DacConfig}, tracks::{RenderableLines}};
|
||||||
use zmq::Socket;
|
use zmq::Socket;
|
||||||
|
@ -20,8 +20,6 @@ use std::sync::{mpsc, Arc};
|
||||||
use std::time::{Instant, Duration};
|
use std::time::{Instant, Duration};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
// use egui_dropdown::DropDownBox;
|
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
nannou::app(model).update(update).run();
|
nannou::app(model).update(update).run();
|
||||||
|
@ -64,7 +62,6 @@ struct LaserSettings {
|
||||||
latency_points: u32,
|
latency_points: u32,
|
||||||
frame_hz: u32,
|
frame_hz: u32,
|
||||||
enable_optimisations: bool,
|
enable_optimisations: bool,
|
||||||
enable_draw_reorder: bool,
|
|
||||||
distance_per_point: f32,
|
distance_per_point: f32,
|
||||||
blank_delay_points: u32,
|
blank_delay_points: u32,
|
||||||
radians_per_point: f32,
|
radians_per_point: f32,
|
||||||
|
@ -84,7 +81,6 @@ impl Default for LaserSettings {
|
||||||
) * 4,
|
) * 4,
|
||||||
frame_hz: 35, //stream::DEFAULT_FRAME_HZ,
|
frame_hz: 35, //stream::DEFAULT_FRAME_HZ,
|
||||||
enable_optimisations: true,
|
enable_optimisations: true,
|
||||||
enable_draw_reorder: true,
|
|
||||||
distance_per_point: InterpolationConfig::DEFAULT_DISTANCE_PER_POINT,
|
distance_per_point: InterpolationConfig::DEFAULT_DISTANCE_PER_POINT,
|
||||||
blank_delay_points: InterpolationConfig::DEFAULT_BLANK_DELAY_POINTS,
|
blank_delay_points: InterpolationConfig::DEFAULT_BLANK_DELAY_POINTS,
|
||||||
radians_per_point: InterpolationConfig::DEFAULT_RADIANS_PER_POINT,
|
radians_per_point: InterpolationConfig::DEFAULT_RADIANS_PER_POINT,
|
||||||
|
@ -162,9 +158,9 @@ fn zmq_receive(model: &mut GuiModel) {
|
||||||
for (_dac, stream_config) in (&model.laser_streams).into_iter() {
|
for (_dac, stream_config) 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 lines_for_laser: RenderableLines = lines.clone();
|
||||||
let sending = stream_config.stream.send(move |laser_model: &mut LaserModel| {
|
let sending = stream_config.stream.send(move |laser| {
|
||||||
let laser_lines: RenderableLines = lines_for_laser;
|
let laser_lines: RenderableLines = lines_for_laser;
|
||||||
laser_model.current_lines = laser_lines;
|
laser.current_lines = laser_lines;
|
||||||
});
|
});
|
||||||
if let Err(e) = sending {
|
if let Err(e) = sending {
|
||||||
println!("Error sending to laser! {e:?}");
|
println!("Error sending to laser! {e:?}");
|
||||||
|
@ -198,7 +194,8 @@ fn get_dac_configs() -> DacConfigMap{
|
||||||
DacId::Helios { id: 926298163 },
|
DacId::Helios { id: 926298163 },
|
||||||
DacConfig{
|
DacConfig{
|
||||||
name: "Helios#1".into(),
|
name: "Helios#1".into(),
|
||||||
.. DacConfig::default()
|
homography: python_cv_h_into_mat3(TMP_PYTHON_LASER_H),
|
||||||
|
filters: PointFilters::default(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
dac_configs.insert(
|
dac_configs.insert(
|
||||||
|
@ -214,7 +211,8 @@ fn get_dac_configs() -> DacConfigMap{
|
||||||
},
|
},
|
||||||
DacConfig{
|
DacConfig{
|
||||||
name: "ED - 192.168.8.101".into(),
|
name: "ED - 192.168.8.101".into(),
|
||||||
.. DacConfig::default()
|
homography: python_cv_h_into_mat3(TMP_DESK_CLUBMAX),
|
||||||
|
filters: PointFilters::default(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
dac_configs.insert(
|
dac_configs.insert(
|
||||||
|
@ -230,8 +228,8 @@ fn get_dac_configs() -> DacConfigMap{
|
||||||
},
|
},
|
||||||
DacConfig{
|
DacConfig{
|
||||||
name: "ED - 192.168.9.101".into(),
|
name: "ED - 192.168.9.101".into(),
|
||||||
.. DacConfig::default()
|
homography: python_cv_h_into_mat3(TMP_DESK_CLUBMAX),
|
||||||
// filters: PointFilters::default(),
|
filters: PointFilters::default(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
dac_configs.insert(
|
dac_configs.insert(
|
||||||
|
@ -247,7 +245,8 @@ fn get_dac_configs() -> DacConfigMap{
|
||||||
},
|
},
|
||||||
DacConfig{
|
DacConfig{
|
||||||
name: "Emulator".into(),
|
name: "Emulator".into(),
|
||||||
.. DacConfig::default()
|
homography: python_cv_h_into_mat3(TMP_DESK_CLUBMAX),
|
||||||
|
filters: PointFilters::default(),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
dac_configs
|
dac_configs
|
||||||
|
@ -356,35 +355,8 @@ fn model(app: &App) -> GuiModel {
|
||||||
|
|
||||||
fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){
|
fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){
|
||||||
|
|
||||||
let current_points: LaserPoints = (&model.current_lines).into();
|
let points: LaserPoints = (&model.current_lines).into();
|
||||||
// let points = LaserPoints { points: vec!(
|
|
||||||
// laser::Point{
|
|
||||||
// position:[ 9.4, 7.2],
|
|
||||||
// color: [1.,1.,0.],
|
|
||||||
// weight: 0,
|
|
||||||
// },
|
|
||||||
// laser::Point{
|
|
||||||
// position:[ 12.4, 7.2],
|
|
||||||
// color: [1.,1.,0.],
|
|
||||||
// weight: 0,
|
|
||||||
// },
|
|
||||||
// laser::Point{
|
|
||||||
// position:[ 12.4, 4.2],
|
|
||||||
// color: [1.,1.,0.],
|
|
||||||
// weight: 0,
|
|
||||||
// },
|
|
||||||
// laser::Point{
|
|
||||||
// position:[ 9.4, 4.2],
|
|
||||||
// color: [1.,1.,0.],
|
|
||||||
// weight: 0,
|
|
||||||
// },
|
|
||||||
// ), space: CoordinateSpace::World };
|
|
||||||
let space = &model.current_lines.space;
|
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);
|
|
||||||
|
|
||||||
let pointno = points.points.len();
|
let pointno = points.points.len();
|
||||||
|
|
||||||
let new_points = model.config.filters.apply(&points);
|
let new_points = model.config.filters.apply(&points);
|
||||||
|
@ -393,11 +365,6 @@ fn laser_frame_producer(model: &mut LaserModel, frame: &mut laser::Frame){
|
||||||
println!("Cropped Points {} (was: {})", new_laser_points.len(), pointno);
|
println!("Cropped Points {} (was: {})", new_laser_points.len(), pointno);
|
||||||
}
|
}
|
||||||
|
|
||||||
// on reconnect gives Unknown
|
|
||||||
// dbg!(&model.config);
|
|
||||||
// dbg!(&points.points[0]);
|
|
||||||
// dbg!(&new_laser_points[0]);
|
|
||||||
|
|
||||||
frame.add_lines(new_laser_points);
|
frame.add_lines(new_laser_points);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -424,7 +391,6 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
.detected_dac(dac.clone())
|
.detected_dac(dac.clone())
|
||||||
.build()
|
.build()
|
||||||
.expect("failed to establish stream with newly detected DAC");
|
.expect("failed to establish stream with newly detected DAC");
|
||||||
// dbg!(stream.enable_draw_reorder());
|
|
||||||
model.laser_streams.insert(dac.id(), StreamConfig{ stream, config: config.clone() });
|
model.laser_streams.insert(dac.id(), StreamConfig{ stream, config: config.clone() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -459,25 +425,14 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
// TODO: keeps looping on disconnect.
|
// TODO: keeps looping on disconnect.
|
||||||
println!("attempting to restart stream with DAC {:?}", dac.id());
|
println!("attempting to restart stream with DAC {:?}", dac.id());
|
||||||
let dac_id = dac.id();
|
let dac_id = dac.id();
|
||||||
let config = match model.per_laser_config.contains_key(&dac.id()) {
|
|
||||||
true => &model.per_laser_config[&dac.id()],
|
|
||||||
false => {
|
|
||||||
println!("Found unknown DAC, try to register it in get_dac_configs()");
|
|
||||||
dbg!(&dac.id());
|
|
||||||
&DacConfig::default()
|
|
||||||
},
|
|
||||||
};
|
|
||||||
match model
|
match model
|
||||||
.laser_api
|
.laser_api
|
||||||
.new_frame_stream(model.laser_model.with_config(config), laser_frame_producer)
|
.new_frame_stream(model.laser_model.clone(), laser_frame_producer)
|
||||||
.detected_dac(dac)
|
.detected_dac(dac)
|
||||||
.build()
|
.build()
|
||||||
{
|
{
|
||||||
Err(err) => eprintln!("failed to restart stream: {}", err),
|
Err(err) => eprintln!("failed to restart stream: {}", err),
|
||||||
Ok(stream) => {
|
Ok(stream) => {model.laser_streams.insert(dac_id, StreamConfig{stream, config: stream_config.config});},
|
||||||
println!("Reinsert stream. {:?}", dac_id);
|
|
||||||
model.laser_streams.insert(dac_id, StreamConfig{stream, config: stream_config.config});
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,23 +517,8 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui
|
if ui
|
||||||
.add_enabled(laser_settings.enable_optimisations,
|
.add(
|
||||||
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_config) in laser_streams.iter() {
|
|
||||||
stream_config.stream
|
|
||||||
.enable_draw_reorder(laser_settings.enable_draw_reorder)
|
|
||||||
.ok();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ui
|
|
||||||
.add_enabled(laser_settings.enable_optimisations,
|
|
||||||
egui::Slider::new(&mut laser_settings.distance_per_point, 0.01..=1.0)
|
egui::Slider::new(&mut laser_settings.distance_per_point, 0.01..=1.0)
|
||||||
.text("Distance Per Point"),
|
.text("Distance Per Point"),
|
||||||
)
|
)
|
||||||
|
@ -590,7 +530,7 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ui
|
if ui
|
||||||
.add_enabled(laser_settings.enable_optimisations,
|
.add(
|
||||||
egui::Slider::new(&mut laser_settings.blank_delay_points, 0..=32)
|
egui::Slider::new(&mut laser_settings.blank_delay_points, 0..=32)
|
||||||
.text("Blank Delay (Points)"),
|
.text("Blank Delay (Points)"),
|
||||||
)
|
)
|
||||||
|
@ -603,9 +543,7 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
}
|
}
|
||||||
let mut degrees = rad_to_deg(laser_settings.radians_per_point);
|
let mut degrees = rad_to_deg(laser_settings.radians_per_point);
|
||||||
if ui
|
if ui
|
||||||
.add_enabled(laser_settings.enable_optimisations,
|
.add(egui::Slider::new(&mut degrees, 1.0..=180.0).text("Degrees Per Point"))
|
||||||
egui::Slider::new(&mut degrees, 1.0..=180.0).text("Degrees Per Point")
|
|
||||||
)
|
|
||||||
.changed()
|
.changed()
|
||||||
{
|
{
|
||||||
let radians = deg_to_rad(degrees);
|
let radians = deg_to_rad(degrees);
|
||||||
|
@ -639,73 +577,6 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
|
|
||||||
let stream_config: &mut StreamConfig = laser_streams.get_mut(&selected_stream_value).expect("Selected stream not found in configs");
|
let stream_config: &mut StreamConfig = laser_streams.get_mut(&selected_stream_value).expect("Selected stream not found in configs");
|
||||||
|
|
||||||
|
|
||||||
let source = &mut stream_config.config.source;
|
|
||||||
// for source_option in STREAM_SOURCES {
|
|
||||||
// if ui.radio_value(source, source_option.clone(), format!("{:?}", &source_option)).changed() {
|
|
||||||
// println!("Clicked!")
|
|
||||||
// };
|
|
||||||
|
|
||||||
// }
|
|
||||||
egui::ComboBox::from_label("Source")
|
|
||||||
.selected_text(format!("{source:?}"))
|
|
||||||
.show_ui(ui, |ui| {
|
|
||||||
for source_option in STREAM_SOURCES {
|
|
||||||
if ui.selectable_value(source, source_option.clone(), format!("{:?}", &source_option)).clicked() {
|
|
||||||
// let source = source_option;
|
|
||||||
stream_config.stream.send(move |laser_model: &mut LaserModel| {
|
|
||||||
laser_model.config.source = source_option;
|
|
||||||
}).unwrap();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
// ui.selectable_value(source, StreamSource::CurrentLines, "Zmq Stream");
|
|
||||||
// ui.selectable_value(source, StreamSource::Rectangle, "Rectangle");
|
|
||||||
// ui.selectable_value(source, StreamSource::Grid, "Grid");
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// ui.radio_value(source, StreamSource::Rectangle, "Rectangle");
|
|
||||||
// ui.radio_value(source, StreamSource::Grid, "Grid");
|
|
||||||
|
|
||||||
// if ui.add(DropDownBox::from_iter(
|
|
||||||
// vec!(StreamSource::CurrentLines, StreamSource::Rectangle, StreamSource::Grid(5)),
|
|
||||||
// "test_dropbox",
|
|
||||||
// &mut stream_config.config.source,
|
|
||||||
// |ui, text| ui.selectable_label(false, text)
|
|
||||||
// )).changed() {
|
|
||||||
// println!("Changed source! {:?}", stream_config.config.source);
|
|
||||||
// let source = stream_config.config.source;
|
|
||||||
// stream_config.stream.send(move |laser_model: &mut LaserModel| {
|
|
||||||
// laser_model.config.source = source;
|
|
||||||
// }).unwrap();
|
|
||||||
// }
|
|
||||||
// if ui.add(
|
|
||||||
// egui::ComboBox::from_label("Source")
|
|
||||||
// .selected_text(format!("{source:?}"))
|
|
||||||
// // .show_ui(ui, |ui| {
|
|
||||||
// // ui.selectable_value(source, StreamSource::CurrentLines, "Zmq Stream");
|
|
||||||
// // ui.selectable_value(source, StreamSource::Rectangle, "Rectangle");
|
|
||||||
// // ui.selectable_value(source, StreamSource::Grid(5), "Grid");
|
|
||||||
// // })
|
|
||||||
// ).changed()
|
|
||||||
// {
|
|
||||||
// let source = stream_config.config.source;
|
|
||||||
// stream_config.stream.send(move |laser_model: &mut LaserModel| {
|
|
||||||
// laser_model.config.source = source;
|
|
||||||
// }).unwrap();
|
|
||||||
// }
|
|
||||||
|
|
||||||
if ui
|
|
||||||
.add(egui::Slider::new(&mut stream_config.config.filters.dim.intensity, 0.0..=1.).text("Dimming"))
|
|
||||||
.changed()
|
|
||||||
{
|
|
||||||
let factor = stream_config.config.filters.dim.intensity;
|
|
||||||
stream_config.stream.send(move |laser_model: &mut LaserModel| {
|
|
||||||
laser_model.config.filters.dim.intensity = factor;
|
|
||||||
}).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ui
|
if ui
|
||||||
.add(egui::Slider::new(&mut stream_config.config.filters.dim.intensity, 0.0..=1.).text("Dimming"))
|
.add(egui::Slider::new(&mut stream_config.config.filters.dim.intensity, 0.0..=1.).text("Dimming"))
|
||||||
.changed()
|
.changed()
|
||||||
|
@ -727,10 +598,8 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Pincushion / Pillow / Barrel distortion. Generally, only needed for the x-axis
|
|
||||||
|
|
||||||
if ui
|
if ui
|
||||||
.add(egui::Slider::new(&mut stream_config.config.filters.pincushion.k_x, -0.5..=0.5).text("Pincushion x"))
|
.add(egui::Slider::new(&mut stream_config.config.filters.pincushion.k_x, -1.0..=1.).text("Pincushion x"))
|
||||||
.changed()
|
.changed()
|
||||||
{
|
{
|
||||||
let factor = stream_config.config.filters.pincushion.k_x;
|
let factor = stream_config.config.filters.pincushion.k_x;
|
||||||
|
@ -740,17 +609,7 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui
|
if ui
|
||||||
.add(egui::Slider::new(&mut stream_config.config.filters.pincushion.k_x2, -0.2..=0.2).text("Higher order pincushion x"))
|
.add(egui::Slider::new(&mut stream_config.config.filters.pincushion.k_y, -1.0..=1.).text("Pincushion y"))
|
||||||
.changed()
|
|
||||||
{
|
|
||||||
let factor = stream_config.config.filters.pincushion.k_x2;
|
|
||||||
stream_config.stream.send(move |laser_model: &mut LaserModel| {
|
|
||||||
laser_model.config.filters.pincushion.k_x2 = factor;
|
|
||||||
}).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ui
|
|
||||||
.add(egui::Slider::new(&mut stream_config.config.filters.pincushion.k_y, -0.5..=0.5).text("Pincushion y"))
|
|
||||||
.changed()
|
.changed()
|
||||||
{
|
{
|
||||||
let factor = stream_config.config.filters.pincushion.k_y;
|
let factor = stream_config.config.filters.pincushion.k_y;
|
||||||
|
@ -759,16 +618,6 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
}).unwrap();
|
}).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ui
|
|
||||||
.add(egui::Slider::new(&mut stream_config.config.filters.pincushion.k_y2, -0.2..=0.2).text("Higher order pincushion y"))
|
|
||||||
.changed()
|
|
||||||
{
|
|
||||||
let factor = stream_config.config.filters.pincushion.k_y2;
|
|
||||||
stream_config.stream.send(move |laser_model: &mut LaserModel| {
|
|
||||||
laser_model.config.filters.pincushion.k_y2 = factor;
|
|
||||||
}).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ui
|
if ui
|
||||||
.checkbox(&mut stream_config.config.filters.crop.enabled ,"Crop")
|
.checkbox(&mut stream_config.config.filters.crop.enabled ,"Crop")
|
||||||
|
@ -782,6 +631,53 @@ fn update(_app: &App, model: &mut GuiModel, update: Update) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ui.heading("Connected DACs");
|
||||||
|
|
||||||
|
// if laser_streams.is_empty() {
|
||||||
|
// ui.label("no streams");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (_dac_id, stream_config) in laser_streams.iter_mut() {
|
||||||
|
// let dac: laser::DetectedDac = stream_config.stream
|
||||||
|
// .dac()
|
||||||
|
// .expect("`dac` returned `None` even though one was specified during stream creation");
|
||||||
|
// ui.add(egui::Label::new(format!("{:?}", dac.id())));
|
||||||
|
|
||||||
|
// if ui
|
||||||
|
// // todo : from custom dac config:
|
||||||
|
// .add(egui::Slider::new(&mut stream_config.config.filters.dim.intensity, 0.0..=1.).text("Dimming"))
|
||||||
|
// .changed()
|
||||||
|
// {
|
||||||
|
// for (_dac_id, laser_stream) in laser_streams.iter() {
|
||||||
|
// let factor = model.laser_model.dimming;
|
||||||
|
// // let lines = get_laser_lines(version);
|
||||||
|
// laser_stream.stream.send(move |laser| {
|
||||||
|
// // laser: LaserModel
|
||||||
|
// laser.config.filters.dim.intensity = factor;
|
||||||
|
// // laser.dimming = factor;
|
||||||
|
// }).unwrap();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
//if egui::ComboBox::from_label("Homography")
|
||||||
|
// .selected_text(format!("{radio:?}"))
|
||||||
|
// .show_ui(ui, |ui| {
|
||||||
|
// ui.selectable_value(radio, Enum::First, "First");
|
||||||
|
// ui.selectable_value(radio, Enum::Second, "Second");
|
||||||
|
// ui.selectable_value(radio, Enum::Third, "Third");
|
||||||
|
// })
|
||||||
|
// .changed() {
|
||||||
|
// let sending = laser_stream.send(move |laser| {
|
||||||
|
// let laser_lines: RenderableLines = lines_for_laser;
|
||||||
|
// laser.current_lines = laser_lines;
|
||||||
|
// });
|
||||||
|
// if let Err(e) = sending {
|
||||||
|
// println!("Error sending to laser! {e:?}");
|
||||||
|
// }
|
||||||
|
// };
|
||||||
} else {
|
} else {
|
||||||
ui.label("Select a DAC");
|
ui.label("Select a DAC");
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,47 +11,45 @@ pub trait Filter {
|
||||||
fn apply(&self, points: &LaserPoints) -> LaserPoints;
|
fn apply(&self, points: &LaserPoints) -> LaserPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct HomographyFilter {
|
pub struct HomographyFilter {
|
||||||
pub homography_matrix: Mat3
|
pub homography_matrix: Mat3
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct CropFilter {
|
pub struct CropFilter {
|
||||||
pub enabled: bool
|
pub enabled: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct DimFilter {
|
pub struct DimFilter {
|
||||||
pub intensity: f32
|
pub intensity: f32
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct ScaleFilter {
|
pub struct ScaleFilter {
|
||||||
pub factor: f32
|
pub factor: f32
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct PincushionFilter {
|
pub struct PincushionFilter {
|
||||||
pub k_x: f32,
|
pub k_x: f32,
|
||||||
pub k_x2: f32,
|
pub k_y: f32
|
||||||
pub k_y: f32,
|
|
||||||
pub k_y2: f32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
// // TODO consider moving to struct?
|
// TODO consider moving to struct?
|
||||||
// pub enum PointFilter {
|
pub enum PointFilter {
|
||||||
// Homography(HomographyFilter),
|
Homography(HomographyFilter),
|
||||||
// Dim(DimFilter),
|
Dim(DimFilter),
|
||||||
// Scale(ScaleFilter),
|
Scale(ScaleFilter),
|
||||||
// Pincushion(PincushionFilter),
|
Pincushion(PincushionFilter),
|
||||||
// Crop(CropFilter),
|
Crop(CropFilter),
|
||||||
// }
|
}
|
||||||
|
|
||||||
// pub struct PointFilterList(Vec<PointFilter>); // deprecated
|
pub struct PointFilterList(Vec<PointFilter>); // deprecated
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct PointFilters{
|
pub struct PointFilters{
|
||||||
pub dim: DimFilter,
|
pub dim: DimFilter,
|
||||||
pub homography: HomographyFilter,
|
pub homography: HomographyFilter,
|
||||||
|
@ -97,7 +95,7 @@ impl Default for PointFilters {
|
||||||
homography: HomographyFilter::default(),
|
homography: HomographyFilter::default(),
|
||||||
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_y: 0.},
|
||||||
crop: CropFilter{ enabled: true },
|
crop: CropFilter{ enabled: true },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,17 +313,9 @@ impl Filter for PincushionFilter {
|
||||||
|
|
||||||
let projected_positions: Vec<laser::Point> = points.points.iter().map(|point| {
|
let projected_positions: Vec<laser::Point> = points.points.iter().map(|point| {
|
||||||
let p = point.position;
|
let p = point.position;
|
||||||
|
|
||||||
// Apply Brown-Conrady model of distortion
|
|
||||||
|
|
||||||
// https://en.wikipedia.org/wiki/Distortion_(optics)#Software_correction
|
|
||||||
// calculate radius (though we might be able to get away, just using p[1] and p[0]
|
|
||||||
// as we calculate axes independently)
|
|
||||||
let radius = (p[0].powi(2) + p[1].powi(2)).sqrt();
|
|
||||||
|
|
||||||
let new_position = [
|
let new_position = [
|
||||||
p[0] * (1. + self.k_x * radius.powi(2)+ self.k_x2 * radius.powi(4)),
|
p[0] * (1. + self.k_x * p[0].powi(2)),
|
||||||
p[1] * (1. + self.k_y * radius.powi(2)+ self.k_y2 * radius.powi(4))
|
p[1] * (1. + self.k_y * p[1].powi(2))
|
||||||
];
|
];
|
||||||
|
|
||||||
laser::Point {
|
laser::Point {
|
||||||
|
|
|
@ -2,11 +2,10 @@ 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::{PointFilter, PointFilters}, tracks::CoordinateSpace};
|
||||||
|
|
||||||
use super::tracks::{RenderableLines};
|
use super::tracks::{RenderableLines};
|
||||||
|
|
||||||
|
|
||||||
pub struct LaserPoints{
|
pub struct LaserPoints{
|
||||||
pub points: Vec<laser::Point>,
|
pub points: Vec<laser::Point>,
|
||||||
pub space: CoordinateSpace
|
pub space: CoordinateSpace
|
||||||
|
@ -47,7 +46,7 @@ pub fn apply_homography_matrix(h: Mat3, p: &[f32; 2]) -> [f32; 2]{
|
||||||
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_lines: RenderableLines,
|
||||||
// pub dimming: f32,
|
pub dimming: f32,
|
||||||
pub config: DacConfig, // per dac configuration
|
pub config: DacConfig, // per dac configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +55,7 @@ impl LaserModel{
|
||||||
Self{
|
Self{
|
||||||
t: Instant::now(),
|
t: Instant::now(),
|
||||||
current_lines: RenderableLines::new(),
|
current_lines: RenderableLines::new(),
|
||||||
// dimming: 0.3,
|
dimming: 0.3,
|
||||||
config: DacConfig::default(),
|
config: DacConfig::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,29 +81,15 @@ pub struct LaserTimer {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct DacConfig{
|
pub struct DacConfig{
|
||||||
// #[serde(with = "DacIdSerializable")]
|
// #[serde(with = "DacIdSerializable")]
|
||||||
// id: DacId,
|
// id: DacId,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
// pub homography: Mat3,
|
pub homography: Mat3,
|
||||||
pub source: StreamSource,
|
pub filters: PointFilters
|
||||||
pub filters: PointFilters,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
|
||||||
pub enum StreamSource {
|
|
||||||
CurrentLines,
|
|
||||||
Rectangle,
|
|
||||||
Grid, // lines
|
|
||||||
Circle, // segments
|
|
||||||
Spiral,
|
|
||||||
}
|
|
||||||
|
|
||||||
// usefull to create pull downs with an iterator
|
|
||||||
pub const STREAM_SOURCES: [StreamSource; 5] = [StreamSource::CurrentLines, StreamSource::Rectangle, StreamSource::Grid, StreamSource::Circle, StreamSource::Spiral];
|
|
||||||
|
|
||||||
|
|
||||||
const LASER_H: Mat3 = python_cv_h_into_mat3(TMP_PYTHON_LASER_H);
|
const LASER_H: Mat3 = python_cv_h_into_mat3(TMP_PYTHON_LASER_H);
|
||||||
const LASER_H_CM: Mat3 = python_cv_h_into_mat3(TMP_DESK_CLUBMAX);
|
const LASER_H_CM: Mat3 = python_cv_h_into_mat3(TMP_DESK_CLUBMAX);
|
||||||
|
|
||||||
|
@ -113,87 +98,6 @@ 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(), homography: LASER_H, filters: PointFilters::default().with_homography(LASER_H) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Default for LaserPoints {
|
|
||||||
fn default() -> LaserPoints {
|
|
||||||
LaserPoints { points: Vec::new(), space: CoordinateSpace::World }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// the different shapes that override the provided lines if needed
|
|
||||||
impl StreamSource{
|
|
||||||
pub fn get_shape(&self, current_lines: LaserPoints) -> LaserPoints {
|
|
||||||
match self {
|
|
||||||
Self::CurrentLines => current_lines,
|
|
||||||
Self::Rectangle => LaserPoints { points: vec!(
|
|
||||||
laser::Point{
|
|
||||||
position:[0xFFF as f32, 0xFFF as f32],
|
|
||||||
color: [1.,1.,1.],
|
|
||||||
weight: 0,
|
|
||||||
},
|
|
||||||
laser::Point{
|
|
||||||
position:[0xFFF as f32, 0.0],
|
|
||||||
color: [1.,1.,1.],
|
|
||||||
weight: 0,
|
|
||||||
},
|
|
||||||
laser::Point{
|
|
||||||
position:[0.0, 0.0],
|
|
||||||
color: [1.,1.,1.],
|
|
||||||
weight: 0,
|
|
||||||
},
|
|
||||||
laser::Point{
|
|
||||||
position:[0.0, 0xFFF as f32],
|
|
||||||
color: [1.,1.,1.],
|
|
||||||
weight: 0,
|
|
||||||
},
|
|
||||||
laser::Point{
|
|
||||||
position:[0xFFF as f32, 0xFFF as f32],
|
|
||||||
color: [1.,1.,1.],
|
|
||||||
weight: 0,
|
|
||||||
},
|
|
||||||
), space: CoordinateSpace::Laser },
|
|
||||||
Self::Grid => {
|
|
||||||
let mut points = Vec::new();
|
|
||||||
for i in (0..=0xFFF).step_by(0xFFF / 5) {
|
|
||||||
points.push(laser::Point{
|
|
||||||
position:[i as f32, 0.],
|
|
||||||
color: [0., 0., 0.],
|
|
||||||
weight: 0,
|
|
||||||
});
|
|
||||||
for j in (0..=0xFFF).step_by(0xFFF / 10) {
|
|
||||||
points.push(laser::Point{
|
|
||||||
position:[i as f32, j as f32],
|
|
||||||
color: [1.,1.,1.],
|
|
||||||
weight: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
points.push(points[points.len()-1].blanked());
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in (0..=0xFFF).step_by(0xFFF / 5) {
|
|
||||||
points.push(laser::Point{
|
|
||||||
position:[0., i as f32],
|
|
||||||
color: [0., 0., 0.],
|
|
||||||
weight: 0,
|
|
||||||
});
|
|
||||||
for j in (0..=0xFFF).step_by(0xFFF / 10) {
|
|
||||||
points.push(laser::Point{
|
|
||||||
position:[j as f32, i as f32],
|
|
||||||
color: [1.,1.,1.],
|
|
||||||
weight: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
points.push(points[points.len()-1].blanked());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LaserPoints { points, space: CoordinateSpace::Laser }
|
|
||||||
},
|
|
||||||
_ => LaserPoints::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue