From b352ef5d5546be4b13bcf7ccaed8709379da1432 Mon Sep 17 00:00:00 2001 From: Joshua Barretto Date: Sat, 14 Nov 2020 16:03:01 +0000 Subject: [PATCH] Terrain pop-in, fixed agent pathfinding in water --- assets/voxygen/shaders/terrain-frag.glsl | 2 + assets/voxygen/shaders/terrain-vert.glsl | 2 +- common/src/path.rs | 16 ++++---- common/src/sys/agent.rs | 7 +++- common/src/sys/phys.rs | 2 +- voxygen/src/scene/terrain.rs | 48 +++++++++++++----------- 6 files changed, 46 insertions(+), 31 deletions(-) diff --git a/assets/voxygen/shaders/terrain-frag.glsl b/assets/voxygen/shaders/terrain-frag.glsl index 6a66c431bf..b16431be7c 100644 --- a/assets/voxygen/shaders/terrain-frag.glsl +++ b/assets/voxygen/shaders/terrain-frag.glsl @@ -61,10 +61,12 @@ out vec4 tgt_color; #include void main() { + /* float nz = abs(hash(vec4(floor((f_pos + focus_off.xyz) * 5.0), 0))); if (nz > (tick.x - load_time) / 0.5 || distance(focus_pos.xy, f_pos.xy) / view_distance.x + nz * 0.1 > 1.0) { discard; } + */ // discard; // vec4 f_col_light = textureGrad(t_col_light, f_uv_pos / texSize, 0.25, 0.25); diff --git a/assets/voxygen/shaders/terrain-vert.glsl b/assets/voxygen/shaders/terrain-vert.glsl index 421568dd53..3f318ca007 100644 --- a/assets/voxygen/shaders/terrain-vert.glsl +++ b/assets/voxygen/shaders/terrain-vert.glsl @@ -75,7 +75,7 @@ void main() { f_pos = f_chunk_pos + model_offs - focus_off.xyz; f_load_time = load_time; - //f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0)); + f_pos.z -= 250.0 * (1.0 - min(1.0001 - 0.02 / pow(tick.x - load_time, 10.0), 1.0)); // f_pos.z -= min(32.0, 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0)); // vec3 light_col = vec3( diff --git a/common/src/path.rs b/common/src/path.rs index 6f26190773..10f6fbcdba 100644 --- a/common/src/path.rs +++ b/common/src/path.rs @@ -65,6 +65,8 @@ pub struct TraversalConfig { pub slow_factor: f32, /// Whether the agent is currently on the ground. pub on_ground: bool, + /// Whether the agent is currently in water. + pub in_liquid: bool, /// The distance to the target below which it is considered reached. pub min_tgt_dist: f32, } @@ -127,7 +129,7 @@ impl Route { // Determine whether we're close enough to the next to to consider it completed let dist_sqrd = pos.xy().distance_squared(closest_tgt.xy()); if dist_sqrd < traversal_cfg.node_tolerance.powf(2.0) * if be_precise { 0.25 } else { 1.0 } - && (pos.z - closest_tgt.z > 1.2 || (pos.z - closest_tgt.z > -0.2 && traversal_cfg.on_ground)) + && (pos.z - closest_tgt.z > 1.2 || (pos.z - closest_tgt.z > -0.2 && (traversal_cfg.on_ground || traversal_cfg.in_liquid))) && (pos.z - closest_tgt.z < 1.2 || (pos.z - closest_tgt.z < 2.9 && vel.z < -0.05)) && vel.z <= 0.0 // Only consider the node reached if there's nothing solid between us and it @@ -434,15 +436,15 @@ where V: BaseVol + ReadVol, { vol.get(pos - Vec3::new(0, 0, 1)) - .map(|b| b.is_solid() && b.solid_height() == 1.0) + .map(|b| b.is_filled()) .unwrap_or(false) && vol .get(pos + Vec3::new(0, 0, 0)) - .map(|b| !b.is_solid()) + .map(|b| !b.is_filled()) .unwrap_or(true) && vol .get(pos + Vec3::new(0, 0, 1)) - .map(|b| !b.is_solid()) + .map(|b| !b.is_filled()) .unwrap_or(true) } @@ -531,17 +533,17 @@ where && ((dir.z < 1 || vol .get(pos + Vec3::unit_z() * 2) - .map(|b| !b.is_solid()) + .map(|b| !b.is_filled()) .unwrap_or(true)) && (dir.z < 2 || vol .get(pos + Vec3::unit_z() * 3) - .map(|b| !b.is_solid()) + .map(|b| !b.is_filled()) .unwrap_or(true)) && (dir.z >= 0 || vol .get(pos + *dir + Vec3::unit_z() * 2) - .map(|b| !b.is_solid()) + .map(|b| !b.is_filled()) .unwrap_or(true))) }) .map(move |(pos, dir)| pos + dir) diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs index 67e9256de5..bf6758ade9 100644 --- a/common/src/sys/agent.rs +++ b/common/src/sys/agent.rs @@ -223,6 +223,7 @@ impl<'a> System<'a> for Sys { node_tolerance, slow_factor, on_ground: physics_state.on_ground, + in_liquid: physics_state.in_liquid.is_some(), min_tgt_dist: 1.25, }, ) { @@ -232,7 +233,8 @@ impl<'a> System<'a> for Sys { .unwrap_or(Vec2::zero()) * speed.min(agent.rtsim_controller.speed_factor); inputs.jump.set_state(bearing.z > 1.5); - inputs.climb = Some(comp::Climb::Up).filter(|_| bearing.z > 1.5); + inputs.climb = Some(comp::Climb::Up) + .filter(|_| bearing.z > 1.5 || physics_state.in_liquid.is_some()); inputs.move_z = bearing.z; } } else { @@ -303,6 +305,7 @@ impl<'a> System<'a> for Sys { node_tolerance, slow_factor, on_ground: physics_state.on_ground, + in_liquid: physics_state.in_liquid.is_some(), min_tgt_dist: AVG_FOLLOW_DIST, }, ) { @@ -429,6 +432,7 @@ impl<'a> System<'a> for Sys { node_tolerance, slow_factor, on_ground: physics_state.on_ground, + in_liquid: physics_state.in_liquid.is_some(), min_tgt_dist: 1.25, }, ) { @@ -590,6 +594,7 @@ impl<'a> System<'a> for Sys { node_tolerance, slow_factor, on_ground: physics_state.on_ground, + in_liquid: physics_state.in_liquid.is_some(), min_tgt_dist: 1.25, }, ) { diff --git a/common/src/sys/phys.rs b/common/src/sys/phys.rs index 704c39339d..ef83c3e940 100644 --- a/common/src/sys/phys.rs +++ b/common/src/sys/phys.rs @@ -28,7 +28,7 @@ pub const BOUYANCY: f32 = 1.0; // 60. pub const FRIC_GROUND: f32 = 0.15; pub const FRIC_AIR: f32 = 0.0125; -pub const FRIC_FLUID: f32 = 0.2; +pub const FRIC_FLUID: f32 = 0.4; // Integrates forces, calculates the new velocity based off of the old velocity // dt = delta time diff --git a/voxygen/src/scene/terrain.rs b/voxygen/src/scene/terrain.rs index 5f7af950e0..398b864e15 100644 --- a/voxygen/src/scene/terrain.rs +++ b/voxygen/src/scene/terrain.rs @@ -36,11 +36,21 @@ use vek::*; const SPRITE_SCALE: Vec3 = Vec3::new(1.0 / 11.0, 1.0 / 11.0, 1.0 / 11.0); -#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] -enum Visibility { - OutOfRange = 0, - InRange = 1, - Visible = 2, +#[derive(Clone, Copy, Debug)] +struct Visibility { + in_range: bool, + in_frustum: bool, +} + +impl Visibility { + /// Should the chunk actually get rendered? + fn is_visible(&self) -> bool { + // Currently, we don't take into account in_range to allow all chunks to do pop-in. + // This isn't really a problem because we no longer have VD mist or anything like that. + // Also, we don't load chunks outside of the VD anyway so this literally just controls + // which chunks get actually rendered. + /*self.in_range &&*/ self.in_frustum + } } pub struct TerrainChunkData { @@ -237,7 +247,7 @@ pub struct Terrain { impl TerrainChunkData { pub fn can_shadow_sun(&self) -> bool { - self.visible == Visibility::Visible || self.can_shadow_sun + self.visible.is_visible() || self.can_shadow_sun } } @@ -751,7 +761,10 @@ impl Terrain { load_time, }]) .expect("Failed to upload chunk locals to the GPU!"), - visible: Visibility::OutOfRange, + visible: Visibility { + in_range: false, + in_frustum: false, + }, can_shadow_point: false, can_shadow_sun: false, blocks_of_interest: response.blocks_of_interest, @@ -793,10 +806,7 @@ impl Terrain { let distance_2 = Vec2::::from(focus_pos).distance_squared(nearest_in_chunk); let in_range = distance_2 < loaded_distance.powf(2.0); - if !in_range { - chunk.visible = Visibility::OutOfRange; - continue; - } + chunk.visible.in_range = in_range; // Ensure the chunk is within the view frustum let chunk_min = [chunk_pos.x, chunk_pos.y, chunk.z_bounds.0]; @@ -810,11 +820,7 @@ impl Terrain { .coherent_test_against_frustum(&frustum, chunk.frustum_last_plane_index); chunk.frustum_last_plane_index = last_plane_index; - chunk.visible = if in_frustum { - Visibility::Visible - } else { - Visibility::InRange - }; + chunk.visible.in_frustum = in_frustum; let chunk_box = Aabb { min: Vec3::from(chunk_min), max: Vec3::from(chunk_max), @@ -910,7 +916,7 @@ impl Terrain { // NOTE: We deliberately avoid doing this computation for chunks we already know // are visible, since by definition they'll always intersect the visible view // frustum. - .filter(|chunk| chunk.1.visible <= Visibility::InRange) + .filter(|chunk| !chunk.1.visible.in_frustum) .for_each(|(&pos, chunk)| { chunk.can_shadow_sun = can_shadow_sun(pos, chunk); }); @@ -958,7 +964,7 @@ impl Terrain { pub fn visible_chunk_count(&self) -> usize { self.chunks .iter() - .filter(|(_, c)| c.visible == Visibility::Visible) + .filter(|(_, c)| c.visible.is_visible()) .count() } @@ -1046,7 +1052,7 @@ impl Terrain { .take(self.chunks.len()); for (_, chunk) in chunk_iter { - if chunk.visible == Visibility::Visible { + if chunk.visible.is_visible() { renderer.render_terrain_chunk( &chunk.opaque_model, &self.col_lights, @@ -1086,7 +1092,7 @@ impl Terrain { let chunk_size = V::RECT_SIZE.map(|e| e as f32); let chunk_mag = (chunk_size * (f32::consts::SQRT_2 * 0.5)).magnitude_squared(); for (pos, chunk) in chunk_iter.clone() { - if chunk.visible == Visibility::Visible { + if chunk.visible.is_visible() { let sprite_low_detail_distance = sprite_render_distance * 0.75; let sprite_mid_detail_distance = sprite_render_distance * 0.5; let sprite_hid_detail_distance = sprite_render_distance * 0.35; @@ -1146,7 +1152,7 @@ impl Terrain { // Translucent chunk_iter .clone() - .filter(|(_, chunk)| chunk.visible == Visibility::Visible) + .filter(|(_, chunk)| chunk.visible.is_visible()) .filter_map(|(_, chunk)| { chunk .fluid_model