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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#[macro_use]
extern crate glium;
extern crate gridsim;
extern crate rayon;

#[cfg(feature = "multinode")]
extern crate serde;

mod run;

pub use run::Loop;

use rayon::prelude::*;

#[derive(Copy, Clone, Debug)]
struct SquareVert {
    color: [f32; 3],
    position: [f32; 2],
}

implement_vertex!(SquareVert, color, position);

/// Stores information to render
pub struct Renderer {
    square: glium::Program,
}

impl Renderer {
    pub fn new<D: glium::backend::Facade>(display: &D) -> Renderer {
        Renderer {
            square: glium::Program::from_source(
                display,
                include_str!("square.vert"),
                include_str!("square.frag"),
                Some(include_str!("square.geom")),
            )
            .unwrap(),
        }
    }

    /// Takes a glium Facade, a drawing Surface, a Grid, a transform, and a cell to color map.
    ///
    /// Renders the cells in a space from <-1, -1> to <1, 1> which is transformed with the transform matrix.
    pub fn render<
        'a,
        D: glium::backend::Facade,
        Su: glium::Surface,
        S: gridsim::Sim<'a>,
        Color: Fn(&S::Cell) -> [f32; 3] + Sync,
        Filter: Fn(&S::Cell) -> bool + Sync,
    >(
        &self,
        display: &D,
        surface: &mut Su,
        grid: &gridsim::SquareGrid<'a, S>,
        draw_params: glium::DrawParameters,
        cell_color: Color,
        filter: Filter,
    ) -> Result<(), glium::DrawError>
    where
        S::Cell: Sync,
    {
        let width = grid.get_width();
        let height = grid.get_height();
        let verts: Vec<_> = grid
            .get_cells()
            .par_iter()
            .enumerate()
            .filter(|(_, cell)| filter(&cell))
            .map(|(ix, cell)| SquareVert {
                color: cell_color(cell),
                position: [
                    2.0 * (ix % width) as f32 / width as f32 - 1.0,
                    2.0 * (ix / width) as f32 / height as f32 - 1.0,
                ],
            })
            .collect();
        let indices = glium::index::NoIndices(glium::index::PrimitiveType::Points);
        let dims: [f32; 2] = [
            2.0 / grid.get_width() as f32,
            2.0 / grid.get_height() as f32,
        ];
        let uniforms = &uniform! { dims: dims };
        let vertex_buffer = glium::VertexBuffer::new(display, &verts[..]).unwrap();
        surface.draw(
            &vertex_buffer,
            &indices,
            &self.square,
            uniforms,
            &draw_params,
        )
    }
}