split into separate files
This commit is contained in:
parent
215f694d88
commit
33123cb9c3
5 changed files with 278 additions and 233 deletions
90
src/fixture.rs
Normal file
90
src/fixture.rs
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
use {
|
||||||
|
prisma::{Rgb},
|
||||||
|
cgmath::{Vector2},
|
||||||
|
std::boxed::Box,
|
||||||
|
crate::view::ColorGrid
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub trait FixtureDriver {
|
||||||
|
fn send(&self, pixels: &Vec<Rgb<u8>>);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Fixture {
|
||||||
|
pub resolution: Vector2<u32>,
|
||||||
|
pub position: Vector2<f32>,
|
||||||
|
pub rotation: f32,
|
||||||
|
pub scale: f32,
|
||||||
|
pub brightness: f32,
|
||||||
|
pub buffer: Vec< Rgb<u8> >,
|
||||||
|
pub driver: Option<Box<dyn FixtureDriver>>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Fixture {
|
||||||
|
pub fn new_stripe() -> Self {
|
||||||
|
let mut fixture = Fixture {
|
||||||
|
resolution: Vector2::new(1, 72),
|
||||||
|
position: Vector2::new(0.0, 0.0),
|
||||||
|
rotation: 0.0,
|
||||||
|
scale: 0.015,
|
||||||
|
brightness: 0.8,
|
||||||
|
buffer: Vec::new(),
|
||||||
|
driver: None
|
||||||
|
};
|
||||||
|
fixture.buffer.resize(
|
||||||
|
(fixture.resolution.x*fixture.resolution.y) as usize,
|
||||||
|
Rgb::new(0,0,0));
|
||||||
|
fixture
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_matrix() -> Self {
|
||||||
|
let mut fixture = Fixture {
|
||||||
|
resolution: Vector2::new(15, 20),
|
||||||
|
position: Vector2::new(0.0, 0.0),
|
||||||
|
rotation: 0.0,
|
||||||
|
scale: 0.03,
|
||||||
|
brightness: 0.8,
|
||||||
|
buffer: Vec::new(),
|
||||||
|
driver: None
|
||||||
|
};
|
||||||
|
fixture.buffer.resize(
|
||||||
|
(fixture.resolution.x*fixture.resolution.y) as usize,
|
||||||
|
Rgb::new(0,0,0)
|
||||||
|
);
|
||||||
|
fixture
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_driver(mut self, driver: Box<dyn FixtureDriver>) -> Self {
|
||||||
|
self.driver = Some(driver);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn offset(mut self, offset: Vector2<f32>) -> Self {
|
||||||
|
self.position += offset;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_global_pos(&self, pixel_pos: &Vector2<u32>) -> Vector2<f32> {
|
||||||
|
let centered_pixpos : Vector2<f32>
|
||||||
|
= pixel_pos.map(|f| f as f32) - (self.resolution.map(|f| f as f32)/2.0);
|
||||||
|
self.position + centered_pixpos * self.scale
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_buffer(&mut self, view: &Box<dyn ColorGrid>) {
|
||||||
|
for xi in 0 .. self.resolution.x {
|
||||||
|
for yi in 0 ..self.resolution.y {
|
||||||
|
let gpos = self.get_global_pos(&Vector2::new(xi, yi));
|
||||||
|
let col = view.get(&gpos);
|
||||||
|
|
||||||
|
let index = xi + yi * self.resolution.x;
|
||||||
|
self.buffer[index as usize] = Rgb::new(
|
||||||
|
(col.red() * 255.0 * self.brightness) as u8,
|
||||||
|
(col.green() * 255.0 * self.brightness) as u8,
|
||||||
|
(col.blue() * 255.0 * self.brightness) as u8
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
269
src/main.rs
269
src/main.rs
|
@ -13,11 +13,19 @@ use {
|
||||||
angle::Turns
|
angle::Turns
|
||||||
};
|
};
|
||||||
|
|
||||||
trait ColorGrid {
|
mod fixture;
|
||||||
fn get(&self, pos: &Vector2<f32>) -> Rgb<f32>;
|
mod setup;
|
||||||
}
|
mod view;
|
||||||
|
mod stripe_driver;
|
||||||
|
|
||||||
struct TestAnimation {
|
use crate::{
|
||||||
|
view::ColorGrid,
|
||||||
|
fixture::Fixture,
|
||||||
|
setup::LightingSetup,
|
||||||
|
stripe_driver::StripeDriver,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Breathing {
|
||||||
t: Arc<RwLock<Duration>>
|
t: Arc<RwLock<Duration>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,242 +46,31 @@ fn get_angle(p: &Vector2<f32>) -> f32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ColorGrid for TestAnimation {
|
impl ColorGrid for Breathing {
|
||||||
fn get(&self, p: &Vector2<f32>) -> Rgb<f32> {
|
fn get(&self, p: &Vector2<f32>) -> Rgb<f32> {
|
||||||
let millis = self.t.read().unwrap().as_millis();
|
let millis = self.t.read().unwrap().as_millis();
|
||||||
|
|
||||||
let p1 = p + Vector2::new(0.0,1.0);
|
let p1 = p + Vector2::new(0.0,0.5);
|
||||||
let r2 = p1.x*p1.x + p1.y*p1.y;
|
let r2 = p1.x*p1.x + p1.y*p1.y;
|
||||||
let v = if r2 > 1.0 { 1.0 } else { r2 };
|
let v = if r2 > 1.0 { 1.0 } else { r2 };
|
||||||
|
let phi = ( get_angle(&p1) );
|
||||||
let phi : f32 = (
|
let mirrorphi = if phi < 0.5 { phi } else { 1.0-phi };
|
||||||
(millis as f32 / 4000.0) +
|
let gamma = (
|
||||||
(
|
(30.0) *
|
||||||
100.0 + (millis%20000) as f32 / 300.0
|
mirrorphi *
|
||||||
) * get_angle(&p1)
|
( 0.5+ 0.5*f32::sin(millis as f32 / 4000.0) )
|
||||||
) % 1.0;
|
) % 1.0;
|
||||||
|
|
||||||
Rgb::from_color(
|
Rgb::from_color(
|
||||||
&Hsv::<f32, Turns<f32>>::new(
|
&Hsv::<f32, Turns<f32>>::new(
|
||||||
Turns( ((millis as f32 / 8000.0) + phi*0.2)%1.0 ),
|
Turns( 0.25+0.25*f32::sin(millis as f32/8000.0) + gamma*0.5 ),
|
||||||
0.5 + r2 * 0.5,
|
0.5 + r2 * 0.5,
|
||||||
phi,
|
mirrorphi,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait FixtureDriver {
|
|
||||||
fn send(&self, pixels: &Vec<Rgb<u8>>);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Fixture {
|
|
||||||
resolution: Vector2<u32>,
|
|
||||||
position: Vector2<f32>,
|
|
||||||
rotation: f32,
|
|
||||||
scale: f32,
|
|
||||||
brightness: f32,
|
|
||||||
buffer: Vec< Rgb<u8> >,
|
|
||||||
|
|
||||||
driver: Option<Box<dyn FixtureDriver>>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Fixture {
|
|
||||||
pub fn new_stripe() -> Self {
|
|
||||||
let mut fixture = Fixture {
|
|
||||||
resolution: Vector2::new(1, 72),
|
|
||||||
position: Vector2::new(0.0, 0.0),
|
|
||||||
rotation: 0.0,
|
|
||||||
scale: 0.01,
|
|
||||||
brightness: 0.8,
|
|
||||||
buffer: Vec::new(),
|
|
||||||
driver: None
|
|
||||||
};
|
|
||||||
fixture.buffer.resize(
|
|
||||||
(fixture.resolution.x*fixture.resolution.y) as usize,
|
|
||||||
Rgb::new(0,0,0));
|
|
||||||
fixture
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new_matrix() -> Self {
|
|
||||||
let mut fixture = Fixture {
|
|
||||||
resolution: Vector2::new(15, 20),
|
|
||||||
position: Vector2::new(0.0, 0.0),
|
|
||||||
rotation: 0.0,
|
|
||||||
scale: 0.03,
|
|
||||||
brightness: 0.8,
|
|
||||||
buffer: Vec::new(),
|
|
||||||
driver: None
|
|
||||||
};
|
|
||||||
fixture.buffer.resize(
|
|
||||||
(fixture.resolution.x*fixture.resolution.y) as usize,
|
|
||||||
Rgb::new(0,0,0)
|
|
||||||
);
|
|
||||||
fixture
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_driver(mut self, driver: Box<dyn FixtureDriver>) -> Self {
|
|
||||||
self.driver = Some(driver);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn offset(mut self, offset: Vector2<f32>) -> Self {
|
|
||||||
self.position += offset;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_global_pos(&self, pixel_pos: &Vector2<u32>) -> Vector2<f32> {
|
|
||||||
let centered_pixpos : Vector2<f32>
|
|
||||||
= pixel_pos.map(|f| f as f32) - (self.resolution.map(|f| f as f32)/2.0);
|
|
||||||
self.position + centered_pixpos * self.scale
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_buffer(&mut self, view: &Box<dyn ColorGrid>) {
|
|
||||||
for xi in 0 .. self.resolution.x {
|
|
||||||
for yi in 0 ..self.resolution.y {
|
|
||||||
let gpos = self.get_global_pos(&Vector2::new(xi, yi));
|
|
||||||
let col = view.get(&gpos);
|
|
||||||
|
|
||||||
let index = xi + yi * self.resolution.x;
|
|
||||||
self.buffer[index as usize] = Rgb::new(
|
|
||||||
(col.red() * 255.0 * self.brightness) as u8,
|
|
||||||
(col.green() * 255.0 * self.brightness) as u8,
|
|
||||||
(col.blue() * 255.0 * self.brightness) as u8
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct LightingSetup {
|
|
||||||
fixtures: Vec<Fixture>,
|
|
||||||
t: Arc<RwLock<Duration>>,
|
|
||||||
|
|
||||||
view: Box<dyn ColorGrid>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LightingSetup {
|
|
||||||
fn new(fixtures: Vec<Fixture>) -> Self {
|
|
||||||
let t = Arc::new(RwLock::new(Duration::from_millis(0)));
|
|
||||||
LightingSetup {
|
|
||||||
fixtures,
|
|
||||||
t: t.clone(),
|
|
||||||
view: Box::new(
|
|
||||||
TestAnimation{ t }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_buffers(&mut self) {
|
|
||||||
for fixture in self.fixtures.iter_mut() {
|
|
||||||
fixture.update_buffer( &self.view );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_outputs(&mut self) {
|
|
||||||
for fixture in self.fixtures.iter() {
|
|
||||||
if let Some(driver) = fixture.driver.as_ref() {
|
|
||||||
driver.send( &fixture.buffer );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_preview(
|
|
||||||
&self,
|
|
||||||
buffer: &mut softbuffer::Buffer<'_, Arc<winit::window::Window>, Arc<winit::window::Window>>,
|
|
||||||
width: u32,
|
|
||||||
height: u32
|
|
||||||
) {
|
|
||||||
// pixels per Unit
|
|
||||||
let mindim = u32::min(width, height);
|
|
||||||
let midx = width/2;
|
|
||||||
let midy = height/2;
|
|
||||||
|
|
||||||
// background
|
|
||||||
for index in 0..(width * height) {
|
|
||||||
let y = index / width;
|
|
||||||
let x = index % width;
|
|
||||||
|
|
||||||
let xf = (x as f32 - width as f32/2.0) / mindim as f32;
|
|
||||||
let yf = -(y as f32 - height as f32/2.0) / mindim as f32;
|
|
||||||
|
|
||||||
let color = self.view.get(&Vector2::new(xf, yf));
|
|
||||||
|
|
||||||
let red = (color.red() * 32.0) as u32;
|
|
||||||
let green = (color.green() * 32.0) as u32;
|
|
||||||
let blue = (color.blue() * 32.0) as u32;
|
|
||||||
|
|
||||||
buffer[index as usize] = blue | (green << 8) | (red << 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
for fixture in self.fixtures.iter() {
|
|
||||||
let pixel_width = fixture.scale * mindim as f32;
|
|
||||||
|
|
||||||
for fx in 0..fixture.resolution.x {
|
|
||||||
for fy in 0..fixture.resolution.y {
|
|
||||||
// get global position for pixel
|
|
||||||
let gpos = fixture.get_global_pos(&Vector2::new(fx, fy));
|
|
||||||
|
|
||||||
// get start coordinates for pixel
|
|
||||||
let xi = (midx as f32 + gpos.x*mindim as f32) as u32;
|
|
||||||
let yi = (midy as f32 - gpos.y*mindim as f32) as u32;
|
|
||||||
|
|
||||||
let col = fixture.buffer[(fx+fy*fixture.resolution.x) as usize];
|
|
||||||
let bufval = col.blue() as u32 | ((col.green() as u32) << 8) | ((col.red() as u32) << 16);
|
|
||||||
|
|
||||||
// draw pixel
|
|
||||||
for xl in 0..(pixel_width*0.6) as u32 {
|
|
||||||
for yl in 0..(pixel_width*0.6) as u32 {
|
|
||||||
if (xi+xl) < width && (yi+yl) < height {
|
|
||||||
let index = (xi+xl) + (yi+yl)*width;
|
|
||||||
buffer[index as usize] = bufval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct StripeDriver {
|
|
||||||
socket: Arc<RwLock<std::net::UdpSocket>>,
|
|
||||||
addr: String
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StripeDriver {
|
|
||||||
fn new(addr: &str, socket: Arc<RwLock<std::net::UdpSocket>>) -> Self {
|
|
||||||
StripeDriver {
|
|
||||||
addr: addr.into(),
|
|
||||||
socket
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FixtureDriver for StripeDriver {
|
|
||||||
fn send(&self, pixels: &Vec<Rgb<u8>>) {
|
|
||||||
const STRIPE_LEN : usize = 72;
|
|
||||||
let mut buf = [0 as u8; STRIPE_LEN*3];
|
|
||||||
|
|
||||||
for x in 0 .. STRIPE_LEN {
|
|
||||||
buf[x*3+0] = pixels[x].green();
|
|
||||||
buf[x*3+1] = pixels[x].red();
|
|
||||||
buf[x*3+2] = pixels[x].blue();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.socket.write().unwrap().send_to(&buf, &self.addr);
|
|
||||||
|
|
||||||
let mut rbuf = [0 as u8; 8];
|
|
||||||
match
|
|
||||||
self.socket.write().unwrap().recv(&mut rbuf) {
|
|
||||||
Ok(_) => {}
|
|
||||||
Err(_) => {
|
|
||||||
eprintln!("missing response from stripe");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[async_std::main]
|
#[async_std::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let event_loop = EventLoop::new().unwrap();
|
let event_loop = EventLoop::new().unwrap();
|
||||||
|
@ -287,27 +84,33 @@ async fn main() {
|
||||||
socket.write().unwrap().set_read_timeout(Some(std::time::Duration::from_millis(500)));
|
socket.write().unwrap().set_read_timeout(Some(std::time::Duration::from_millis(500)));
|
||||||
socket.write().unwrap().set_write_timeout(Some(std::time::Duration::from_millis(50)));
|
socket.write().unwrap().set_write_timeout(Some(std::time::Duration::from_millis(50)));
|
||||||
|
|
||||||
|
let t = Arc::new(RwLock::new(Duration::from_millis(0)));
|
||||||
|
|
||||||
let mut lighting_setup = LightingSetup::new(
|
let mut lighting_setup = LightingSetup::new(
|
||||||
vec![
|
vec![
|
||||||
Fixture::new_matrix(),
|
Fixture::new_matrix(),
|
||||||
// .with_driver( Box::new(MatrixTcpDriver::new("ip:port")) ),
|
// .with_driver( Box::new(MatrixTcpDriver::new("ip:port")) ),
|
||||||
|
|
||||||
Fixture::new_stripe()
|
Fixture::new_stripe()
|
||||||
.with_driver( Box::new(StripeDriver::new("192.168.0.111:4210", socket.clone())) )
|
// .with_driver( Box::new(StripeDriver::new("192.168.0.111:4210", socket.clone())) )
|
||||||
.offset(Vector2::new(-0.5, 0.0)),
|
.offset(Vector2::new(-0.5, 0.0)),
|
||||||
|
|
||||||
Fixture::new_stripe()
|
Fixture::new_stripe()
|
||||||
.with_driver( Box::new(StripeDriver::new("192.168.0.112:4210", socket.clone())) )
|
// .with_driver( Box::new(StripeDriver::new("192.168.0.112:4210", socket.clone())) )
|
||||||
.offset(Vector2::new(-0.4, 0.0)),
|
.offset(Vector2::new(-0.4, 0.0)),
|
||||||
|
|
||||||
Fixture::new_stripe()
|
Fixture::new_stripe()
|
||||||
.with_driver( Box::new(StripeDriver::new("192.168.0.113:4210", socket.clone())) )
|
// .with_driver( Box::new(StripeDriver::new("192.168.0.113:4210", socket.clone())) )
|
||||||
.offset(Vector2::new(0.4, 0.0)),
|
.offset(Vector2::new(0.4, 0.0)),
|
||||||
|
|
||||||
Fixture::new_stripe()
|
Fixture::new_stripe()
|
||||||
.with_driver( Box::new(StripeDriver::new("192.168.0.114:4210", socket.clone())))
|
// .with_driver( Box::new(StripeDriver::new("192.168.0.114:4210", socket.clone())))
|
||||||
.offset(Vector2::new(0.5, 0.0))
|
.offset(Vector2::new(0.5, 0.0))
|
||||||
]
|
],
|
||||||
|
|
||||||
|
Box::new(
|
||||||
|
Breathing{ t: t.clone() }
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
let tbegin = std::time::Instant::now();
|
let tbegin = std::time::Instant::now();
|
||||||
|
@ -317,9 +120,9 @@ async fn main() {
|
||||||
tcur + Duration::from_millis(10)
|
tcur + Duration::from_millis(10)
|
||||||
));
|
));
|
||||||
|
|
||||||
*lighting_setup.t.write().unwrap() = tcur - tbegin;
|
*t.write().unwrap() = tcur - tbegin;
|
||||||
lighting_setup.update_buffers();
|
lighting_setup.update_buffers();
|
||||||
lighting_setup.update_outputs();
|
//lighting_setup.update_outputs();
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested } if window_id == window.id() => {
|
Event::WindowEvent { window_id, event: WindowEvent::RedrawRequested } if window_id == window.id() => {
|
||||||
|
|
99
src/setup.rs
Normal file
99
src/setup.rs
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
fixture::Fixture,
|
||||||
|
view::ColorGrid
|
||||||
|
},
|
||||||
|
cgmath::Vector2,
|
||||||
|
std::time::Duration,
|
||||||
|
std::sync::{Arc, RwLock}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct LightingSetup {
|
||||||
|
fixtures: Vec<Fixture>,
|
||||||
|
t: Arc<RwLock<Duration>>,
|
||||||
|
|
||||||
|
view: Box<dyn ColorGrid>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LightingSetup {
|
||||||
|
pub fn new(fixtures: Vec<Fixture>, view: Box<dyn ColorGrid>) -> Self {
|
||||||
|
let t = Arc::new(RwLock::new(Duration::from_millis(0)));
|
||||||
|
LightingSetup {
|
||||||
|
fixtures,
|
||||||
|
t: t.clone(),
|
||||||
|
view
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_buffers(&mut self) {
|
||||||
|
for fixture in self.fixtures.iter_mut() {
|
||||||
|
fixture.update_buffer( &self.view );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_outputs(&mut self) {
|
||||||
|
for fixture in self.fixtures.iter() {
|
||||||
|
if let Some(driver) = fixture.driver.as_ref() {
|
||||||
|
driver.send( &fixture.buffer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_preview(
|
||||||
|
&self,
|
||||||
|
buffer: &mut softbuffer::Buffer<'_, Arc<winit::window::Window>, Arc<winit::window::Window>>,
|
||||||
|
width: u32,
|
||||||
|
height: u32
|
||||||
|
) {
|
||||||
|
// pixels per Unit
|
||||||
|
let mindim = u32::min(width, height);
|
||||||
|
let midx = width/2;
|
||||||
|
let midy = height/2;
|
||||||
|
|
||||||
|
// background
|
||||||
|
for index in 0..(width * height) {
|
||||||
|
let y = index / width;
|
||||||
|
let x = index % width;
|
||||||
|
|
||||||
|
let xf = (x as f32 - width as f32/2.0) / mindim as f32;
|
||||||
|
let yf = -(y as f32 - height as f32/2.0) / mindim as f32;
|
||||||
|
|
||||||
|
let color = self.view.get(&Vector2::new(xf, yf));
|
||||||
|
|
||||||
|
let red = (color.red() * 32.0) as u32;
|
||||||
|
let green = (color.green() * 32.0) as u32;
|
||||||
|
let blue = (color.blue() * 32.0) as u32;
|
||||||
|
|
||||||
|
buffer[index as usize] = 0;//blue | (green << 8) | (red << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
for fixture in self.fixtures.iter() {
|
||||||
|
let pixel_width = fixture.scale * mindim as f32;
|
||||||
|
|
||||||
|
for fx in 0..fixture.resolution.x {
|
||||||
|
for fy in 0..fixture.resolution.y {
|
||||||
|
// get global position for pixel
|
||||||
|
let gpos = fixture.get_global_pos(&Vector2::new(fx, fy));
|
||||||
|
|
||||||
|
// get start coordinates for pixel
|
||||||
|
let xi = (midx as f32 + gpos.x*mindim as f32) as u32;
|
||||||
|
let yi = (midy as f32 - gpos.y*mindim as f32) as u32;
|
||||||
|
|
||||||
|
let col = fixture.buffer[(fx+fy*fixture.resolution.x) as usize];
|
||||||
|
let bufval = col.blue() as u32 | ((col.green() as u32) << 8) | ((col.red() as u32) << 16);
|
||||||
|
|
||||||
|
// draw pixel
|
||||||
|
for xl in 0..(pixel_width*0.6) as u32 {
|
||||||
|
for yl in 0..(pixel_width*0.6) as u32 {
|
||||||
|
if (xi+xl) < width && (yi+yl) < height {
|
||||||
|
let index = (xi+xl) + (yi+yl)*width;
|
||||||
|
buffer[index as usize] = bufval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
44
src/stripe_driver.rs
Normal file
44
src/stripe_driver.rs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
use {
|
||||||
|
prisma::{Rgb},
|
||||||
|
std::sync::{Arc, RwLock},
|
||||||
|
crate::fixture::FixtureDriver
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct StripeDriver {
|
||||||
|
socket: Arc<RwLock<std::net::UdpSocket>>,
|
||||||
|
addr: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StripeDriver {
|
||||||
|
fn new(addr: &str, socket: Arc<RwLock<std::net::UdpSocket>>) -> Self {
|
||||||
|
StripeDriver {
|
||||||
|
addr: addr.into(),
|
||||||
|
socket
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FixtureDriver for StripeDriver {
|
||||||
|
fn send(&self, pixels: &Vec<Rgb<u8>>) {
|
||||||
|
const STRIPE_LEN : usize = 72;
|
||||||
|
let mut buf = [0 as u8; STRIPE_LEN*3];
|
||||||
|
|
||||||
|
for x in 0 .. STRIPE_LEN {
|
||||||
|
buf[x*3+0] = pixels[x].green();
|
||||||
|
buf[x*3+1] = pixels[x].red();
|
||||||
|
buf[x*3+2] = pixels[x].blue();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.socket.write().unwrap().send_to(&buf, &self.addr);
|
||||||
|
|
||||||
|
let mut rbuf = [0 as u8; 8];
|
||||||
|
match
|
||||||
|
self.socket.write().unwrap().recv(&mut rbuf) {
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!("missing response from stripe");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
9
src/view.rs
Normal file
9
src/view.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
use {
|
||||||
|
cgmath::Vector2,
|
||||||
|
prisma::Rgb
|
||||||
|
};
|
||||||
|
|
||||||
|
pub trait ColorGrid {
|
||||||
|
fn get(&self, pos: &Vector2<f32>) -> Rgb<f32>;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue