1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
#[macro_use]
mod error;
mod util;
use std::vec::Vec;
use futures::{select, stream::FuturesUnordered, stream::StreamExt};
use minifb::{Key, Window, WindowOptions};
async fn raytrace(row: usize, width: usize) -> Result<(usize, Vec<u32>), error::TracerError> {
let mut buffer: Vec<u32> = vec![0; width];
// TODO: Trace geometry
for i in 0..buffer.len() {
buffer[i as usize] = util::hsv_to_rgb(((row as u32 + i as u32) % 360) as f64, 100.0, 100.0);
}
Ok((row, buffer))
}
async fn run(width: usize, height: usize) -> Result<(), error::TracerError> {
let mut screen_buffer: Vec<u32> = vec![0; width * height];
let mut window = Window::new("racer-tracer", width, height, WindowOptions::default())
.expect("Unable to create window");
window.limit_update_rate(Some(std::time::Duration::from_micros(16600)));
let mut futs = FuturesUnordered::new();
// One future per row is a bit high.
// Could do something less spammy.
for h in 0..height {
futs.push(raytrace(h, width));
}
let mut complete = false;
while window.is_open() && !window.is_key_down(Key::Escape) {
if !complete {
for _ in 1..50 {
select! {
res = futs.select_next_some() => {
let row_buffer = res.expect("Expected to get data");
let start = row_buffer.0 * width;
let end = start + width;
screen_buffer[start..end].copy_from_slice(row_buffer.1.as_slice());
},
complete => {
if !complete {
println!("Completed!");
}
complete = true;
},
}
}
}
window
.update_with_buffer(&screen_buffer, width, height)
.map_err(|e| error::TracerError::FailedToUpdateWindow(e.to_string()))?;
}
Ok(())
}
#[tokio::main]
async fn main() {
if let Err(e) = run(640, 480).await {
eprintln!("{}", e);
std::process::exit(e.into())
}
}
|