Skip to content

Commit cdcd46b

Browse files
committed
mapping works in jumbotron mode now, and started implementing animations
1 parent 27c9468 commit cdcd46b

File tree

1 file changed

+114
-30
lines changed

1 file changed

+114
-30
lines changed

service/src/main.rs

Lines changed: 114 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use std::ffi::c_void;
3030
#[cfg(feature="output_mode_jumbotron")]
3131
use gl_abstractions as gla;
3232
#[cfg(feature="output_mode_jumbotron")]
33-
use gla::{UniformMat4F, Uniform1F, Uniform1UIV, Uniform3FV, Uniform1I, Uniform2F, UniformSampler2D, shader_struct, impl_shader};
33+
use gla::{UniformMat4F, Uniform1F, Uniform1UIV, Uniform3FV, Uniform1I, Uniform1UI, Uniform2F, UniformSampler2D, shader_struct, impl_shader};
3434

3535
#[cfg(feature="output_mode_jumbotron")]
3636
use std::sync::{Arc,Mutex};
@@ -321,14 +321,14 @@ fn send_state_to_client(gui_sender: Option<&Sender<StreamEvent>>, cube: Cube, re
321321
enum CubeDevice{
322322
PhysicalDevice{serial_port:Box<dyn SerialPort>},
323323
TestDevice{sequence:Vec<Twist>, buffer: Vec<u8>, next_twist: Instant},
324-
IdleDevice(),
324+
IdleDevice{},
325325
}
326326

327327
impl Read for CubeDevice{
328328
fn read(&mut self, data: &mut [u8]) -> Result<usize, std::io::Error> {
329329
use CubeDevice::*;
330330
match self{
331-
TestDevice{sequence, buffer, next_twist} => {
331+
TestDevice{sequence, buffer, next_twist, ..} => {
332332
if sequence.len() <= 0 {
333333
// Generate a new sequence
334334
for _ in 0..20{
@@ -341,7 +341,7 @@ impl Read for CubeDevice{
341341
}
342342
while *next_twist < Instant::now() {
343343
let next = sequence.remove(0);
344-
*next_twist = *next_twist + Duration::from_millis(500);
344+
*next_twist = *next_twist + Duration::from_millis(3000);
345345
buffer.extend_from_slice(format!("*{};\n", next).as_bytes());
346346
}
347347
let mut mdata = data;
@@ -352,7 +352,7 @@ impl Read for CubeDevice{
352352
Ok(n)
353353
},
354354
PhysicalDevice{serial_port} => {serial_port.read(data)},
355-
IdleDevice() => {Ok(0)},
355+
IdleDevice{..} => {Ok(0)},
356356
}
357357
}
358358
}
@@ -361,8 +361,7 @@ impl Write for CubeDevice{
361361
fn write(&mut self, data: &[u8]) -> Result<usize, std::io::Error> {
362362
use CubeDevice::*;
363363
match self{
364-
TestDevice{..} => {Ok(data.len())}, // Currently does nothing, could make this display a test output perhaps?
365-
IdleDevice{..} => {Ok(data.len())},
364+
TestDevice{..} | IdleDevice{..} => { Ok(data.len()) },
366365
PhysicalDevice{serial_port} => {serial_port.write(data)},
367366
}
368367
}
@@ -388,7 +387,7 @@ impl CubeDevice{
388387
else if name == "idledevice" {
389388
// testdevice is a special name that refers to a fake cube controller that does not display anything, but will repeatedly apply and unapply
390389
// random sequences for testing purposes
391-
Ok(IdleDevice())
390+
Ok(IdleDevice{})
392391
}
393392
else{
394393
let result = serialport::new(name, 115200).timeout(Duration::from_secs(10)).open();
@@ -403,7 +402,7 @@ impl CubeDevice{
403402
use CubeDevice::*;
404403
match self{
405404
TestDevice{sequence, buffer, next_twist} => Ok(TestDevice{sequence:sequence.clone(), buffer:buffer.clone(), next_twist: *next_twist}),
406-
IdleDevice() => Ok(IdleDevice()),
405+
IdleDevice{} => Ok(IdleDevice{}),
407406
PhysicalDevice{serial_port} => match serial_port.try_clone() {
408407
Ok(cloned) => Ok(PhysicalDevice{serial_port: cloned}),
409408
Err(e) => Err(()), // TODO better error handling here
@@ -561,10 +560,15 @@ shader_struct!{
561560
uniform vec3 u_base_cols[6];
562561
uniform int u_cur_face;
563562
uniform vec2 u_facelet_coords;
563+
uniform float u_border_size;
564564
out vec4 FragColor;
565565
void main() {
566566
vec2 tc = (vec4(u_facelet_coords.xy+UV,0.0,0.0)*u_texture_transform).xy;
567567
FragColor = texture(u_texture,tc);
568+
float b = u_border_size;
569+
if (UV.x < b || UV.x > (1.0-b) || UV.y < b || UV.y > (1.0-b)){
570+
FragColor = vec4(u_base_cols[u_cur_face],1.0);
571+
}
568572
}
569573
"#
570574
,{
@@ -576,6 +580,7 @@ shader_struct!{
576580
u_base_cols: Uniform3FV,
577581
u_cur_face: Uniform1I,
578582
u_facelet_coords: Uniform2F,
583+
u_border_size: Uniform1F,
579584
}
580585
}
581586

@@ -599,36 +604,59 @@ shader_struct!{
599604
uniform float u_anim_pos;
600605
uniform uint u_prev_colours[54];
601606
uniform uint u_cur_colours[54];
607+
uniform uint u_mapping[45];
608+
uniform uint u_map_facenum[45];
609+
uniform uint u_map_subfacenum[45];
602610
uniform vec3 u_base_cols[6];
603-
/*
604-
= {
605-
vec3(1.0,1.0,1.0), // white
606-
vec3(1.0,0.0,0.0), // red
607-
vec3(0.0,0.0,1.0), // blue
608-
vec3(0.0,1.0,0.0), // green
609-
vec3(1.0,1.0,0.0), // yellow
610-
vec3(1.0,0.5,0.0), // orange
611-
};
612-
*/
611+
uniform uint u_twist_face;
612+
uniform float u_twist_dir;
613613
out vec4 FragColor;
614614
layout(location=0) out vec3 tFragColor;
615615
616+
const float PI = 3.1415;
617+
616618
float bulge(float a){
617619
a = (a-0.5)*2;
618620
return 1-a*a*a*a;
619621
}
620622
623+
mat3 translate(float x, float y){
624+
return mat3(
625+
1.0,0.0,x,
626+
0.0,1.0,y,
627+
0.0,0.0,1.0
628+
);
629+
}
630+
631+
mat3 rotate(float a){
632+
return mat3(
633+
cos(a), -sin(a),0.0,
634+
sin(a), cos(a),0.0,
635+
0.0,0.0,1.0
636+
);
637+
}
638+
621639
void main() {
622640
float fp = u_facelet_px;
623641
int ix = int(floor(px_pos.x / fp));
624642
int iy = int(floor(px_pos.y / fp));
625643
int i = iy * 9 + ix;
626644
if (i < 45 && px_pos.y > 0.0 && px_pos.x > 0.0 && px_pos.y < (fp*5) && px_pos.x < (fp*9)){
645+
bool this_face = u_map_facenum[i] == u_twist_face;
646+
bool is_centre = u_map_subfacenum[i] == 4u;
647+
uint j = u_mapping[i];
648+
627649
vec2 fl_coord = vec2(px_pos.x - (ix*u_facelet_px), px_pos.y - (iy*u_facelet_px)) / u_facelet_px;
628-
vec3 prev_base = u_base_cols[u_prev_colours[i]];
650+
if (this_face && is_centre){
651+
float a = (PI/2) * u_anim_pos * -u_twist_dir;
652+
mat3 rot = translate(-0.5,-0.5)*rotate(a) *translate(0.5,0.5);
653+
fl_coord = (vec3(fl_coord,1.0) * rot).xy;
654+
}
655+
656+
vec3 prev_base = u_base_cols[u_prev_colours[j]];
629657
FragColor = vec4(prev_base*bulge(fl_coord.x)*bulge(fl_coord.y), 1.0) * (1.0-u_anim_pos);
630658
631-
vec3 base = u_base_cols[u_cur_colours[i]];
659+
vec3 base = u_base_cols[u_cur_colours[j]];
632660
FragColor += vec4(base*bulge(fl_coord.x)*bulge(fl_coord.y), 1.0) * (u_anim_pos);
633661
}
634662
else{
@@ -644,12 +672,17 @@ shader_struct!{
644672
u_facelet_px: Uniform1F,
645673
u_prev_colours: Uniform1UIV,
646674
u_cur_colours: Uniform1UIV,
675+
u_mapping: Uniform1UIV,
676+
u_map_facenum: Uniform1UIV,
677+
u_map_subfacenum: Uniform1UIV,
647678
u_base_cols: Uniform3FV,
679+
u_twist_face: Uniform1UI,
680+
u_twist_dir: Uniform1F,
648681
}
649682
}
650683

651684
#[cfg(feature="output_mode_jumbotron")]
652-
fn jumbotron_thread_main(config: &CubeConfig, cube_state: Arc<Mutex<Cube>>, prev_cube_state: Arc<Mutex<Cube>>, last_twist: Arc<Mutex<TwistInfo>>) {
685+
fn jumbotron_thread_main(config: &CubeConfig, cube_state: Arc<Mutex<Cube>>, prev_cube_state: Arc<Mutex<Cube>>, last_twist: Arc<Mutex<TwistInfo>>, led_map: Arc<Mutex<LedMap>>) {
653686

654687
fn colour_num(c: cube_model::Colors) -> u32{
655688
use cube_model::Colors::*;
@@ -660,7 +693,7 @@ fn jumbotron_thread_main(config: &CubeConfig, cube_state: Arc<Mutex<Cube>>, prev
660693
Green => 3,
661694
Yellow => 4,
662695
Orange => 5,
663-
Blank => 0,
696+
Blank => 6,
664697
}
665698
}
666699

@@ -856,7 +889,6 @@ fn jumbotron_thread_main(config: &CubeConfig, cube_state: Arc<Mutex<Cube>>, prev
856889

857890
let start_time = Instant::now();
858891

859-
860892
while !window.should_close() {
861893
unsafe {
862894
gl::BindFramebuffer(gl::FRAMEBUFFER, main_buffer);
@@ -883,6 +915,7 @@ fn jumbotron_thread_main(config: &CubeConfig, cube_state: Arc<Mutex<Cube>>, prev
883915
0.0,1.0,0.0, // green
884916
1.0,1.0,0.0, // yellow
885917
1.0,0.5,0.0, // orange
918+
0.0,0.0,0.0, // black (for blank cells)
886919
]);
887920
let screen_transform = [
888921
2.0/winw as f32,0.0,0.0,-1.0,
@@ -907,17 +940,27 @@ fn jumbotron_thread_main(config: &CubeConfig, cube_state: Arc<Mutex<Cube>>, prev
907940
colour_num(cube.faces[f].subfaces[s].color)
908941
}).collect()
909942
};
943+
{
944+
let lm = led_map.lock().unwrap();
945+
shader.u_mapping.set(&lm.indexmap);
946+
shader.u_map_facenum.set(&lm.facemap);
947+
shader.u_map_subfacenum.set(&lm.subfacemap);
948+
}
910949
shader.u_prev_colours.set(prev_cols.as_slice());
911950
shader.u_cur_colours.set(cols.as_slice());
912951
let lt = last_twist.lock().unwrap();
913952
if let Some(t) = lt.time {
914953
let d = Instant::now() - t;
915-
let d = ((d.as_millis() as f32)/300.0).min(1.0);
954+
let d = ((d.as_millis() as f32)/1000.0).min(1.0);
916955
shader.u_anim_pos.set(d);
917956
}
918957
else{
919958
shader.u_anim_pos.set(1.0);
920959
}
960+
if let Some(twist) = lt.twist{
961+
shader.u_twist_face.set(twist.face as u32);
962+
shader.u_twist_dir.set(if twist.reverse {-1.0} else {1.0});
963+
}
921964

922965
unsafe { gl::DrawArrays(gl::TRIANGLE_FAN, 0, 4); }
923966

@@ -972,11 +1015,12 @@ fn jumbotron_thread_main(config: &CubeConfig, cube_state: Arc<Mutex<Cube>>, prev
9721015
0.8,0.8,0.8, // white
9731016
1.0,0.0,0.0, // red
9741017
0.0,0.0,1.0, // blue
975-
0.0,1.0,0.0, // green
976-
1.0,1.0,0.0, // yellow
9771018
1.0,0.5,0.0, // orange
1019+
//1.0,1.0,0.0, // yellow
1020+
0.0,1.0,0.0, // green
1021+
//0.0,0.0,0.0, // black (for blank cells)
9781022
]);
979-
1023+
preview_cube.u_border_size.set(-0.1);
9801024
bind_cube_facelet();
9811025
let sf = 0.3;
9821026
let base_trans = &Transform::scale(height as f32/width as f32,1.0,1.0) * &Transform::scale(sf,sf,sf);
@@ -1006,6 +1050,37 @@ struct TwistInfo{
10061050
time: Option<Instant>,
10071051
}
10081052

1053+
struct LedMap{
1054+
indexmap: [u32;45],
1055+
facemap: [u32;45],
1056+
subfacemap: [u32;45],
1057+
}
1058+
1059+
impl LedMap{
1060+
1061+
fn new() -> Self{
1062+
let mut lm = LedMap{
1063+
indexmap:[0;45],
1064+
facemap:[0;45],
1065+
subfacemap:[0;45],
1066+
};
1067+
lm.set("000102030405060708101112131415161718202122232425262728303132333435363738404142434445464748505152535455565758");
1068+
lm
1069+
}
1070+
1071+
fn set(&mut self, map: &str){
1072+
for i in 0..=44{
1073+
let m = map.as_bytes();
1074+
let fnum = (m[i*2] - b'0') as u32;
1075+
let sfnum = (m[(i*2)+1] - b'0') as u32;
1076+
let num = fnum * 9 + sfnum;
1077+
self.indexmap[i] = if num > 44 { 0 } else { num };
1078+
self.facemap[i] = if num > 44 { 0 } else { fnum };
1079+
self.subfacemap[i] = if num > 44 { 0 } else { sfnum };
1080+
}
1081+
}
1082+
}
1083+
10091084
fn main() {
10101085
println!("Cube service");
10111086

@@ -1119,13 +1194,18 @@ fn main() {
11191194
let mut prev_cube = Arc::new(Mutex::new(Cube::new()));
11201195
let mut last_twist = Arc::new(Mutex::new(TwistInfo{twist:None, time: None}));
11211196

1197+
let mut led_map = Arc::new(Mutex::new(LedMap::new()));
1198+
1199+
led_map.lock().unwrap().set(&config.led_map);
1200+
11221201
#[cfg(feature="output_mode_jumbotron")]
11231202
let jumbotron_thread = if args.jumbotron{
11241203
let cube_state = Arc::clone(&cube);
11251204
let prev_cube_state = Arc::clone(&prev_cube);
1205+
let led_map = Arc::clone(&led_map);
11261206
let config = config.clone();
11271207
let last_twist = last_twist.clone();
1128-
Some(std::thread::spawn(move||{ jumbotron_thread_main(&config, cube_state, prev_cube_state, last_twist); }))
1208+
Some(std::thread::spawn(move||{ jumbotron_thread_main(&config, cube_state, prev_cube_state, last_twist, led_map); }))
11291209
} else { None };
11301210

11311211
let mut gui_sender: Option<Sender<StreamEvent>> = None;
@@ -1170,13 +1250,17 @@ fn main() {
11701250
// All subfaces blank
11711251
device_write.write(b"u ")?;
11721252
device_write.flush()?;
1253+
let mut lm = led_map.lock().unwrap();
1254+
lm.set("000102030405060708101112131415161718202122232425262728303132333435363738404142434445464748505152535455565758");
11731255
}
11741256
,ClientEvent::UpdateLEDMap(new_map) => {
11751257
println!("led map update");
11761258
device_write.write(b"cm")?;
11771259
device_write.write(new_map.as_bytes())?;
11781260
device_write.flush()?;
1179-
config.led_map = new_map;
1261+
config.led_map = new_map.clone();
1262+
let mut lm = led_map.lock().unwrap();
1263+
lm.set(&new_map);
11801264
persist_config(&config, &args.config);
11811265
}
11821266
,ClientEvent::UpdateInputMap(new_map) => {

0 commit comments

Comments
 (0)