Cleanly separate rendering and event handling
authorBernie Innocenti <bernie@codewiz.org>
Sat, 11 Jan 2020 19:52:35 +0000 (04:52 +0900)
committerBernie Innocenti <bernie@codewiz.org>
Sat, 11 Jan 2020 19:52:35 +0000 (04:52 +0900)
Moving to glium 0.26 / glutin 0.22 required adopting a new event loop
stlye, which in turn was the right excuse for a long overdue code
rework. Some things still don't work quite right at this point,
FPS computation is incorrect and some keyboard commands are still
commented out... But hey, the code looks much nicer now!

Cargo.toml
bounding_box.rs
lib.rs
main.rs
release_wasm.sh
rust-rocket
shaded_cube.rs
support/camera.rs
text.rs

index 42244c2016c1d9285ae4ba2504169664258a0d2c..3ee753ad7d36bd9d75a9457556c8965f119d1a84 100644 (file)
@@ -15,8 +15,8 @@ opt-level = 3
 [dependencies]
 cgmath = "*"
 #gleam = "*"
-glium = "0.25.1"
-glutin = "0.21"
+glium = "0.26.0-alpha6"
+glutin = "0.22.0-alpha6"
 image = { version = "*", features = ["png_codec"], optional = true }
 libxm = "1.0.0"
 rust-rocket = { path = "rust-rocket", optional = true }
index 71cee762518b0c1e0e107c79ea88d7458d5ce1af..6625eb546182a45b6e265d899300943fb00d0e2c 100644 (file)
@@ -2,6 +2,7 @@ use crate::cube::Cube;
 use glium;
 use glium::{Display, Program, Surface, implement_vertex};
 use glium::index::{IndexBuffer, PrimitiveType};
