update
This commit is contained in:
@@ -133,6 +133,8 @@ struct TileBuffers {
|
||||
landuse_index_count: u32,
|
||||
water_vertex_buffer: wgpu::Buffer,
|
||||
water_index_count: u32,
|
||||
railway_vertex_buffer: wgpu::Buffer,
|
||||
railway_vertex_count: u32,
|
||||
}
|
||||
|
||||
struct AppState {
|
||||
@@ -141,6 +143,7 @@ struct AppState {
|
||||
buildings: HashMap<(i32, i32, i32), Vec<MapWay>>,
|
||||
landuse: HashMap<(i32, i32, i32), Vec<MapWay>>,
|
||||
water: HashMap<(i32, i32, i32), Vec<MapWay>>,
|
||||
railways: HashMap<(i32, i32, i32), Vec<MapWay>>,
|
||||
buffers: HashMap<(i32, i32, i32), std::sync::Arc<TileBuffers>>,
|
||||
loaded_tiles: HashSet<(i32, i32, i32)>,
|
||||
pending_tiles: HashSet<(i32, i32, i32)>,
|
||||
@@ -340,6 +343,7 @@ pub async fn run() {
|
||||
buildings: HashMap::new(),
|
||||
landuse: HashMap::new(),
|
||||
water: HashMap::new(),
|
||||
railways: HashMap::new(),
|
||||
buffers: HashMap::new(),
|
||||
loaded_tiles: HashSet::new(),
|
||||
pending_tiles: HashSet::new(),
|
||||
@@ -451,6 +455,7 @@ pub async fn run() {
|
||||
let building_pipeline = create_building_pipeline(&device, &config.format, &camera_bind_group_layout);
|
||||
let landuse_pipeline = create_landuse_pipeline(&device, &config.format, &camera_bind_group_layout);
|
||||
let water_pipeline = create_water_pipeline(&device, &config.format, &camera_bind_group_layout);
|
||||
let railway_pipeline = create_railway_pipeline(&device, &config.format, &camera_bind_group_layout);
|
||||
|
||||
|
||||
let window_clone = window.clone();
|
||||
@@ -665,9 +670,26 @@ pub async fn run() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process railways
|
||||
let mut railway_vertex_data = Vec::new();
|
||||
if let Some(railways) = state_guard.railways.get(tile) {
|
||||
for way in railways {
|
||||
if way.points.len() < 2 { continue; }
|
||||
|
||||
for i in 0..way.points.len() - 1 {
|
||||
let p1 = &way.points[i];
|
||||
let p2 = &way.points[i+1];
|
||||
let (x1, y1) = project(p1[0], p1[1]);
|
||||
let (x2, y2) = project(p2[0], p2[1]);
|
||||
railway_vertex_data.push(Vertex { position: [x1, y1] });
|
||||
railway_vertex_data.push(Vertex { position: [x2, y2] });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only create buffers if we have data
|
||||
if !point_instance_data.is_empty() || !road_vertex_data.is_empty() || !building_vertex_data.is_empty() || !landuse_vertex_data.is_empty() || !water_vertex_data.is_empty() {
|
||||
if !point_instance_data.is_empty() || !road_vertex_data.is_empty() || !building_vertex_data.is_empty() || !landuse_vertex_data.is_empty() || !water_vertex_data.is_empty() || !railway_vertex_data.is_empty() {
|
||||
let point_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Tile Instance Buffer"),
|
||||
contents: bytemuck::cast_slice(&point_instance_data),
|
||||
@@ -698,6 +720,12 @@ pub async fn run() {
|
||||
contents: bytemuck::cast_slice(&water_vertex_data),
|
||||
usage: wgpu::BufferUsages::VERTEX,
|
||||
});
|
||||
|
||||
let railway_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
|
||||
label: Some("Tile Railway Buffer"),
|
||||
contents: bytemuck::cast_slice(&railway_vertex_data),
|
||||
usage: wgpu::BufferUsages::VERTEX,
|
||||
});
|
||||
|
||||
state_guard.buffers.insert(*tile, std::sync::Arc::new(TileBuffers {
|
||||
point_instance_buffer: point_buffer,
|
||||
@@ -710,6 +738,8 @@ pub async fn run() {
|
||||
landuse_index_count: landuse_vertex_data.len() as u32,
|
||||
water_vertex_buffer: water_buffer,
|
||||
water_index_count: water_vertex_data.len() as u32,
|
||||
railway_vertex_buffer: railway_buffer,
|
||||
railway_vertex_count: railway_vertex_data.len() as u32,
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -771,6 +801,16 @@ pub async fn run() {
|
||||
None
|
||||
};
|
||||
|
||||
// Fetch railways
|
||||
let url_railways = format!("http://localhost:3000/api/tiles/{}/{}/{}/railways", z, x, y);
|
||||
let railways_data = if let Some(json) = fetch_cached(&url_railways).await {
|
||||
serde_json::from_str::<Vec<MapWay>>(&json).ok()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
|
||||
|
||||
let mut guard = state_clone.lock().unwrap();
|
||||
|
||||
if let Some(nodes) = nodes_data {
|
||||
@@ -799,6 +839,15 @@ pub async fn run() {
|
||||
guard.water.insert((z, x, y), water);
|
||||
}
|
||||
|
||||
if let Some(railways) = railways_data {
|
||||
if !railways.is_empty() {
|
||||
web_sys::console::log_1(&format!("Fetched {} railway items for tile {}/{}/{}", railways.len(), z, x, y).into());
|
||||
}
|
||||
guard.railways.insert((z, x, y), railways);
|
||||
}
|
||||
|
||||
|
||||
|
||||
guard.loaded_tiles.insert((z, x, y));
|
||||
guard.pending_tiles.remove(&(z, x, y));
|
||||
|
||||
@@ -881,6 +930,22 @@ pub async fn run() {
|
||||
rpass.draw(0..buffers.road_vertex_count, 0..1);
|
||||
}
|
||||
|
||||
// Draw Railways (on top of roads?)
|
||||
if buffers.railway_vertex_count > 0 {
|
||||
rpass.set_pipeline(&railway_pipeline);
|
||||
rpass.set_bind_group(0, &camera_bind_group, &[]);
|
||||
rpass.set_vertex_buffer(0, buffers.railway_vertex_buffer.slice(..));
|
||||
rpass.draw(0..buffers.railway_vertex_count, 0..1);
|
||||
}
|
||||
|
||||
// Draw Railways (on top of roads?)
|
||||
if buffers.railway_vertex_count > 0 {
|
||||
rpass.set_pipeline(&railway_pipeline);
|
||||
rpass.set_bind_group(0, &camera_bind_group, &[]);
|
||||
rpass.set_vertex_buffer(0, buffers.railway_vertex_buffer.slice(..));
|
||||
rpass.draw(0..buffers.railway_vertex_count, 0..1);
|
||||
}
|
||||
|
||||
// Draw Buildings (middle layer)
|
||||
if buffers.building_index_count > 0 {
|
||||
rpass.set_pipeline(&building_pipeline);
|
||||
@@ -1370,3 +1435,87 @@ fn create_water_pipeline(
|
||||
multiview: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn create_railway_pipeline(
|
||||
device: &wgpu::Device,
|
||||
format: &wgpu::TextureFormat,
|
||||
bind_group_layout: &wgpu::BindGroupLayout
|
||||
) -> wgpu::RenderPipeline {
|
||||
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: None,
|
||||
source: wgpu::ShaderSource::Wgsl(std::borrow::Cow::Borrowed(r#"
|
||||
struct CameraUniform {
|
||||
params: vec4<f32>,
|
||||
};
|
||||
@group(0) @binding(0)
|
||||
var<uniform> camera: CameraUniform;
|
||||
|
||||
struct VertexInput {
|
||||
@location(0) position: vec2<f32>,
|
||||
};
|
||||
|
||||
struct VertexOutput {
|
||||
@builtin(position) clip_position: vec4<f32>,
|
||||
};
|
||||
|
||||
@vertex
|
||||
fn vs_main(
|
||||
model: VertexInput,
|
||||
) -> VertexOutput {
|
||||
var out: VertexOutput;
|
||||
|
||||
let world_pos = model.position;
|
||||
|
||||
let x = world_pos.x * camera.params.x + camera.params.z;
|
||||
let y = world_pos.y * camera.params.y + camera.params.w;
|
||||
|
||||
out.clip_position = vec4<f32>(x, y, 0.0, 1.0);
|
||||
return out;
|
||||
}
|
||||
|
||||
@fragment
|
||||
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
|
||||
return vec4<f32>(0.3, 0.3, 0.3, 1.0); // Dark grey for railways
|
||||
}
|
||||
"#)),
|
||||
});
|
||||
|
||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||
label: Some("Railway Pipeline Layout"),
|
||||
bind_group_layouts: &[bind_group_layout],
|
||||
push_constant_ranges: &[],
|
||||
});
|
||||
|
||||
device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
|
||||
label: None,
|
||||
layout: Some(&pipeline_layout),
|
||||
vertex: wgpu::VertexState {
|
||||
module: &shader,
|
||||
entry_point: "vs_main",
|
||||
buffers: &[
|
||||
Vertex::desc(),
|
||||
],
|
||||
},
|
||||
fragment: Some(wgpu::FragmentState {
|
||||
module: &shader,
|
||||
entry_point: "fs_main",
|
||||
targets: &[Some(wgpu::ColorTargetState {
|
||||
format: *format,
|
||||
blend: Some(wgpu::BlendState::REPLACE),
|
||||
write_mask: wgpu::ColorWrites::ALL,
|
||||
})],
|
||||
}),
|
||||
primitive: wgpu::PrimitiveState {
|
||||
topology: wgpu::PrimitiveTopology::LineList,
|
||||
strip_index_format: None,
|
||||
front_face: wgpu::FrontFace::Ccw,
|
||||
cull_mode: None,
|
||||
unclipped_depth: false,
|
||||
polygon_mode: wgpu::PolygonMode::Fill,
|
||||
conservative: false,
|
||||
},
|
||||
depth_stencil: None,
|
||||
multisample: wgpu::MultisampleState::default(),
|
||||
multiview: None,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user