Remove close-up camera jitter

This commit is contained in:
Joshua Barretto 2022-10-22 13:24:43 +01:00
parent ae66432a1e
commit 0a5e257b77
4 changed files with 38 additions and 21 deletions

View File

@ -392,11 +392,20 @@ pub fn generate_mesh<'a>(
|atlas_pos, pos, norm, meta| TerrainVertex::new(atlas_pos, pos + mesh_delta, norm, meta);
let create_transparent = |_atlas_pos, pos: Vec3<f32>, norm| {
let key = vol.pos_key(range.min + pos.as_());
let v00 = vol.get_key(key + Vec2::new(0, 0)).map_or(Vec3::zero(), |c| c.meta().river_velocity());
let v10 = vol.get_key(key + Vec2::new(1, 0)).map_or(Vec3::zero(), |c| c.meta().river_velocity());
let v01 = vol.get_key(key + Vec2::new(0, 1)).map_or(Vec3::zero(), |c| c.meta().river_velocity());
let v11 = vol.get_key(key + Vec2::new(1, 1)).map_or(Vec3::zero(), |c| c.meta().river_velocity());
let factor = (range.min + pos.as_()).map(|e| e as f32) / TerrainChunk::RECT_SIZE.map(|e| e as f32);
let v00 = vol
.get_key(key + Vec2::new(0, 0))
.map_or(Vec3::zero(), |c| c.meta().river_velocity());
let v10 = vol
.get_key(key + Vec2::new(1, 0))
.map_or(Vec3::zero(), |c| c.meta().river_velocity());
let v01 = vol
.get_key(key + Vec2::new(0, 1))
.map_or(Vec3::zero(), |c| c.meta().river_velocity());
let v11 = vol
.get_key(key + Vec2::new(1, 1))
.map_or(Vec3::zero(), |c| c.meta().river_velocity());
let factor =
(range.min + pos.as_()).map(|e| e as f32) / TerrainChunk::RECT_SIZE.map(|e| e as f32);
let vel = Lerp::lerp(
Lerp::lerp(v00, v10, factor.x.rem_euclid(1.0)),
Lerp::lerp(v01, v11, factor.x.rem_euclid(1.0)),

View File

@ -29,7 +29,9 @@ impl Vertex {
| (((pos.z + EXTRA_NEG_Z).max(0.0).min((1 << 17) as f32) as u32) & 0x1FFFF) << 12
| (norm_bits & 0x7) << 29,
vel: river_velocity
.map2(Vec2::new(0, 16), |e, off| (((e * 1000.0 + 32768.9) as u16 as u32) << off))
.map2(Vec2::new(0, 16), |e, off| {
(((e * 1000.0 + 32768.9) as u16 as u32) << off)
})
.reduce_bitor(),
}
}

View File

@ -1,6 +1,6 @@
use common::{terrain::TerrainGrid, vol::ReadVol};
use common_base::span;
use core::{f32::consts::PI, fmt::Debug};
use core::{f32::consts::PI, fmt::Debug, ops::Range};
use num::traits::{real::Real, FloatConst};
use treeculler::Frustum;
use vek::*;
@ -12,7 +12,7 @@ const FIRST_PERSON_INTERP_TIME: f32 = 0.1;
const THIRD_PERSON_INTERP_TIME: f32 = 0.1;
const FREEFLY_INTERP_TIME: f32 = 0.0;
const LERP_ORI_RATE: f32 = 15.0;
const CLIPPING_MODE_DISTANCE: f32 = 20.0;
const CLIPPING_MODE_DISTANCE: Range<f32> = 2.0..20.0;
pub const MIN_ZOOM: f32 = 0.1;
// Possible TODO: Add more modes
@ -368,7 +368,7 @@ impl Camera {
) {
span!(_guard, "compute_dependents", "Camera::compute_dependents");
// TODO: More intelligent function to decide on which strategy to use
if self.tgt_dist < CLIPPING_MODE_DISTANCE {
if self.tgt_dist < CLIPPING_MODE_DISTANCE.end {
self.compute_dependents_near(terrain, is_transparent)
} else {
self.compute_dependents_far(terrain, is_transparent)
@ -425,18 +425,23 @@ impl Camera {
.unwrap_or(0.0)
};
if self.dist >= dist {
self.dist = dist;
}
// Recompute only if needed
if (dist - self.tgt_dist).abs() > f32::EPSILON {
let dependents = self.compute_dependents_helper(dist);
self.frustum = self.compute_frustum(&dependents);
self.dependents = dependents;
// If the camera ends up being too close to the focus point, switch policies.
if dist < CLIPPING_MODE_DISTANCE.start {
self.compute_dependents_far(terrain, is_transparent);
} else {
self.dependents = local_dependents;
self.frustum = frustum;
if self.dist >= dist {
self.dist = dist;
}
// Recompute only if needed
if (dist - self.tgt_dist).abs() > f32::EPSILON {
let dependents = self.compute_dependents_helper(dist);
self.frustum = self.compute_frustum(&dependents);
self.dependents = dependents;
} else {
self.dependents = local_dependents;
self.frustum = frustum;
}
}
}

View File

@ -278,7 +278,8 @@ fn mesh_worker(
for y in 0..TerrainChunk::RECT_SIZE.y as i32 {
for z in z_bounds.0 as i32..z_bounds.1 as i32 + 1 {
let rel_pos = Vec3::new(x, y, z);
let wpos = Vec3::from(pos * TerrainChunk::RECT_SIZE.map(|e: u32| e as i32)) + rel_pos;
let wpos = Vec3::from(pos * TerrainChunk::RECT_SIZE.map(|e: u32| e as i32))
+ rel_pos;
let block = if let Ok(block) = volume.get(wpos) {
block