InputMap

Struct InputMap 

Source
pub struct InputMap<F>
where F: Hash + Copy,
{ pub mouse_pos: Vec2, pub recently_pressed: Option<InputCode>, pub text_typed: Option<String>, pub mouse_scale: f32, pub scroll_scale: f32, pub press_sensitivity: f32, /* private fields */ }
Expand description

A struct that handles all your input needs once you’ve hooked it up to winit and gilrs.

use gilrs::Gilrs;
use winit::{event::*, application::*, window::*, event_loop::*};
use winit_input_map::*;
struct App {
    window: Option<Window>,
    input: InputMap<()>,
    gilrs: Gilrs
}
impl ApplicationHandler for App {
    fn resumed(&mut self, event_loop: &ActiveEventLoop) {
        self.window = Some(event_loop.create_window(Window::default_attributes()).unwrap());
    }
    fn window_event(&mut self, event_loop: &ActiveEventLoop, _: WindowId, event: WindowEvent) {
        self.input.update_with_window_event(&event);
        if let WindowEvent::CloseRequested = &event { event_loop.exit() }
    }
    fn device_event(&mut self, _: &ActiveEventLoop, id: DeviceId, event: DeviceEvent) {
        self.input.update_with_device_event(id, &event);
    }
    fn about_to_wait(&mut self, _: &ActiveEventLoop) {
        self.input.update_with_gilrs(&mut self.gilrs);
 
        // put your code here

        self.input.init();
    }
}

Fields§

§mouse_pos: Vec2

The mouse position

§recently_pressed: Option<InputCode>

The last input event, even if it isn’t in the binds. Useful for handling rebinding

§text_typed: Option<String>

The text typed this loop

§mouse_scale: f32

Since most values are from 0-1 reducing the mouse sensitivity will result in better consistancy

§scroll_scale: f32

Since most values are from 0-1 reducing the scroll sensitivity will result in better consistancy

§press_sensitivity: f32

The minimum value something has to be at to count as being pressed. Values over 1 will result in most buttons being unusable

Implementations§

Source§

impl InputMap<()>

Source

pub fn empty() -> InputMap<()>

Use if you dont want to have any actions and binds. Will still have access to everything else.

Source§

impl<F> InputMap<F>
where F: Hash + Copy + Eq,

Source

pub fn new(binds: &Vec<(F, Vec<Vec<InputCode>>)>) -> InputMap<F>

Creates a new input system. Takes the action and a list of its associated binds. An action will count as being pressed if any of the binds are pressed. A bind is a list of InputCodes that need to all be pressed for the bind to count as being pressed.

It’s recommended to use the input_map! macro to reduce boilerplate and increase readability.

use Action::*;
use winit_input_map::*;
use winit::keyboard::KeyCode;
#[derive(Hash, PartialEq, Eq, Clone, Copy)]
enum Action {
    Forward,
    Back,
    Pos,
    Neg
}
// doesnt have to be the same ordered as the enum.
let input = InputMap::new(&vec![
    (Forward, vec![ vec![KeyCode::KeyW.into()] ]),
    (Pos,     vec![ vec![KeyCode::KeyA.into()] ]),
    (Back,    vec![ vec![KeyCode::KeyS.into()] ]),
    (Neg,     vec![ vec![KeyCode::KeyD.into()] ])
]);
Source

pub fn add_binds(&mut self, binds: &Vec<(F, Vec<Vec<InputCode>>)>)

Takes binds and adds them to the currently existing map. The binds!() macro will help reduce the boiler_plate of this function.

Source

pub fn set_binds(&mut self, binds: &Vec<(F, Vec<Vec<InputCode>>)>)

Removes all binds and then adds the inputed binds. The binds!() macro will help reduce the boiler_plate of this function.

Source

pub fn get_binds(&self) -> Vec<(F, Vec<Vec<InputCode>>)>

Returns the current binds of the InputMap, may not be in the same order as the inputed binds.

Source

pub fn update_with_winit(&mut self, event: &Event<()>)

👎Deprecated: use update_with_window_event and update_with_device_event

Updates the input map using a winit event. Make sure to call input.init() when your done with the input this loop.

use winit::{event::*, window::WindowAttributes, event_loop::EventLoop};
use winit_input_map::*;

