summaryrefslogtreecommitdiff
path: root/racer-tracer/src/main.rs
blob: a35773bd0641db3313b6eb87ae6f9979ce280f86 (plain)
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())
    }
}