extern crate camera_capture;
extern crate lase;
extern crate image;
use camera_capture::Frame;
use image::ImageBuffer;
use image::Rgb;
use lase::Point;
use lase::tools::ETHERDREAM_X_MAX as X_MAX;
use lase::tools::ETHERDREAM_X_MIN as X_MIN;
use lase::tools::find_first_etherdream_dac;
use std::f64::consts::PI;
use std::f64;
use std::sync::Arc;
use std::sync::RwLock;
static SPIRAL_POINTS : i32 = 1500;
static BLANKING_POINTS : i32 = 20;
static SPIRAL_GROWTH : f64 = 4.0;
static MAX_RADIUS : f64 = 30000.0;
type Image = ImageBuffer<Rgb<u8>, Frame>;
fn main() {
let frame_buffer : Arc<RwLock<Option<Image>>> = Arc::new(RwLock::new(None));
let frame_buffer2 = frame_buffer.clone();
let webcam_thread = std::thread::spawn(move || {
let cam = camera_capture::create(0).expect("Could not open webcam.")
.fps(30.0)
.expect("Unsupported webcam fps.")
.resolution(320, 240) .expect("Unsupported webcam resolution.")
.start()
.expect("Could not begin webcam.");
for frame in cam {
match frame_buffer2.write() {
Err(_) => println!("Error reading frame from webcam."),
Ok(mut w) => {
*w = Some(frame);
}
}
}
});
println!("Searching for DAC...");
let mut dac = find_first_etherdream_dac().expect("Couldn't find DAC");
static mut pos: i32 = 0;
let _r = dac.play_function(|num_points: u16| {
let mut points = Vec::new();
for _i in 0 .. num_points {
let f = unsafe {
pos = (pos + 1) % (BLANKING_POINTS + SPIRAL_POINTS);
pos
};
if f >= SPIRAL_POINTS {
let (x, y) = get_blanking_point(f - SPIRAL_POINTS);
points.push(Point::xy_binary(x, y, false));
continue;
}
match frame_buffer.read() {
Err(_) => println!("Cannot obtain read lock"),
Ok(maybe_frame) => {
match *maybe_frame {
None => {
let (x, y) = get_spiral_point(f);
points.push(Point::xy_binary(x, y, false));
},
Some(ref frame) => {
let (x, y) = get_spiral_point(f);
let (r, g, b) = laser_color_from_webcam(&frame, x, y);
points.push(Point::xy_rgb(x, y, r, g, b));
},
}
},
}
}
points
});
webcam_thread.join().unwrap();
}
fn get_spiral_point(cursor: i32) -> (i16, i16) {
let i = (cursor as f64) / SPIRAL_POINTS as f64;
let t = i * 2.0 * PI * SPIRAL_GROWTH * 10.0;
let r = MAX_RADIUS as f64 * i;
let x = t.cos() * r;
let y = t.sin() * r;
(x as i16, y as i16)
}
fn get_blanking_point(cursor: i32) -> (i16, i16) {
let (end_x, end_y) = get_spiral_point(SPIRAL_POINTS);
let x = end_x as f64 - end_x as f64 * cursor as f64 / BLANKING_POINTS as f64;
let y = end_y as f64 - end_y as f64 * cursor as f64 / BLANKING_POINTS as f64;
(x as i16, y as i16)
}
fn laser_color_from_webcam(image: &Image,
x: i16, y: i16) -> (u16, u16, u16) {
fn map_point(laser_position: i16, image_scale: u32) -> u32 {
let num = laser_position as f64 - X_MIN as f64;
let denom = X_MAX as f64 - X_MIN as f64;
let ratio = num / denom;
let scale = image_scale as f64; let result = ratio * scale;
result as u32
}
fn webcam_x(laser_x: i16, image_width: u32) -> u32 {
map_point(laser_x, image_width)
}
fn webcam_y(laser_y: i16, image_height : u32) -> u32 {
let laser_y = laser_y * -1; map_point(laser_y, image_height)
}
fn expand_color(color: u8) -> u16 {
if color < 100 {
0
} else {
(color as u16) * 257
}
}
let w_x = webcam_x(x, image.width());
let w_y = webcam_y(y, image.height());
let pix = image.get_pixel(w_x, w_y);
let r = expand_color(pix.data[0]);
let g = expand_color(pix.data[1]);
let b = expand_color(pix.data[2]);
(r, g, b)
}