mirror of
https://github.com/maplibre/maplibre-rs.git
synced 2025-12-08 19:05:57 +00:00
Fix regressions from structure refactoring (#203)
* Add geometry index * Switch to info level for run config * Add setting for present_mode * Remove unused file * Adjust web to new message * Rename transferables * Remove bytemuck and add unsafe code * Add Result to return type of APCs * Add Result to Processable * Resolve unwraps * Remove unwraps and remove unused code
This commit is contained in:
parent
193b06a49d
commit
6367d3641f
2
.idea/runConfigurations/Run_demo__debug_.xml
generated
2
.idea/runConfigurations/Run_demo__debug_.xml
generated
@ -10,7 +10,7 @@
|
||||
<option name="buildTarget" value="REMOTE" />
|
||||
<option name="backtrace" value="SHORT" />
|
||||
<envs>
|
||||
<env name="RUST_LOG" value="debug" />
|
||||
<env name="RUST_LOG" value="info" />
|
||||
</envs>
|
||||
<option name="isRedirectInput" value="false" />
|
||||
<option name="redirectInputPath" value="" />
|
||||
|
||||
@ -4,6 +4,7 @@ use criterion::{criterion_group, criterion_main, Criterion};
|
||||
use maplibre::{
|
||||
benchmarking::io::static_tile_fetcher::StaticTileFetcher,
|
||||
coords::{TileCoords, ZoomLevel},
|
||||
error::Error,
|
||||
io::{
|
||||
pipeline::{PipelineContext, PipelineProcessor, Processable},
|
||||
tile_pipelines::{ParseTile, TessellateLayer},
|
||||
@ -37,10 +38,12 @@ fn parse_tile(c: &mut Criterion) {
|
||||
.sync_fetch_tile(&MUNICH_COORDS)
|
||||
.unwrap()
|
||||
.into_boxed_slice();
|
||||
ParseTile::default().process(
|
||||
(request, data),
|
||||
&mut PipelineContext::new(DummyPipelineProcessor),
|
||||
);
|
||||
ParseTile::default()
|
||||
.process(
|
||||
(request, data),
|
||||
&mut PipelineContext::new(DummyPipelineProcessor),
|
||||
)
|
||||
.unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
@ -57,17 +60,21 @@ fn tessellate_tile(c: &mut Criterion) {
|
||||
.sync_fetch_tile(&MUNICH_COORDS)
|
||||
.unwrap()
|
||||
.into_boxed_slice();
|
||||
let parsed = ParseTile::default().process(
|
||||
(request, data),
|
||||
&mut PipelineContext::new(DummyPipelineProcessor),
|
||||
);
|
||||
let parsed = ParseTile::default()
|
||||
.process(
|
||||
(request, data),
|
||||
&mut PipelineContext::new(DummyPipelineProcessor),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
c.bench_function("tessselate", |b| {
|
||||
b.iter(|| {
|
||||
TessellateLayer::default().process(
|
||||
parsed.clone(),
|
||||
&mut PipelineContext::new(DummyPipelineProcessor),
|
||||
);
|
||||
TessellateLayer::default()
|
||||
.process(
|
||||
parsed.clone(),
|
||||
&mut PipelineContext::new(DummyPipelineProcessor),
|
||||
)
|
||||
.unwrap();
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use cgmath::Vector2;
|
||||
use maplibre::world::ViewState;
|
||||
use maplibre::context::MapContext;
|
||||
use winit::event::{DeviceEvent, KeyboardInput, TouchPhase, WindowEvent};
|
||||
|
||||
use crate::input::{
|
||||
@ -126,16 +126,16 @@ impl InputController {
|
||||
}
|
||||
|
||||
pub trait UpdateState {
|
||||
fn update_state(&mut self, state: &mut ViewState, dt: Duration);
|
||||
fn update_state(&mut self, state: &mut MapContext, dt: Duration);
|
||||
}
|
||||
|
||||
impl UpdateState for InputController {
|
||||
fn update_state(&mut self, state: &mut ViewState, dt: Duration) {
|
||||
self.pan_handler.update_state(state, dt);
|
||||
self.pinch_handler.update_state(state, dt);
|
||||
self.zoom_handler.update_state(state, dt);
|
||||
self.tilt_handler.update_state(state, dt);
|
||||
self.shift_handler.update_state(state, dt);
|
||||
self.query_handler.update_state(state, dt);
|
||||
fn update_state(&mut self, map_context: &mut MapContext, dt: Duration) {
|
||||
self.pan_handler.update_state(map_context, dt);
|
||||
self.pinch_handler.update_state(map_context, dt);
|
||||
self.zoom_handler.update_state(map_context, dt);
|
||||
self.tilt_handler.update_state(map_context, dt);
|
||||
self.shift_handler.update_state(map_context, dt);
|
||||
self.query_handler.update_state(map_context, dt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use cgmath::{EuclideanSpace, Point3, Vector2, Vector3, Zero};
|
||||
use maplibre::{render::camera::Camera, world::ViewState};
|
||||
use maplibre::{context::MapContext, render::camera::Camera, world::World};
|
||||
use winit::event::{ElementState, MouseButton};
|
||||
|
||||
use super::UpdateState;
|
||||
@ -15,7 +15,14 @@ pub struct PanHandler {
|
||||
}
|
||||
|
||||
impl UpdateState for PanHandler {
|
||||
fn update_state(&mut self, state: &mut ViewState, _dt: Duration) {
|
||||
fn update_state(
|
||||
&mut self,
|
||||
MapContext {
|
||||
world: World { view_state, .. },
|
||||
..
|
||||
}: &mut MapContext,
|
||||
_dt: Duration,
|
||||
) {
|
||||
if !self.is_panning {
|
||||
return;
|
||||
}
|
||||
@ -24,7 +31,7 @@ impl UpdateState for PanHandler {
|
||||
if let (Some(window_position), Some(start_window_position)) =
|
||||
(self.window_position, self.start_window_position)
|
||||
{
|
||||
let view_proj = state.view_projection();
|
||||
let view_proj = view_state.view_projection();
|
||||
let inverted_view_proj = view_proj.invert();
|
||||
|
||||
let delta = if let (Some(start), Some(current)) = (
|
||||
@ -45,17 +52,17 @@ impl UpdateState for PanHandler {
|
||||
};
|
||||
|
||||
if self.start_camera_position.is_none() {
|
||||
self.start_camera_position = Some(state.camera().position().to_vec());
|
||||
self.start_camera_position = Some(view_state.camera().position().to_vec());
|
||||
}
|
||||
|
||||
if let Some(start_camera_position) = self.start_camera_position {
|
||||
state.camera_mut().move_to(Point3::from_vec(
|
||||
view_state.camera_mut().move_to(Point3::from_vec(
|
||||
start_camera_position + Vector3::new(delta.x, delta.y, 0.0),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.reference_camera = Some(state.camera().clone());
|
||||
self.reference_camera = Some(view_state.camera().clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use maplibre::world::ViewState;
|
||||
use maplibre::context::MapContext;
|
||||
|
||||
use super::UpdateState;
|
||||
|
||||
pub struct PinchHandler {}
|
||||
|
||||
impl UpdateState for PinchHandler {
|
||||
fn update_state(&mut self, _state: &mut ViewState, _dt: Duration) {
|
||||
fn update_state(&mut self, _map_context: &mut MapContext, _dt: Duration) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use cgmath::Vector2;
|
||||
use maplibre::world::ViewState;
|
||||
use maplibre::{
|
||||
context::MapContext, coords::WorldCoords, io::geometry_index::IndexedGeometry, world::World,
|
||||
};
|
||||
use winit::event::{ElementState, MouseButton};
|
||||
|
||||
use crate::input::UpdateState;
|
||||
@ -11,10 +13,6 @@ pub struct QueryHandler {
|
||||
clicking: bool,
|
||||
}
|
||||
|
||||
/*impl UpdateState for QueryHandler {
|
||||
|
||||
}*/
|
||||
|
||||
impl QueryHandler {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
@ -57,42 +55,59 @@ impl QueryHandler {
|
||||
}
|
||||
|
||||
impl UpdateState for QueryHandler {
|
||||
fn update_state(&mut self, state: &mut ViewState, _dt: Duration) {
|
||||
fn update_state(
|
||||
&mut self,
|
||||
MapContext {
|
||||
world:
|
||||
World {
|
||||
view_state,
|
||||
geometry_index,
|
||||
..
|
||||
},
|
||||
..
|
||||
}: &mut MapContext,
|
||||
_dt: Duration,
|
||||
) {
|
||||
if self.clicking {
|
||||
if let Some(window_position) = self.window_position {
|
||||
let view_proj = state.view_projection();
|
||||
let view_proj = view_state.view_projection();
|
||||
let inverted_view_proj = view_proj.invert();
|
||||
|
||||
let _z = state.visible_level(); // FIXME: can be wrong, if tiles of different z are visible
|
||||
let _zoom = state.zoom();
|
||||
let z = view_state.visible_level(); // FIXME: can be wrong, if tiles of different z are visible
|
||||
let zoom = view_state.zoom();
|
||||
|
||||
if let Some(_coordinates) = state.camera().window_to_world_at_ground(
|
||||
if let Some(coordinates) = view_state.camera().window_to_world_at_ground(
|
||||
&window_position,
|
||||
&inverted_view_proj,
|
||||
false,
|
||||
) {
|
||||
// TODO reenable
|
||||
/*state
|
||||
.scheduler()
|
||||
.schedule(state.scheduler(), move |thread_local| async move {
|
||||
if let Some(geometries) = thread_local.query_point(
|
||||
if let Some(geometries) = geometry_index
|
||||
.query_point(
|
||||
&WorldCoords {
|
||||
x: coordinates.x,
|
||||
y: coordinates.y,
|
||||
},
|
||||
z,
|
||||
zoom,
|
||||
) {
|
||||
log::info!(
|
||||
"{:?}",
|
||||
geometries
|
||||
.iter()
|
||||
.map(|geometry| &geometry.properties)
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
}
|
||||
})
|
||||
.unwrap();*/
|
||||
)
|
||||
.map(|geometries| {
|
||||
geometries
|
||||
.iter()
|
||||
.cloned()
|
||||
.cloned()
|
||||
.collect::<Vec<IndexedGeometry<f64>>>()
|
||||
})
|
||||
{
|
||||
log::info!(
|
||||
"Clicked on geometry: {:?}",
|
||||
geometries
|
||||
.iter()
|
||||
.map(|geometry| &geometry.properties)
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
} else {
|
||||
log::info!("No geometry found.",);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.clicking = false;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use cgmath::{Vector3, Zero};
|
||||
use maplibre::world::ViewState;
|
||||
use maplibre::{context::MapContext, world::World};
|
||||
|
||||
use super::UpdateState;
|
||||
|
||||
@ -13,11 +13,18 @@ pub struct ShiftHandler {
|
||||
}
|
||||
|
||||
impl UpdateState for ShiftHandler {
|
||||
fn update_state(&mut self, state: &mut ViewState, dt: Duration) {
|
||||
fn update_state(
|
||||
&mut self,
|
||||
MapContext {
|
||||
world: World { view_state, .. },
|
||||
..
|
||||
}: &mut MapContext,
|
||||
dt: Duration,
|
||||
) {
|
||||
let dt = dt.as_secs_f64() * (1.0 / self.speed);
|
||||
|
||||
let delta = self.camera_translate * dt;
|
||||
state.camera_mut().move_relative(delta);
|
||||
view_state.camera_mut().move_relative(delta);
|
||||
self.camera_translate -= delta;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use cgmath::{Deg, Zero};
|
||||
use maplibre::world::ViewState;
|
||||
use maplibre::{context::MapContext, world::World};
|
||||
|
||||
use super::UpdateState;
|
||||
|
||||
@ -13,11 +13,21 @@ pub struct TiltHandler {
|
||||
}
|
||||
|
||||
impl UpdateState for TiltHandler {
|
||||
fn update_state(&mut self, state: &mut ViewState, dt: Duration) {
|
||||
fn update_state(
|
||||
&mut self,
|
||||
MapContext {
|
||||
world: World {
|
||||
view_state: _view_state,
|
||||
..
|
||||
},
|
||||
..
|
||||
}: &mut MapContext,
|
||||
dt: Duration,
|
||||
) {
|
||||
let dt = dt.as_secs_f64() * (1.0 / self.speed);
|
||||
|
||||
let delta = self.delta_pitch * dt;
|
||||
state.camera_mut().pitch_self(delta);
|
||||
_view_state.camera_mut().pitch_self(delta);
|
||||
self.delta_pitch -= delta;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use cgmath::{Vector2, Vector3};
|
||||
use maplibre::{coords::Zoom, world::ViewState};
|
||||
use maplibre::{context::MapContext, coords::Zoom, world::World};
|
||||
|
||||
use super::UpdateState;
|
||||
|
||||
@ -12,19 +12,26 @@ pub struct ZoomHandler {
|
||||
}
|
||||
|
||||
impl UpdateState for ZoomHandler {
|
||||
fn update_state(&mut self, state: &mut ViewState, _dt: Duration) {
|
||||
fn update_state(
|
||||
&mut self,
|
||||
MapContext {
|
||||
world: World { view_state, .. },
|
||||
..
|
||||
}: &mut MapContext,
|
||||
_dt: Duration,
|
||||
) {
|
||||
if let Some(zoom_delta) = self.zoom_delta {
|
||||
if let Some(window_position) = self.window_position {
|
||||
let current_zoom = state.zoom();
|
||||
let current_zoom = view_state.zoom();
|
||||
let next_zoom = current_zoom + zoom_delta;
|
||||
|
||||
state.update_zoom(next_zoom);
|
||||
view_state.update_zoom(next_zoom);
|
||||
self.zoom_delta = None;
|
||||
|
||||
let view_proj = state.view_projection();
|
||||
let view_proj = view_state.view_projection();
|
||||
let inverted_view_proj = view_proj.invert();
|
||||
|
||||
if let Some(cursor_position) = state.camera().window_to_world_at_ground(
|
||||
if let Some(cursor_position) = view_state.camera().window_to_world_at_ground(
|
||||
&window_position,
|
||||
&inverted_view_proj,
|
||||
false,
|
||||
@ -37,7 +44,7 @@ impl UpdateState for ZoomHandler {
|
||||
cursor_position.z,
|
||||
) - cursor_position;
|
||||
|
||||
state.camera_mut().move_relative(delta);
|
||||
view_state.camera_mut().move_relative(delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ impl<ET: 'static + PartialEq + Debug> EventLoop<ET> for WinitEventLoop<ET> {
|
||||
last_render_time = now;
|
||||
|
||||
if let Ok(map_context) = map.context_mut() {
|
||||
input_controller.update_state(map_context.world.view_state_mut(), dt);
|
||||
input_controller.update_state(map_context, dt);
|
||||
}
|
||||
|
||||
match map.run_schedule() {
|
||||
@ -193,8 +193,8 @@ pub struct WinitEventLoopProxy<ET: 'static> {
|
||||
}
|
||||
|
||||
impl<ET: 'static> EventLoopProxy<ET> for WinitEventLoopProxy<ET> {
|
||||
fn send_event(&self, event: ET) {
|
||||
self.proxy.send_event(event); // FIXME: Handle unwrap
|
||||
fn send_event(&self, event: ET) -> Result<(), Error> {
|
||||
self.proxy.send_event(event).map_err(|e| Error::EventLoop)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,16 +5,12 @@
|
||||
|
||||
use maplibre_build_tools::wgsl::validate_project_wgsl;
|
||||
|
||||
const MUNICH_X: u32 = 17425;
|
||||
const MUNICH_Y: u32 = 11365;
|
||||
const MUNICH_Z: u8 = 15;
|
||||
|
||||
/*use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use serde_json::Value;*/
|
||||
|
||||
fn generate_type_def() -> Option<u32> {
|
||||
/* let f = File::open("style-spec-v8.json").unwrap();
|
||||
/*
|
||||
fn generate_type_def() {
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use serde_json::Value;
|
||||
let f = File::open("style-spec-v8.json").unwrap();
|
||||
let mut reader = BufReader::new(f);
|
||||
let result = serde_json::from_reader::<_, Value>(&mut reader).unwrap();
|
||||
|
||||
@ -26,10 +22,9 @@ fn generate_type_def() -> Option<u32> {
|
||||
|
||||
}
|
||||
|
||||
println!("cargo:warning={:?}", version);*/
|
||||
|
||||
Some(5)
|
||||
println!("cargo:warning={:?}", version);
|
||||
}
|
||||
*/
|
||||
|
||||
#[cfg(feature = "embed-static-tiles")]
|
||||
fn embed_tiles_statically() {
|
||||
@ -37,6 +32,10 @@ fn embed_tiles_statically() {
|
||||
|
||||
use maplibre_build_tools::mbtiles::extract;
|
||||
|
||||
const MUNICH_X: u32 = 17425;
|
||||
const MUNICH_Y: u32 = 11365;
|
||||
const MUNICH_Z: u8 = 15;
|
||||
|
||||
/// Tiles which can be used by StaticTileFetcher.
|
||||
fn clean_static_tiles() -> std::path::PathBuf {
|
||||
let out_dir = std::env::var("OUT_DIR").unwrap();
|
||||
|
||||
@ -7,7 +7,7 @@ use std::{
|
||||
};
|
||||
|
||||
use bytemuck_derive::{Pod, Zeroable};
|
||||
use cgmath::{num_traits::Pow, AbsDiffEq, Matrix4, Point3, Vector3};
|
||||
use cgmath::{AbsDiffEq, Matrix4, Point3, Vector3};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
@ -521,10 +521,6 @@ pub struct WorldCoords {
|
||||
pub y: f64,
|
||||
}
|
||||
|
||||
fn tiles_with_z(z: u8) -> f64 {
|
||||
2.0.pow(z)
|
||||
}
|
||||
|
||||
impl WorldCoords {
|
||||
pub fn from_lat_lon(lat_lon: LatLon, zoom: Zoom) -> WorldCoords {
|
||||
let tile_size = TILE_SIZE * 2.0_f64.powf(zoom.0);
|
||||
|
||||
@ -11,6 +11,7 @@ use crate::render::error::RenderError;
|
||||
pub enum Error {
|
||||
APC,
|
||||
Scheduler,
|
||||
EventLoop,
|
||||
Network(String),
|
||||
Tesselation(TessellationError),
|
||||
Render(RenderError),
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use crate::{
|
||||
environment::Environment,
|
||||
error::Error,
|
||||
map::Map,
|
||||
window::{HeadedMapWindow, MapWindowConfig},
|
||||
};
|
||||
@ -12,7 +13,7 @@ pub trait EventLoopConfig {
|
||||
}
|
||||
|
||||
pub trait EventLoopProxy<T: 'static> {
|
||||
fn send_event(&self, event: T);
|
||||
fn send_event(&self, event: T) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
pub trait EventLoop<ET: 'static + PartialEq> {
|
||||
|
||||
@ -115,7 +115,7 @@ impl HeadlessMap {
|
||||
data,
|
||||
),
|
||||
&mut pipeline_context,
|
||||
);
|
||||
)?;
|
||||
|
||||
let processor = pipeline_context
|
||||
.take_processor::<HeadlessPipelineProcessor>()
|
||||
|
||||
@ -28,29 +28,31 @@ use crate::{
|
||||
#[derive(Clone)]
|
||||
pub enum Message<T: Transferables> {
|
||||
TileTessellated(T::TileTessellated),
|
||||
UnavailableLayer(T::UnavailableLayer),
|
||||
TessellatedLayer(T::TessellatedLayer),
|
||||
LayerUnavailable(T::LayerUnavailable),
|
||||
LayerTessellated(T::LayerTessellated),
|
||||
|
||||
LayerIndexed(T::LayerIndexed),
|
||||
}
|
||||
|
||||
/// Inputs for an [`AsyncProcedure`]
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub enum Input {
|
||||
TileRequest(TileRequest),
|
||||
NotYetImplemented, // TODO: Placeholder, should be removed when second input is added
|
||||
}
|
||||
|
||||
/// Allows sending messages from workers to back to the caller.
|
||||
pub trait Context<T: Transferables, HC: HttpClient>: Send + 'static {
|
||||
/// Send a message back to the caller.
|
||||
// FIXME (wasm-executor): handle results send() calls
|
||||
fn send(&self, data: Message<T>) -> Result<(), Error>;
|
||||
|
||||
fn source_client(&self) -> &SourceClient<HC>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "thread-safe-futures")]
|
||||
pub type AsyncProcedureFuture = Pin<Box<(dyn Future<Output = ()> + Send + 'static)>>;
|
||||
pub type AsyncProcedureFuture = Pin<Box<(dyn Future<Output = Result<(), Error>> + Send + 'static)>>;
|
||||
#[cfg(not(feature = "thread-safe-futures"))]
|
||||
pub type AsyncProcedureFuture = Pin<Box<(dyn Future<Output = ()> + 'static)>>;
|
||||
pub type AsyncProcedureFuture = Pin<Box<(dyn Future<Output = Result<(), Error>> + 'static)>>;
|
||||
|
||||
/// Type definitions for asynchronous procedure calls. These functions can be called in an
|
||||
/// [`AsyncProcedureCall`]. Functions of this type are required to be statically available at
|
||||
@ -167,7 +169,8 @@ impl<HC: HttpClient, S: Scheduler> AsyncProcedureCall<HC> for SchedulerAsyncProc
|
||||
source_client: SourceClient::new(HttpSourceClient::new(client)),
|
||||
},
|
||||
)
|
||||
.await;
|
||||
.await
|
||||
.unwrap();
|
||||
})
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ use geozero::{
|
||||
error::GeozeroError, geo_types::GeoWriter, ColumnValue, FeatureProcessor, GeomProcessor,
|
||||
PropertyProcessor,
|
||||
};
|
||||
use log::warn;
|
||||
use rstar::{Envelope, PointDistance, RTree, RTreeObject, AABB};
|
||||
|
||||
use crate::{
|
||||
@ -217,6 +218,9 @@ impl GeomProcessor for IndexProcessor {
|
||||
fn point_begin(&mut self, idx: usize) -> Result<(), GeozeroError> {
|
||||
self.geo_writer.point_begin(idx)
|
||||
}
|
||||
fn point_end(&mut self, idx: usize) -> Result<(), GeozeroError> {
|
||||
self.geo_writer.point_end(idx)
|
||||
}
|
||||
fn multipoint_begin(&mut self, size: usize, idx: usize) -> Result<(), GeozeroError> {
|
||||
self.geo_writer.multipoint_begin(size, idx)
|
||||
}
|
||||
@ -246,6 +250,9 @@ impl GeomProcessor for IndexProcessor {
|
||||
fn multipolygon_begin(&mut self, size: usize, idx: usize) -> Result<(), GeozeroError> {
|
||||
self.geo_writer.multipolygon_begin(size, idx)
|
||||
}
|
||||
fn multipolygon_end(&mut self, idx: usize) -> Result<(), GeozeroError> {
|
||||
self.geo_writer.multipolygon_end(idx)
|
||||
}
|
||||
}
|
||||
|
||||
impl PropertyProcessor for IndexProcessor {
|
||||
@ -295,17 +302,19 @@ impl FeatureProcessor for IndexProcessor {
|
||||
}
|
||||
/// End of feature geometry processing.
|
||||
fn geometry_end(&mut self) -> Result<(), GeozeroError> {
|
||||
let geometry = self.geo_writer.take_geometry().unwrap();
|
||||
let geometry = self.geo_writer.take_geometry();
|
||||
|
||||
match geometry {
|
||||
Geometry::Polygon(polygon) => self.geometries.push(
|
||||
Some(Geometry::Polygon(polygon)) => self.geometries.push(
|
||||
IndexedGeometry::from_polygon(polygon, self.properties.take().unwrap()).unwrap(),
|
||||
),
|
||||
Geometry::LineString(linestring) => self.geometries.push(
|
||||
Some(Geometry::LineString(linestring)) => self.geometries.push(
|
||||
IndexedGeometry::from_linestring(linestring, self.properties.take().unwrap())
|
||||
.unwrap(),
|
||||
),
|
||||
_ => {}
|
||||
_ => {
|
||||
warn!("Unknown geometry in index")
|
||||
}
|
||||
};
|
||||
|
||||
Ok(())
|
||||
|
||||
@ -12,7 +12,6 @@ use crate::{
|
||||
};
|
||||
|
||||
/// Processes events which happen during the pipeline execution
|
||||
// FIXME (wasm-executor): handle results for messages below
|
||||
pub trait PipelineProcessor: Downcast {
|
||||
fn tile_finished(&mut self, _coords: &WorldTileCoords) -> Result<(), Error> {
|
||||
Ok(())
|
||||
@ -73,7 +72,11 @@ pub trait Processable {
|
||||
type Input;
|
||||
type Output;
|
||||
|
||||
fn process(&self, input: Self::Input, context: &mut PipelineContext) -> Self::Output;
|
||||
fn process(
|
||||
&self,
|
||||
input: Self::Input,
|
||||
context: &mut PipelineContext,
|
||||
) -> Result<Self::Output, Error>;
|
||||
}
|
||||
|
||||
/// A pipeline which consists of multiple steps. Steps are [`Processable`] workloads. Later steps
|
||||
@ -105,8 +108,12 @@ where
|
||||
type Input = P::Input;
|
||||
type Output = N::Output;
|
||||
|
||||
fn process(&self, input: Self::Input, context: &mut PipelineContext) -> Self::Output {
|
||||
let output = self.step.process(input, context);
|
||||
fn process(
|
||||
&self,
|
||||
input: Self::Input,
|
||||
context: &mut PipelineContext,
|
||||
) -> Result<Self::Output, Error> {
|
||||
let output = self.step.process(input, context)?;
|
||||
self.next_step.process(output, context)
|
||||
}
|
||||
}
|
||||
@ -128,8 +135,12 @@ impl<I> Processable for PipelineEnd<I> {
|
||||
type Input = I;
|
||||
type Output = I;
|
||||
|
||||
fn process(&self, input: Self::Input, _context: &mut PipelineContext) -> Self::Output {
|
||||
input
|
||||
fn process(
|
||||
&self,
|
||||
input: Self::Input,
|
||||
_context: &mut PipelineContext,
|
||||
) -> Result<Self::Output, Error> {
|
||||
Ok(input)
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,8 +148,12 @@ impl<I, O> Processable for &fn(input: I, context: &mut PipelineContext) -> O {
|
||||
type Input = I;
|
||||
type Output = O;
|
||||
|
||||
fn process(&self, input: Self::Input, context: &mut PipelineContext) -> Self::Output {
|
||||
(self)(input, context)
|
||||
fn process(
|
||||
&self,
|
||||
input: Self::Input,
|
||||
context: &mut PipelineContext,
|
||||
) -> Result<Self::Output, Error> {
|
||||
Ok((self)(input, context))
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,8 +161,12 @@ impl<I, O> Processable for fn(input: I, context: &mut PipelineContext) -> O {
|
||||
type Input = I;
|
||||
type Output = O;
|
||||
|
||||
fn process(&self, input: Self::Input, context: &mut PipelineContext) -> Self::Output {
|
||||
(self)(input, context)
|
||||
fn process(
|
||||
&self,
|
||||
input: Self::Input,
|
||||
context: &mut PipelineContext,
|
||||
) -> Result<Self::Output, Error> {
|
||||
Ok((self)(input, context))
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,8 +199,12 @@ where
|
||||
type Input = I;
|
||||
type Output = O;
|
||||
|
||||
fn process(&self, input: Self::Input, context: &mut PipelineContext) -> Self::Output {
|
||||
(self.func)(input, context)
|
||||
fn process(
|
||||
&self,
|
||||
input: Self::Input,
|
||||
context: &mut PipelineContext,
|
||||
) -> Result<Self::Output, Error> {
|
||||
Ok((self.func)(input, context))
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +234,8 @@ mod tests {
|
||||
add_two as fn(u8, &mut PipelineContext) -> u32,
|
||||
PipelineEnd::default(),
|
||||
)
|
||||
.process(5u8, &mut context);
|
||||
.process(5u8, &mut context)
|
||||
.unwrap();
|
||||
assert_eq!(output, 7);
|
||||
|
||||
let output: u32 = DataPipeline::new(
|
||||
@ -221,7 +245,8 @@ mod tests {
|
||||
PipelineEnd::default(),
|
||||
),
|
||||
)
|
||||
.process(5u32, &mut context);
|
||||
.process(5u32, &mut context)
|
||||
.unwrap();
|
||||
assert_eq!(output, 8);
|
||||
}
|
||||
|
||||
@ -235,8 +260,9 @@ mod tests {
|
||||
ClosureProcessable::from(|input: u8, _context: &mut PipelineContext| -> u32 {
|
||||
input as u32 + 2 + outer_value
|
||||
});
|
||||
let output: u32 =
|
||||
DataPipeline::new(closure, PipelineEnd::default()).process(5u8, &mut context);
|
||||
let output: u32 = DataPipeline::new(closure, PipelineEnd::default())
|
||||
.process(5u8, &mut context)
|
||||
.unwrap();
|
||||
assert_eq!(output, 10);
|
||||
|
||||
// with into()
|
||||
@ -245,7 +271,8 @@ mod tests {
|
||||
.into(),
|
||||
PipelineEnd::<u32>::default(),
|
||||
)
|
||||
.process(5u8, &mut context);
|
||||
.process(5u8, &mut context)
|
||||
.unwrap();
|
||||
assert_eq!(output, 10);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@ use geozero::GeozeroDatasource;
|
||||
use prost::Message;
|
||||
|
||||
use crate::{
|
||||
error::Error,
|
||||
io::{
|
||||
geometry_index::IndexProcessor,
|
||||
pipeline::{DataPipeline, PipelineContext, PipelineEnd, Processable},
|
||||
@ -19,14 +20,13 @@ impl Processable for ParseTile {
|
||||
type Input = (TileRequest, Box<[u8]>);
|
||||
type Output = (TileRequest, geozero::mvt::Tile);
|
||||
|
||||
// TODO (perf): Maybe force inline
|
||||
fn process(
|
||||
&self,
|
||||
(tile_request, data): Self::Input,
|
||||
_context: &mut PipelineContext,
|
||||
) -> Self::Output {
|
||||
) -> Result<Self::Output, Error> {
|
||||
let tile = geozero::mvt::Tile::decode(data.as_ref()).expect("failed to load tile");
|
||||
(tile_request, tile)
|
||||
Ok((tile_request, tile))
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,19 +37,21 @@ impl Processable for IndexLayer {
|
||||
type Input = (TileRequest, geozero::mvt::Tile);
|
||||
type Output = (TileRequest, geozero::mvt::Tile);
|
||||
|
||||
// TODO (perf): Maybe force inline
|
||||
fn process(
|
||||
&self,
|
||||
(tile_request, tile): Self::Input,
|
||||
(tile_request, mut tile): Self::Input,
|
||||
context: &mut PipelineContext,
|
||||
) -> Self::Output {
|
||||
let index = IndexProcessor::new();
|
||||
) -> Result<Self::Output, Error> {
|
||||
let mut index = IndexProcessor::new();
|
||||
|
||||
for layer in &mut tile.layers {
|
||||
layer.process(&mut index).unwrap();
|
||||
}
|
||||
|
||||
// FIXME: Handle result
|
||||
context
|
||||
.processor_mut()
|
||||
.layer_indexing_finished(&tile_request.coords, index.get_geometries());
|
||||
(tile_request, tile)
|
||||
.layer_indexing_finished(&tile_request.coords, index.get_geometries())?;
|
||||
Ok((tile_request, tile))
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,12 +62,11 @@ impl Processable for TessellateLayer {
|
||||
type Input = (TileRequest, geozero::mvt::Tile);
|
||||
type Output = (TileRequest, geozero::mvt::Tile);
|
||||
|
||||
// TODO (perf): Maybe force inline
|
||||
fn process(
|
||||
&self,
|
||||
(tile_request, mut tile): Self::Input,
|
||||
context: &mut PipelineContext,
|
||||
) -> Self::Output {
|
||||
) -> Result<Self::Output, Error> {
|
||||
let coords = &tile_request.coords;
|
||||
|
||||
for layer in &mut tile.layers {
|
||||
@ -79,10 +80,9 @@ impl Processable for TessellateLayer {
|
||||
|
||||
let mut tessellator = ZeroTessellator::<IndexDataType>::default();
|
||||
if let Err(e) = layer.process(&mut tessellator) {
|
||||
// FIXME: Handle result
|
||||
context
|
||||
.processor_mut()
|
||||
.layer_unavailable(coords, layer_name);
|
||||
.layer_unavailable(coords, layer_name)?;
|
||||
|
||||
tracing::error!(
|
||||
"layer {} at {} tesselation failed {:?}",
|
||||
@ -91,13 +91,12 @@ impl Processable for TessellateLayer {
|
||||
e
|
||||
);
|
||||
} else {
|
||||
// FIXME: Handle result
|
||||
context.processor_mut().layer_tesselation_finished(
|
||||
coords,
|
||||
tessellator.buffer.into(),
|
||||
tessellator.feature_indices,
|
||||
cloned_layer,
|
||||
);
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,10 +107,9 @@ impl Processable for TessellateLayer {
|
||||
.collect::<HashSet<_>>();
|
||||
|
||||
for missing_layer in tile_request.layers.difference(&available_layers) {
|
||||
// FIXME: Handle result
|
||||
context
|
||||
.processor_mut()
|
||||
.layer_unavailable(coords, missing_layer);
|
||||
.layer_unavailable(coords, missing_layer)?;
|
||||
|
||||
tracing::info!(
|
||||
"requested layer {} at {} not found in tile",
|
||||
@ -122,17 +120,21 @@ impl Processable for TessellateLayer {
|
||||
|
||||
tracing::info!("tile tessellated at {} finished", &tile_request.coords);
|
||||
|
||||
// FIXME: Handle result
|
||||
context.processor_mut().tile_finished(&tile_request.coords);
|
||||
context
|
||||
.processor_mut()
|
||||
.tile_finished(&tile_request.coords)?;
|
||||
|
||||
(tile_request, tile)
|
||||
Ok((tile_request, tile))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_vector_tile_pipeline() -> impl Processable<Input = <ParseTile as Processable>::Input> {
|
||||
DataPipeline::new(
|
||||
ParseTile,
|
||||
DataPipeline::new(TessellateLayer, PipelineEnd::default()),
|
||||
DataPipeline::new(
|
||||
TessellateLayer,
|
||||
DataPipeline::new(IndexLayer, PipelineEnd::default()),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@ -150,7 +152,7 @@ mod tests {
|
||||
|
||||
impl PipelineProcessor for DummyPipelineProcessor {}
|
||||
|
||||
#[test] // TODO: Add proper tile byte array
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test() {
|
||||
let mut context = PipelineContext::new(DummyPipelineProcessor);
|
||||
@ -162,7 +164,7 @@ mod tests {
|
||||
coords: (0, 0, ZoomLevel::default()).into(),
|
||||
layers: Default::default(),
|
||||
},
|
||||
Box::new([0]),
|
||||
Box::new([0]), // TODO: Add proper tile byte array
|
||||
),
|
||||
&mut context,
|
||||
);
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
use geozero::mvt::{tile, tile::Layer};
|
||||
use geozero::mvt::tile::Layer;
|
||||
|
||||
use crate::{
|
||||
coords::WorldTileCoords,
|
||||
io::tile_repository::StoredLayer,
|
||||
io::{geometry_index::TileIndex, tile_repository::StoredLayer},
|
||||
render::ShaderVertex,
|
||||
tessellation::{IndexDataType, OverAlignedVertexBuffer},
|
||||
};
|
||||
@ -16,6 +16,8 @@ pub trait TileTessellated: Send {
|
||||
pub trait UnavailableLayer: Send {
|
||||
fn new(coords: WorldTileCoords, layer_name: String) -> Self;
|
||||
|
||||
fn coords(&self) -> &WorldTileCoords;
|
||||
|
||||
fn to_stored_layer(self) -> StoredLayer;
|
||||
}
|
||||
|
||||
@ -24,11 +26,20 @@ pub trait TessellatedLayer: Send {
|
||||
coords: WorldTileCoords,
|
||||
buffer: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
|
||||
feature_indices: Vec<u32>,
|
||||
layer_data: tile::Layer,
|
||||
layer_data: Layer,
|
||||
) -> Self;
|
||||
|
||||
fn coords(&self) -> &WorldTileCoords;
|
||||
|
||||
fn to_stored_layer(self) -> StoredLayer;
|
||||
}
|
||||
|
||||
pub trait IndexedLayer: Send + From<(WorldTileCoords, TileIndex)> {
|
||||
fn coords(&self) -> &WorldTileCoords;
|
||||
|
||||
fn to_tile_index(self) -> TileIndex;
|
||||
}
|
||||
|
||||
pub struct DefaultTileTessellated {
|
||||
pub coords: WorldTileCoords,
|
||||
}
|
||||
@ -43,16 +54,20 @@ impl TileTessellated for DefaultTileTessellated {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DefaultUnavailableLayer {
|
||||
pub struct DefaultLayerUnavailable {
|
||||
pub coords: WorldTileCoords,
|
||||
pub layer_name: String,
|
||||
}
|
||||
|
||||
impl UnavailableLayer for DefaultUnavailableLayer {
|
||||
impl UnavailableLayer for DefaultLayerUnavailable {
|
||||
fn new(coords: WorldTileCoords, layer_name: String) -> Self {
|
||||
Self { coords, layer_name }
|
||||
}
|
||||
|
||||
fn coords(&self) -> &WorldTileCoords {
|
||||
&self.coords
|
||||
}
|
||||
|
||||
fn to_stored_layer(self) -> StoredLayer {
|
||||
StoredLayer::UnavailableLayer {
|
||||
coords: self.coords,
|
||||
@ -61,7 +76,7 @@ impl UnavailableLayer for DefaultUnavailableLayer {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DefaultTessellatedLayer {
|
||||
pub struct DefaultLayerTesselated {
|
||||
pub coords: WorldTileCoords,
|
||||
pub buffer: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
|
||||
/// Holds for each feature the count of indices.
|
||||
@ -69,7 +84,7 @@ pub struct DefaultTessellatedLayer {
|
||||
pub layer_data: Layer, // FIXME (perf): Introduce a better structure for this
|
||||
}
|
||||
|
||||
impl TessellatedLayer for DefaultTessellatedLayer {
|
||||
impl TessellatedLayer for DefaultLayerTesselated {
|
||||
fn new(
|
||||
coords: WorldTileCoords,
|
||||
buffer: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
|
||||
@ -84,6 +99,10 @@ impl TessellatedLayer for DefaultTessellatedLayer {
|
||||
}
|
||||
}
|
||||
|
||||
fn coords(&self) -> &WorldTileCoords {
|
||||
&self.coords
|
||||
}
|
||||
|
||||
fn to_stored_layer(self) -> StoredLayer {
|
||||
StoredLayer::TessellatedLayer {
|
||||
coords: self.coords,
|
||||
@ -94,10 +113,32 @@ impl TessellatedLayer for DefaultTessellatedLayer {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DefaultLayerIndexed {
|
||||
coords: WorldTileCoords,
|
||||
index: TileIndex,
|
||||
}
|
||||
|
||||
impl From<(WorldTileCoords, TileIndex)> for DefaultLayerIndexed {
|
||||
fn from((coords, index): (WorldTileCoords, TileIndex)) -> Self {
|
||||
Self { coords, index }
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexedLayer for DefaultLayerIndexed {
|
||||
fn coords(&self) -> &WorldTileCoords {
|
||||
&self.coords
|
||||
}
|
||||
|
||||
fn to_tile_index(self) -> TileIndex {
|
||||
self.index
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Transferables: 'static {
|
||||
type TileTessellated: TileTessellated;
|
||||
type UnavailableLayer: UnavailableLayer;
|
||||
type TessellatedLayer: TessellatedLayer;
|
||||
type LayerUnavailable: UnavailableLayer;
|
||||
type LayerTessellated: TessellatedLayer;
|
||||
type LayerIndexed: IndexedLayer;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@ -105,6 +146,7 @@ pub struct DefaultTransferables;
|
||||
|
||||
impl Transferables for DefaultTransferables {
|
||||
type TileTessellated = DefaultTileTessellated;
|
||||
type UnavailableLayer = DefaultUnavailableLayer;
|
||||
type TessellatedLayer = DefaultTessellatedLayer;
|
||||
type LayerUnavailable = DefaultLayerUnavailable;
|
||||
type LayerTessellated = DefaultLayerTesselated;
|
||||
type LayerIndexed = DefaultLayerIndexed;
|
||||
}
|
||||
|
||||
@ -1,26 +0,0 @@
|
||||
/* pub fn resume(&mut self, window: &<E::MapWindowConfig as MapWindowConfig>::MapWindow) {
|
||||
if let EventuallyMapContext::Full(map_context) = &mut self.map_context {
|
||||
let renderer = &mut map_context.renderer;
|
||||
renderer.state.recreate_surface(window, &renderer.instance);
|
||||
}
|
||||
}*/
|
||||
|
||||
/* pub async fn late_init(&mut self) -> bool {
|
||||
match &self.map_context {
|
||||
EventuallyMapContext::Full(_) => false,
|
||||
EventuallyMapContext::Uninizalized(PrematureMapContext {
|
||||
wgpu_settings,
|
||||
renderer_settings,
|
||||
..
|
||||
}) => {
|
||||
let window = self.map_window_config.create();
|
||||
let renderer =
|
||||
Renderer::initialize(&window, wgpu_settings.clone(), renderer_settings.clone())
|
||||
.await
|
||||
.unwrap(); // TODO: Remove unwrap
|
||||
self.map_context.make_full(renderer);
|
||||
true
|
||||
}
|
||||
EventuallyMapContext::_Uninitialized => false,
|
||||
}
|
||||
}*/
|
||||
@ -15,16 +15,6 @@ use crate::render::{
|
||||
RenderState,
|
||||
};
|
||||
|
||||
pub mod graph {
|
||||
// Labels for input nodes
|
||||
pub mod input {}
|
||||
// Labels for non-input nodes
|
||||
pub mod node {
|
||||
pub const MAIN_PASS_DEPENDENCIES: &str = "main_pass_dependencies";
|
||||
pub const MAIN_PASS_DRIVER: &str = "main_pass_driver";
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MainPassNode {}
|
||||
|
||||
impl MainPassNode {
|
||||
|
||||
@ -76,7 +76,7 @@ impl BufferedTextureHead {
|
||||
use std::{fs::File, io::Write};
|
||||
// Note that we're not calling `.await` here.
|
||||
let buffer_slice = self.output_buffer.slice(..);
|
||||
let buffer_future = buffer_slice.map_async(wgpu::MapMode::Read, |_| ());
|
||||
buffer_slice.map_async(wgpu::MapMode::Read, |_| ());
|
||||
|
||||
// Poll the device in a blocking manner so that our future resolves.
|
||||
// In an actual application, `device.poll(...)` should
|
||||
@ -139,8 +139,7 @@ impl Surface {
|
||||
format: settings.texture_format,
|
||||
width: size.width(),
|
||||
height: size.height(),
|
||||
//present_mode: wgpu::PresentMode::Immediate,
|
||||
present_mode: wgpu::PresentMode::Fifo, // VSync
|
||||
present_mode: settings.present_mode,
|
||||
};
|
||||
|
||||
let surface = unsafe { instance.create_surface(window.raw()) };
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use wgpu::PresentMode;
|
||||
pub use wgpu::{Backends, Features, Limits, PowerPreference, TextureFormat};
|
||||
|
||||
/// Provides configuration for renderer initialization. Use [`Device::features`](crate::renderer::Device::features),
|
||||
@ -104,6 +105,8 @@ pub struct RendererSettings {
|
||||
pub msaa: Msaa,
|
||||
pub texture_format: TextureFormat,
|
||||
pub depth_texture_format: TextureFormat,
|
||||
/// Present mode for surfaces if a surface is used.
|
||||
pub present_mode: PresentMode,
|
||||
}
|
||||
|
||||
impl Default for RendererSettings {
|
||||
@ -132,6 +135,7 @@ impl Default for RendererSettings {
|
||||
texture_format: TextureFormat::Bgra8UnormSrgb,
|
||||
|
||||
depth_texture_format: TextureFormat::Depth24PlusStencil8,
|
||||
present_mode: PresentMode::AutoVsync,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -29,6 +29,7 @@ impl Stage for UploadStage {
|
||||
World {
|
||||
tile_repository,
|
||||
view_state,
|
||||
..
|
||||
},
|
||||
style,
|
||||
renderer: Renderer { queue, state, .. },
|
||||
|
||||
@ -11,7 +11,7 @@ use crate::{
|
||||
error::Error,
|
||||
io::{
|
||||
apc::{Context, Message},
|
||||
geometry_index::IndexedGeometry,
|
||||
geometry_index::{IndexedGeometry, TileIndex},
|
||||
pipeline::PipelineProcessor,
|
||||
source_client::HttpClient,
|
||||
transferables::{TessellatedLayer, TileTessellated, Transferables, UnavailableLayer},
|
||||
@ -52,7 +52,7 @@ impl<'c, T: Transferables, HC: HttpClient, C: Context<T, HC>> PipelineProcessor
|
||||
layer_name: &str,
|
||||
) -> Result<(), Error> {
|
||||
self.context
|
||||
.send(Message::UnavailableLayer(T::UnavailableLayer::new(
|
||||
.send(Message::LayerUnavailable(T::LayerUnavailable::new(
|
||||
*coords,
|
||||
layer_name.to_owned(),
|
||||
)))
|
||||
@ -66,7 +66,7 @@ impl<'c, T: Transferables, HC: HttpClient, C: Context<T, HC>> PipelineProcessor
|
||||
layer_data: tile::Layer,
|
||||
) -> Result<(), Error> {
|
||||
self.context
|
||||
.send(Message::TessellatedLayer(T::TessellatedLayer::new(
|
||||
.send(Message::LayerTessellated(T::LayerTessellated::new(
|
||||
*coords,
|
||||
buffer,
|
||||
feature_indices,
|
||||
@ -76,36 +76,13 @@ impl<'c, T: Transferables, HC: HttpClient, C: Context<T, HC>> PipelineProcessor
|
||||
|
||||
fn layer_indexing_finished(
|
||||
&mut self,
|
||||
_coords: &WorldTileCoords,
|
||||
_geometries: Vec<IndexedGeometry<f64>>,
|
||||
coords: &WorldTileCoords,
|
||||
geometries: Vec<IndexedGeometry<f64>>,
|
||||
) -> Result<(), Error> {
|
||||
// FIXME (wasm-executor): Readd
|
||||
/* if let Ok(mut geometry_index) = self.state.geometry_index.lock() {
|
||||
geometry_index.index_tile(coords, TileIndex::Linear { list: geometries })
|
||||
}*/
|
||||
Ok(())
|
||||
self.context
|
||||
.send(Message::LayerIndexed(T::LayerIndexed::from((
|
||||
*coords,
|
||||
TileIndex::Linear { list: geometries },
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME (wasm-executor): Readd
|
||||
/*pub fn query_point(
|
||||
&self,
|
||||
world_coords: &WorldCoords,
|
||||
z: ZoomLevel,
|
||||
zoom: Zoom,
|
||||
) -> Option<Vec<IndexedGeometry<f64>>> {
|
||||
if let Ok(geometry_index) = self.geometry_index.lock() {
|
||||
geometry_index
|
||||
.query_point(world_coords, z, zoom)
|
||||
.map(|geometries| {
|
||||
geometries
|
||||
.iter()
|
||||
.cloned()
|
||||
.cloned()
|
||||
.collect::<Vec<IndexedGeometry<f64>>>()
|
||||
})
|
||||
} else {
|
||||
unimplemented!()
|
||||
}
|
||||
}*/
|
||||
//}
|
||||
|
||||
@ -8,7 +8,7 @@ use crate::{
|
||||
io::{
|
||||
apc::{AsyncProcedureCall, Message},
|
||||
tile_repository::StoredLayer,
|
||||
transferables::{TessellatedLayer, TileTessellated, UnavailableLayer},
|
||||
transferables::{IndexedLayer, TessellatedLayer, TileTessellated, UnavailableLayer},
|
||||
},
|
||||
kernel::Kernel,
|
||||
schedule::Stage,
|
||||
@ -29,32 +29,40 @@ impl<E: Environment> Stage for PopulateTileStore<E> {
|
||||
fn run(
|
||||
&mut self,
|
||||
MapContext {
|
||||
world: World {
|
||||
tile_repository, ..
|
||||
},
|
||||
world:
|
||||
World {
|
||||
tile_repository,
|
||||
geometry_index,
|
||||
..
|
||||
},
|
||||
..
|
||||
}: &mut MapContext,
|
||||
) {
|
||||
if let Some(result) = self.kernel.apc().receive() {
|
||||
match result {
|
||||
Message::TileTessellated(tranferred) => {
|
||||
let coords = tranferred.coords();
|
||||
tile_repository.mark_tile_succeeded(coords);
|
||||
Message::TileTessellated(message) => {
|
||||
let coords = message.coords();
|
||||
|
||||
tracing::trace!("Tile at {} finished loading", coords);
|
||||
log::warn!("Tile at {} finished loading", coords);
|
||||
|
||||
tile_repository.mark_tile_succeeded(coords);
|
||||
}
|
||||
// FIXME: deduplicate
|
||||
Message::UnavailableLayer(tranferred) => {
|
||||
let layer: StoredLayer = tranferred.to_stored_layer();
|
||||
Message::LayerUnavailable(message) => {
|
||||
let layer: StoredLayer = message.to_stored_layer();
|
||||
|
||||
tracing::debug!(
|
||||
"Layer {} at {} reached main thread",
|
||||
layer.layer_name(),
|
||||
layer.get_coords()
|
||||
);
|
||||
|
||||
tile_repository.put_layer(layer);
|
||||
}
|
||||
Message::TessellatedLayer(data) => {
|
||||
let layer: StoredLayer = data.to_stored_layer();
|
||||
Message::LayerTessellated(message) => {
|
||||
let layer: StoredLayer = message.to_stored_layer();
|
||||
|
||||
tracing::debug!(
|
||||
"Layer {} at {} reached main thread",
|
||||
layer.layer_name(),
|
||||
@ -65,8 +73,16 @@ impl<E: Environment> Stage for PopulateTileStore<E> {
|
||||
layer.layer_name(),
|
||||
layer.get_coords()
|
||||
);
|
||||
|
||||
tile_repository.put_layer(layer);
|
||||
}
|
||||
Message::LayerIndexed(message) => {
|
||||
let coords = *message.coords();
|
||||
|
||||
log::warn!("Layer index at {} reached main thread", coords);
|
||||
|
||||
geometry_index.index_tile(&coords, message.to_tile_index());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,6 +40,7 @@ impl<E: Environment> Stage for RequestStage<E> {
|
||||
World {
|
||||
tile_repository,
|
||||
view_state,
|
||||
..
|
||||
},
|
||||
style,
|
||||
..
|
||||
@ -68,14 +69,11 @@ pub fn schedule<
|
||||
input: Input,
|
||||
context: C,
|
||||
) -> AsyncProcedureFuture {
|
||||
// FIXME: improve input handling
|
||||
let input = match input {
|
||||
Input::TileRequest(input) => Some(input),
|
||||
_ => None,
|
||||
}
|
||||
.unwrap(); // FIXME (wasm-executor): Remove unwrap
|
||||
|
||||
Box::pin(async move {
|
||||
let Input::TileRequest(input) = input else {
|
||||
return Err(Error::APC)
|
||||
};
|
||||
|
||||
let coords = input.coords;
|
||||
let client = context.source_client();
|
||||
|
||||
@ -89,24 +87,24 @@ pub fn schedule<
|
||||
phantom_hc: Default::default(),
|
||||
});
|
||||
let pipeline = build_vector_tile_pipeline();
|
||||
pipeline.process((input, data), &mut pipeline_context);
|
||||
pipeline.process((input, data), &mut pipeline_context)?;
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("{:?}", &e);
|
||||
for to_load in &input.layers {
|
||||
tracing::warn!("layer {} at {} unavailable", to_load, coords);
|
||||
// FIXME: Handle result
|
||||
context.send(
|
||||
Message::UnavailableLayer(<<E::AsyncProcedureCall as AsyncProcedureCall<
|
||||
Message::LayerUnavailable(<<E::AsyncProcedureCall as AsyncProcedureCall<
|
||||
E::HttpClient,
|
||||
>>::Transferables as Transferables>::UnavailableLayer::new(
|
||||
>>::Transferables as Transferables>::LayerUnavailable::new(
|
||||
input.coords,
|
||||
to_load.to_string(),
|
||||
)),
|
||||
);
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ use cgmath::Angle;
|
||||
|
||||
use crate::{
|
||||
coords::{LatLon, ViewRegion, WorldCoords, Zoom, ZoomLevel, TILE_SIZE},
|
||||
io::tile_repository::TileRepository,
|
||||
io::{geometry_index::GeometryIndex, tile_repository::TileRepository},
|
||||
render::camera::{Camera, Perspective, ViewProjection},
|
||||
util::ChangeObserver,
|
||||
window::WindowSize,
|
||||
@ -13,6 +13,7 @@ use crate::{
|
||||
pub struct World {
|
||||
pub view_state: ViewState,
|
||||
pub tile_repository: TileRepository,
|
||||
pub geometry_index: GeometryIndex,
|
||||
}
|
||||
|
||||
impl World {
|
||||
@ -46,10 +47,12 @@ impl World {
|
||||
);
|
||||
|
||||
let tile_repository = TileRepository::new();
|
||||
let geometry_index = GeometryIndex::new();
|
||||
|
||||
World {
|
||||
view_state,
|
||||
tile_repository,
|
||||
geometry_index,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -44,8 +44,6 @@ console_log = { version = "0.2.0", features = ["color"] }
|
||||
tracing-wasm = { version = "0.2.1", optional = true } # TODO: Low quality dependency
|
||||
# For passing Inputs in AsyncProcedureCalls
|
||||
serde_json = "1.0.85"
|
||||
bytemuck = "1.12.1" # FIXME (wasm-executor): Remove
|
||||
bytemuck_derive = "1.2.1" # FIXME (wasm-executor): Remove
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen-test = "0.3.31"
|
||||
|
||||
@ -43,7 +43,6 @@ impl Scheduler for WebWorkerPoolScheduler {
|
||||
Ok(JsValue::undefined())
|
||||
})
|
||||
})
|
||||
.unwrap(); // FIXME (wasm-executor): remove unwrap
|
||||
Ok(())
|
||||
.map_err(|e| Error::Scheduler)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use std::{cell::RefCell, mem, rc::Rc};
|
||||
use std::{cell::RefCell, mem, mem::size_of, rc::Rc, slice};
|
||||
|
||||
use js_sys::Uint8Array;
|
||||
use log::info;
|
||||
@ -15,7 +15,8 @@ use web_sys::{DedicatedWorkerGlobalScope, Worker};
|
||||
|
||||
use crate::{
|
||||
platform::singlethreaded::transferables::{
|
||||
InnerData, LinearTessellatedLayer, LinearTransferables,
|
||||
InnerData, LinearLayerIndexed, LinearLayerTesselated, LinearLayerUnavailable,
|
||||
LinearTileTessellated, LinearTransferables,
|
||||
},
|
||||
WHATWGFetchHttpClient,
|
||||
};
|
||||
@ -27,22 +28,26 @@ type UsedContext = PassingContext;
|
||||
#[derive(Debug)]
|
||||
enum SerializedMessageTag {
|
||||
TileTessellated = 1,
|
||||
UnavailableLayer = 2,
|
||||
TessellatedLayer = 3,
|
||||
LayerUnavailable = 2,
|
||||
LayerTessellated = 3,
|
||||
LayerIndexed = 4,
|
||||
}
|
||||
|
||||
impl SerializedMessageTag {
|
||||
fn from_u32(tag: u32) -> Option<Self> {
|
||||
match tag {
|
||||
x if x == SerializedMessageTag::UnavailableLayer as u32 => {
|
||||
Some(SerializedMessageTag::UnavailableLayer)
|
||||
x if x == SerializedMessageTag::LayerUnavailable as u32 => {
|
||||
Some(SerializedMessageTag::LayerUnavailable)
|
||||
}
|
||||
x if x == SerializedMessageTag::TessellatedLayer as u32 => {
|
||||
Some(SerializedMessageTag::TessellatedLayer)
|
||||
x if x == SerializedMessageTag::LayerTessellated as u32 => {
|
||||
Some(SerializedMessageTag::LayerTessellated)
|
||||
}
|
||||
x if x == SerializedMessageTag::TileTessellated as u32 => {
|
||||
Some(SerializedMessageTag::TileTessellated)
|
||||
}
|
||||
x if x == SerializedMessageTag::LayerIndexed as u32 => {
|
||||
Some(SerializedMessageTag::LayerIndexed)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -58,34 +63,61 @@ trait SerializableMessage {
|
||||
|
||||
impl SerializableMessage for Message<LinearTransferables> {
|
||||
fn serialize(&self) -> &[u8] {
|
||||
match self {
|
||||
Message::TileTessellated(data) => bytemuck::bytes_of(data),
|
||||
Message::UnavailableLayer(data) => bytemuck::bytes_of(data),
|
||||
Message::TessellatedLayer(data) => bytemuck::bytes_of(data.data.as_ref()),
|
||||
unsafe {
|
||||
match self {
|
||||
// TODO https://github.com/Lokathor/bytemuck/blob/518baf9c0b73c92b4ea4406fe15e005c6d71535a/src/internal.rs#L333
|
||||
Message::TileTessellated(message) => slice::from_raw_parts(
|
||||
message as *const LinearTileTessellated as *mut u8,
|
||||
size_of::<LinearTileTessellated>(),
|
||||
),
|
||||
Message::LayerUnavailable(message) => slice::from_raw_parts(
|
||||
message as *const LinearLayerUnavailable as *mut u8,
|
||||
size_of::<LinearLayerUnavailable>(),
|
||||
),
|
||||
Message::LayerTessellated(message) => slice::from_raw_parts(
|
||||
message.data.as_ref() as *const InnerData as *mut u8,
|
||||
size_of::<InnerData>(),
|
||||
),
|
||||
Message::LayerIndexed(message) => slice::from_raw_parts(
|
||||
message as *const LinearLayerIndexed as *mut u8,
|
||||
size_of::<LinearLayerIndexed>(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize(tag: SerializedMessageTag, data: Uint8Array) -> Message<UsedTransferables> {
|
||||
match tag {
|
||||
SerializedMessageTag::TileTessellated => {
|
||||
Message::<UsedTransferables>::TileTessellated(*bytemuck::from_bytes::<
|
||||
<UsedTransferables as Transferables>::TileTessellated,
|
||||
>(&data.to_vec()))
|
||||
}
|
||||
SerializedMessageTag::UnavailableLayer => {
|
||||
Message::<UsedTransferables>::UnavailableLayer(*bytemuck::from_bytes::<
|
||||
<UsedTransferables as Transferables>::UnavailableLayer,
|
||||
>(&data.to_vec()))
|
||||
}
|
||||
SerializedMessageTag::TessellatedLayer => {
|
||||
Message::<UsedTransferables>::TessellatedLayer(LinearTessellatedLayer {
|
||||
data: unsafe {
|
||||
let mut uninit = Box::<InnerData>::new_zeroed();
|
||||
data.raw_copy_to_ptr(uninit.as_mut_ptr() as *mut u8);
|
||||
type TileTessellated = <UsedTransferables as Transferables>::TileTessellated;
|
||||
type UnavailableLayer = <UsedTransferables as Transferables>::LayerUnavailable;
|
||||
type IndexedLayer = <UsedTransferables as Transferables>::LayerIndexed;
|
||||
unsafe {
|
||||
// TODO: https://github.com/Lokathor/bytemuck/blob/518baf9c0b73c92b4ea4406fe15e005c6d71535a/src/internal.rs#L159
|
||||
match tag {
|
||||
SerializedMessageTag::TileTessellated => {
|
||||
Message::<UsedTransferables>::TileTessellated(
|
||||
(&*(data.to_vec().as_slice() as *const [u8] as *const TileTessellated))
|
||||
.clone(),
|
||||
)
|
||||
}
|
||||
SerializedMessageTag::LayerUnavailable => {
|
||||
Message::<UsedTransferables>::LayerUnavailable(
|
||||
(&*(data.to_vec().as_slice() as *const [u8] as *const UnavailableLayer))
|
||||
.clone(),
|
||||
)
|
||||
}
|
||||
SerializedMessageTag::LayerTessellated => {
|
||||
Message::<UsedTransferables>::LayerTessellated(LinearLayerTesselated {
|
||||
data: unsafe {
|
||||
let mut uninit = Box::<InnerData>::new_zeroed();
|
||||
data.raw_copy_to_ptr(uninit.as_mut_ptr() as *mut u8);
|
||||
|
||||
uninit.assume_init()
|
||||
},
|
||||
})
|
||||
uninit.assume_init()
|
||||
},
|
||||
})
|
||||
}
|
||||
SerializedMessageTag::LayerIndexed => Message::<UsedTransferables>::LayerIndexed(
|
||||
(&*(data.to_vec().as_slice() as *const [u8] as *const IndexedLayer)).clone(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,8 +125,9 @@ impl SerializableMessage for Message<LinearTransferables> {
|
||||
fn tag(&self) -> SerializedMessageTag {
|
||||
match self {
|
||||
Message::TileTessellated(_) => SerializedMessageTag::TileTessellated,
|
||||
Message::UnavailableLayer(_) => SerializedMessageTag::UnavailableLayer,
|
||||
Message::TessellatedLayer(_) => SerializedMessageTag::TessellatedLayer,
|
||||
Message::LayerUnavailable(_) => SerializedMessageTag::LayerUnavailable,
|
||||
Message::LayerTessellated(_) => SerializedMessageTag::LayerTessellated,
|
||||
Message::LayerIndexed(_) => SerializedMessageTag::LayerIndexed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,91 +1,73 @@
|
||||
use bytemuck::{TransparentWrapper, Zeroable};
|
||||
use bytemuck_derive::{Pod, Zeroable};
|
||||
use log::warn;
|
||||
use maplibre::{
|
||||
benchmarking::tessellation::{IndexDataType, OverAlignedVertexBuffer},
|
||||
coords::WorldTileCoords,
|
||||
io::{
|
||||
geometry_index::TileIndex,
|
||||
tile_repository::StoredLayer,
|
||||
transferables::{TessellatedLayer, TileTessellated, Transferables, UnavailableLayer},
|
||||
transferables::{
|
||||
IndexedLayer, TessellatedLayer, TileTessellated, Transferables, UnavailableLayer,
|
||||
},
|
||||
},
|
||||
render::ShaderVertex,
|
||||
tile::Layer,
|
||||
};
|
||||
|
||||
// FIXME (wasm-executor): properly do this!, fix this whole file
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct WrapperWorldTileCoords(WorldTileCoords);
|
||||
unsafe impl TransparentWrapper<WorldTileCoords> for WrapperWorldTileCoords {}
|
||||
unsafe impl bytemuck::Zeroable for WrapperWorldTileCoords {}
|
||||
unsafe impl bytemuck::Pod for WrapperWorldTileCoords {}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct LongVertexShader([ShaderVertex; 15000]);
|
||||
unsafe impl TransparentWrapper<[ShaderVertex; 15000]> for LongVertexShader {}
|
||||
unsafe impl bytemuck::Zeroable for LongVertexShader {}
|
||||
unsafe impl bytemuck::Pod for LongVertexShader {}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct LongIndices([IndexDataType; 40000]);
|
||||
unsafe impl TransparentWrapper<[IndexDataType; 40000]> for LongIndices {}
|
||||
unsafe impl bytemuck::Zeroable for LongIndices {}
|
||||
unsafe impl bytemuck::Pod for LongIndices {}
|
||||
|
||||
#[derive(Copy, Clone, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
pub struct LinearTileTessellated {
|
||||
pub coords: WrapperWorldTileCoords,
|
||||
pub coords: WorldTileCoords,
|
||||
pub _padding: u8,
|
||||
}
|
||||
|
||||
impl TileTessellated for LinearTileTessellated {
|
||||
fn new(coords: WorldTileCoords) -> Self {
|
||||
Self {
|
||||
coords: WrapperWorldTileCoords::wrap(coords),
|
||||
coords,
|
||||
_padding: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn coords(&self) -> &WorldTileCoords {
|
||||
WrapperWorldTileCoords::peel_ref(&self.coords)
|
||||
&self.coords
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
pub struct LinearUnavailableLayer {
|
||||
pub coords: WrapperWorldTileCoords,
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct LinearLayerUnavailable {
|
||||
pub coords: WorldTileCoords,
|
||||
pub layer_name: [u8; 32],
|
||||
}
|
||||
|
||||
impl UnavailableLayer for LinearUnavailableLayer {
|
||||
impl UnavailableLayer for LinearLayerUnavailable {
|
||||
fn new(coords: WorldTileCoords, layer_name: String) -> Self {
|
||||
let mut new_layer_name = [0; 32];
|
||||
new_layer_name[0..layer_name.len()].clone_from_slice(layer_name.as_bytes());
|
||||
Self {
|
||||
coords: WrapperWorldTileCoords::wrap(coords),
|
||||
coords,
|
||||
layer_name: new_layer_name,
|
||||
}
|
||||
}
|
||||
|
||||
fn coords(&self) -> &WorldTileCoords {
|
||||
&self.coords
|
||||
}
|
||||
|
||||
fn to_stored_layer(self) -> StoredLayer {
|
||||
StoredLayer::UnavailableLayer {
|
||||
coords: WrapperWorldTileCoords::peel(self.coords),
|
||||
coords: self.coords,
|
||||
layer_name: String::from_utf8(Vec::from(self.layer_name)).unwrap(), // FIXME (wasm-executor): Remove unwrap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Pod, Zeroable)]
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct InnerData {
|
||||
pub coords: WrapperWorldTileCoords,
|
||||
pub coords: WorldTileCoords,
|
||||
pub layer_name: [u8; 32],
|
||||
pub layer_name_len: usize,
|
||||
pub vertices: LongVertexShader,
|
||||
pub vertices: [ShaderVertex; 15000],
|
||||
pub vertices_len: usize,
|
||||
pub indices: LongIndices,
|
||||
pub indices: [IndexDataType; 40000],
|
||||
pub indices_len: usize,
|
||||
pub usable_indices: u32,
|
||||
/// Holds for each feature the count of indices.
|
||||
@ -94,11 +76,11 @@ pub struct InnerData {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct LinearTessellatedLayer {
|
||||
pub struct LinearLayerTesselated {
|
||||
pub data: Box<InnerData>,
|
||||
}
|
||||
|
||||
impl TessellatedLayer for LinearTessellatedLayer {
|
||||
impl TessellatedLayer for LinearLayerTesselated {
|
||||
fn new(
|
||||
coords: WorldTileCoords,
|
||||
buffer: OverAlignedVertexBuffer<ShaderVertex, IndexDataType>,
|
||||
@ -106,15 +88,15 @@ impl TessellatedLayer for LinearTessellatedLayer {
|
||||
layer_data: Layer,
|
||||
) -> Self {
|
||||
let mut data = Box::new(InnerData {
|
||||
coords: WrapperWorldTileCoords::wrap(coords),
|
||||
coords,
|
||||
|
||||
layer_name: [0; 32],
|
||||
layer_name_len: layer_data.name.len(),
|
||||
|
||||
vertices: LongVertexShader::wrap([ShaderVertex::zeroed(); 15000]),
|
||||
vertices: [ShaderVertex::new([0.0, 0.0], [0.0, 0.0]); 15000],
|
||||
vertices_len: buffer.buffer.vertices.len(),
|
||||
|
||||
indices: LongIndices::wrap([IndexDataType::zeroed(); 40000]),
|
||||
indices: [0; 40000],
|
||||
indices_len: buffer.buffer.indices.len(),
|
||||
|
||||
usable_indices: buffer.usable_indices,
|
||||
@ -127,15 +109,15 @@ impl TessellatedLayer for LinearTessellatedLayer {
|
||||
warn!("vertices too large");
|
||||
return Self {
|
||||
data: Box::new(InnerData {
|
||||
coords: WrapperWorldTileCoords::wrap(coords),
|
||||
coords,
|
||||
|
||||
layer_name: [0; 32],
|
||||
layer_name_len: 0,
|
||||
|
||||
vertices: LongVertexShader::wrap([ShaderVertex::zeroed(); 15000]),
|
||||
vertices: [ShaderVertex::new([0.0, 0.0], [0.0, 0.0]); 15000],
|
||||
vertices_len: 0,
|
||||
|
||||
indices: LongIndices::wrap([IndexDataType::zeroed(); 40000]),
|
||||
indices: [0; 40000],
|
||||
indices_len: 0,
|
||||
|
||||
usable_indices: 0,
|
||||
@ -150,15 +132,15 @@ impl TessellatedLayer for LinearTessellatedLayer {
|
||||
warn!("indices too large");
|
||||
return Self {
|
||||
data: Box::new(InnerData {
|
||||
coords: WrapperWorldTileCoords::wrap(coords),
|
||||
coords,
|
||||
|
||||
layer_name: [0; 32],
|
||||
layer_name_len: 0,
|
||||
|
||||
vertices: LongVertexShader::wrap([ShaderVertex::zeroed(); 15000]),
|
||||
vertices: [ShaderVertex::new([0.0, 0.0], [0.0, 0.0]); 15000],
|
||||
vertices_len: 0,
|
||||
|
||||
indices: LongIndices::wrap([IndexDataType::zeroed(); 40000]),
|
||||
indices: [0; 40000],
|
||||
indices_len: 0,
|
||||
|
||||
usable_indices: 0,
|
||||
@ -173,15 +155,15 @@ impl TessellatedLayer for LinearTessellatedLayer {
|
||||
warn!("feature_indices too large");
|
||||
return Self {
|
||||
data: Box::new(InnerData {
|
||||
coords: WrapperWorldTileCoords::wrap(coords),
|
||||
coords,
|
||||
|
||||
layer_name: [0; 32],
|
||||
layer_name_len: 0,
|
||||
|
||||
vertices: LongVertexShader::wrap([ShaderVertex::zeroed(); 15000]),
|
||||
vertices: [ShaderVertex::new([0.0, 0.0], [0.0, 0.0]); 15000],
|
||||
vertices_len: 0,
|
||||
|
||||
indices: LongIndices::wrap([IndexDataType::zeroed(); 40000]),
|
||||
indices: [0; 40000],
|
||||
indices_len: 0,
|
||||
|
||||
usable_indices: 0,
|
||||
@ -192,25 +174,29 @@ impl TessellatedLayer for LinearTessellatedLayer {
|
||||
};
|
||||
}
|
||||
|
||||
data.vertices.0[0..buffer.buffer.vertices.len()].clone_from_slice(&buffer.buffer.vertices);
|
||||
data.indices.0[0..buffer.buffer.indices.len()].clone_from_slice(&buffer.buffer.indices);
|
||||
data.vertices[0..buffer.buffer.vertices.len()].clone_from_slice(&buffer.buffer.vertices);
|
||||
data.indices[0..buffer.buffer.indices.len()].clone_from_slice(&buffer.buffer.indices);
|
||||
data.feature_indices[0..feature_indices.len()].clone_from_slice(&feature_indices);
|
||||
data.layer_name[0..layer_data.name.len()].clone_from_slice(layer_data.name.as_bytes());
|
||||
|
||||
Self { data }
|
||||
}
|
||||
|
||||
fn coords(&self) -> &WorldTileCoords {
|
||||
&self.data.coords
|
||||
}
|
||||
|
||||
fn to_stored_layer(self) -> StoredLayer {
|
||||
// TODO: Avoid copies here
|
||||
StoredLayer::TessellatedLayer {
|
||||
coords: WrapperWorldTileCoords::peel(self.data.coords),
|
||||
coords: self.data.coords,
|
||||
layer_name: String::from_utf8(Vec::from(
|
||||
&self.data.layer_name[..self.data.layer_name_len],
|
||||
))
|
||||
.unwrap(), // FIXME (wasm-executor): Remove unwrap
|
||||
buffer: OverAlignedVertexBuffer::from_slices(
|
||||
&self.data.vertices.0[..self.data.vertices_len],
|
||||
&self.data.indices.0[..self.data.indices_len],
|
||||
&self.data.vertices[..self.data.vertices_len],
|
||||
&self.data.indices[..self.data.indices_len],
|
||||
self.data.usable_indices,
|
||||
),
|
||||
feature_indices: Vec::from(&self.data.feature_indices[..self.data.feature_indices_len]),
|
||||
@ -218,10 +204,33 @@ impl TessellatedLayer for LinearTessellatedLayer {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct LinearLayerIndexed {
|
||||
pub coords: WorldTileCoords,
|
||||
}
|
||||
|
||||
impl From<(WorldTileCoords, TileIndex)> for LinearLayerIndexed {
|
||||
fn from((coords, _index): (WorldTileCoords, TileIndex)) -> Self {
|
||||
Self { coords }
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexedLayer for LinearLayerIndexed {
|
||||
fn coords(&self) -> &WorldTileCoords {
|
||||
&self.coords
|
||||
}
|
||||
|
||||
fn to_tile_index(self) -> TileIndex {
|
||||
// FIXME replace this stub implementation
|
||||
TileIndex::Linear { list: vec![] }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LinearTransferables;
|
||||
|
||||
impl Transferables for LinearTransferables {
|
||||
type TileTessellated = LinearTileTessellated;
|
||||
type UnavailableLayer = LinearUnavailableLayer;
|
||||
type TessellatedLayer = LinearTessellatedLayer;
|
||||
type LayerUnavailable = LinearLayerUnavailable;
|
||||
type LayerTessellated = LinearLayerTesselated;
|
||||
type LayerIndexed = LinearLayerIndexed;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user