mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added cursor trapping, more documentation
This commit is contained in:
parent
c9d877de7a
commit
45d5a0a396
@ -14,7 +14,7 @@ uniform u_globals {
|
||||
vec4 cam_pos;
|
||||
vec4 focus_pos;
|
||||
vec4 view_distance;
|
||||
vec4 tod;
|
||||
vec4 time_of_day;
|
||||
vec4 time;
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,7 @@ uniform u_globals {
|
||||
vec4 cam_pos;
|
||||
vec4 focus_pos;
|
||||
vec4 view_distance;
|
||||
vec4 tod;
|
||||
vec4 time_of_day;
|
||||
vec4 time;
|
||||
};
|
||||
|
||||
|
@ -14,7 +14,7 @@ uniform u_globals {
|
||||
vec4 cam_pos;
|
||||
vec4 focus_pos;
|
||||
vec4 view_distance;
|
||||
vec4 tod;
|
||||
vec4 time_of_day;
|
||||
vec4 time;
|
||||
};
|
||||
|
||||
|
@ -14,7 +14,7 @@ uniform u_globals {
|
||||
vec4 cam_pos;
|
||||
vec4 focus_pos;
|
||||
vec4 view_distance;
|
||||
vec4 tod;
|
||||
vec4 time_of_day;
|
||||
vec4 time;
|
||||
};
|
||||
|
||||
|
@ -12,8 +12,6 @@ pub use crate::error::Error;
|
||||
use std::mem;
|
||||
|
||||
// Library
|
||||
use glutin;
|
||||
use failure;
|
||||
use log;
|
||||
use pretty_env_logger;
|
||||
|
||||
@ -28,6 +26,12 @@ pub struct GlobalState {
|
||||
window: Window,
|
||||
}
|
||||
|
||||
impl GlobalState {
|
||||
pub fn on_play_state_changed(&mut self) {
|
||||
self.window.untrap_cursor();
|
||||
}
|
||||
}
|
||||
|
||||
// States can either close (and revert to a previous state), push a new state on top of themselves,
|
||||
// or switch to a totally different state
|
||||
pub enum PlayStateResult {
|
||||
@ -82,23 +86,27 @@ fn main() {
|
||||
log::info!("Shutting down all states...");
|
||||
while states.last().is_some() {
|
||||
states.pop().map(|old_state| {
|
||||
log::info!("Popped state '{}'", old_state.name())
|
||||
log::info!("Popped state '{}'", old_state.name());
|
||||
global_state.on_play_state_changed();
|
||||
});
|
||||
}
|
||||
},
|
||||
PlayStateResult::Pop => {
|
||||
states.pop().map(|old_state| {
|
||||
log::info!("Popped state '{}'", old_state.name())
|
||||
log::info!("Popped state '{}'", old_state.name());
|
||||
global_state.on_play_state_changed();
|
||||
});
|
||||
},
|
||||
PlayStateResult::Push(new_state) => {
|
||||
log::info!("Pushed state '{}'", new_state.name());
|
||||
states.push(new_state);
|
||||
global_state.on_play_state_changed();
|
||||
},
|
||||
PlayStateResult::Switch(mut new_state) => {
|
||||
states.last_mut().map(|old_state| {
|
||||
log::info!("Switching to state '{}' from state '{}'", new_state.name(), old_state.name());
|
||||
mem::swap(old_state, &mut new_state);
|
||||
global_state.on_play_state_changed();
|
||||
});
|
||||
},
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ use crate::{
|
||||
PlayStateResult,
|
||||
GlobalState,
|
||||
window::Event,
|
||||
render,
|
||||
session::SessionState,
|
||||
};
|
||||
|
||||
@ -44,8 +43,9 @@ impl PlayState for TitleState {
|
||||
|
||||
// Finish the frame
|
||||
global_state.window.renderer_mut().flush();
|
||||
global_state.window.display()
|
||||
.expect("Failed to display window");
|
||||
global_state.window
|
||||
.swap_buffers()
|
||||
.expect("Failed to swap window buffers");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ pub mod mesh;
|
||||
pub mod model;
|
||||
pub mod pipelines;
|
||||
pub mod renderer;
|
||||
mod util;
|
||||
|
||||
// Reexports
|
||||
pub use self::{
|
||||
|
@ -11,6 +11,9 @@ use gfx::{
|
||||
};
|
||||
use vek::*;
|
||||
|
||||
// Local
|
||||
use super::util::arr_to_mat;
|
||||
|
||||
gfx_defines! {
|
||||
constant Globals {
|
||||
view_mat: [[f32; 4]; 4] = "view_mat",
|
||||
@ -18,32 +21,43 @@ gfx_defines! {
|
||||
cam_pos: [f32; 4] = "cam_pos",
|
||||
focus_pos: [f32; 4] = "focus_pos",
|
||||
view_distance: [f32; 4] = "view_distance",
|
||||
tod: [f32; 4] = "tod",
|
||||
time_of_day: [f32; 4] = "time_of_day",
|
||||
time: [f32; 4] = "time",
|
||||
}
|
||||
}
|
||||
|
||||
impl Globals {
|
||||
pub fn new() -> Self {
|
||||
// TODO: Get rid of this ugliness
|
||||
#[rustfmt::skip]
|
||||
fn f32_arr_to_mat(arr: [f32; 16]) -> [[f32; 4]; 4] {
|
||||
[
|
||||
[arr[ 0], arr[ 1], arr[ 2], arr[ 3]],
|
||||
[arr[ 4], arr[ 5], arr[ 6], arr[ 7]],
|
||||
[arr[ 8], arr[ 9], arr[10], arr[11]],
|
||||
[arr[12], arr[13], arr[14], arr[15]],
|
||||
]
|
||||
}
|
||||
|
||||
/// Create global consts with default values.
|
||||
pub fn default() -> Self {
|
||||
Self {
|
||||
view_mat: f32_arr_to_mat(Mat4::identity().into_col_array()),
|
||||
proj_mat: f32_arr_to_mat(Mat4::identity().into_col_array()),
|
||||
view_mat: arr_to_mat(Mat4::identity().into_col_array()),
|
||||
proj_mat: arr_to_mat(Mat4::identity().into_col_array()),
|
||||
cam_pos: [0.0; 4],
|
||||
focus_pos: [0.0; 4],
|
||||
view_distance: [0.0; 4],
|
||||
tod: [0.0; 4],
|
||||
time_of_day: [0.0; 4],
|
||||
time: [0.0; 4],
|
||||
}
|
||||
}
|
||||
|
||||
/// Create global consts from the provided parameters.
|
||||
pub fn new(
|
||||
view_mat: Mat4<f32>,
|
||||
proj_mat: Mat4<f32>,
|
||||
cam_pos: Vec3<f32>,
|
||||
focus_pos: Vec3<f32>,
|
||||
view_distance: f32,
|
||||
time_of_day: f32,
|
||||
time: f32,
|
||||
) -> Self {
|
||||
Self {
|
||||
view_mat: arr_to_mat(view_mat.into_col_array()),
|
||||
proj_mat: arr_to_mat(proj_mat.into_col_array()),
|
||||
cam_pos: Vec4::from(cam_pos).into_array(),
|
||||
focus_pos: Vec4::from(focus_pos).into_array(),
|
||||
view_distance: [view_distance; 4],
|
||||
time_of_day: [time_of_day; 4],
|
||||
time: [time; 4],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ gfx_defines! {
|
||||
}
|
||||
|
||||
impl Locals {
|
||||
pub fn new() -> Self {
|
||||
pub fn default() -> Self {
|
||||
Self { nul: [0.0; 4] }
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,8 @@ pub struct Renderer {
|
||||
}
|
||||
|
||||
impl Renderer {
|
||||
/// Create a new `Renderer` from a variety of backend-specific components and the window targets.
|
||||
/// Create a new `Renderer` from a variety of backend-specific components and the window
|
||||
/// targets.
|
||||
pub fn new(
|
||||
device: gfx_backend::Device,
|
||||
mut factory: gfx_backend::Factory,
|
||||
@ -99,13 +100,25 @@ impl Renderer {
|
||||
Ok(Consts::new(&mut self.factory))
|
||||
}
|
||||
|
||||
/// Create a new set of constants and update then with a value.
|
||||
pub fn create_consts_with<T: Copy + gfx::traits::Pod>(&mut self, val: T) -> Result<Consts<T>, RenderError> {
|
||||
/// Create a new set of constants with a value.
|
||||
pub fn create_consts_with<T: Copy + gfx::traits::Pod>(
|
||||
&mut self,
|
||||
val: T
|
||||
) -> Result<Consts<T>, RenderError> {
|
||||
let mut consts = self.create_consts()?;
|
||||
consts.update(&mut self.encoder, val)?;
|
||||
Ok(consts)
|
||||
}
|
||||
|
||||
/// Update a set of constants with a new value.
|
||||
pub fn update_consts<T: Copy + gfx::traits::Pod>(
|
||||
&mut self,
|
||||
consts: &mut Consts<T>,
|
||||
val: T
|
||||
) -> Result<(), RenderError> {
|
||||
consts.update(&mut self.encoder, val)
|
||||
}
|
||||
|
||||
/// Create a new model from the provided mesh.
|
||||
pub fn create_model<P: Pipeline>(&mut self, mesh: &Mesh<P>) -> Result<Model<P>, RenderError> {
|
||||
Ok(Model::new(
|
||||
@ -136,7 +149,6 @@ impl Renderer {
|
||||
}
|
||||
|
||||
struct GfxPipeline<P: gfx::pso::PipelineInit> {
|
||||
program: gfx::handle::Program<gfx_backend::Resources>,
|
||||
pso: gfx::pso::PipelineState<gfx_backend::Resources, P::Meta>,
|
||||
}
|
||||
|
||||
@ -166,10 +178,12 @@ fn create_pipeline<'a, P: gfx::pso::PipelineInit>(
|
||||
)
|
||||
// Do some funky things to work around an oddity in gfx's error ownership rules
|
||||
.map_err(|err| RenderError::PipelineError(match err {
|
||||
gfx::PipelineStateError::Program(err) => gfx::PipelineStateError::Program(err),
|
||||
gfx::PipelineStateError::DescriptorInit(err) => gfx::PipelineStateError::DescriptorInit(err.into()),
|
||||
gfx::PipelineStateError::DeviceCreate(err) => gfx::PipelineStateError::DeviceCreate(err),
|
||||
gfx::PipelineStateError::Program(err) =>
|
||||
gfx::PipelineStateError::Program(err),
|
||||
gfx::PipelineStateError::DescriptorInit(err) =>
|
||||
gfx::PipelineStateError::DescriptorInit(err.into()),
|
||||
gfx::PipelineStateError::DeviceCreate(err) =>
|
||||
gfx::PipelineStateError::DeviceCreate(err),
|
||||
}))?,
|
||||
program,
|
||||
})
|
||||
}
|
||||
|
10
voxygen/src/render/util.rs
Normal file
10
voxygen/src/render/util.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// TODO: Get rid of this ugliness
|
||||
#[rustfmt::skip]
|
||||
pub fn arr_to_mat(arr: [f32; 16]) -> [[f32; 4]; 4] {
|
||||
[
|
||||
[arr[ 0], arr[ 1], arr[ 2], arr[ 3]],
|
||||
[arr[ 4], arr[ 5], arr[ 6], arr[ 7]],
|
||||
[arr[ 8], arr[ 9], arr[10], arr[11]],
|
||||
[arr[12], arr[13], arr[14], arr[15]],
|
||||
]
|
||||
}
|
@ -21,15 +21,15 @@ impl Camera {
|
||||
Self {
|
||||
focus: Vec3::zero(),
|
||||
ori: Vec3::zero(),
|
||||
dist: 10.0,
|
||||
dist: 5.0,
|
||||
fov: 1.3,
|
||||
aspect: 1.618,
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute the transformation matrices (view matrix and projection matrix) for the camera.
|
||||
pub fn compute_matrices(&self) -> (Mat4<f32>, Mat4<f32>) {
|
||||
let view = Mat4::<f32>::identity()
|
||||
pub fn compute_dependents(&self) -> (Mat4<f32>, Mat4<f32>, Vec3<f32>) {
|
||||
let view_mat = Mat4::<f32>::identity()
|
||||
* Mat4::translation_3d(-Vec3::unit_z() * self.dist)
|
||||
* Mat4::rotation_z(self.ori.z)
|
||||
* Mat4::rotation_x(self.ori.y)
|
||||
@ -37,13 +37,21 @@ impl Camera {
|
||||
* Mat4::rotation_3d(PI / 2.0, -Vec4::unit_x())
|
||||
* Mat4::translation_3d(-self.focus);
|
||||
|
||||
let proj = Mat4::perspective_rh_no(
|
||||
let proj_mat = Mat4::perspective_rh_no(
|
||||
self.fov,
|
||||
self.aspect,
|
||||
NEAR_PLANE,
|
||||
FAR_PLANE,
|
||||
);
|
||||
|
||||
(view, proj)
|
||||
// TODO: Make this more efficient
|
||||
let cam_pos = Vec3::from(view_mat.inverted() * Vec4::unit_w());
|
||||
|
||||
(view_mat, proj_mat, cam_pos)
|
||||
}
|
||||
|
||||
/// Get the focus position of the camera.
|
||||
pub fn get_focus_pos(&self) -> Vec3<f32> { self.focus }
|
||||
/// Set the focus position of the camera.
|
||||
pub fn set_focus_pos(&mut self, focus: Vec3<f32>) { self.focus = focus; }
|
||||
}
|
||||
|
@ -31,19 +31,36 @@ impl Scene {
|
||||
Self {
|
||||
camera: Camera::new(),
|
||||
globals: renderer
|
||||
.create_consts_with(Globals::new())
|
||||
.create_consts_with(Globals::default())
|
||||
.unwrap(),
|
||||
skybox: Skybox {
|
||||
model: renderer
|
||||
.create_model(&create_skybox_mesh())
|
||||
.unwrap(),
|
||||
locals: renderer
|
||||
.create_consts_with(SkyboxLocals::new())
|
||||
.create_consts_with(SkyboxLocals::default())
|
||||
.unwrap(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maintain_gpu_data(&mut self, renderer: &mut Renderer) {
|
||||
// Compute camera matrices
|
||||
let (view_mat, proj_mat, cam_pos) = self.camera.compute_dependents();
|
||||
|
||||
// Update global constants
|
||||
renderer.update_consts(&mut self.globals, Globals::new(
|
||||
view_mat,
|
||||
proj_mat,
|
||||
cam_pos,
|
||||
self.camera.get_focus_pos(),
|
||||
10.0,
|
||||
0.0,
|
||||
0.0,
|
||||
))
|
||||
.expect("Failed to update global constants");
|
||||
}
|
||||
|
||||
/// Render the scene using the provided `Renderer`
|
||||
pub fn render_to(&self, renderer: &mut Renderer) {
|
||||
// Render the skybox first (it appears over everything else so must be rendered first)
|
||||
|
@ -31,6 +31,9 @@ const BG_COLOR: Rgba<f32> = Rgba { r: 0.0, g: 0.3, b: 1.0, a: 1.0 };
|
||||
|
||||
impl PlayState for SessionState {
|
||||
fn play(&mut self, global_state: &mut GlobalState) -> PlayStateResult {
|
||||
// Trap the cursor
|
||||
global_state.window.trap_cursor();
|
||||
|
||||
// Game loop
|
||||
loop {
|
||||
// Handle window events
|
||||
@ -44,6 +47,9 @@ impl PlayState for SessionState {
|
||||
}
|
||||
}
|
||||
|
||||
// Maintain scene GPU data
|
||||
self.scene.maintain_gpu_data(global_state.window.renderer_mut());
|
||||
|
||||
// Clear the screen
|
||||
global_state.window.renderer_mut().clear(BG_COLOR);
|
||||
|
||||
@ -52,8 +58,9 @@ impl PlayState for SessionState {
|
||||
|
||||
// Finish the frame
|
||||
global_state.window.renderer_mut().flush();
|
||||
global_state.window.display()
|
||||
.expect("Failed to display window");
|
||||
global_state.window
|
||||
.swap_buffers()
|
||||
.expect("Failed to swap window buffers");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Library
|
||||
use glutin;
|
||||
use gfx_window_glutin;
|
||||
use vek::*;
|
||||
|
||||
// Crate
|
||||
use crate::{
|
||||
@ -73,13 +74,30 @@ impl Window {
|
||||
events
|
||||
}
|
||||
|
||||
pub fn display(&self) -> Result<(), Error> {
|
||||
pub fn swap_buffers(&self) -> Result<(), Error> {
|
||||
self.window.swap_buffers()
|
||||
.map_err(|err| Error::BackendError(Box::new(err)))
|
||||
}
|
||||
|
||||
pub fn trap_cursor(&mut self) {
|
||||
self.window.hide_cursor(true);
|
||||
self.window.grab_cursor(true)
|
||||
.expect("Failed to grab cursor");
|
||||
}
|
||||
|
||||
pub fn untrap_cursor(&mut self) {
|
||||
self.window.hide_cursor(false);
|
||||
self.window.grab_cursor(false)
|
||||
.expect("Failed to ungrab cursor");
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an incoming event from the window
|
||||
pub enum Event {
|
||||
/// The window has been requested to close.
|
||||
Close,
|
||||
/// A key has been typed that corresponds to a specific character.
|
||||
Char(char),
|
||||
/// The cursor has been panned across the screen while trapped.
|
||||
CursorPan(Vec2<f32>),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user