+use std::rc::Rc;
 
 pub fn solid_fill_program(display: &Display) -> Program {
     let vertex_shader_src = include_str!("shaders/solid.vert");
@@ -13,14 +14,14 @@ pub fn solid_fill_program(display: &Display) -> Program {
 struct Vertex { position: [f32; 3] }
 implement_vertex!(Vertex, position);
 
-pub struct BoundingBox<'a> {
+pub struct BoundingBox {
     vertexes: glium::VertexBuffer<Vertex>,
-    program: &'a Program,
+    program: Rc<Program>,
     indices: IndexBuffer<u16>,
 }
 
-impl<'a> BoundingBox<'a> {
-    pub fn new(display: &Display, c: &Cube, program: &'a Program) -> BoundingBox<'a> {
+impl BoundingBox {
+    pub fn new(display: &Display, c: &Cube, program: Rc<Program>) -> BoundingBox {
         let vertex_data = [
             Vertex { position: [c.xmin, c.ymin, c.zmin] },
             Vertex { position: [c.xmax, c.ymin, c.zmin] },
@@ -54,6 +55,6 @@ impl<'a> BoundingBox<'a> {
             blend: glium::Blend::alpha_blending(),
             ..Default::default()
         };
-        frame.draw(&self.vertexes, &self.indices, self.program, uniforms, &params).unwrap();
+        frame.draw(&self.vertexes, &self.indices, &self.program, uniforms, &params).unwrap();
     }
 }
diff --git a/lib.rs b/lib.rs
index 25e275c56e2140f07e6079599278c149b7ec13b4..24ef697840c82b47f266cf512ed8310939f7f831 100644 (file)
--- a/lib.rs
+++ b/lib.rs
@@ -10,6 +10,8 @@ pub mod timer;
 pub use crate::bounding_box::BoundingBox;
 pub use crate::cube::Cube;
 pub use crate::shaded_cube::ShadedCube;
+pub use crate::text::Text;
+pub use crate::timer::Timer;
 
 #[cfg(feature = "image")]
 pub fn screenshot(display : &glium::Display) {
diff --git a/main.rs b/main.rs
index 1ad2eea7d77b543a34cfd1cbb7b258e03bf2da55..86a17c2c61e0d8f288c91a0f679893db95259729 100644 (file)
--- a/main.rs
+++ b/main.rs
@@ -1,11 +1,12 @@
 use cgmath::conv::array4x4;
 use cgmath::{Euler, Matrix4, Rad, SquareMatrix, Vector3, Vector4, Zero};
-use glium::glutin::VirtualKeyCode;
-use glium::glutin::WindowEvent::KeyboardInput;
-use glium::{Surface, uniform};
+use glium::glutin::event::{ self, Event, VirtualKeyCode, WindowEvent };
+use glium::glutin::event_loop::{ ControlFlow };
+use glium::{Display, Program, Surface, uniform};
 use mandelwow_lib::*;
 use std::f32::consts::PI;
-use crate::timer::Timer;
+use std::rc::Rc;
+use std::time::{Duration, Instant};
 
 #[cfg(target_os = "emscripten")]
 use std::os::raw::{c_int, c_void};
@@ -25,6 +26,170 @@ fn gl_info(display: &glium::Display) {
     }
 }
 
+const SEA_XSIZE: usize = 40;
+const SEA_ZSIZE: usize = 25;
+
+struct World<'a> {
+    display: Display,
+
+    mandelwow_program: Rc<Program>,
+    mandelwow_bounds: Cube,
+    mandelwow_bbox: BoundingBox,
+    bounding_box_enabled: bool,
+
+    shaded_cube: ShadedCube,
+    text: Text<'a>,
+
+    sea: [[Vector3<f32>; SEA_ZSIZE]; SEA_XSIZE],
+
+    // For the zoom animation synchronized to the drum-hits
+    hit_time: f32,
+    last_hit: f32,
+}
+
+impl<'a> World<'a> {
+    pub fn new(display: glium::Display) -> World<'a> {
+        let mandelwow_program = Rc::new(mandelwow::program(&display));
+        let bounding_box_program = Rc::new(bounding_box::solid_fill_program(&display));
+        let shaded_program = Rc::new(shaded_cube::shaded_program(&display));
+
+        // These are the bounds for the 3D slice of the 4D Mandelwow
+        let mandelwow_bounds = Cube {
+            xmin: -2.0,
+            xmax: 0.7,
+            ymin: -1.0,
+            ymax: 1.0,
+            zmin: -1.1,
+            zmax: 1.1,
+        };
+
+        // Generate a wavy sea made of cubes
+        let sea_xmin = -20.0f32;
+        let sea_xmax = 20.0f32;
+        let sea_y = -2.5;
+        let sea_zmin = -2.0f32;
+        let sea_zmax = -27.0f32;
+        let sea_xstep = (sea_xmax - sea_xmin) / (SEA_XSIZE as f32);
+        let sea_zstep = (sea_zmax - sea_zmin) / (SEA_ZSIZE as f32);
+        println!("xstep={} ystep={:?}", sea_xstep, sea_zstep);
+
+        let mut sea = [[Vector3::zero(); SEA_ZSIZE]; SEA_XSIZE];
+        for x in 0..SEA_XSIZE {
+            for z in 0..SEA_ZSIZE {
+                sea[x][z] = Vector3 {
+                    x: sea_xmin + (x as f32) * sea_xstep,
+                    y: sea_y,
+                    z: sea_zmin + (z as f32) * sea_zstep,
+                };
+            }
+        }
+
+        World {
+            mandelwow_program,
+            mandelwow_bbox: BoundingBox::new(
+                &display, &mandelwow_bounds, bounding_box_program.clone()),
+            mandelwow_bounds,
+            bounding_box_enabled: true,
+
+            shaded_cube: ShadedCube::new(&display, shaded_program.clone()),
+            text: text::Text::new(&display),
+            sea: sea,
+
+            hit_time: 0.0,
+            last_hit: 0.0,
+
+            display,
+        }
+    }
+
+    fn draw_frame(
+        &self,
+        camera: &support::camera::CameraState,
+        t: f32,
+    ) {
+        let perspview = camera.get_perspview();
+
+        let hit_delta = t - self.hit_time;
+        let hit_scale = 1. / (1. + hit_delta * hit_delta * 15.0) + 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 = self.display.draw();
+        frame.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
+
+        let rotation = Matrix4::from(Euler {
+            x: Rad(t.sin() / 3.),
+            y: Rad(t.sin() / 2.),
+            z: Rad(t / 1.5),
+        });
+        let z_trans = -3.0; // Send the model back a little bit so it fits the screen.
+        let scale = Matrix4::from_diagonal(Vector4::new(hit_scale, hit_scale, hit_scale, 1.0));
+        let model2 = Matrix4::from_translation(Vector3::unit_z() * z_trans) * rotation * scale;
+        let model = array4x4(model2);
+
+        // 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 self.bounding_box_enabled {
+            let uniforms = uniform! {
+                model: model,
+                view:  camera.get_view(),
+                perspective: camera.get_perspective(),
+            };
+            self.mandelwow_bbox.draw(&mut frame, &uniforms);
+        }
+
+        let text_rot = Matrix4::from_angle_x(cgmath::Deg(-90.0f32));
+        let text_pos = Matrix4::from_translation(Vector3 {
+            x: 0.0,
+            y: 0.501,
+            z: 0.0f32,
+        }) * text_rot;
+        for x in 0..SEA_XSIZE {
+            for z in 0..SEA_ZSIZE {
+                let wave = ((x as f32 / SEA_XSIZE as f32 * PI * 5.0 + t * 2.0).sin()
+                    + (z as f32 / SEA_ZSIZE as f32 * PI * 3.0 + t * 3.0).sin())
+                    * 0.3;
+                let model = Matrix4::from_translation(
+                    self.sea[x][z]
+                        + Vector3 {
+                            x: 0.,
+                            y: wave,
+                            z: 0.,
+                        },
+                );
+                let uniforms = uniform! {
+                    model: array4x4(model),
+                    perspview: perspview,
+                    col: [0., (1. - wave).abs() * 0.5,  wave.abs()],
+                };
+                self.shaded_cube.draw(&mut frame, &uniforms);
+                let model = model * text_pos;
+                let c = (x + z * SEA_XSIZE) as u8 as char;
+                self.text.draw(&mut frame, c, &model, &perspview);
+            }
+        }
+
+        mandelwow::draw(
+            &self.display,
+            &mut frame,
+            &self.mandelwow_program,
+            model,
+            &camera,
+            &self.mandelwow_bounds,
+            wow,
+        );
+
+        frame.finish().unwrap();
+    }
+}
+
+
 #[cfg(target_os = "emscripten")]
 #[allow(non_camel_case_types)]
 type em_callback_func = unsafe extern "C" fn();
@@ -71,11 +236,13 @@ where
 
 //extern crate gleam;
 
+/*
 extern "C" {
     fn emscripten_GetProcAddress(
         name: *const ::std::os::raw::c_char,
     ) -> *const ::std::os::raw::c_void;
 }
+*/
 
 fn main() {
     /*
@@ -88,218 +255,107 @@ fn main() {
 
     let mut soundplayer = sound::start();
 
-    let mut events_loop = glium::glutin::EventsLoop::new();
-    let window = glium::glutin::WindowBuilder::new()
+    let event_loop = glutin::event_loop::EventLoop::new();
+    //let fullscreen = Some(glutin::window::Fullscreen::Borderless(event_loop.primary_monitor()));
+    let window = glutin::window::WindowBuilder::new()
         //.with_dimensions(1280, 720)
-        .with_fullscreen(Some(events_loop.get_primary_monitor()));
+        //.with_fullscreen(fullscreen);
+        ;
     //.with_title("MandelWow");
-    let context = glium::glutin::ContextBuilder::new()
+    let context = glutin::ContextBuilder::new()
         //.with_gl_profile(glutin::GlProfile::Core)
-        //.with_gl(glium::glutin::GlRequest::Specific(glium::glutin::Api::WebGl, (2, 0)))
-        .with_gl(glium::glutin::GlRequest::Specific(
-            glium::glutin::Api::OpenGlEs,
+        //.with_gl(glutin::GlRequest::Specific(glutin::Api::WebGl, (2, 0)))
+        .with_gl(glutin::GlRequest::Specific(
+            glutin::Api::OpenGlEs,
             (3, 0),
         ))
-        //.with_gl(glium::glutin::GlRequest::Specific(glium::glutin::Api::OpenGl, (4, 0)))
+        //.with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (4, 0)))
         //.with_depth_buffer(24)
         .with_vsync(true);
-    let display = glium::Display::new(window, context, &events_loop).unwrap();
-    gl_info(&display);
 
-    let mut text = text::Text::new(&display, 'A');
-    let mandelwow_program = mandelwow::program(&display);
-    let bounding_box_program = bounding_box::solid_fill_program(&display);
-    let shaded_program = shaded_cube::shaded_program(&display);
+    let display = glium::Display::new(window, context, &event_loop).unwrap();
+    gl_info(&display);
+    let mut world = World::new(display);
 
     let mut timer = Timer::new();
     let mut camera = support::camera::CameraState::new();
-    let bounding_box_enabled = true;
     let _fullscreen = true;
 
-    // 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,
-    };
-
-    let mandelwow_bbox = bounding_box::BoundingBox::new(&display, &bounds, &bounding_box_program);
-    let shaded_cube = ShadedCube::new(&display, &shaded_program);
-
-    const SEA_XSIZE: usize = 40;
-    const SEA_ZSIZE: usize = 25;
-    let sea_xmin = -20.0f32;
-    let sea_xmax = 20.0f32;
-    let sea_y = -2.5;
-    let sea_zmin = -2.0f32;
-    let sea_zmax = -27.0f32;
-    let sea_xstep = (sea_xmax - sea_xmin) / (SEA_XSIZE as f32);
-    let sea_zstep = (sea_zmax - sea_zmin) / (SEA_ZSIZE as f32);
-    println!("xstep={} ystep={:?}", sea_xstep, sea_zstep);
-
-    let mut sea = [[Vector3::zero(); SEA_ZSIZE]; SEA_XSIZE];
-    for x in 0..SEA_XSIZE {
-        for z in 0..SEA_ZSIZE {
-            sea[x][z] = Vector3 {
-                x: sea_xmin + (x as f32) * sea_xstep,
-                y: sea_y,
-                z: sea_zmin + (z as f32) * sea_zstep,
-            };
-        }
-    }
-
-    let mut last_hit = 0.0f32;
-    let mut hit_time = 0.0f32;
-    set_main_loop_callback(|| {
+    event_loop.run(move |event, _, control_flow| {
         let t = timer.t;
         let new_hit = sound::hit_event(&mut soundplayer);
-        if new_hit > last_hit {
-            hit_time = t;
+        if new_hit > world.last_hit {
+            world.hit_time = t;
         }
-        last_hit = new_hit;
-        let hit_delta = t - hit_time;
-        let hit_scale = 1. / (1. + hit_delta * hit_delta * 15.0) + 1.;
+        world.last_hit = new_hit;
 
         camera.update();
-        let perspview = camera.get_perspview();
-
-        // 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 rotation = Matrix4::from(Euler {
-            x: Rad(t.sin() / 3.),
-            y: Rad(t.sin() / 2.),
-            z: Rad(t / 1.5),
-        });
-        let z_trans = -3.0; // Send the model back a little bit so it fits the screen.
-        let scale = Matrix4::from_diagonal(Vector4::new(hit_scale, hit_scale, hit_scale, 1.0));
-        let model2 = Matrix4::from_translation(Vector3::unit_z() * z_trans) * rotation * scale;
-        let model = array4x4(model2);
-
-        // 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(),
-            };
-            mandelwow_bbox.draw(&mut frame, &uniforms);
-        }
 
-        let text_rot = Matrix4::from_angle_x(cgmath::Deg(-90.0f32));
-        let text_pos = Matrix4::from_translation(Vector3 {
-            x: 0.0,
-            y: 0.501,
-            z: 0.0f32,
-        }) * text_rot;
-        for x in 0..SEA_XSIZE {
-            for z in 0..SEA_ZSIZE {
-                let wave = ((x as f32 / SEA_XSIZE as f32 * PI * 5.0 + t * 2.0).sin()
-                    + (z as f32 / SEA_ZSIZE as f32 * PI * 3.0 + t * 3.0).sin())
-                    * 0.3;
-                let model = Matrix4::from_translation(
-                    sea[x][z]
-                        + Vector3 {
-                            x: 0.,
-                            y: wave,
-                            z: 0.,
-                        },
-                );
-                let uniforms = uniform! {
-                    model: array4x4(model),
-                    perspview: perspview,
-                    col: [0., (1. - wave).abs() * 0.5,  wave.abs()],
-                };
-                shaded_cube.draw(&mut frame, &uniforms);
-                text.model = model * text_pos;
-                text.character = (x + z * SEA_XSIZE) as u8 as char;
-                text.draw(&mut frame, &perspview);
-            }
+        *control_flow = ControlFlow::WaitUntil(Instant::now() + Duration::from_nanos(16666667));
+        match event {
+            Event::NewEvents(cause) => {
+                match cause {
+                    event::StartCause::ResumeTimeReached { .. } | event::StartCause::Init => {
+                        world.draw_frame(&camera, t);
+                    },
+                    _ => {}
+                }
+            } _ => (),
         }
-
-        mandelwow::draw(
-            &display,
-            &mut frame,
-            &mandelwow_program,
-            model,
-            &camera,
-            &bounds,
-            wow,
-        );
-
-        frame.finish().unwrap();
-
-        let mut action = support::Action::Continue;
-        events_loop.poll_events(|event| {
-            if let glium::glutin::Event::WindowEvent { event, .. } = event {
-                camera.process_input(&event);
-                match event {
-                    glium::glutin::WindowEvent::CloseRequested => action = support::Action::Stop,
-                    KeyboardInput { input, .. } => {
-                        if input.state == glium::glutin::ElementState::Pressed {
-                            if let Some(key) = input.virtual_keycode {
-                                match key {
-                                    VirtualKeyCode::Escape | VirtualKeyCode::Q => {
-                                        action = support::Action::Stop;
-                                    }
-                                    _ => (),
+        if let Event::WindowEvent { event, .. } = event {
+            camera.process_input(&event);
+            match event {
+                WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
+                WindowEvent::KeyboardInput { input, .. } => {
+                    if input.state == event::ElementState::Pressed {
+                        if let Some(key) = input.virtual_keycode {
+                            match key {
+                                VirtualKeyCode::Escape | VirtualKeyCode::Q => {
+                                    *control_flow = ControlFlow::Exit;
                                 }
+                                _ => (),
                             }
                         }
                     }
-                    /*
-                    KeyboardInput { input: glutin::KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::Escape), .. } } |
-                    KeyboardInput { input: glutin::KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::Q), .. } } => {
-                        return support::Action::Stop
-                    },
-                    KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::B) } => {
-                        bounding_box_enabled ^= true;
-                    },
-                    KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::P) } => {
-                        timer.pause ^= true;
-                    },
-                    KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::PageUp) } => {
-                        timer.t += 0.01;
-                    },
-                    KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::PageDown) } => {
-                        timer.t -= 0.01;
-                    },
-                    KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::F10) } => {
-                        screenshot(&display);
-                    },
-                    KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::F11) } => {
-                        fullscreen ^= true;
-                        if fullscreen {
-                            // Not implemented on Linux
-                            glutin::WindowBuilder::new()
-                                .with_fullscreen(glutin::get_primary_monitor())
-                                .with_depth_buffer(24)
-                                .rebuild_glium(&display).unwrap();
-                        } else {
-                            glutin::WindowBuilder::new()
-                                .rebuild_glium(&display).unwrap();
-                        }
-                    },
-                    */
-                    _ => (),
                 }
+                /*
+                KeyboardInput { input: glutin::KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::Escape), .. } } |
+                KeyboardInput { input: glutin::KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::Q), .. } } => {
+                    *control_flow = ControlFlow::Exit;
+                },
+                KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::B) } => {
+                    bounding_box_enabled ^= true;
+                },
+                KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::P) } => {
+                    timer.pause ^= true;
+                },
+                KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::PageUp) } => {
+                    timer.t += 0.01;
+                },
+                KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::PageDown) } => {
+                    timer.t -= 0.01;
+                },
+                KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::F10) } => {
+                    screenshot(&display);
+                },
+                KeyboardInput { state: Pressed, virtual_keycode: Some(VirtualKeyCode::F11) } => {
+                    fullscreen ^= true;
+                    if fullscreen {
+                        // Not implemented on Linux
+                        glutin::WindowBuilder::new()
+                            .with_fullscreen(glutin::get_primary_monitor())
+                            .with_depth_buffer(24)
+                            .rebuild_glium(&display).unwrap();
+                    } else {
+                        glutin::WindowBuilder::new()
+                            .rebuild_glium(&display).unwrap();
+                    }
+                },
+                */
+                _ => (),
             }
-        });
+        }
 
         timer.update();