let mut event_loop = EventLoop::new().unwrap();
event_loop.set_control_flow(winit::event_loop::ControlFlow::Poll);
let _window = event_loop.create_window(WindowAttributes::default()).unwrap();

let mut input = input_map!();

event_loop.run(|event, target|{
    input.update_with_winit(&event);
    match &event{
        Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => target.exit(),
        Event::AboutToWait => input.init(),
        _ => ()
    }
});
Source

pub fn update_with_device_event(&mut self, id: DeviceId, event: &DeviceEvent)

Source

pub fn update_with_window_event(&mut self, event: &WindowEvent)

Source

pub fn update_with_gilrs(&mut self, gilrs: &mut Gilrs)

Source

pub fn init(&mut self)

Makes the input map ready to recieve new events.

Source

pub fn pressing(&self, action: F) -> bool

Checks if action is being pressed currently based on the press_sensitivity. same as self.value(action) >= self.press_sensitivty.

Source

pub fn value(&self, action: F) -> f32

Checks how much an action is being pressed. May be higher than 1 in the case of scroll wheels, mouse movement or when multiple binds are bound to an action.

Source

pub fn pressed(&self, action: F) -> bool

Checks if action was just pressed.

Examples found in repository?
examples/simple-fxaa.rs (line 148)
13fn main() {
14    use Action::*;
15    let event_loop = EventLoop::new().unwrap();
16    event_loop.set_control_flow(ControlFlow::Poll);
17
18    let mut colour = ResizableTexture2d::default();
19    let mut depth = ResizableDepthTexture2d::default();
20
21    let input = { use base_input_codes::*; input_map!(
22        (Left,    ArrowLeft,  KeyA, LeftStickLeft ),
23        (Right,   ArrowRight, KeyD, LeftStickRight),
24        (Forward, ArrowUp,    KeyW, LeftStickUp   ),
25        (Back,    ArrowDown,  KeyS, LeftStickDown ),
26        (LookRight, MouseMoveRight, RightStickRight),
27        (LookLeft,  MouseMoveLeft,  RightStickLeft ),
28        (LookUp,    MouseMoveUp,    RightStickUp   ),
29        (LookDown,  MouseMoveDown,  RightStickDown ),
30        (FXAA,      KeyF,       GamepadInput::North)
31    ) };
32    struct Graphics {
33        screen_indices: IndexBuffer<u32>,
34        screen_vertices: VertexBuffer<Vertex>,
35        screen_uvs: VertexBuffer<TextureCoords>,
36
37        teapot_indices: IndexBuffer<u16>,
38        teapot_vertices: VertexBuffer<Vertex>,
39        teapot_uvs: VertexBuffer<TextureCoords>,
40        teapot_normals: VertexBuffer<Normal>,
41
42        fxaa: Program, normal: Program, program: Program
43    }
44    let graphics: Rc<RefCell<Option<Graphics>>> = Rc::default();
45    let graphics_setup = graphics.clone();
46
47    let draw_parameters = DrawParameters {
48        backface_culling: draw_parameters::BackfaceCullingMode::CullClockwise,
49        ..params::alias_3d()
50    };
51    let mut fxaa_on = true;
52    
53    let mut pos = vec3(0.0, 0.0, -30.0);
54    let mut rot = vec2(0.0, 0.0);
55    
56    let mut frame_start = Instant::now();
57
58    thin_engine::builder(input).with_setup(|display, window, _| {
59        window.set_title("FXAA Test");
60        let _ = window.set_cursor_grab(CursorGrabMode::Confined);
61        let _ = window.set_cursor_grab(CursorGrabMode::Locked);
62        window.set_cursor_visible(false);
63
64        let (screen_indices, screen_vertices, screen_uvs) = mesh!(
65            display, &screen::INDICES, &screen::VERTICES, &screen::UVS
66        ).unwrap();
67        let (teapot_indices, teapot_vertices, teapot_uvs, teapot_normals) = mesh!(
68            display, &teapot::INDICES, &teapot::VERTICES, &[] as &[TextureCoords; 0], &teapot::NORMALS
69        ).unwrap();
70
71        let program = Program::from_source(
72            display,
73            "#version 140
74            in vec3 position;
75            in vec3 normal;
76            
77            out vec3 v_normal;
78
79            uniform mat4 model;
80            uniform mat4 perspective;
81            uniform mat4 camera;
82
83            void main() {
84                mat3 norm_mat = transpose(inverse(mat3(camera * model)));
85                v_normal = normalize(norm_mat * normal);
86                gl_Position = perspective * camera * model * vec4(position, 1);
87            }",
88            "#version 140
89            out vec4 colour;
90            in vec3 v_normal;
91            uniform vec3 light;
92            uniform mat4 camera;
93            uniform vec3 ambient;
94            uniform vec3 albedo;
95            uniform float shine;
96            void main() {
97                vec3 camera_dir = inverse(mat3(camera)) * vec3(0, 0, -1);
98                vec3 half_dir = normalize(camera_dir + light);
99                float specular = pow(max(dot(half_dir, v_normal), 0.0), shine);
100                float light_level = max(dot(light, v_normal), 0.0);
101                colour = vec4(albedo * light_level + ambient + vec3(specular), 1.0);
102            }", None
103        ).unwrap();
104        let fxaa = shaders::fxaa_shader(display).unwrap();
105        let normal = Program::from_source(
106            display,
107            "#version 140
108            in vec2 texture_coords;
109            out vec2 uv;
110            in vec3 position;
111            void main() {
112                uv = texture_coords;
113                gl_Position = vec4(position, 1);
114            }", 
115            "#version 140
116            in vec2 uv;
117            uniform sampler2D tex;
118            out vec4 colour;
119            void main() {
120                colour = texture(tex, uv);
121            }", None
122        ).unwrap();
123        graphics_setup.replace(Some(Graphics {
124            screen_indices, screen_vertices, screen_uvs,
125            teapot_indices, teapot_vertices, teapot_uvs, teapot_normals,
126            program, normal, fxaa
127        }));
128    }).with_update(|input, display, _, _, _| {
129        let graphics = graphics.borrow();
130        let Graphics {
131            screen_indices, screen_vertices, screen_uvs,
132            teapot_indices, teapot_vertices, teapot_uvs, teapot_normals,
133            program, normal, fxaa
134        } = graphics.as_ref().unwrap();
135        let teapot_mesh = (teapot_vertices, teapot_normals, teapot_uvs);
136        let screen_mesh = (screen_vertices, screen_uvs);
137
138        let delta_time = frame_start.elapsed().as_secs_f32();
139        frame_start = Instant::now();
140
141        // using a small resolution to better show the effect of fxaa.
142        let size = (380, 216);
143        display.resize(size);
144        depth.resize_to_display(&display);
145        colour.resize_to_display(&display);
146
147        // press f or gamepad north to toggle FXAA
148        if input.pressed(FXAA) { fxaa_on = !fxaa_on }
149
150        let colour = colour.texture();
151        let depth = depth.texture();
152        let mut frame = SimpleFrameBuffer::with_depth_buffer(
153            display, colour, depth
154        ).unwrap();
155
156        let perspective = Mat4::perspective_3d(size, 1.0, 1024.0, 0.1);
157
158        // set camera rotation
159        let look_move = input.dir(LookRight, LookLeft, LookUp, LookDown);
160        rot += look_move.scale(delta_time * 15.0);
161        rot.y = rot.y.clamp(-PI / 2.0, PI / 2.0);
162        let rx = Quat::from_y_rot(rot.x);
163        let ry = Quat::from_x_rot(-rot.y);
164        let rot = rx * ry;
165
166        // move player based on camera
167        let dir = input.dir_max_len_1(Right, Left, Forward, Back);
168        let move_dir = vec3(dir.x, 0.0, dir.y).scale(5.0*delta_time);
169        pos += Mat3::from_rot(rx) * move_dir;
170
171        frame.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
172        // draw teapot
173        frame.draw(
174            teapot_mesh, teapot_indices,
175            program, &uniform! {
176                perspective: perspective,
177                model: Mat4::from_scale(Vec3::splat(0.1)),
178                camera: Mat4::from_inverse_transform(pos, Vec3::ONE, rot),
179                light:   vec3(0.1, 0.25, -1.0).normalise(),
180                albedo:  vec3(0.5, 0.1,   0.4),
181                ambient: vec3(0.0, 0.05,  0.1),
182                shine: 50.0f32,
183            },
184            &draw_parameters,
185        ).unwrap();
186
187        let mut frame = display.draw();
188        frame.draw(
189            screen_mesh, screen_indices, if fxaa_on { fxaa } else { normal },
190            &shaders::fxaa_uniforms(colour), &DrawParameters::default()
191        ).unwrap();
192        frame.finish().unwrap();
193    }).build(event_loop).unwrap();
194}
Source

