Implement mouse panning and streamline keyboard movement.
[mandelwow.git] / mandelwow.rs
1 // Wow. Such fractal.
2
3 use cube::Cube;
4 use glium;
5 use glium::index::PrimitiveType;
6 use glium::Surface;
7 use support;
8
9
10 /*
11 fn mand(cx: f32, cy: f32) -> [f32; 3] {
12     let maxiter = 64;
13     let mut iter = maxiter;
14     let mut zx = cx;
15     let mut zy = cy;
16     while iter > 0 {
17         let zx2 = zx * zx;
18         let zy2 = zy * zy;
19         if zx2 + zy2 > 4.0 {
20             return [iter as f32 / maxiter as f32, 1.0, 1.0];
21         }
22         zy = zx * zy * 2.0 + cy;
23         zx = zx2 - zy2 + cx;
24         iter -= 1;
25     }
26
27     [0.0, 0.0, 0.0]
28 }
29 */
30
31 pub fn program(display: &glium::Display) -> glium::Program {
32     return program!(display,
33         140 => {
34             vertex: include_str!("mandelwow.vert"),
35             fragment: include_str!("mandelwow.frag"),
36         }).unwrap();
37 }
38
39 fn mandel<U>(display: &glium::Display,
40           frame: &mut glium::Frame,
41           program: &glium::Program,
42           uniforms: &U,
43           bounds: &Cube,
44           z: [f32; 2]) where U: glium::uniforms::Uniforms {
45
46     #[derive(Copy, Clone)]
47     struct Vertex {
48         position: [f32; 3],
49         color: [f32; 3],
50     }
51     implement_vertex!(Vertex, position, color);
52
53     let xmin = bounds.xmin;
54     let xmax = bounds.xmax;
55     let ymin = bounds.ymin;
56     let ymax = bounds.ymax;
57
58     let width = xmax - xmin;
59     let height = ymax - ymin;
60     let xres: usize = 1;
61     let yres: usize = 1;
62     let xstep = width / (xres as f32);
63     let ystep = height / (yres as f32);
64     let vb_size = (xres * 2 + 4) * yres;
65     let mut v : Vec<Vertex> = Vec::with_capacity(vb_size);
66     v.resize(vb_size, Vertex { position: [0.0, 0.0, -1.0], color: [0.0, 0.0, 0.0] });
67     let mut i: usize = 0;
68     let mut vy = ymin;
69     let vz = z[1];
70     for _ in 0..yres {
71         let mut vx = xmin;
72         let c = [0.0, 0.0, 1.0];
73         v[i] = Vertex { position: [vx, vy+ystep, vz], color: c }; i += 1;
74         v[i] = Vertex { position: [vx, vy,       vz], color: c }; i += 1;
75         for _ in 0..xres {
76             //let c = mand(vx, vy);
77             v[i] = Vertex { position: [vx+xstep, vy+ystep, vz], color: c }; i += 1;
78             v[i] = Vertex { position: [vx+xstep, vy,       vz], color: c }; i += 1;
79             vx += xstep;
80         }
81         v[i] = Vertex { position: [vx,   vy, vz], color: c }; i += 1;
82         v[i] = Vertex { position: [xmin, vy, vz], color: c }; i += 1;
83         vy += ystep;
84     }
85
86     //let vb = glium::VertexBuffer::empty_persistent(display, width*height*3).unwrap();
87     let vb = glium::VertexBuffer::new(display, &v).unwrap();
88
89     let indices = glium::index::NoIndices(PrimitiveType::TriangleStrip);
90     //let indices = glium::index::NoIndices(PrimitiveType::LineStrip);
91     //let indices = glium::IndexBuffer::new(display, PrimitiveType::TrianglesList,
92     //                                      &[0u16, 1, 2]).unwrap();
93
94     let params = glium::DrawParameters {
95         depth: glium::Depth {
96             test: glium::draw_parameters::DepthTest::IfLess,
97             write: true,
98             ..Default::default()
99         },
100         blend: glium::Blend::alpha_blending(),
101         ..Default::default()
102     };
103
104     frame.draw(&vb, &indices, program, uniforms, &params).unwrap();
105 }
106
107 pub fn draw(display: &glium::Display,
108              mut frame: &mut glium::Frame,
109              program: &glium::Program,
110              model: [[f32; 4]; 4],
111              camera: &support::camera::CameraState,
112              bounds: &Cube,
113              mandel_w: f32) {
114     let mut z0 = [mandel_w, 0f32];
115     let zres = 30;
116     let zmin = bounds.zmin;
117     let zmax = bounds.zmax;
118     let zstep = (zmax - zmin) / zres as f32;
119     let mut zy = zmin;
120     // zres + 1 to reach the other face of the cube (fencepost error)
121     for _ in 0..(zres + 1) {
122         z0[1] = zy;
123         zy += zstep;
124
125         let uniforms = uniform! {
126             z0: z0,
127             model: model,
128             view:  camera.get_view(),
129             perspective: camera.get_perspective(),
130         };
131
132         mandel(&display, &mut frame, &program, &uniforms, bounds, z0);
133     }
134 }