-
-        action
     });
 }
index 477000fe148f4872b12704e6a749bc2b76d87c83..43fdf2305eef0d00f768691c6b171ef67118be27 100755 (executable)
@@ -1,7 +1,8 @@
 set -e
 export CFLAGS="-O2"
 export CXXFLAGS="$CFLAGS"
-cargo rustc --target wasm32-unknown-emscripten --release --bin mandelwow -- -C link-args='--emrun -s USE_SDL=2 -s ASSERTIONS=2 --preload-file flora.xm'
+cargo rustc --target wasm32-unknown-emscripten --release --bin mandelwow -- \
+  -C link-args='--emrun -s USE_SDL=2 -s ERROR_ON_MISSING_LIBRARIES=0 -s ASSERTIONS=2 --preload-file flora.xm'
 cp -a target/wasm32-unknown-emscripten/release/mandelwow.{js,wasm} .
 cp -a target/wasm32-unknown-emscripten/release/deps/mandelwow.data .
 emrun .
index 801bf1dac67576477c8d194fe74fc101f5c32226..3ca2caba4878c73bfa4d2d7a36c2f3b943f9888a 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 801bf1dac67576477c8d194fe74fc101f5c32226
+Subproject commit 3ca2caba4878c73bfa4d2d7a36c2f3b943f9888a
index 6019a12702d6932aada4dc73d58d5d79d200a4df..211f23fa17ad30609ddda9a9c5cbcf0c8c5d0e00 100644 (file)
@@ -1,6 +1,7 @@
 use glium;
 use glium::{Display, Program, Surface, implement_vertex};
 use glium::index::{IndexBuffer, PrimitiveType};
