I am currently working on simple Rendering in Rust using the OpenGL Wrapper Glium. I have a simple 3D model and a Camera ready set up and started working on a fitting camera controller. I'm using device_query to check for keyboard input and if it's a Specific Keyboard input I just change the x and y coordinates. This works, however it works really bad, inconstantly and choppy.
My Event loop:
event_loop.run(move |event, _, control_flow| {
let next_frame_time =
std::time::Instant::now() + std::time::Duration::from_nanos(16_666_667);
####### This is where I change the coordinates ########
x = keyboardinput::keyboard_input_x(x);
y = keyboardinput::keyboard_input_y(y);
*control_flow = glutin::event_loop::ControlFlow::WaitUntil(next_frame_time);
match event {
glutin::event::Event::WindowEvent { event, .. } => match event {
glutin::event::WindowEvent::CloseRequested => {
*control_flow = glutin::event_loop::ControlFlow::Exit;
return;
}
_ => return,
},
glutin::event::Event::NewEvents(cause) => match cause {
glutin::event::StartCause::ResumeTimeReached { .. } => (),
glutin::event::StartCause::Init => (),
_ => return,
},
_ => return,
}
This is my Keyboard input rs file:
use device_query::{DeviceQuery, DeviceState, Keycode};
pub fn keyboard_input_x(mut x: f32) -> f32 {
let device_state = DeviceState::new();
let keys: Vec<Keycode> = device_state.get_keys();
for key in keys.iter() {
println!("Pressed key: {:?}", key);
if key == &Keycode::W {
x -= 0.03;
return x;
}
if key == &Keycode::S {
x += 0.03;
return x;
}
}
return x;
}
pub fn keyboard_input_y(mut y: f32) -> f32 {
let device_state = DeviceState::new();
let keys: Vec<Keycode> = device_state.get_keys();
for key in keys.iter() {
println!("Pressed key: {:?}", key);
if key == &Keycode::Space {
y += 0.03;
return y;
}
if key == &Keycode::LControl {
y -= 0.03;
return y;
}
}
return y;
}
What can I do the make the camera as smooth as possible?
Instead of directly updating your x
/y
position in the input handler, create two variables holding your x velocity and y velocity (xv
/yv
), and then in your input handler do something like this:
bool space_pressed = false;
for key in keys.iter() {
if key == &Keycode::Space {
space_pressed = true;
}
}
if space_pressed {
yv = 1.0; // Move up.
} else {
yv = 0.0; // Don't move.
}
And in your main loop where you compute each frame, count the amount of time since the last frame in seconds (often called delta-t or dt
), and integrate your x velocity and y velocity to a new position:
// Update camera position.
x += xv * dt;
y += yv * dt;
Now when you hold space you will move up at a constant velocity, rather than unpredictably and choppy.