mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'zesterer/small-fixes' into 'master'
Camera tweaks See merge request veloren/veloren!1004
This commit is contained in:
commit
012aebbfd6
@ -9,8 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Added context-sensitive crosshair
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Improved camera aiming
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
## [0.6.0] - 2020-05-16
|
## [0.6.0] - 2020-05-16
|
||||||
|
@ -54,7 +54,7 @@ void main() {
|
|||||||
vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
|
vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
|
||||||
|
|
||||||
if ((flags & 1) == 1 && int(cam_mode) == 1) {
|
if ((flags & 1) == 1 && int(cam_mode) == 1) {
|
||||||
float distance = distance(vec3(cam_pos), vec3(model_mat * vec4(vec3(0), 1))) - 2;
|
float distance = distance(vec3(cam_pos), focus_pos.xyz) - 2;
|
||||||
|
|
||||||
float opacity = clamp(distance / distance_divider, 0, 1);
|
float opacity = clamp(distance / distance_divider, 0, 1);
|
||||||
|
|
||||||
|
@ -42,6 +42,8 @@ void main() {
|
|||||||
combined_mat *
|
combined_mat *
|
||||||
vec4(pos, 1)).xyz;
|
vec4(pos, 1)).xyz;
|
||||||
|
|
||||||
|
f_pos.z -= 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0);
|
||||||
|
|
||||||
f_col = vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0;
|
f_col = vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0;
|
||||||
|
|
||||||
f_ao = float(v_ao_bone & 0x3u) / 4.0;
|
f_ao = float(v_ao_bone & 0x3u) / 4.0;
|
||||||
|
@ -29,7 +29,7 @@ uniform u_bones {
|
|||||||
out vec4 tgt_color;
|
out vec4 tgt_color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
float distance = distance(vec3(cam_pos), vec3(model_mat * vec4(vec3(0), 1))) - 2;
|
float distance = distance(vec3(cam_pos), focus_pos.xyz) - 2;
|
||||||
|
|
||||||
float opacity = clamp(distance / distance_divider, 0, 1);
|
float opacity = clamp(distance / distance_divider, 0, 1);
|
||||||
|
|
||||||
|
@ -91,6 +91,17 @@ impl CharacterState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_aimed(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
CharacterState::BasicMelee(_)
|
||||||
|
| CharacterState::BasicRanged(_)
|
||||||
|
| CharacterState::DashMelee(_)
|
||||||
|
| CharacterState::TripleStrike(_)
|
||||||
|
| CharacterState::BasicBlock => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_block(&self) -> bool {
|
pub fn is_block(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
CharacterState::BasicBlock => true,
|
CharacterState::BasicBlock => true,
|
||||||
|
@ -207,6 +207,11 @@ pub struct DebugInfo {
|
|||||||
pub num_figures_visible: u32,
|
pub num_figures_visible: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct HudInfo {
|
||||||
|
pub is_aiming: bool,
|
||||||
|
pub is_first_person: bool,
|
||||||
|
}
|
||||||
|
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
SendMessage(String),
|
SendMessage(String),
|
||||||
AdjustMousePan(u32),
|
AdjustMousePan(u32),
|
||||||
@ -455,6 +460,7 @@ pub struct Hud {
|
|||||||
slot_manager: slots::SlotManager,
|
slot_manager: slots::SlotManager,
|
||||||
hotbar: hotbar::State,
|
hotbar: hotbar::State,
|
||||||
events: Vec<Event>,
|
events: Vec<Event>,
|
||||||
|
crosshair_opacity: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hud {
|
impl Hud {
|
||||||
@ -529,6 +535,7 @@ impl Hud {
|
|||||||
slot_manager,
|
slot_manager,
|
||||||
hotbar: hotbar::State::new(),
|
hotbar: hotbar::State::new(),
|
||||||
events: Vec::new(),
|
events: Vec::new(),
|
||||||
|
crosshair_opacity: 0.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -544,6 +551,7 @@ impl Hud {
|
|||||||
global_state: &GlobalState,
|
global_state: &GlobalState,
|
||||||
debug_info: DebugInfo,
|
debug_info: DebugInfo,
|
||||||
dt: Duration,
|
dt: Duration,
|
||||||
|
info: HudInfo,
|
||||||
) -> Vec<Event> {
|
) -> Vec<Event> {
|
||||||
let mut events = std::mem::replace(&mut self.events, Vec::new());
|
let mut events = std::mem::replace(&mut self.events, Vec::new());
|
||||||
let (ref mut ui_widgets, ref mut tooltip_manager) = self.ui.set_widgets();
|
let (ref mut ui_widgets, ref mut tooltip_manager) = self.ui.set_widgets();
|
||||||
@ -602,7 +610,14 @@ impl Hud {
|
|||||||
.set(self.ids.death_bg, ui_widgets);
|
.set(self.ids.death_bg, ui_widgets);
|
||||||
}
|
}
|
||||||
// Crosshair
|
// Crosshair
|
||||||
if !self.show.help && !stats.is_dead {
|
let show_crosshair = (info.is_aiming || info.is_first_person) && !stats.is_dead;
|
||||||
|
self.crosshair_opacity = Lerp::lerp(
|
||||||
|
self.crosshair_opacity,
|
||||||
|
if show_crosshair { 1.0 } else { 0.0 },
|
||||||
|
5.0 * dt.as_secs_f32(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if !self.show.help {
|
||||||
Image::new(
|
Image::new(
|
||||||
// TODO: Do we want to match on this every frame?
|
// TODO: Do we want to match on this every frame?
|
||||||
match global_state.settings.gameplay.crosshair_type {
|
match global_state.settings.gameplay.crosshair_type {
|
||||||
@ -617,7 +632,7 @@ impl Hud {
|
|||||||
1.0,
|
1.0,
|
||||||
1.0,
|
1.0,
|
||||||
1.0,
|
1.0,
|
||||||
global_state.settings.gameplay.crosshair_transp,
|
self.crosshair_opacity * global_state.settings.gameplay.crosshair_transp,
|
||||||
)))
|
)))
|
||||||
.set(self.ids.crosshair_outer, ui_widgets);
|
.set(self.ids.crosshair_outer, ui_widgets);
|
||||||
Image::new(self.imgs.crosshair_inner)
|
Image::new(self.imgs.crosshair_inner)
|
||||||
@ -2330,6 +2345,7 @@ impl Hud {
|
|||||||
debug_info: DebugInfo,
|
debug_info: DebugInfo,
|
||||||
camera: &Camera,
|
camera: &Camera,
|
||||||
dt: Duration,
|
dt: Duration,
|
||||||
|
info: HudInfo,
|
||||||
) -> Vec<Event> {
|
) -> Vec<Event> {
|
||||||
// conrod eats tabs. Un-eat a tabstop so tab completion can work
|
// conrod eats tabs. Un-eat a tabstop so tab completion can work
|
||||||
if self.ui.ui.global_input().events().any(|event| {
|
if self.ui.ui.global_input().events().any(|event| {
|
||||||
@ -2355,7 +2371,7 @@ impl Hud {
|
|||||||
if let Some(maybe_id) = self.to_focus.take() {
|
if let Some(maybe_id) = self.to_focus.take() {
|
||||||
self.ui.focus_widget(maybe_id);
|
self.ui.focus_widget(maybe_id);
|
||||||
}
|
}
|
||||||
let events = self.update_layout(client, global_state, debug_info, dt);
|
let events = self.update_layout(client, global_state, debug_info, dt, info);
|
||||||
let camera::Dependents {
|
let camera::Dependents {
|
||||||
view_mat, proj_mat, ..
|
view_mat, proj_mat, ..
|
||||||
} = camera.dependents();
|
} = camera.dependents();
|
||||||
|
@ -168,9 +168,10 @@ impl Camera {
|
|||||||
pub fn zoom_switch(&mut self, delta: f32) {
|
pub fn zoom_switch(&mut self, delta: f32) {
|
||||||
if delta > 0_f32 || self.mode != CameraMode::FirstPerson {
|
if delta > 0_f32 || self.mode != CameraMode::FirstPerson {
|
||||||
let t = self.tgt_dist + delta;
|
let t = self.tgt_dist + delta;
|
||||||
|
const MIN_THIRD_PERSON: f32 = 2.35;
|
||||||
match self.mode {
|
match self.mode {
|
||||||
CameraMode::ThirdPerson => {
|
CameraMode::ThirdPerson => {
|
||||||
if t < 1_f32 {
|
if t < MIN_THIRD_PERSON {
|
||||||
self.set_mode(CameraMode::FirstPerson);
|
self.set_mode(CameraMode::FirstPerson);
|
||||||
} else {
|
} else {
|
||||||
self.tgt_dist = t;
|
self.tgt_dist = t;
|
||||||
@ -178,16 +179,16 @@ impl Camera {
|
|||||||
},
|
},
|
||||||
CameraMode::FirstPerson => {
|
CameraMode::FirstPerson => {
|
||||||
self.set_mode(CameraMode::ThirdPerson);
|
self.set_mode(CameraMode::ThirdPerson);
|
||||||
self.tgt_dist = 1_f32;
|
self.tgt_dist = MIN_THIRD_PERSON;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the distance of the camera from the target
|
/// Get the distance of the camera from the focus
|
||||||
pub fn get_distance(&self) -> f32 { self.tgt_dist }
|
pub fn get_distance(&self) -> f32 { self.dist }
|
||||||
|
|
||||||
/// Set the distance of the camera from the target (i.e., zoom).
|
/// Set the distance of the camera from the focus (i.e., zoom).
|
||||||
pub fn set_distance(&mut self, dist: f32) { self.tgt_dist = dist; }
|
pub fn set_distance(&mut self, dist: f32) { self.tgt_dist = dist; }
|
||||||
|
|
||||||
pub fn update(&mut self, time: f64, dt: f32, smoothing_enabled: bool) {
|
pub fn update(&mut self, time: f64, dt: f32, smoothing_enabled: bool) {
|
||||||
@ -197,16 +198,33 @@ impl Camera {
|
|||||||
self.dist = f32::lerp(
|
self.dist = f32::lerp(
|
||||||
self.dist,
|
self.dist,
|
||||||
self.tgt_dist,
|
self.tgt_dist,
|
||||||
(delta as f32) / self.interp_time(),
|
0.65 * (delta as f32) / self.interp_time(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.focus - self.tgt_focus).magnitude() > 0.01 {
|
if (self.focus - self.tgt_focus).magnitude_squared() > 0.001 {
|
||||||
self.focus = Vec3::lerp(
|
let lerped_focus = Lerp::lerp(
|
||||||
self.focus,
|
self.focus,
|
||||||
self.tgt_focus,
|
self.tgt_focus,
|
||||||
(delta as f32) / self.interp_time(),
|
(delta as f32) / self.interp_time()
|
||||||
|
* if matches!(self.mode, CameraMode::FirstPerson) {
|
||||||
|
2.0
|
||||||
|
} else {
|
||||||
|
1.0
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Snap when close enough in x/y, but lerp otherwise
|
||||||
|
if (self.focus.xy() - self.tgt_focus.xy()).magnitude_squared() > 2.0f32.powf(2.0) {
|
||||||
|
self.focus.x = lerped_focus.x;
|
||||||
|
self.focus.y = lerped_focus.y;
|
||||||
|
} else {
|
||||||
|
self.focus.x = self.tgt_focus.x;
|
||||||
|
self.focus.y = self.tgt_focus.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always lerp in z
|
||||||
|
self.focus.z = lerped_focus.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
let lerp_angle = |a: f32, b: f32, rate: f32| {
|
let lerp_angle = |a: f32, b: f32, rate: f32| {
|
||||||
@ -280,5 +298,13 @@ impl Camera {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the mode of the camera
|
/// Get the mode of the camera
|
||||||
pub fn get_mode(&self) -> CameraMode { self.mode }
|
pub fn get_mode(&self) -> CameraMode {
|
||||||
|
// Perfom a bit of a trick... don't report first-person until the camera has
|
||||||
|
// lerped close enough to the player.
|
||||||
|
match self.mode {
|
||||||
|
CameraMode::FirstPerson if self.dist < 0.5 => CameraMode::FirstPerson,
|
||||||
|
CameraMode::FirstPerson => CameraMode::ThirdPerson,
|
||||||
|
mode => mode,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,7 @@ pub struct SceneData<'a> {
|
|||||||
pub mouse_smoothing: bool,
|
pub mouse_smoothing: bool,
|
||||||
pub sprite_render_distance: f32,
|
pub sprite_render_distance: f32,
|
||||||
pub figure_lod_render_distance: f32,
|
pub figure_lod_render_distance: f32,
|
||||||
|
pub is_aiming: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Scene {
|
impl Scene {
|
||||||
@ -198,7 +199,8 @@ impl Scene {
|
|||||||
let is_running = ecs
|
let is_running = ecs
|
||||||
.read_storage::<comp::Vel>()
|
.read_storage::<comp::Vel>()
|
||||||
.get(scene_data.player_entity)
|
.get(scene_data.player_entity)
|
||||||
.map(|v| v.0.magnitude_squared() > RUNNING_THRESHOLD.powi(2));
|
.map(|v| v.0.magnitude_squared() > RUNNING_THRESHOLD.powi(2))
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
let on_ground = ecs
|
let on_ground = ecs
|
||||||
.read_storage::<comp::PhysicsState>()
|
.read_storage::<comp::PhysicsState>()
|
||||||
@ -229,18 +231,18 @@ impl Scene {
|
|||||||
CameraMode::FirstPerson => {
|
CameraMode::FirstPerson => {
|
||||||
if player_rolling {
|
if player_rolling {
|
||||||
player_scale * 0.8
|
player_scale * 0.8
|
||||||
} else if is_running.unwrap_or(false) && on_ground.unwrap_or(false) {
|
} else if is_running && on_ground.unwrap_or(false) {
|
||||||
player_scale * 1.6 + (scene_data.state.get_time() as f32 * 17.0).sin() * 0.05
|
player_scale * 1.65 + (scene_data.state.get_time() as f32 * 17.0).sin() * 0.05
|
||||||
} else {
|
} else {
|
||||||
player_scale * 1.6
|
player_scale * 1.65
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
CameraMode::ThirdPerson => 1.2,
|
CameraMode::ThirdPerson if scene_data.is_aiming => player_scale * 2.1,
|
||||||
|
CameraMode::ThirdPerson => player_scale * 1.65,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.camera.set_focus_pos(
|
self.camera
|
||||||
player_pos + Vec3::unit_z() * (up + dist * 0.15 - tilt.min(0.0) * dist * 0.4),
|
.set_focus_pos(player_pos + Vec3::unit_z() * (up - tilt.min(0.0).sin() * dist * 0.6));
|
||||||
);
|
|
||||||
|
|
||||||
// Tick camera for interpolation.
|
// Tick camera for interpolation.
|
||||||
self.camera.update(
|
self.camera.update(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
ecs::MyEntity,
|
ecs::MyEntity,
|
||||||
hud::{DebugInfo, Event as HudEvent, Hud, PressBehavior},
|
hud::{DebugInfo, Event as HudEvent, Hud, HudInfo, PressBehavior},
|
||||||
i18n::{i18n_asset_key, VoxygenLocalization},
|
i18n::{i18n_asset_key, VoxygenLocalization},
|
||||||
key_state::KeyState,
|
key_state::KeyState,
|
||||||
menu::char_selection::CharSelectionState,
|
menu::char_selection::CharSelectionState,
|
||||||
@ -166,6 +166,25 @@ impl PlayState for SessionState {
|
|||||||
_ => cam_pos, // Should never happen, but a safe fallback
|
_ => cam_pos, // Should never happen, but a safe fallback
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let (is_aiming, aim_dir_offset) = {
|
||||||
|
let client = self.client.borrow();
|
||||||
|
let is_aiming = client
|
||||||
|
.state()
|
||||||
|
.read_storage::<comp::CharacterState>()
|
||||||
|
.get(client.entity())
|
||||||
|
.map(|cs| cs.is_aimed())
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
(
|
||||||
|
is_aiming,
|
||||||
|
if is_aiming {
|
||||||
|
Vec3::unit_z() * 0.025
|
||||||
|
} else {
|
||||||
|
Vec3::zero()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let cam_dir: Vec3<f32> = Vec3::from(view_mat.inverted() * -Vec4::unit_z());
|
let cam_dir: Vec3<f32> = Vec3::from(view_mat.inverted() * -Vec4::unit_z());
|
||||||
|
|
||||||
// Check to see whether we're aiming at anything
|
// Check to see whether we're aiming at anything
|
||||||
@ -435,7 +454,7 @@ impl PlayState for SessionState {
|
|||||||
|
|
||||||
if !free_look {
|
if !free_look {
|
||||||
ori = self.scene.camera().get_orientation();
|
ori = self.scene.camera().get_orientation();
|
||||||
self.inputs.look_dir = Dir::from_unnormalized(cam_dir).unwrap();
|
self.inputs.look_dir = Dir::from_unnormalized(cam_dir + aim_dir_offset).unwrap();
|
||||||
}
|
}
|
||||||
// Calculate the movement input vector of the player from the current key
|
// Calculate the movement input vector of the player from the current key
|
||||||
// presses and the camera direction.
|
// presses and the camera direction.
|
||||||
@ -511,6 +530,13 @@ impl PlayState for SessionState {
|
|||||||
},
|
},
|
||||||
&self.scene.camera(),
|
&self.scene.camera(),
|
||||||
clock.get_last_delta(),
|
clock.get_last_delta(),
|
||||||
|
HudInfo {
|
||||||
|
is_aiming,
|
||||||
|
is_first_person: matches!(
|
||||||
|
self.scene.camera().get_mode(),
|
||||||
|
camera::CameraMode::FirstPerson
|
||||||
|
),
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Look for changes in the localization files
|
// Look for changes in the localization files
|
||||||
@ -737,6 +763,7 @@ impl PlayState for SessionState {
|
|||||||
.graphics
|
.graphics
|
||||||
.figure_lod_render_distance
|
.figure_lod_render_distance
|
||||||
as f32,
|
as f32,
|
||||||
|
is_aiming,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Runs if either in a multiplayer server or the singleplayer server is unpaused
|
// Runs if either in a multiplayer server or the singleplayer server is unpaused
|
||||||
|
Loading…
Reference in New Issue
Block a user