This commit is contained in:
Dongho Kim
2025-12-19 02:24:05 +09:00
parent 1dcdce3ef1
commit 136723ca24
20 changed files with 1422 additions and 603 deletions

View File

@@ -105,17 +105,20 @@ pub async fn run() {
});
let mut msaa_view = msaa_texture.create_view(&wgpu::TextureViewDescriptor::default());
// Domain State
// Domain State - Initial view centered on Munich (lat 48.1351, lon 11.5820)
let camera = Arc::new(Mutex::new(Camera {
x: 0.5307617,
y: 0.3500976,
zoom: 2048.0,
x: 0.5322, // Munich longitude in Mercator
y: 0.3195, // Munich latitude in Mercator
zoom: 4000.0, // Good city-level zoom
aspect: width as f32 / height as f32,
}));
let mut input = InputState::new();
let state = Arc::new(Mutex::new(AppState::new()));
TransitService::set_global_state(state.clone());
// Label camera tracking
let mut last_label_camera: (f32, f32, f32) = (0.0, 0.0, 0.0); // (x, y, zoom)
// Camera Buffer
let is_dark_init = win.document()
@@ -313,7 +316,7 @@ pub async fn run() {
config.height = height;
surface.configure(&device, &config);
// Recreate MSAA
// Recreate MSAA texture for the new size
msaa_texture = device.create_texture(&wgpu::TextureDescriptor {
label: Some("Multisampled Texture"),
size: wgpu::Extent3d { width, height, depth_or_array_layers: 1 },
@@ -395,6 +398,9 @@ pub async fn run() {
};
if let Some(data) = tile_data {
// Pre-compute labels from tile data (expensive, but only once per tile)
let labels = crate::labels::extract_labels(&data);
let mut guard = state_clone.lock().unwrap();
guard.nodes.insert((z, x, y), data.nodes);
guard.ways.insert((z, x, y), data.ways);
@@ -402,6 +408,7 @@ pub async fn run() {
guard.landuse.insert((z, x, y), data.landuse);
guard.water.insert((z, x, y), data.water);
guard.railways.insert((z, x, y), data.railways);
guard.tile_labels.insert((z, x, y), labels);
guard.loaded_tiles.insert((z, x, y));
guard.pending_tiles.remove(&(z, x, y));
window_clone.request_redraw();
@@ -544,15 +551,7 @@ pub async fn run() {
}
}
rpass.set_pipeline(&render_service.railway_pipeline);
rpass.set_bind_group(0, &camera_bind_group, &[]);
for buffers in &tiles_to_render {
if buffers.railway_vertex_count > 0 {
rpass.set_vertex_buffer(0, buffers.railway_vertex_buffer.slice(..));
rpass.draw(0..buffers.railway_vertex_count, 0..1);
}
}
// Buildings (rendered before railways so transit lines appear on top)
rpass.set_pipeline(&render_service.building_pipeline);
rpass.set_bind_group(0, &camera_bind_group, &[]);
for buffers in &tiles_to_render {
@@ -561,29 +560,51 @@ pub async fn run() {
rpass.draw(0..buffers.building_index_count, 0..1);
}
}
// Railways (rendered LAST so they appear on top of roads and buildings)
rpass.set_pipeline(&render_service.railway_pipeline);
rpass.set_bind_group(0, &camera_bind_group, &[]);
for buffers in &tiles_to_render {
if buffers.railway_vertex_count > 0 {
rpass.set_vertex_buffer(0, buffers.railway_vertex_buffer.slice(..));
rpass.draw(0..buffers.railway_vertex_count, 0..1);
}
}
}
queue.submit(Some(encoder.finish()));
frame.present();
// Extract minimal data to avoid RefCell conflicts in winit
let (cam_x, cam_y, cam_zoom, cam_aspect) = {
let cam = camera.lock().unwrap();
(cam.x, cam.y, cam.zoom, cam.aspect)
};
let (nodes_for_labels, show_transit, user_location) = {
let s = state.lock().unwrap();
(s.nodes.clone(), s.show_transit, s.user_location)
// We hold the lock for update_labels to avoid cloning the massive nodes map
let state_guard = state.lock().unwrap();
let camera_guard = camera.lock().unwrap();
// Helper struct to represent camera for update_labels
let temp_camera = Camera {
x: camera_guard.x,
y: camera_guard.y,
zoom: camera_guard.zoom,
aspect: camera_guard.aspect
};
// Construct temporary Camera and AppState for update_labels
let temp_camera = Camera { x: cam_x, y: cam_y, zoom: cam_zoom, aspect: cam_aspect };
let mut temp_state = AppState::new();
temp_state.nodes = nodes_for_labels;
temp_state.show_transit = show_transit;
// Update labels every frame to ensure they move smoothly with the map
// Performance is maintained through zoom-based label limits in labels.rs
last_label_camera = (camera_guard.x, camera_guard.y, camera_guard.zoom);
update_labels(
&web_sys::window().unwrap(),
&temp_camera,
&state_guard,
config.width as f64,
config.height as f64,
window.scale_factor()
);
// Now call update_labels without holding any locks
update_labels(&web_sys::window().unwrap(), &temp_camera, &temp_state, config.width as f64, config.height as f64, window.scale_factor());
let user_location = state_guard.user_location;
let show_transit = state_guard.show_transit;
drop(camera_guard);
drop(state_guard);
// Update user location indicator (blue dot)
if let Some((lat, lon)) = user_location {