+use std::rc::Rc;
 
 pub fn shaded_program(display: &Display) -> Program {
     let vertex_shader_src = include_str!("shaders/shaded.vert");
@@ -15,14 +16,14 @@ struct Vertex {
 }
 implement_vertex!(Vertex, position, normal);
 
-pub struct ShadedCube<'a> {
+pub struct ShadedCube {
     vertexes: glium::VertexBuffer<Vertex>,
-    program: &'a Program,
+    program: Rc<Program>,
     indices: IndexBuffer<u16>,
 }
 
-impl<'a> ShadedCube<'a> {
-    pub fn new(display: &Display, program: &'a Program) -> ShadedCube<'a> {
+impl<'a> ShadedCube {
+    pub fn new(display: &Display, program: Rc<Program>) -> ShadedCube {
         //      x--->
         //      4 ──────┐ 5
         //      ╱┆     ╱│
@@ -71,6 +72,6 @@ impl<'a> ShadedCube<'a> {
             backface_culling: glium::draw_parameters::BackfaceCullingMode::CullClockwise,
             ..Default::default()
         };
-        frame.draw(&self.vertexes, &self.indices, self.program, uniforms, &params).unwrap();
+        frame.draw(&self.vertexes, &self.indices, &self.program, uniforms, &params).unwrap();
     }
 }
index 5ae1c8c762be67db17a0d3bfa880f21c9c05a33e..db6c55ac6b103723999c7efd959ed1650cd91ce3 100644 (file)
@@ -1,7 +1,7 @@
 use cgmath::{Matrix4, Vector4};
 use cgmath::conv::array4x4;
 use glium;
-use glium::glutin::VirtualKeyCode;
+use glium::glutin::event::{ ElementState, VirtualKeyCode, WindowEvent };
 use std::f32;
 use std::f32::consts::PI;
 use crate::support::vec3::Vec3;
@@ -163,9 +163,10 @@ impl CameraState {
         //println!("camera_dir = {:?}", self.dir);
     }
 
-    pub fn process_input(&mut self, event: &glium::glutin::WindowEvent) {
+    pub fn process_input(&mut self, event: &WindowEvent) {
+        //println!("camera event={:?}", event);
         match event {
-            &glium::glutin::WindowEvent::CursorMoved { position, .. }  => {
+            &WindowEvent::CursorMoved { position, .. }  => {
                 let (x, y) = (position.x as i32, position.y as i32);
                 if self.mouse_x == -1 {
                     // Set initial absolute position.
@@ -177,8 +178,8 @@ impl CameraState {
                 self.mouse_x = x;
                 self.mouse_y = y;
             }
-            &glium::glutin::WindowEvent::KeyboardInput { input, .. } => {
-                let pressed = input.state == glium::glutin::ElementState::Pressed;
+            &WindowEvent::KeyboardInput { input, .. } => {
+                let pressed = input.state == ElementState::Pressed;
                 let key = match input.virtual_keycode {
                     Some(key) => key,
                     None => return,
diff --git a/text.rs b/text.rs
index 3d5d73cfcf92688095d43f2fb30c7e1d2512887a..4c66a285cbdd5ab689c478834cf6692ece11f825 100644 (file)
--- a/text.rs
+++ b/text.rs
@@ -1,5 +1,5 @@
 use cgmath::conv::array4x4;
-use cgmath::{Matrix4, Vector3};
+use cgmath::Matrix4;
 use glium;
 use glium::{Display, Program, Surface, implement_vertex, texture, uniform};
 use std;
@@ -57,12 +57,10 @@ pub struct Text<'a> {
     index_buffer: glium::IndexBuffer<u16>,
     program: glium::Program,
     params: glium::DrawParameters<'a>,
-    pub model: Matrix4<f32>,
-    pub character: char,
 }
 
 impl<'a> Text<'a> {
-    pub fn new(display: &Display, character: char) -> Text<'_> {
+    pub fn new(display: &Display) -> Text<'a> {
         let (w, h, pixels) = c64_font();
         let image = glium::texture::RawImage2d {
             data: std::borrow::Cow::from(pixels),
@@ -124,19 +122,17 @@ impl<'a> Text<'a> {
             index_buffer: index_buffer,
             program: text_program(display),
             params: params,
-            model: Matrix4::from_translation(Vector3::unit_z() * (-1.0)),
-            character: character,
         }
     }
 
-    pub fn draw(&self, frame: &mut glium::Frame, perspview: &[[f32; 4]; 4]) {
+    pub fn draw(&self, frame: &mut glium::Frame, c: char, model: &Matrix4<f32>, perspview: &[[f32; 4]; 4]) {
         let uniforms =
             uniform! {
-            model: array4x4(self.model),
+            model: array4x4(*model),
             perspview: *perspview,
             tex: self.tex.sampled()
                 .magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest),
-            index: self.character as i32,
+            index: c as i32,
             // RGB values from http://unusedino.de/ec64/technical/misc/vic656x/colors/
             bgcolor: srgb([ 64,  50, 133u8]),  //  6 - blue
             fgcolor: srgb([120, 106, 189u8]),  // 14 - light blue