Skip to content

Commit 33ca259

Browse files
committed
new shape and allow 1:1 height in format
1 parent c598af3 commit 33ca259

File tree

4 files changed

+180
-84
lines changed

4 files changed

+180
-84
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "draw-together"
3-
version = "2.2.3"
3+
version = "2.2.4"
44
edition = "2021"
55

66
[[bin]]

src/data.rs

+114-52
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,29 @@ pub enum Action {
1414
DrawCircleHollow,
1515
DrawTriangleNormal,
1616
DrawTriangleHollow,
17+
DrawHexagonNormal,
18+
DrawHexagonHollow,
1719
}
1820

1921
const RESOLUTION: usize = RESOLUTION_WIDTH * RESOLUTION_HEIGHT;
2022
const RESOLUTION_HEIGHT: usize = 1000;
2123
const RESOLUTION_WIDTH: usize = 1920;
2224

2325
// binary format:
24-
// 0-0: action (3b) + height (5b)
25-
// 1-3: x (12b) + y (12b)
26-
// 4-6: color
26+
// (4b) action | byte 1
27+
// (4b) height | byte 1
28+
//
29+
// (3b) height | byte 2
30+
// (5b) x | byte 2
31+
//
32+
// (6b) x | byte 3
33+
// (2b) y | byte 3
34+
//
35+
// (8b) y | byte 4
36+
//
37+
// (8b) color[0]| byte 5
38+
// (8b) color[1]| byte 6
39+
// (8b) color[2]| byte 7
2740

