Terrain pop-in, fixed agent pathfinding in water

This commit is contained in:
Joshua Barretto 2020-11-14 16:03:01 +00:00
parent 717fd88565
commit b352ef5d55
6 changed files with 46 additions and 31 deletions

View File

@ -61,10 +61,12 @@ out vec4 tgt_color;
#include <lod.glsl>
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);

View File

@ -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(

View File

@ -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<Vox = Block> + 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)

View File

@ -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,
},
) {

View File

@ -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

View File

@ -36,11 +36,21 @@ use vek::*;
const SPRITE_SCALE: Vec3<f32> = 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<V: RectRasterableVol> {
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<V: RectRasterableVol> Terrain<V> {
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<V: RectRasterableVol> Terrain<V> {
let distance_2 = Vec2::<f32>::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<V: RectRasterableVol> Terrain<V> {
.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<V: RectRasterableVol> Terrain<V> {
// 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<V: RectRasterableVol> Terrain<V> {
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<V: RectRasterableVol> Terrain<V> {
.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<V: RectRasterableVol> Terrain<V> {
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<V: RectRasterableVol> Terrain<V> {
// Translucent
chunk_iter
.clone()
.filter(|(_, chunk)| chunk.visible == Visibility::Visible)
.filter(|(_, chunk)| chunk.visible.is_visible())
.filter_map(|(_, chunk)| {
chunk
.fluid_model