diff --git a/client/src/lib.rs b/client/src/lib.rs index 1f20cc1227..1a360460c4 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -69,7 +69,7 @@ pub struct Client { entity: EcsEntity, view_distance: Option, - loaded_distance: Option, + loaded_distance: f32, pending_chunks: HashMap, Instant>, } @@ -153,7 +153,7 @@ impl Client { state, entity, view_distance, - loaded_distance: None, + loaded_distance: 0.0, pending_chunks: HashMap::new(), }) @@ -260,7 +260,7 @@ impl Client { self.view_distance } - pub fn loaded_distance(&self) -> Option { + pub fn loaded_distance(&self) -> f32 { self.loaded_distance } @@ -410,8 +410,9 @@ impl Client { } // Request chunks from the server. - let mut all_loaded = true; - 'outer: for dist in 0..(view_distance as i32) + 1 { + self.loaded_distance = ((view_distance * TerrainChunkSize::RECT_SIZE.x) as f32).powi(2); + // +1 so we can find a chunk that's outside the vd for better fog + for dist in 0..view_distance as i32 + 1 { // Only iterate through chunks that need to be loaded for circular vd // The (dist - 2) explained: // -0.5 because a chunk is visible if its corner is within the view distance @@ -428,6 +429,7 @@ impl Client { dist }; + let mut skip_mode = false; for i in -top..top + 1 { let keys = [ chunk_pos + Vec2::new(dist, i), @@ -438,25 +440,32 @@ impl Client { for key in keys.iter() { if self.state.terrain().get_key(*key).is_none() { - if !self.pending_chunks.contains_key(key) { + if !skip_mode && !self.pending_chunks.contains_key(key) { if self.pending_chunks.len() < 4 { self.postbox .send_message(ClientMsg::TerrainChunkRequest { key: *key }); self.pending_chunks.insert(*key, Instant::now()); } else { - break 'outer; + skip_mode = true; } } - all_loaded = false; + let dist_to_player = + (self.state.terrain().key_pos(*key).map(|x| x as f32) + + TerrainChunkSize::RECT_SIZE.map(|x| x as f32) / 2.0) + .distance_squared(pos.0.into()); + + if dist_to_player < self.loaded_distance { + self.loaded_distance = dist_to_player; + } } } } - - if all_loaded { - self.loaded_distance = Some((dist - 1).max(0) as u32); - } } + self.loaded_distance = self.loaded_distance.sqrt() + - ((TerrainChunkSize::RECT_SIZE.x as f32 / 2.0).powi(2) + + (TerrainChunkSize::RECT_SIZE.y as f32 / 2.0).powi(2)) + .sqrt(); // If chunks are taking too long, assume they're no longer pending. let now = Instant::now(); diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs index 42bf449c1f..dfaa32e2ed 100644 --- a/voxygen/src/hud/mod.rs +++ b/voxygen/src/hud/mod.rs @@ -1433,8 +1433,9 @@ impl Hud { .set(self.ids.velocity, ui_widgets); // Loaded distance Text::new(&format!( - "View distance: {} chunks", - client.loaded_distance().unwrap_or(0) + "View distance: {:.2} blocks ({:.2} chunks)", + client.loaded_distance(), + client.loaded_distance() / TerrainChunk::RECT_SIZE.x as f32, )) .color(TEXT_COLOR) .down_from(self.ids.velocity, 5.0) diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 9be5180727..e571e175c7 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -208,7 +208,7 @@ impl Scene { let (view_mat, proj_mat, cam_pos) = self.camera.compute_dependents(client); // Update chunk loaded distance smoothly for nice shader fog - let loaded_distance = client.loaded_distance().unwrap_or(0) as f32 * 32.0; // TODO: No magic! + let loaded_distance = client.loaded_distance(); self.loaded_distance = (0.98 * self.loaded_distance + 0.02 * loaded_distance).max(0.01); // Update light constants