mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'qutrin/camera-modes' into 'master'
Camera Modes See merge request veloren/veloren!355
This commit is contained in:
commit
d77d4dc60e
@ -9,7 +9,7 @@ use crate::{
|
||||
PostProcessLocals, PostProcessPipeline, Renderer, SkyboxLocals, SkyboxPipeline,
|
||||
},
|
||||
scene::{
|
||||
camera::Camera,
|
||||
camera::{Camera, CameraMode},
|
||||
figure::{FigureModelCache, FigureState},
|
||||
},
|
||||
};
|
||||
@ -52,7 +52,7 @@ impl Scene {
|
||||
Self {
|
||||
globals: renderer.create_consts(&[Globals::default()]).unwrap(),
|
||||
lights: renderer.create_consts(&[Light::default(); 32]).unwrap(),
|
||||
camera: Camera::new(resolution.x / resolution.y),
|
||||
camera: Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson),
|
||||
|
||||
skybox: Skybox {
|
||||
model: renderer.create_model(&create_skybox_mesh()).unwrap(),
|
||||
|
@ -7,6 +7,14 @@ const NEAR_PLANE: f32 = 0.01;
|
||||
const FAR_PLANE: f32 = 10000.0;
|
||||
|
||||
const INTERP_TIME: f32 = 0.1;
|
||||
pub const MIN_ZOOM: f32 = 0.1;
|
||||
|
||||
// Possible TODO: Add more modes
|
||||
#[derive(PartialEq, Clone, Copy)]
|
||||
pub enum CameraMode {
|
||||
FirstPerson,
|
||||
ThirdPerson,
|
||||
}
|
||||
|
||||
pub struct Camera {
|
||||
tgt_focus: Vec3<f32>,
|
||||
@ -16,13 +24,14 @@ pub struct Camera {
|
||||
dist: f32,
|
||||
fov: f32,
|
||||
aspect: f32,
|
||||
mode: CameraMode,
|
||||
|
||||
last_time: Option<f64>,
|
||||
}
|
||||
|
||||
impl Camera {
|
||||
/// Create a new `Camera` with default parameters.
|
||||
pub fn new(aspect: f32) -> Self {
|
||||
pub fn new(aspect: f32, mode: CameraMode) -> Self {
|
||||
Self {
|
||||
tgt_focus: Vec3::unit_z() * 10.0,
|
||||
focus: Vec3::unit_z() * 10.0,
|
||||
@ -31,6 +40,8 @@ impl Camera {
|
||||
dist: 10.0,
|
||||
fov: 1.1,
|
||||
aspect,
|
||||
mode,
|
||||
|
||||
last_time: None,
|
||||
}
|
||||
}
|
||||
@ -103,8 +114,13 @@ impl Camera {
|
||||
|
||||
/// Zoom the camera by the given delta, limiting the input accordingly.
|
||||
pub fn zoom_by(&mut self, delta: f32) {
|
||||
// Clamp camera dist to the 0 <= x <= infinity range
|
||||
self.tgt_dist = (self.tgt_dist + delta).max(0.0);
|
||||
match self.mode {
|
||||
CameraMode::ThirdPerson => {
|
||||
// Clamp camera dist to the 2 <= x <= infinity range
|
||||
self.tgt_dist = (self.tgt_dist + delta).max(2.0);
|
||||
}
|
||||
CameraMode::FirstPerson => {}
|
||||
};
|
||||
}
|
||||
|
||||
/// Get the distance of the camera from the target
|
||||
@ -156,4 +172,24 @@ impl Camera {
|
||||
pub fn get_fov(&self) -> f32 {
|
||||
self.fov
|
||||
}
|
||||
|
||||
/// Set the mode of the camera.
|
||||
pub fn set_mode(&mut self, mode: CameraMode) {
|
||||
if self.mode != mode {
|
||||
self.mode = mode;
|
||||
match self.mode {
|
||||
CameraMode::ThirdPerson => {
|
||||
self.zoom_by(5.0);
|
||||
}
|
||||
CameraMode::FirstPerson => {
|
||||
self.set_distance(MIN_ZOOM);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the mode of the camera
|
||||
pub fn get_mode(&self) -> CameraMode {
|
||||
self.mode
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ use crate::{
|
||||
render::{
|
||||
Consts, FigureBoneData, FigureLocals, FigurePipeline, Globals, Light, Mesh, Model, Renderer,
|
||||
},
|
||||
scene::camera::{Camera, CameraMode},
|
||||
};
|
||||
use client::Client;
|
||||
use common::{
|
||||
@ -842,6 +843,7 @@ impl FigureMgr {
|
||||
client: &mut Client,
|
||||
globals: &Consts<Globals>,
|
||||
lights: &Consts<Light>,
|
||||
camera: &Camera,
|
||||
) {
|
||||
let tick = client.get_tick();
|
||||
let ecs = client.state().ecs();
|
||||
@ -897,6 +899,18 @@ impl FigureMgr {
|
||||
.get_or_create_model(renderer, *body, tick)
|
||||
.0;
|
||||
|
||||
// Don't render the player's body while in first person mode
|
||||
if camera.get_mode() == CameraMode::FirstPerson
|
||||
&& client
|
||||
.state()
|
||||
.read_storage::<comp::Body>()
|
||||
.get(client.entity())
|
||||
.is_some()
|
||||
&& entity == client.entity()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
renderer.render_figure(model, globals, locals, bone_consts, lights);
|
||||
} else {
|
||||
warn!("Body has no saved figure");
|
||||
|
@ -2,7 +2,11 @@ pub mod camera;
|
||||
pub mod figure;
|
||||
pub mod terrain;
|
||||
|
||||
use self::{camera::Camera, figure::FigureMgr, terrain::Terrain};
|
||||
use self::{
|
||||
camera::{Camera, CameraMode},
|
||||
figure::FigureMgr,
|
||||
terrain::Terrain,
|
||||
};
|
||||
use crate::{
|
||||
render::{
|
||||
create_pp_mesh, create_skybox_mesh, Consts, Globals, Light, Model, PostProcessLocals,
|
||||
@ -52,7 +56,7 @@ impl Scene {
|
||||
Self {
|
||||
globals: renderer.create_consts(&[Globals::default()]).unwrap(),
|
||||
lights: renderer.create_consts(&[Light::default(); 32]).unwrap(),
|
||||
camera: Camera::new(resolution.x / resolution.y),
|
||||
camera: Camera::new(resolution.x / resolution.y, CameraMode::ThirdPerson),
|
||||
|
||||
skybox: Skybox {
|
||||
model: renderer.create_model(&create_skybox_mesh()).unwrap(),
|
||||
@ -191,6 +195,17 @@ impl Scene {
|
||||
proj_mat,
|
||||
);
|
||||
|
||||
if client
|
||||
.state()
|
||||
.read_storage::<comp::CanBuild>()
|
||||
.get(client.entity())
|
||||
.is_some()
|
||||
{
|
||||
self.camera.set_mode(CameraMode::FirstPerson);
|
||||
} else {
|
||||
self.camera.set_mode(CameraMode::ThirdPerson);
|
||||
}
|
||||
|
||||
// Maintain the figures.
|
||||
self.figure_mgr.maintain(renderer, client);
|
||||
|
||||
@ -206,7 +221,7 @@ impl Scene {
|
||||
// Render terrain and figures.
|
||||
self.terrain.render(renderer, &self.globals, &self.lights);
|
||||
self.figure_mgr
|
||||
.render(renderer, client, &self.globals, &self.lights);
|
||||
.render(renderer, client, &self.globals, &self.lights, &self.camera);
|
||||
|
||||
renderer.render_post_process(
|
||||
&self.postprocess.model,
|
||||
|
@ -2,7 +2,7 @@ use crate::{
|
||||
hud::{DebugInfo, Event as HudEvent, Hud},
|
||||
key_state::KeyState,
|
||||
render::Renderer,
|
||||
scene::Scene,
|
||||
scene::{camera::Camera, Scene},
|
||||
settings::Settings,
|
||||
window::{Event, GameInput, Window},
|
||||
Direction, Error, GlobalState, PlayState, PlayStateResult,
|
||||
@ -91,6 +91,13 @@ impl PlayState for SessionState {
|
||||
self.client.borrow_mut().send_chat(cmd.to_string());
|
||||
}
|
||||
}
|
||||
// Compute camera data
|
||||
let get_cam_data = |camera: &Camera, client: &Client| {
|
||||
let (view_mat, _, cam_pos) = camera.compute_dependents(client);
|
||||
let cam_dir: Vec3<f32> = Vec3::from(view_mat.inverted() * -Vec4::unit_z());
|
||||
|
||||
(cam_dir, cam_pos)
|
||||
};
|
||||
|
||||
// Game loop
|
||||
let mut current_client_state = self.client.borrow().get_client_state();
|
||||
@ -121,9 +128,7 @@ impl PlayState for SessionState {
|
||||
.get(client.entity())
|
||||
.is_some()
|
||||
{
|
||||
let cam_pos = self.scene.camera().compute_dependents(&client).2;
|
||||
let cam_dir =
|
||||
(self.scene.camera().get_focus_pos() - cam_pos).normalized();
|
||||
let (cam_dir, cam_pos) = get_cam_data(&self.scene.camera(), &client);
|
||||
|
||||
let (d, b) = {
|
||||
let terrain = client.state().terrain();
|
||||
@ -134,7 +139,7 @@ impl PlayState for SessionState {
|
||||
if b {
|
||||
let pos =
|
||||
(cam_pos + cam_dir * (d - 0.01)).map(|e| e.floor() as i32);
|
||||
client.place_block(pos, self.selected_block); // TODO: Handle block color with a command
|
||||
client.place_block(pos, self.selected_block);
|
||||
}
|
||||
} else {
|
||||
self.controller.attack = state
|
||||
@ -150,9 +155,8 @@ impl PlayState for SessionState {
|
||||
.get(client.entity())
|
||||
.is_some()
|
||||
{
|
||||
let cam_pos = self.scene.camera().compute_dependents(&client).2;
|
||||
let cam_dir =
|
||||
(self.scene.camera().get_focus_pos() - cam_pos).normalized();
|
||||
let (cam_dir, cam_pos) =
|
||||
get_cam_data(&self.scene.camera(), &client);
|
||||
|
||||
let (d, b) = {
|
||||
let terrain = client.state().terrain();
|
||||
@ -179,9 +183,8 @@ impl PlayState for SessionState {
|
||||
.is_some()
|
||||
{
|
||||
if state {
|
||||
let cam_pos = self.scene.camera().compute_dependents(&client).2;
|
||||
let cam_dir =
|
||||
(self.scene.camera().get_focus_pos() - cam_pos).normalized();
|
||||
let (cam_dir, cam_pos) =
|
||||
get_cam_data(&self.scene.camera(), &client);
|
||||
|
||||
if let Ok(Some(block)) = client
|
||||
.state()
|
||||
|
Loading…
Reference in New Issue
Block a user