Limit the tiles in view (#147)

* Limit the tiles in view by DEFAULT_TILE_VIEW_SIZE
This commit is contained in:
Max Ammann 2022-07-17 15:52:35 +02:00 committed by GitHub
parent 85fea15a7f
commit d69f81f37f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 48 additions and 44 deletions

View File

@ -1,4 +1,4 @@
use crate::coords::{LatLon, WorldCoords, Zoom, ZoomLevel, TILE_SIZE};
use crate::coords::{LatLon, ViewRegion, WorldCoords, Zoom, ZoomLevel, TILE_SIZE};
use crate::io::tile_repository::TileRepository;
use crate::render::camera::{Camera, Perspective, ViewProjection};
use crate::util::ChangeObserver;
@ -42,6 +42,14 @@ impl ViewState {
}
}
pub fn create_view_region(&self) -> Option<ViewRegion> {
self.camera
.view_region_bounding_box(&self.view_projection().invert())
.map(|bounding_box| {
ViewRegion::new(bounding_box, 0, 32, *self.zoom, self.visible_level())
})
}
pub fn view_projection(&self) -> ViewProjection {
self.camera.calc_view_proj(&self.perspective)
}

View File

@ -540,12 +540,22 @@ impl From<Point3<f64>> for WorldCoords {
pub struct ViewRegion {
min_tile: WorldTileCoords,
max_tile: WorldTileCoords,
z: ZoomLevel,
/// At which zoom level does this region exist
zoom_level: ZoomLevel,
/// Padding around this view region
padding: i32,
/// The maximum amount of tiles this view region contains
max_n_tiles: usize,
}
impl ViewRegion {
pub fn new(view_region: Aabb2<f64>, padding: i32, zoom: Zoom, z: ZoomLevel) -> Self {
pub fn new(
view_region: Aabb2<f64>,
padding: i32,
max_n_tiles: usize,
zoom: Zoom,
z: ZoomLevel,
) -> Self {
let min_world: WorldCoords = WorldCoords::at_ground(view_region.min.x, view_region.min.y);
let min_world_tile: WorldTileCoords = min_world.into_world_tile(z, zoom);
let max_world: WorldCoords = WorldCoords::at_ground(view_region.max.x, view_region.max.y);
@ -554,13 +564,14 @@ impl ViewRegion {
Self {
min_tile: min_world_tile,
max_tile: max_world_tile,
z,
zoom_level: z,
max_n_tiles,
padding,
}
}
pub fn zoom_level(&self) -> ZoomLevel {
self.z
self.zoom_level
}
pub fn is_in_view(&self, &world_coords: &WorldTileCoords) -> bool {
@ -568,16 +579,18 @@ impl ViewRegion {
&& world_coords.y <= self.max_tile.y + self.padding
&& world_coords.x >= self.min_tile.x - self.padding
&& world_coords.y >= self.min_tile.y - self.padding
&& world_coords.z == self.z
&& world_coords.z == self.zoom_level
}
pub fn iter(&self) -> impl Iterator<Item = WorldTileCoords> + '_ {
(self.min_tile.x - self.padding..self.max_tile.x + 1 + self.padding).flat_map(move |x| {
(self.min_tile.y - self.padding..self.max_tile.y + 1 + self.padding).map(move |y| {
let tile_coord: WorldTileCoords = (x, y, self.z).into();
tile_coord
(self.min_tile.x - self.padding..self.max_tile.x + 1 + self.padding)
.flat_map(move |x| {
(self.min_tile.y - self.padding..self.max_tile.y + 1 + self.padding).map(move |y| {
let tile_coord: WorldTileCoords = (x, y, self.zoom_level).into();
tile_coord
})
})
})
.take(self.max_n_tiles)
}
}
@ -696,6 +709,7 @@ mod tests {
for tile_coords in ViewRegion::new(
Aabb2::new(Point2::new(0.0, 0.0), Point2::new(2000.0, 2000.0)),
1,
32,
Zoom::default(),
ZoomLevel::default(),
)

View File

@ -33,16 +33,7 @@ impl Stage for ExtractStage {
if let (Initialized(tile_view_pattern), Initialized(buffer_pool)) =
(tile_view_pattern, &buffer_pool)
{
let visible_level = view_state.visible_level();
let view_proj = view_state.view_projection();
let view_region = view_state
.camera
.view_region_bounding_box(&view_proj.invert())
.map(|bounding_box| {
ViewRegion::new(bounding_box, 0, *view_state.zoom, visible_level)
});
let view_region = view_state.create_view_region();
if let Some(view_region) = &view_region {
let zoom = view_state.zoom();

View File

@ -8,14 +8,12 @@ use crate::render::resource::{Globals, RenderPipeline};
use crate::render::shaders;
use crate::render::shaders::{Shader, ShaderTileMetadata};
use crate::render::tile_pipeline::TilePipeline;
use crate::render::tile_view_pattern::TileViewPattern;
use crate::render::tile_view_pattern::{TileViewPattern, DEFAULT_TILE_VIEW_SIZE};
use crate::schedule::Stage;
use crate::Renderer;
use std::mem::size_of;
pub const TILE_VIEW_SIZE: wgpu::BufferAddress = 32;
#[derive(Default)]
pub struct ResourceStage;
@ -83,7 +81,8 @@ impl Stage for ResourceStage {
state.tile_view_pattern.initialize(|| {
let tile_view_buffer_desc = wgpu::BufferDescriptor {
label: Some("tile view buffer"),
size: size_of::<ShaderTileMetadata>() as wgpu::BufferAddress * TILE_VIEW_SIZE,
size: size_of::<ShaderTileMetadata>() as wgpu::BufferAddress
* DEFAULT_TILE_VIEW_SIZE,
usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
mapped_at_creation: false,
};

View File

@ -30,8 +30,6 @@ impl Stage for UploadStage {
..
}: &mut MapContext,
) {
let visible_level = view_state.visible_level();
let view_proj = view_state.view_projection();
if let Initialized(globals_bind_group) = &state.globals_bind_group {
@ -52,10 +50,7 @@ impl Stage for UploadStage {
);
}
let view_region = view_state
.camera
.view_region_bounding_box(&view_proj.invert())
.map(|bounding_box| ViewRegion::new(bounding_box, 0, *view_state.zoom, visible_level));
let view_region = view_state.create_view_region();
if let Some(view_region) = &view_region {
self.upload_tile_geometry(state, queue, tile_repository, style, view_region);

View File

@ -12,6 +12,8 @@ use std::marker::PhantomData;
use std::mem::size_of;
use std::ops::Range;
pub const DEFAULT_TILE_VIEW_SIZE: wgpu::BufferAddress = 32 * 4;
/// The tile mask pattern assigns each tile a value which can be used for stencil testing.
pub struct TileViewPattern<Q, B> {
in_view: Vec<TileInView>,
@ -159,11 +161,13 @@ impl<Q: Queue<B>, B> TileViewPattern<Q, B> {
}
}
queue.write_buffer(
&self.buffer.inner,
0,
bytemuck::cast_slice(buffer.as_slice()),
);
let raw_buffer = bytemuck::cast_slice(buffer.as_slice());
if raw_buffer.len() as wgpu::BufferAddress > self.buffer.inner_size {
/* FIXME: We need to avoid this case by either choosing a proper size
(DEFAULT_TILE_VIEW_SIZE), or resizing the buffer */
panic!("Buffer is too small to store the tile pattern!");
}
queue.write_buffer(&self.buffer.inner, 0, raw_buffer);
}
pub fn stencil_reference_value(&self, world_coords: &WorldTileCoords) -> u8 {

View File

@ -55,14 +55,7 @@ where
..
}: &mut MapContext,
) {
let visible_level = view_state.visible_level();
let view_proj = view_state.view_projection();
let view_region = view_state
.camera
.view_region_bounding_box(&view_proj.invert())
.map(|bounding_box| ViewRegion::new(bounding_box, 0, *view_state.zoom, visible_level));
let view_region = view_state.create_view_region();
if view_state.camera.did_change(0.05) || view_state.zoom.did_change(0.05) || self.try_failed
{