mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Limit the tiles in view (#147)
* Limit the tiles in view by DEFAULT_TILE_VIEW_SIZE
This commit is contained in:
parent
85fea15a7f
commit
d69f81f37f
@ -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)
|
||||
}
|
||||
|
||||
@ -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(),
|
||||
)
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user