Move sound code to sound.rs
[mandelwow.git] / mandelwow.rs
index 28080feaf488322dda15a5a77e7a26329e6b58eb..4c5d25e74bdd7fb7098a185287ab57952a74c1ed 100644 (file)
@@ -1,22 +1,21 @@
+// Wow. Such fractal.
+
 #[macro_use]
 
 extern crate glium;
 extern crate glutin;
 #[macro_use]
 
 extern crate glium;
 extern crate glutin;
+extern crate libxm;
+extern crate sdl2;
 
 
-use glium::DisplayBuild;
-use glium::Surface;
-use glium::index::PrimitiveType;
-use glium::index::IndexBuffer;
+use glium::{DisplayBuild, Surface};
+use glium::index::{IndexBuffer, PrimitiveType};
+use glutin::ElementState::Pressed;
+use glutin::Event::KeyboardInput;
+use glutin::VirtualKeyCode;
 
 
+mod sound;
 mod support;
 
 mod support;
 
-#[derive(Copy, Clone)]
-struct Vertex {
-    position: [f32; 3],
-    color: [f32; 3],
-}
-implement_vertex!(Vertex, position, color);
-
 #[derive(Copy, Clone)]
 struct Cube {
     xmin: f32,
 #[derive(Copy, Clone)]
 struct Cube {
     xmin: f32,
@@ -137,7 +136,6 @@ fn bounding_box<U>(display: &glium::Display,
                    program: &glium::Program,
                    uniforms: &U,
                    cube: &Cube) where U: glium::uniforms::Uniforms {
                    program: &glium::Program,
                    uniforms: &U,
                    cube: &Cube) where U: glium::uniforms::Uniforms {
-    // Draw the bounding box
 
     #[derive(Copy, Clone)]
     struct Vertex { position: [f32; 3] }
 
     #[derive(Copy, Clone)]
     struct Vertex { position: [f32; 3] }
@@ -155,30 +153,48 @@ fn bounding_box<U>(display: &glium::Display,
     ];
     let vb = glium::VertexBuffer::new(display, &cube).unwrap();
 
     ];
     let vb = glium::VertexBuffer::new(display, &cube).unwrap();
 
+    let params = glium::DrawParameters {
+        depth: glium::Depth {
+            test: glium::draw_parameters::DepthTest::IfLess,
+            write: true,
+            ..Default::default()
+        },
+        blend: glium::Blend::alpha_blending(),
+        ..Default::default()
+    };
+
     let front_indices = IndexBuffer::new(display, PrimitiveType::LineLoop,
                                          &[0, 1, 2, 3u16]).unwrap();
     let front_indices = IndexBuffer::new(display, PrimitiveType::LineLoop,
                                          &[0, 1, 2, 3u16]).unwrap();
-    frame.draw(&vb, &front_indices, program, uniforms, &Default::default()).unwrap();
+    frame.draw(&vb, &front_indices, program, uniforms, &params).unwrap();
 
     let back_indices = IndexBuffer::new(display, PrimitiveType::LineLoop,
                                         &[4, 5, 6, 7u16]).unwrap();
 
     let back_indices = IndexBuffer::new(display, PrimitiveType::LineLoop,
                                         &[4, 5, 6, 7u16]).unwrap();
-    frame.draw(&vb, &back_indices, program, uniforms, &Default::default()).unwrap();
+    frame.draw(&vb, &back_indices, program, uniforms, &params).unwrap();
 
     let sides_indices = IndexBuffer::new(display, PrimitiveType::LinesList,
                                          &[0, 4, 1, 5, 2, 6, 3, 7u16]).unwrap();
 
     let sides_indices = IndexBuffer::new(display, PrimitiveType::LinesList,
                                          &[0, 4, 1, 5, 2, 6, 3, 7u16]).unwrap();
-    frame.draw(&vb, &sides_indices, program, uniforms, &Default::default()).unwrap();
+    frame.draw(&vb, &sides_indices, program, uniforms, &params).unwrap();
 }
 
 fn mandel<U>(display: &glium::Display,
           frame: &mut glium::Frame,
           program: &glium::Program,
           uniforms: &U,
 }
 
 fn mandel<U>(display: &glium::Display,
           frame: &mut glium::Frame,
           program: &glium::Program,
           uniforms: &U,
+          bounds: &Cube,
           z: [f32; 2]) where U: glium::uniforms::Uniforms {
           z: [f32; 2]) where U: glium::uniforms::Uniforms {
-    let xmin = -2.0;
-    let xmax =  0.7;
-    let ymin = -1.0;
-    let ymax =  1.0;
-    let zmin = -1.2;
-    let zmax =  1.2;
+
+    #[derive(Copy, Clone)]
+    struct Vertex {
+        position: [f32; 3],
+        color: [f32; 3],
+    }
+    implement_vertex!(Vertex, position, color);
+
+    let xmin = bounds.xmin;
+    let xmax = bounds.xmax;
+    let ymin = bounds.ymin;
+    let ymax = bounds.ymax;
+
     let width = xmax - xmin;
     let height = ymax - ymin;
     let xres: usize = 1;
     let width = xmax - xmin;
     let height = ymax - ymin;
     let xres: usize = 1;
@@ -219,10 +235,10 @@ fn mandel<U>(display: &glium::Display,
         depth: glium::Depth {
             test: glium::draw_parameters::DepthTest::IfLess,
             write: true,
         depth: glium::Depth {
             test: glium::draw_parameters::DepthTest::IfLess,
             write: true,
-            .. Default::default()
+            ..Default::default()
         },
         blend: glium::Blend::alpha_blending(),
         },
         blend: glium::Blend::alpha_blending(),
-        .. Default::default()
+        ..Default::default()
     };
 
     frame.draw(&vb, &indices, program, uniforms, &params).unwrap();
     };
 
     frame.draw(&vb, &indices, program, uniforms, &params).unwrap();
@@ -233,12 +249,12 @@ fn mandelwow(display: &glium::Display,
              program: &glium::Program,
              model: [[f32; 4]; 4],
              camera: &support::camera::CameraState,
              program: &glium::Program,
              model: [[f32; 4]; 4],
              camera: &support::camera::CameraState,
-             cube: &Cube,
+             bounds: &Cube,
              mandel_w: f32) {
     let mut z0 = [mandel_w, 0f32];
     let zres = 50;
              mandel_w: f32) {
     let mut z0 = [mandel_w, 0f32];
     let zres = 50;
-    let zmin = cube.zmin;
-    let zmax = cube.zmax;
+    let zmin = bounds.zmin;
+    let zmax = bounds.zmax;
     let zstep = (zmax - zmin) / zres as f32;
     let mut zy = zmin;
     for _ in 0..zres {
     let zstep = (zmax - zmin) / zres as f32;
     let mut zy = zmin;
     for _ in 0..zres {
@@ -252,22 +268,30 @@ fn mandelwow(display: &glium::Display,
             perspective: camera.get_perspective(),
         };
 
             perspective: camera.get_perspective(),
         };
 
-        mandel(&display, &mut frame, &program, &uniforms, z0);
+        mandel(&display, &mut frame, &program, &uniforms, bounds, z0);
     }
 }
 
 fn main() {
     }
 }
 
 fn main() {
+    sound::start();
+
     let display = glium::glutin::WindowBuilder::new()
     let display = glium::glutin::WindowBuilder::new()
-        .with_dimensions(1024, 768)
+        //.with_dimensions(1024, 768)
+        .with_fullscreen(glutin::get_primary_monitor())
         .with_depth_buffer(24)
         .with_depth_buffer(24)
+        .with_vsync()
         .with_title(format!("MandelWow"))
         .build_glium()
         .unwrap();
 
         .with_title(format!("MandelWow"))
         .build_glium()
         .unwrap();
 
+    let program = mandelwow_program(&display);
+    let bounding_box_program = solid_fill_program(&display);
+
     let mut camera = support::camera::CameraState::new();
     let mut t: f32 = 0.0;
     let mut camera = support::camera::CameraState::new();
     let mut t: f32 = 0.0;
-    let mut z = [ 0.0, 0.0f32 ];
     let mut pause = false;
     let mut pause = false;
+    let mut bounding_box_enabled = true;
+    let mut fullscreen = true;
 
     support::start_loop(|| {
         camera.update();
 
     support::start_loop(|| {
         camera.update();
@@ -277,18 +301,28 @@ fn main() {
             t += 0.01;
         }
 
             t += 0.01;
         }
 
-        // Compute a sine wave slicing the Mandelwow along its 4th dimension.
+        // These are the bounds of the 3D Mandelwow section which we render in 3-space.
+        let bounds = Cube {
+            xmin: -2.0,
+            xmax:  0.7,
+            ymin: -1.0,
+            ymax:  1.0,
+            zmin: -1.2,
+            zmax:  1.2,
+        };
+
+        // Vary the wow factor to slice the Mandelwow along its 4th dimension.
         let wmin = -0.8;
         let wmax =  0.8;
         let wsize = wmax - wmin;
         let wmin = -0.8;
         let wmax =  0.8;
         let wsize = wmax - wmin;
-        let mandel_w = ((t.sin() + 1.0) / 2.0) * wsize + wmin;
+        let wow = (((t * 0.7).sin() + 1.0) / 2.0) * wsize + wmin;
 
 
-        //println!("t={} z={:?} camera={:?}", t, z, camera.get_pos());
+        //println!("t={} w={:?} camera={:?}", t, w, camera.get_pos());
 
         let mut frame = display.draw();
         frame.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
 
 
         let mut frame = display.draw();
         frame.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
 
-        let z_trans = -2.0;  // How far back to move the model
+        let z_trans = -2.0;  // Send the model back a little bit so it fits the screen.
         let model = [
             [ t.cos(),  t.sin(),  0.0,     0.0],
             [-t.sin(),  t.cos(),  0.0,     0.0],
         let model = [
             [ t.cos(),  t.sin(),  0.0,     0.0],
             [-t.sin(),  t.cos(),  0.0,     0.0],
@@ -296,47 +330,55 @@ fn main() {
             [     0.0,  0.0,      z_trans, 1.0f32]
         ];
 
             [     0.0,  0.0,      z_trans, 1.0f32]
         ];
 
-        let program = mandelwow_program(&display);
-        let bounding_box_program = solid_fill_program(&display);
-
-        let bounds = Cube {
-            xmin: -2.0,
-            xmax:  0.7,
-            ymin: -1.0,
-            ymax:  1.0,
-            zmin: -1.2,
-            zmax:  1.2,
-        };
-
-        mandelwow(&display, &mut frame, &program, model, &camera, &bounds, mandel_w);
+        // Draw the bounding box before the fractal, when the Z-buffer is still clear,
+        // so the lines behind the semi-translucent areas will be drawn.
+        if bounding_box_enabled {
+            let uniforms = uniform! {
+                model: model,
+                view:  camera.get_view(),
+                perspective: camera.get_perspective(),
+            };
+            bounding_box(&display, &mut frame, &bounding_box_program, &uniforms, &bounds);
+        }
 
 
-        let uniforms = uniform! {
-            model: model,
-            view:  camera.get_view(),
-            perspective: camera.get_perspective(),
-        };
-        bounding_box(&display, &mut frame, &bounding_box_program, &uniforms, &bounds);
+        mandelwow(&display, &mut frame, &program, model, &camera, &bounds, wow);
+        frame.finish().unwrap();
 
         for ev in display.poll_events() {
             match ev {
 
         for ev in display.poll_events() {
             match ev {
-                glium::glutin::Event::Closed => {
-                    frame.finish().unwrap();
+                glium::glutin::Event::Closed |
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::Escape)) |
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::Q)) => {
                     return support::Action::Stop
                 },
                     return support::Action::Stop
                 },
-                glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::PageUp)) => {
-                    t += 0.01;
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::B)) => {
+                    bounding_box_enabled ^= true;
                 },
                 },
-                glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::PageDown)) => {
-                    t -= 0.01;
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::F)) => {
+                    fullscreen ^= true;
+                    if fullscreen {
+                        glutin::WindowBuilder::new()
+                            .with_fullscreen(glutin::get_primary_monitor())
+                            .rebuild_glium(&display).unwrap();
+                    } else {
+                        glutin::WindowBuilder::new()
+                            .rebuild_glium(&display).unwrap();
+                    }
                 },
                 },
-                glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::P)) => {
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::P)) => {
                     pause ^= true;
                 },
                     pause ^= true;
                 },
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::PageUp)) => {
+                    t += 0.01;
+                },
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::PageDown)) => {
+                    t -= 0.01;
+                },
                 ev => camera.process_input(&ev),
             }
         }
 
                 ev => camera.process_input(&ev),
             }
         }
 
-        frame.finish().unwrap();
         support::Action::Continue
     });
         support::Action::Continue
     });
+
 }
 }