pub fn released(&self, action: F) -> bool

Checks if action was just released.

Source

pub fn axis(&self, pos: F, neg: F) -> f32

Returns f32 based on how much pos and neg are pressed. may return values higher than 1.0 in the case of mouse movement and scrolling. usefull for movement controls. for 2d values see dir and dir_max_len_1

let move_dir = input.axis(Neg, Pos);

same as input.value(pos) - input.value(neg)

Source

pub fn dir(&self, pos_x: F, neg_x: F, pos_y: F, neg_y: F) -> Vec2

Returns a vector based off of the x and y axis. Can return values with a length higher than 1, if this is undesirable see dir_max_len_1.

Examples found in repository?
examples/simple-fxaa.rs (line 159)
13fn main() {
14    use Action::*;
15    let event_loop = EventLoop::new().unwrap();
16    event_loop.set_control_flow(ControlFlow::Poll);
17
18    let mut colour = ResizableTexture2d::default();
19    let mut depth = ResizableDepthTexture2d::default();
20
21    let input = { use base_input_codes::*; input_map!(
22        (Left,    ArrowLeft,  KeyA, LeftStickLeft ),
23        (Right,   ArrowRight, KeyD, LeftStickRight),
24        (Forward, ArrowUp,    KeyW, LeftStickUp   ),
25        (Back,    ArrowDown,  KeyS, LeftStickDown ),
26        (LookRight, MouseMoveRight, RightStickRight),
27        (LookLeft,  MouseMoveLeft,  RightStickLeft ),
28        (LookUp,    MouseMoveUp,    RightStickUp   ),
29        (LookDown,  MouseMoveDown,  RightStickDown ),
30        (FXAA,      KeyF,       GamepadInput::North)
31    ) };
32    struct Graphics {
33        screen_indices: IndexBuffer<u32>,
34        screen_vertices: VertexBuffer<Vertex>,
35        screen_uvs: VertexBuffer<TextureCoords>,
36
37        teapot_indices: IndexBuffer<u16>,
38        teapot_vertices: VertexBuffer<Vertex>,
39        teapot_uvs: VertexBuffer<TextureCoords>,
40        teapot_normals: VertexBuffer<Normal>,
41
42        fxaa: Program, normal: Program, program: Program
43    }
44    let graphics: Rc<RefCell<Option<Graphics>>> = Rc::default();
45    let graphics_setup = graphics.clone();
46
47    let draw_parameters = DrawParameters {
48        backface_culling: draw_parameters::BackfaceCullingMode::CullClockwise,
49        ..params::alias_3d()
50    };
51    let mut fxaa_on = true;
52    
53    let mut pos = vec3(0.0, 0.0, -30.0);
54    let mut rot = vec2(0.0, 0.0);
55    
56    let mut frame_start = Instant::now();
57
58    thin_engine::builder(input).with_setup(|display, window, _| {
59        window.set_title("FXAA Test");
60        let _ = window.set_cursor_grab(CursorGrabMode::Confined);
61        let _ = window.set_cursor_grab(CursorGrabMode::Locked);
62        window.set_cursor_visible(false);
63
64        let (screen_indices, screen_vertices, screen_uvs) = mesh!(
65            display, &screen::INDICES, &screen::VERTICES, &screen::UVS
66        ).unwrap();
67        let (teapot_indices, teapot_vertices, teapot_uvs, teapot_normals) = mesh!(
68            display, &teapot::INDICES, &teapot::VERTICES, &[] as &[TextureCoords; 0], &teapot::NORMALS
69        ).unwrap();
70
71        let program = Program::from_source(
72            display,
73            "#version 140
74            in vec3 position;
75            in vec3 normal;
76            
77            out vec3 v_normal;
78
79            uniform mat4 model;
80            uniform mat4 perspective;
81            uniform mat4 camera;
82
83            void main() {
84                mat3 norm_mat = transpose(inverse(mat3(camera * model)));
85                v_normal = normalize(norm_mat * normal);
86                gl_Position = perspective * camera * model * vec4(position, 1);
87            }",
88            "#version 140
89            out vec4 colour;
90            in vec3 v_normal;
91            uniform vec3 light;
92            uniform mat4 camera;
93            uniform vec3 ambient;
94            uniform vec3 albedo;
95            uniform float shine;
96            void main() {
97                vec3 camera_dir = inverse(mat3(camera)) * vec3(0, 0, -1);
98                vec3 half_dir = normalize(camera_dir + light);
99                float specular = pow(max(dot(half_dir, v_normal), 0.0), shine);
100                float light_level = max(dot(light, v_normal), 0.0);
101                colour = vec4(albedo * light_level + ambient + vec3(specular), 1.0);
102            }", None
103        ).unwrap();
104        let fxaa = shaders::fxaa_shader(display).unwrap();
105        let normal = Program::from_source(
106            display,
107            "#version 140
108            in vec2 texture_coords;
109            out vec2 uv;
110            in vec3 position;
111            void main() {
112                uv = texture_coords;
113                gl_Position = vec4(position, 1);
114            }", 
115            "#version 140
116            in vec2 uv;
117            uniform sampler2D tex;
118            out vec4 colour;
119            void main() {
120                colour = texture(tex, uv);
121            }", None
122        ).unwrap();
123        graphics_setup.replace(Some(Graphics {
124            screen_indices, screen_vertices, screen_uvs,
125            teapot_indices, teapot_vertices, teapot_uvs, teapot_normals,
126            program, normal, fxaa
127        }));
128    }).with_update(|input, display, _, _, _| {
129        let graphics = graphics.borrow();
130        let Graphics {
131            screen_indices, screen_vertices, screen_uvs,
132            teapot_indices, teapot_vertices, teapot_uvs, teapot_normals,
133            program, normal, fxaa
134        } = graphics.as_ref().unwrap();
135        let teapot_mesh = (teapot_vertices, teapot_normals, teapot_uvs);
136        let screen_mesh = (screen_vertices, screen_uvs);
137
138        let delta_time = frame_start.elapsed().as_secs_f32();
139        frame_start = Instant::now();
140
141        // using a small resolution to better show the effect of fxaa.
142        let size = (380, 216);
143        display.resize(size);
144        depth.resize_to_display(&display);
145        colour.resize_to_display(&display);
146
147        // press f or gamepad north to toggle FXAA
148        if input.pressed(FXAA) { fxaa_on = !fxaa_on }
149
150        let colour = colour.texture();
151        let depth = depth.texture();
152        let mut frame = SimpleFrameBuffer::with_depth_buffer(
153            display, colour, depth
154        ).unwrap();
155
156        let perspective = Mat4::perspective_3d(size, 1.0, 1024.0, 0.1);
157
158        // set camera rotation
159        let look_move = input.dir(LookRight, LookLeft, LookUp, LookDown);
160        rot += look_move.scale(delta_time * 15.0);
161        rot.y = rot.y.clamp(-PI / 2.0, PI / 2.0);
162        let rx = Quat::from_y_rot(rot.x);
163        let ry = Quat::from_x_rot(-rot.y);
164        let rot = rx * ry;
165
166        // move player based on camera
167        let dir = input.dir_max_len_1(Right, Left, Forward, Back);
168        let move_dir = vec3(dir.x, 0.0, dir.y).scale(5.0*delta_time);
169        pos += Mat3::from_rot(rx) * move_dir;
170
171        frame.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
172        // draw teapot
173        frame.draw(
174            teapot_mesh, teapot_indices,
175            program, &uniform! {
176                perspective: perspective,
177                model: Mat4::from_scale(Vec3::splat(0.1)),
178                camera: Mat4::from_inverse_transform(pos, Vec3::ONE, rot),
179                light:   vec3(0.1, 0.25, -1.0).normalise(),
180                albedo:  vec3(0.5, 0.1,   0.4),
181                ambient: vec3(0.0, 0.05,  0.1),
182                shine: 50.0f32,
183            },
184            &draw_parameters,
185        ).unwrap();
186
187        let mut frame = display.draw();
188        frame.draw(
189            screen_mesh, screen_indices, if fxaa_on { fxaa } else { normal },
190            &shaders::fxaa_uniforms(colour), &DrawParameters::default()
191        ).unwrap();
192        frame.finish().unwrap();
193    }).build(event_loop).unwrap();
194}
Source

