From 4168a7f814e1ed23a2f6e93d312c87bb2cb3005a Mon Sep 17 00:00:00 2001 From: Bernie Innocenti Date: Sat, 8 Apr 2017 13:31:51 -0400 Subject: [PATCH] Modularize a bit more: split mandelwow and cube to separate files. --- cube.rs | 11 +++ main.rs | 206 +++++++++++++++++++++++++++++++++++++++++++++++ mandelwow.rs | 223 +++------------------------------------------------ 3 files changed, 226 insertions(+), 214 deletions(-) create mode 100644 cube.rs create mode 100644 main.rs diff --git a/cube.rs b/cube.rs new file mode 100644 index 0000000..de5315b --- /dev/null +++ b/cube.rs @@ -0,0 +1,11 @@ +use std::f32; + +#[derive(Copy, Clone)] +pub struct Cube { + pub xmin: f32, + pub ymin: f32, + pub zmin: f32, + pub xmax: f32, + pub ymax: f32, + pub zmax: f32, +} diff --git a/main.rs b/main.rs new file mode 100644 index 0000000..dac8b37 --- /dev/null +++ b/main.rs @@ -0,0 +1,206 @@ +// Wow. Such fractal. + +#[macro_use] + +extern crate glium; +extern crate glutin; +extern crate libxm; +extern crate sdl2; + +use cube::Cube; +use glium::{DisplayBuild, Surface}; +use glium::index::{IndexBuffer, PrimitiveType}; +use glutin::ElementState::Pressed; +use glutin::Event::KeyboardInput; +use glutin::VirtualKeyCode; + +mod cube; +mod mandelwow; +mod sound; +mod support; + +fn solid_fill_program(display: &glium::Display) -> glium::Program { + let vertex_shader_src = r#" + #version 140 + in vec3 position; + uniform mat4 perspective; + uniform mat4 view; + uniform mat4 model; + + void main() { + mat4 modelview = view * model; + gl_Position = perspective * modelview * vec4(position, 1.0); + } + "#; + + let fragment_shader_src = r#" + #version 140 + + out vec4 color; + + void main() { + color = vec4(1.0, 1.0, 1.0, 1.0); + } + "#; + + return glium::Program::from_source(display, + vertex_shader_src, + fragment_shader_src, + None).unwrap(); +} + +fn bounding_box(display: &glium::Display, + frame: &mut glium::Frame, + program: &glium::Program, + uniforms: &U, + cube: &Cube) where U: glium::uniforms::Uniforms { + + #[derive(Copy, Clone)] + struct Vertex { position: [f32; 3] } + implement_vertex!(Vertex, position); + + let cube = [ + Vertex { position: [cube.xmin, cube.ymin, cube.zmin] }, + Vertex { position: [cube.xmax, cube.ymin, cube.zmin] }, + Vertex { position: [cube.xmax, cube.ymax, cube.zmin] }, + Vertex { position: [cube.xmin, cube.ymax, cube.zmin] }, + Vertex { position: [cube.xmin, cube.ymin, cube.zmax] }, + Vertex { position: [cube.xmax, cube.ymin, cube.zmax] }, + Vertex { position: [cube.xmax, cube.ymax, cube.zmax] }, + Vertex { position: [cube.xmin, cube.ymax, cube.zmax] }, + ]; + 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(); + frame.draw(&vb, &front_indices, program, uniforms, ¶ms).unwrap(); + + let back_indices = IndexBuffer::new(display, PrimitiveType::LineLoop, + &[4, 5, 6, 7u16]).unwrap(); + frame.draw(&vb, &back_indices, program, uniforms, ¶ms).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, ¶ms).unwrap(); +} + +fn main() { + sound::start(); + + let display = glium::glutin::WindowBuilder::new() + //.with_dimensions(1024, 768) + .with_fullscreen(glutin::get_primary_monitor()) + .with_depth_buffer(24) + .with_vsync() + .with_title(format!("MandelWow")) + .build_glium() + .unwrap(); + + let mandelwow_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 pause = false; + let mut bounding_box_enabled = true; + let mut fullscreen = true; + + support::start_loop(|| { + camera.update(); + + if !pause { + // Increment time + t += 0.01; + } + + // 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.1, + zmax: 1.1, + }; + + // 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 wow = (((t * 0.7).sin() + 1.0) / 2.0) * wsize + wmin; + + //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 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], + [ 0.0, 0.0, 1.0, 0.0], + [ 0.0, 0.0, z_trans, 1.0f32] + ]; + + // 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); + } + + mandelwow::draw(&display, &mut frame, &mandelwow_program, model, &camera, &bounds, wow); + frame.finish().unwrap(); + + for ev in display.poll_events() { + match ev { + glium::glutin::Event::Closed | + KeyboardInput(Pressed, _, Some(VirtualKeyCode::Escape)) | + KeyboardInput(Pressed, _, Some(VirtualKeyCode::Q)) => { + return support::Action::Stop + }, + KeyboardInput(Pressed, _, Some(VirtualKeyCode::B)) => { + bounding_box_enabled ^= true; + }, + 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(); + } + }, + KeyboardInput(Pressed, _, Some(VirtualKeyCode::P)) => { + pause ^= true; + }, + KeyboardInput(Pressed, _, Some(VirtualKeyCode::PageUp)) => { + t += 0.01; + }, + KeyboardInput(Pressed, _, Some(VirtualKeyCode::PageDown)) => { + t -= 0.01; + }, + ev => camera.process_input(&ev), + } + } + + support::Action::Continue + }); + +} diff --git a/mandelwow.rs b/mandelwow.rs index 80c46d4..76ca54e 100644 --- a/mandelwow.rs +++ b/mandelwow.rs @@ -1,30 +1,11 @@ // Wow. Such fractal. -#[macro_use] +use cube::Cube; +use glium; +use glium::index::PrimitiveType; +use glium::Surface; +use support; -extern crate glium; -extern crate glutin; -extern crate libxm; -extern crate sdl2; - -use glium::{DisplayBuild, Surface}; -use glium::index::{IndexBuffer, PrimitiveType}; -use glutin::ElementState::Pressed; -use glutin::Event::KeyboardInput; -use glutin::VirtualKeyCode; - -mod sound; -mod support; - -#[derive(Copy, Clone)] -struct Cube { - xmin: f32, - ymin: f32, - zmin: f32, - xmax: f32, - ymax: f32, - zmax: f32, -} /* fn mand(cx: f32, cy: f32) -> [f32; 3] { @@ -47,7 +28,7 @@ fn mand(cx: f32, cy: f32) -> [f32; 3] { } */ -fn mandelwow_program(display: &glium::Display) -> glium::Program { +pub fn program(display: &glium::Display) -> glium::Program { return program!(display, 140 => { vertex: r#" @@ -101,81 +82,6 @@ fn mandelwow_program(display: &glium::Display) -> glium::Program { }).unwrap(); } -fn solid_fill_program(display: &glium::Display) -> glium::Program { - let vertex_shader_src = r#" - #version 140 - in vec3 position; - uniform mat4 perspective; - uniform mat4 view; - uniform mat4 model; - - void main() { - mat4 modelview = view * model; - gl_Position = perspective * modelview * vec4(position, 1.0); - } - "#; - - let fragment_shader_src = r#" - #version 140 - - out vec4 color; - - void main() { - color = vec4(1.0, 1.0, 1.0, 1.0); - } - "#; - - return glium::Program::from_source(display, - vertex_shader_src, - fragment_shader_src, - None).unwrap(); -} - -fn bounding_box(display: &glium::Display, - frame: &mut glium::Frame, - program: &glium::Program, - uniforms: &U, - cube: &Cube) where U: glium::uniforms::Uniforms { - - #[derive(Copy, Clone)] - struct Vertex { position: [f32; 3] } - implement_vertex!(Vertex, position); - - let cube = [ - Vertex { position: [cube.xmin, cube.ymin, cube.zmin] }, - Vertex { position: [cube.xmax, cube.ymin, cube.zmin] }, - Vertex { position: [cube.xmax, cube.ymax, cube.zmin] }, - Vertex { position: [cube.xmin, cube.ymax, cube.zmin] }, - Vertex { position: [cube.xmin, cube.ymin, cube.zmax] }, - Vertex { position: [cube.xmax, cube.ymin, cube.zmax] }, - Vertex { position: [cube.xmax, cube.ymax, cube.zmax] }, - Vertex { position: [cube.xmin, cube.ymax, cube.zmax] }, - ]; - 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(); - frame.draw(&vb, &front_indices, program, uniforms, ¶ms).unwrap(); - - let back_indices = IndexBuffer::new(display, PrimitiveType::LineLoop, - &[4, 5, 6, 7u16]).unwrap(); - frame.draw(&vb, &back_indices, program, uniforms, ¶ms).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, ¶ms).unwrap(); -} - fn mandel(display: &glium::Display, frame: &mut glium::Frame, program: &glium::Program, @@ -226,8 +132,8 @@ fn mandel(display: &glium::Display, //let vb = glium::VertexBuffer::empty_persistent(display, width*height*3).unwrap(); let vb = glium::VertexBuffer::new(display, &v).unwrap(); - let indices = glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip); - //let indices = glium::index::NoIndices(glium::index::PrimitiveType::LineStrip); + let indices = glium::index::NoIndices(PrimitiveType::TriangleStrip); + //let indices = glium::index::NoIndices(PrimitiveType::LineStrip); //let indices = glium::IndexBuffer::new(display, PrimitiveType::TrianglesList, // &[0u16, 1, 2]).unwrap(); @@ -244,7 +150,7 @@ fn mandel(display: &glium::Display, frame.draw(&vb, &indices, program, uniforms, ¶ms).unwrap(); } -fn mandelwow(display: &glium::Display, +pub fn draw(display: &glium::Display, mut frame: &mut glium::Frame, program: &glium::Program, model: [[f32; 4]; 4], @@ -272,114 +178,3 @@ fn mandelwow(display: &glium::Display, mandel(&display, &mut frame, &program, &uniforms, bounds, z0); } } - -fn main() { - sound::start(); - - let display = glium::glutin::WindowBuilder::new() - //.with_dimensions(1024, 768) - .with_fullscreen(glutin::get_primary_monitor()) - .with_depth_buffer(24) - .with_vsync() - .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 pause = false; - let mut bounding_box_enabled = true; - let mut fullscreen = true; - - support::start_loop(|| { - camera.update(); - - if !pause { - // Increment time - t += 0.01; - } - - // 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.1, - zmax: 1.1, - }; - - // 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 wow = (((t * 0.7).sin() + 1.0) / 2.0) * wsize + wmin; - - //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 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], - [ 0.0, 0.0, 1.0, 0.0], - [ 0.0, 0.0, z_trans, 1.0f32] - ]; - - // 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); - } - - mandelwow(&display, &mut frame, &program, model, &camera, &bounds, wow); - frame.finish().unwrap(); - - for ev in display.poll_events() { - match ev { - glium::glutin::Event::Closed | - KeyboardInput(Pressed, _, Some(VirtualKeyCode::Escape)) | - KeyboardInput(Pressed, _, Some(VirtualKeyCode::Q)) => { - return support::Action::Stop - }, - KeyboardInput(Pressed, _, Some(VirtualKeyCode::B)) => { - bounding_box_enabled ^= true; - }, - 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(); - } - }, - KeyboardInput(Pressed, _, Some(VirtualKeyCode::P)) => { - pause ^= true; - }, - KeyboardInput(Pressed, _, Some(VirtualKeyCode::PageUp)) => { - t += 0.01; - }, - KeyboardInput(Pressed, _, Some(VirtualKeyCode::PageDown)) => { - t -= 0.01; - }, - ev => camera.process_input(&ev), - } - } - - support::Action::Continue - }); - -} -- 2.25.1