2841
#[derive(Debug)]
2942
pub struct ClientMessage {
@@ -37,61 +50,32 @@ pub struct ClientMessage {
3750
}
3851

3952
impl ClientMessage {
40-
fn decode_u12(data: &[u8]) -> [u16; 2] {
41-
let mut buf: [u16; 2] = [0; 2];
42-
43-
buf[0] = (data[0] as u16) | ((data[1] as u16 & 0xf) << 8);
44-
buf[1] = ((data[1] as u16) >> 4) | ((data[2] as u16) << 4);
45-
46-
buf
47-
}
48-
49-
fn encode_u12(data: [u16; 2]) -> [u8; 3] {
50-
let mut buf = [0; 3];
51-
52-
buf[0] = (data[0] & 0xff) as u8;
53-
buf[1] = ((data[0] >> 8) | (data[1] << 4)) as u8;
54-
buf[2] = (data[1] >> 4) as u8;
55-
56-
buf
57-
}
58-
59-
fn decode_u3(data: u8) -> u8 {
60-
data & 0b111
61-
}
62-
63-
fn encode_u3(data: u8) -> u8 {
64-
data & 0b111
65-
}
66-
67-
fn decode_u5(data: u8) -> u8 {
68-
data >> 3
69-
}
70-
71-
fn encode_u5(data: u8) -> u8 {
72-
data << 3
73-
}
74-
7553
pub fn decode(data: &[u8]) -> Option<Self> {
7654
if data.len() != 7 {
7755
return None;
7856
}
7957

80-
let action_height = data[0];
81-
let action = match Self::decode_u3(action_height) {
58+
let action = match (data[0] >> 4) & 0xF {
8259
0 => Action::Erase,
8360
1 => Action::DrawCubeNormal,
8461
2 => Action::DrawCubeHollow,
8562
3 => Action::DrawCircleNormal,
8663
4 => Action::DrawCircleHollow,
8764
5 => Action::DrawTriangleNormal,
8865
6 => Action::DrawTriangleHollow,
66+
7 => Action::DrawHexagonNormal,
67+
8 => Action::DrawHexagonHollow,
8968
_ => return None,
9069
};
9170

92-
let height = Self::decode_u5(action_height);
93-
94-
let [x, y] = Self::decode_u12(&data[1..4]);
71+
let height_high = data[0] & 0xF;
72+
let height_low = (data[1] >> 5) & 0x7;
73+
let height = (height_high << 3) | height_low;
74+
let x_high = data[1] & 0x1F;
75+
let x_low = (data[2] >> 2) & 0x3F;
76+
let x = ((x_high as u16) << 6) | (x_low as u16);
77+
let y_high = data[2] & 0x3;
78+
let y = ((y_high as u16) << 8) | (data[3] as u16);
9579
let color = [data[4], data[5], data[6]];
9680

9781
if height == 0 || x >= RESOLUTION_WIDTH as u16 || y >= RESOLUTION_HEIGHT as u16 {
@@ -110,17 +94,23 @@ impl ClientMessage {
11094
pub fn encode(&self) -> [u8; 7] {
11195
let mut buf = [0; 7];
11296

113-
buf[0] = Self::encode_u3(match self.action {
97+
let action_value = match self.action {
11498
Action::Erase => 0,
11599
Action::DrawCubeNormal => 1,
116100
Action::DrawCubeHollow => 2,
117101
Action::DrawCircleNormal => 3,
118102
Action::DrawCircleHollow => 4,
119103
Action::DrawTriangleNormal => 5,
120104
Action::DrawTriangleHollow => 6,
121-
}) | Self::encode_u5(self.height);
122-
buf[1..4].copy_from_slice(&Self::encode_u12([self.x, self.y]));
123-
buf[4..7].copy_from_slice(&self.color);
105+
Action::DrawHexagonNormal => 7,
106+
Action::DrawHexagonHollow => 8,
107+
};
108+
109+
buf[0] = (action_value << 4) | ((self.height >> 3) & 0xF);
110+
buf[1] = ((self.height & 0x7) << 5) | ((self.x >> 6) as u8 & 0x1F);
111+
buf[2] = (((self.x & 0x3F) << 2) | ((self.y >> 8) & 0x3)) as u8;
112+
buf[3] = self.y as u8;
113+
buf[4..].copy_from_slice(&self.color);
124114

125115
if std::env::var("DEBUG").is_ok() {
126116
println!("encoded: {:?}", &self);
@@ -206,7 +196,7 @@ impl Data {
206196
for message in data {
207197
match message.action {
208198
Action::Erase => {
209-
let height = (message.height as f64) * 1.5 * 4.0;
199+
let height = (message.height as f64) * 1.5;
210200

211201
let start_x = message.x.saturating_sub(height as u16) as usize;
212202
let end_x =
@@ -226,7 +216,7 @@ impl Data {
226216
}
227217
}
228218
Action::DrawCubeNormal => {
229-
let height = message.height as usize * 4;
219+
let height = message.height as usize;
230220

231221
let start_x = message.x as usize;
232222
let end_x =
@@ -244,7 +234,7 @@ impl Data {
244234
}
245235
}
246236
Action::DrawCubeHollow => {
247-
let height = message.height as usize * 4;
237+
let height = message.height as usize;
248238

249239
let start_x = message.x as usize;
250240
let end_x =
@@ -285,7 +275,7 @@ impl Data {
285275
}
286276
}
287277
Action::DrawCircleNormal | Action::DrawCircleHollow => {
288-
let radius = message.height as usize * 4;
278+
let radius = message.height as usize;
289279
let is_hollow = matches!(message.action, Action::DrawCircleHollow);
290280

291281
let start_x = message.x.saturating_sub(radius as u16) as usize;
@@ -337,7 +327,7 @@ impl Data {
337327
}
338328
}
339329
Action::DrawTriangleNormal | Action::DrawTriangleHollow => {
340-
let height = message.height as usize * 4;
330+
let height = message.height as usize;
341331
let is_hollow = matches!(message.action, Action::DrawTriangleHollow);
342332

343333
let x1 = message.x as i32;
@@ -370,6 +360,78 @@ impl Data {
370360
}
371361
}
372362
}
363+
Action::DrawHexagonNormal | Action::DrawHexagonHollow => {
364+
let is_hollow = matches!(message.action, Action::DrawHexagonHollow);
365+
let size = message.height as f32;
366+
let center_x = message.x as f32;
367+
let center_y = message.y as f32;
368+
369+
let points: [(f32, f32); 6] = (0..6)
370+
.map(|i| {
371+
let angle = (i as f32) * std::f32::consts::PI / 3.0;
372+
let x = center_x + size * angle.cos();
373+
let y = center_y + size * angle.sin();
374+
(x, y)
375+
})
376+
.collect::<Vec<_>>()
377+
.try_into()
378+
.unwrap();
379+
380+
if is_hollow {
381+
for i in 0..6 {
382+
let start = points[i];
383+
let end = points[(i + 1) % 6];
384+
draw_line_fast(
385+
&mut self_data,
386+
start.0 as i32,
387+
start.1 as i32,
388+
end.0 as i32,
389+
end.1 as i32,
390+
&message.color,
391+
);
392+
}
393+
} else {
394+
let min_y = points.iter().map(|(_, y)| *y as i32).min().unwrap();
395+
let max_y = points.iter().map(|(_, y)| *y as i32).max().unwrap();
396+
397+
for y in min_y..=max_y {
398+
let mut intersections = Vec::new();
399+
400+
for i in 0..6 {
401+
let start = points[i];
402+
let end = points[(i + 1) % 6];
403+
404+
if (start.1 <= y as f32 && end.1 > y as f32)
405+
|| (end.1 <= y as f32 && start.1 > y as f32)
406+
{
407+
let x = if start.1 == end.1 {
408+
start.0
409+
} else {
410+
start.0
411+
+ (y as f32 - start.1) * (end.0 - start.0)
412+
/ (end.1 - start.1)
413+
};
414+
intersections.push(x as i32);
415+
}
416+
}
417+
418+
intersections.sort_unstable();
419+
420+
for chunk in intersections.chunks(2) {
421+
if chunk.len() == 2 {
422+
let start_x = chunk[0].max(0).min(RESOLUTION_WIDTH as i32 - 1);
423+
let end_x = chunk[1].max(0).min(RESOLUTION_WIDTH as i32 - 1);
424+
425+
for x in start_x..=end_x {
426+
let index =
427+
(y as usize * RESOLUTION_WIDTH + x as usize) * 3;
428+
self_data[index..index + 3].copy_from_slice(&message.color);
429+
}
430+
}
431+
}
432+
}
433+
}
434+
}
373435
}
374436
}
375437

0 commit comments

Comments
 (0)