mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added camera panning and cursor trapping
This commit is contained in:
parent
45d5a0a396
commit
979f47420d
@ -21,12 +21,14 @@ use crate::{
|
|||||||
window::Window,
|
window::Window,
|
||||||
};
|
};
|
||||||
|
|
||||||
// A type used to store state that is shared between all play states
|
/// A type used to store state that is shared between all play states
|
||||||
pub struct GlobalState {
|
pub struct GlobalState {
|
||||||
window: Window,
|
window: Window,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlobalState {
|
impl GlobalState {
|
||||||
|
/// Called after a change in play state has occured (usually used to reverse any temporary
|
||||||
|
/// effects a state may have made).
|
||||||
pub fn on_play_state_changed(&mut self) {
|
pub fn on_play_state_changed(&mut self) {
|
||||||
self.window.untrap_cursor();
|
self.window.untrap_cursor();
|
||||||
}
|
}
|
||||||
|
@ -31,14 +31,23 @@ use gfx_device_gl as gfx_backend;
|
|||||||
// Library
|
// Library
|
||||||
use gfx;
|
use gfx;
|
||||||
|
|
||||||
/// Used to represent one of many possible errors that may be omitted by the rendering code
|
/// Used to represent one of many possible errors that may be omitted by the rendering subsystem
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum RenderError {
|
pub enum RenderError {
|
||||||
PipelineError(gfx::PipelineStateError<String>),
|
PipelineError(gfx::PipelineStateError<String>),
|
||||||
UpdateError(gfx::UpdateError<usize>),
|
UpdateError(gfx::UpdateError<usize>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Used to represent a specific rendering configuration
|
/// Used to represent a specific rendering configuration.
|
||||||
|
///
|
||||||
|
/// Note that pipelines are tied to the
|
||||||
|
/// rendering backend, and as such it is necessary to modify the rendering subsystem when adding
|
||||||
|
/// new pipelines - custom pipelines are not currently an objective of the rendering subsystem.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// - `SkyboxPipeline`
|
||||||
|
/// - `CharacterPipeline`
|
||||||
pub trait Pipeline {
|
pub trait Pipeline {
|
||||||
type Vertex:
|
type Vertex:
|
||||||
Clone +
|
Clone +
|
||||||
|
@ -66,10 +66,10 @@ pub fn create_mesh() -> Mesh<SkyboxPipeline> {
|
|||||||
// +x
|
// +x
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
mesh.push_quad(Quad::new(
|
mesh.push_quad(Quad::new(
|
||||||
Vertex { pos: [ 1.0, -1.0, -1.0] },
|
Vertex { pos: [ 1.0, -1.0, 1.0] },
|
||||||
Vertex { pos: [ 1.0, 1.0, 1.0] },
|
Vertex { pos: [ 1.0, 1.0, 1.0] },
|
||||||
Vertex { pos: [ 1.0, 1.0, -1.0] },
|
Vertex { pos: [ 1.0, 1.0, -1.0] },
|
||||||
Vertex { pos: [ 1.0, -1.0, 1.0] },
|
Vertex { pos: [ 1.0, -1.0, -1.0] },
|
||||||
));
|
));
|
||||||
// -y
|
// -y
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
@ -82,10 +82,10 @@ pub fn create_mesh() -> Mesh<SkyboxPipeline> {
|
|||||||
// +y
|
// +y
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
mesh.push_quad(Quad::new(
|
mesh.push_quad(Quad::new(
|
||||||
Vertex { pos: [ 1.0, 1.0, -1.0] },
|
Vertex { pos: [ 1.0, 1.0, 1.0] },
|
||||||
Vertex { pos: [-1.0, 1.0, 1.0] },
|
Vertex { pos: [-1.0, 1.0, 1.0] },
|
||||||
Vertex { pos: [-1.0, 1.0, -1.0] },
|
Vertex { pos: [-1.0, 1.0, -1.0] },
|
||||||
Vertex { pos: [ 1.0, 1.0, 1.0] },
|
Vertex { pos: [ 1.0, 1.0, -1.0] },
|
||||||
));
|
));
|
||||||
// -z
|
// -z
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
@ -98,10 +98,10 @@ pub fn create_mesh() -> Mesh<SkyboxPipeline> {
|
|||||||
// +z
|
// +z
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
mesh.push_quad(Quad::new(
|
mesh.push_quad(Quad::new(
|
||||||
Vertex { pos: [-1.0, -1.0, 1.0] },
|
Vertex { pos: [-1.0, 1.0, 1.0] },
|
||||||
Vertex { pos: [ 1.0, 1.0, 1.0] },
|
Vertex { pos: [ 1.0, 1.0, 1.0] },
|
||||||
Vertex { pos: [ 1.0, -1.0, 1.0] },
|
Vertex { pos: [ 1.0, -1.0, 1.0] },
|
||||||
Vertex { pos: [-1.0, 1.0, 1.0] },
|
Vertex { pos: [-1.0, -1.0, 1.0] },
|
||||||
));
|
));
|
||||||
|
|
||||||
mesh
|
mesh
|
||||||
|
@ -32,7 +32,7 @@ pub type TgtDepthView = gfx::handle::DepthStencilView<gfx_backend::Resources, Tg
|
|||||||
|
|
||||||
/// A type that encapsulates rendering state. `Renderer` is central to Voxygen's rendering
|
/// A type that encapsulates rendering state. `Renderer` is central to Voxygen's rendering
|
||||||
/// subsystem and contains any state necessary to interact with the GPU, along with pipeline state
|
/// subsystem and contains any state necessary to interact with the GPU, along with pipeline state
|
||||||
/// objects (PSOs) needed to renderer different kinds of model to the screen.
|
/// objects (PSOs) needed to renderer different kinds of models to the screen.
|
||||||
pub struct Renderer {
|
pub struct Renderer {
|
||||||
device: gfx_backend::Device,
|
device: gfx_backend::Device,
|
||||||
encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
encoder: gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
||||||
@ -127,7 +127,7 @@ impl Renderer {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Queue the rendering of the provided skybox model in the upcoming frame
|
/// Queue the rendering of the provided skybox model in the upcoming frame.
|
||||||
pub fn render_skybox(
|
pub fn render_skybox(
|
||||||
&mut self,
|
&mut self,
|
||||||
model: &Model<skybox::SkyboxPipeline>,
|
model: &Model<skybox::SkyboxPipeline>,
|
||||||
@ -152,7 +152,7 @@ struct GfxPipeline<P: gfx::pso::PipelineInit> {
|
|||||||
pso: gfx::pso::PipelineState<gfx_backend::Resources, P::Meta>,
|
pso: gfx::pso::PipelineState<gfx_backend::Resources, P::Meta>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new pipeline from the provided vertex shader and fragment shader
|
/// Create a new pipeline from the provided vertex shader and fragment shader.
|
||||||
fn create_pipeline<'a, P: gfx::pso::PipelineInit>(
|
fn create_pipeline<'a, P: gfx::pso::PipelineInit>(
|
||||||
factory: &mut gfx_backend::Factory,
|
factory: &mut gfx_backend::Factory,
|
||||||
pipe: P,
|
pipe: P,
|
||||||
|
@ -50,6 +50,15 @@ impl Camera {
|
|||||||
(view_mat, proj_mat, cam_pos)
|
(view_mat, proj_mat, cam_pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Rotate the camera about its focus by the given delta, limiting the input accordingly.
|
||||||
|
pub fn rotate_by(&mut self, delta: Vec3<f32>) {
|
||||||
|
self.ori += delta;
|
||||||
|
// Clamp camera pitch to the vertical limits
|
||||||
|
self.ori.y = self.ori.y
|
||||||
|
.min(PI / 2.0)
|
||||||
|
.max(-PI / 2.0);
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the focus position of the camera.
|
/// Get the focus position of the camera.
|
||||||
pub fn get_focus_pos(&self) -> Vec3<f32> { self.focus }
|
pub fn get_focus_pos(&self) -> Vec3<f32> { self.focus }
|
||||||
/// Set the focus position of the camera.
|
/// Set the focus position of the camera.
|
||||||
|
@ -1,14 +1,20 @@
|
|||||||
pub mod camera;
|
pub mod camera;
|
||||||
|
|
||||||
|
// Library
|
||||||
|
use vek::*;
|
||||||
|
|
||||||
// Crate
|
// Crate
|
||||||
use crate::render::{
|
use crate::{
|
||||||
Consts,
|
render::{
|
||||||
Globals,
|
Consts,
|
||||||
Model,
|
Globals,
|
||||||
Renderer,
|
Model,
|
||||||
SkyboxPipeline,
|
Renderer,
|
||||||
SkyboxLocals,
|
SkyboxPipeline,
|
||||||
create_skybox_mesh,
|
SkyboxLocals,
|
||||||
|
create_skybox_mesh,
|
||||||
|
},
|
||||||
|
window::Event,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Local
|
// Local
|
||||||
@ -19,6 +25,9 @@ struct Skybox {
|
|||||||
locals: Consts<SkyboxLocals>,
|
locals: Consts<SkyboxLocals>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Don't hard-code this
|
||||||
|
const CURSOR_PAN_SCALE: f32 = 0.005;
|
||||||
|
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
camera: Camera,
|
camera: Camera,
|
||||||
globals: Consts<Globals>,
|
globals: Consts<Globals>,
|
||||||
@ -44,6 +53,20 @@ impl Scene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Handle an incoming user input event (i.e: cursor moved, key pressed, window closed, etc.).
|
||||||
|
pub fn handle_input_event(&mut self, event: Event) -> bool {
|
||||||
|
match event {
|
||||||
|
// Panning the cursor makes the camera rotate
|
||||||
|
Event::CursorPan(delta) => {
|
||||||
|
self.camera.rotate_by(Vec3::from(delta) * CURSOR_PAN_SCALE);
|
||||||
|
true
|
||||||
|
},
|
||||||
|
// All other events are unhandled
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Maintain and update GPU data such as constant buffers, models, etc.
|
||||||
pub fn maintain_gpu_data(&mut self, renderer: &mut Renderer) {
|
pub fn maintain_gpu_data(&mut self, renderer: &mut Renderer) {
|
||||||
// Compute camera matrices
|
// Compute camera matrices
|
||||||
let (view_mat, proj_mat, cam_pos) = self.camera.compute_dependents();
|
let (view_mat, proj_mat, cam_pos) = self.camera.compute_dependents();
|
||||||
|
@ -38,13 +38,14 @@ impl PlayState for SessionState {
|
|||||||
loop {
|
loop {
|
||||||
// Handle window events
|
// Handle window events
|
||||||
for event in global_state.window.fetch_events() {
|
for event in global_state.window.fetch_events() {
|
||||||
match event {
|
let _handled = match event {
|
||||||
Event::Close => return PlayStateResult::Shutdown,
|
Event::Close => return PlayStateResult::Shutdown,
|
||||||
// When 'q' is pressed, exit the session
|
// When 'q' is pressed, exit the session
|
||||||
Event::Char('q') => return PlayStateResult::Pop,
|
Event::Char('q') => return PlayStateResult::Pop,
|
||||||
// Ignore all other events
|
// Pass all other events to the scene
|
||||||
_ => {},
|
event => self.scene.handle_input_event(event),
|
||||||
}
|
};
|
||||||
|
// TODO: Do something if the event wasn't handled?
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maintain scene GPU data
|
// Maintain scene GPU data
|
||||||
|
@ -69,6 +69,11 @@ impl Window {
|
|||||||
glutin::WindowEvent::ReceivedCharacter(c) => events.push(Event::Char(c)),
|
glutin::WindowEvent::ReceivedCharacter(c) => events.push(Event::Char(c)),
|
||||||
_ => {},
|
_ => {},
|
||||||
},
|
},
|
||||||
|
glutin::Event::DeviceEvent { event, .. } => match event {
|
||||||
|
glutin::DeviceEvent::MouseMotion { delta: (dx, dy), .. } =>
|
||||||
|
events.push(Event::CursorPan(Vec2::new(dx as f32, dy as f32))),
|
||||||
|
_ => {},
|
||||||
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
});
|
});
|
||||||
events
|
events
|
||||||
|
Loading…
Reference in New Issue
Block a user