pub fn dir_max_len_1(&self, pos_x: F, neg_x: F, pos_y: F, neg_y: F) -> Vec2

Returns a vector based off of x and y axis with a maximum length of 1 (the same as a normalised vector). If this undesirable see dir.

Examples found in repository?
examples/simple-fxaa.rs (line 167)
13fn main() {
14    use Action::*;
15    let event_loop = EventLoop::new().unwrap();
16    event_loop.set_control_flow(ControlFlow::Poll);
17
18    let mut colour = ResizableTexture2d::default();
19    let mut depth = ResizableDepthTexture2d::default();
20
21    let input = { use base_input_codes::*; input_map!(
22        (Left,    ArrowLeft,  KeyA, LeftStickLeft ),
23        (Right,   ArrowRight, KeyD, LeftStickRight),
24        (Forward, ArrowUp,    KeyW, LeftStickUp   ),
25        (Back,    ArrowDown,  KeyS, LeftStickDown ),
26        (LookRight, MouseMoveRight, RightStickRight),
27        (LookLeft,  MouseMoveLeft,  RightStickLeft ),
28        (LookUp,    MouseMoveUp,    RightStickUp   ),
29        (LookDown,  MouseMoveDown,  RightStickDown ),
30        (FXAA,      KeyF,       GamepadInput::North)
31    ) };
32    struct Graphics {
33        screen_indices: IndexBuffer<u32>,
34        screen_vertices: VertexBuffer<Vertex>,
35        screen_uvs: VertexBuffer<TextureCoords>,
36
37        teapot_indices: IndexBuffer<u16>,
38        teapot_vertices: VertexBuffer<Vertex>,
39        teapot_uvs: VertexBuffer<TextureCoords>,
40        teapot_normals: VertexBuffer<Normal>,
41
42        fxaa: Program, normal: Program, program: Program
43    }
44    let graphics: Rc<RefCell<Option<Graphics>>> = Rc::default();
45    let graphics_setup = graphics.clone();
46
47    let draw_parameters = DrawParameters {
48        backface_culling: draw_parameters::BackfaceCullingMode::CullClockwise,
49        ..params::alias_3d()
50    };
51    let mut fxaa_on = true;
52    
53    let mut pos = vec3(0.0, 0.0, -30.0);
54    let mut rot = vec2(0.0, 0.0);
55    
56    let mut frame_start = Instant::now();
57
58    thin_engine::builder(input).with_setup(|display, window, _| {
59        window.set_title("FXAA Test");
60        let _ = window.set_cursor_grab(CursorGrabMode::Confined);
61        let _ = window.set_cursor_grab(CursorGrabMode::Locked);
62        window.set_cursor_visible(false);
63
64        let (screen_indices, screen_vertices, screen_uvs) = mesh!(
65            display, &screen::INDICES, &screen::VERTICES, &screen::UVS
66        ).unwrap();
67        let (teapot_indices, teapot_vertices, teapot_uvs, teapot_normals) = mesh!(
68            display, &teapot::INDICES, &teapot::VERTICES, &[] as &[TextureCoords; 0], &teapot::NORMALS
69        ).unwrap();
70
71        let program = Program::from_source(
72            display,
73            "#version 140
74            in vec3 position;
75            in vec3 normal;
76            
77            out vec3 v_normal;
78
79            uniform mat4 model;
80            uniform mat4 perspective;
81            uniform mat4 camera;
82
83            void main() {
84                mat3 norm_mat = transpose(inverse(mat3(camera * model)));
85                v_normal = normalize(norm_mat * normal);
86                gl_Position = perspective * camera * model * vec4(position, 1);
87            }",
88            "#version 140
89            out vec4 colour;
90            in vec3 v_normal;
91            uniform vec3 light;
92            uniform mat4 camera;
93            uniform vec3 ambient;
94            uniform vec3 albedo;
95            uniform float shine;
96            void main() {
97                vec3 camera_dir = inverse(mat3(camera)) * vec3(0, 0, -1);
98                vec3 half_dir = normalize(camera_dir + light);
99                float specular = pow(max(dot(half_dir, v_normal), 0.0), shine);
100                float light_level = max(dot(light, v_normal), 0.0);
101                colour = vec4(albedo * light_level + ambient + vec3(specular), 1.0);
102            }", None
103        ).unwrap();
104        let fxaa = shaders::fxaa_shader(display).unwrap();
105        let normal = Program::from_source(
106            display,
107            "#version 140
108            in vec2 texture_coords;
109            out vec2 uv;
110            in vec3 position;
111            void main() {
112                uv = texture_coords;
113                gl_Position = vec4(position, 1);
114            }", 
115            "#version 140
116            in vec2 uv;
117            uniform sampler2D tex;
118            out vec4 colour;
119            void main() {
120                colour = texture(tex, uv);
121            }", None
122        ).unwrap();
123        graphics_setup.replace(Some(Graphics {
124            screen_indices, screen_vertices, screen_uvs,
125            teapot_indices, teapot_vertices, teapot_uvs, teapot_normals,
126            program, normal, fxaa
127        }));
128    }).with_update(|input, display, _, _, _| {
129        let graphics = graphics.borrow();
130        let Graphics {
131            screen_indices, screen_vertices, screen_uvs,
132            teapot_indices, teapot_vertices, teapot_uvs, teapot_normals,
133            program, normal, fxaa
134        } = graphics.as_ref().unwrap();
135        let teapot_mesh = (teapot_vertices, teapot_normals, teapot_uvs);
136        let screen_mesh = (screen_vertices, screen_uvs);
137
138        let delta_time = frame_start.elapsed().as_secs_f32();
139        frame_start = Instant::now();
140
141        // using a small resolution to better show the effect of fxaa.
142        let size = (380, 216);
143        display.resize(size);
144        depth.resize_to_display(&display);
145        colour.resize_to_display(&display);
146
147        // press f or gamepad north to toggle FXAA
148        if input.pressed(FXAA) { fxaa_on = !fxaa_on }
149
150        let colour = colour.texture();
151        let depth = depth.texture();
152        let mut frame = SimpleFrameBuffer::with_depth_buffer(
153            display, colour, depth
154        ).unwrap();
155
156        let perspective = Mat4::perspective_3d(size, 1.0, 1024.0, 0.1);
157
158        // set camera rotation
159        let look_move = input.dir(LookRight, LookLeft, LookUp, LookDown);
160        rot += look_move.scale(delta_time * 15.0);
161        rot.y = rot.y.clamp(-PI / 2.0, PI / 2.0);
162        let rx = Quat::from_y_rot(rot.x);
163        let ry = Quat::from_x_rot(-rot.y);
164        let rot = rx * ry;
165
166        // move player based on camera
167        let dir = input.dir_max_len_1(Right, Left, Forward, Back);
168        let move_dir = vec3(dir.x, 0.0, dir.y).scale(5.0*delta_time);
169        pos += Mat3::from_rot(rx) * move_dir;
170
171        frame.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
172        // draw teapot
173        frame.draw(
174            teapot_mesh, teapot_indices,
175            program, &uniform! {
176                perspective: perspective,
177                model: Mat4::from_scale(Vec3::splat(0.1)),
178                camera: Mat4::from_inverse_transform(pos, Vec3::ONE, rot),
179                light:   vec3(0.1, 0.25, -1.0).normalise(),
180                albedo:  vec3(0.5, 0.1,   0.4),
181                ambient: vec3(0.0, 0.05,  0.1),
182                shine: 50.0f32,
183            },
184            &draw_parameters,
185        ).unwrap();
186
187        let mut frame = display.draw();
188        frame.draw(
189            screen_mesh, screen_indices, if fxaa_on { fxaa } else { normal },
190            &shaders::fxaa_uniforms(colour), &DrawParameters::default()
191        ).unwrap();
192        frame.finish().unwrap();
193    }).build(event_loop).unwrap();
194}

Trait Implementations§

Source§

impl<F> Default for InputMap<F>
where F: Hash + Copy,

Source§

fn default() -> InputMap<F>

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<F> Freeze for InputMap<F>

§

impl<F> RefUnwindSafe for InputMap<F>
where F: RefUnwindSafe,

§

impl<F> Send for InputMap<F>
where F: Send,

§

impl<F> Sync for InputMap<F>
where F: Sync,

§

impl<F> Unpin for InputMap<F>
where F: Unpin,

§

impl<F> UnwindSafe for InputMap<F>
where F: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more