1use std::borrow::Cow;
2
3use cgmath::{Matrix3, Vector3};
4
5use crate::{
6 context::MapContext,
7 coords::{EXTENT, TILE_SIZE},
8 euclid::Point2D,
9 legacy::{
10 buckets::symbol_bucket::PlacedSymbol,
11 collision_feature::{CollisionBox, CollisionFeature},
12 collision_index::CollisionIndex,
13 geometry::feature_index::{IndexedSubfeature, RefIndexedSubfeature},
14 geometry_tile_data::GeometryCoordinates,
15 MapMode,
16 },
17 render::{
18 eventually::{Eventually, Eventually::Initialized},
19 shaders::SDFShaderFeatureMetadata,
20 tile_view_pattern::WgpuTileViewPattern,
21 Renderer,
22 },
23 sdf::{SymbolBufferPool, SymbolLayersDataComponent},
24 tcs::system::{System, SystemError, SystemResult},
25};
26
27pub struct CollisionSystem {}
28
29impl Default for CollisionSystem {
30 fn default() -> Self {
31 Self::new()
32 }
33}
34
35impl CollisionSystem {
36 pub fn new() -> Self {
37 Self {}
38 }
39}
40
41impl System for CollisionSystem {
42 fn name(&self) -> Cow<'static, str> {
43 "sdf_populate_world_system".into()
44 }
45
46 fn run(
47 &mut self,
48 MapContext {
49 world,
50 view_state,
51 renderer: Renderer { device, queue, .. },
52 ..
53 }: &mut MapContext,
54 ) -> SystemResult {
55 let Some((Initialized(tile_view_pattern), Initialized(symbol_buffer_pool))) =
56 world.resources.query_mut::<(
57 &mut Eventually<WgpuTileViewPattern>,
58 &mut Eventually<SymbolBufferPool>,
59 )>()
60 else {
61 return Err(SystemError::Dependencies);
62 };
63
64 if !view_state.did_camera_change() {
65 }
68
69 let mut collision_index = CollisionIndex::new(view_state, MapMode::Continuous);
70
71 for view_tile in tile_view_pattern.iter() {
72 let coords = view_tile.coords();
73 if let Some(component) = world.tiles.query::<&SymbolLayersDataComponent>(coords) {
74 for layer in &component.layers {
75 let metadata_count = if layer.features.is_empty() {
76 layer.new_buffer.buffer.vertices.len()
77 } else {
78 layer
79 .features
80 .last()
81 .map(|feature| feature.indices.end)
82 .unwrap_or_default()
83 };
84 let mut feature_metadata =
85 vec![SDFShaderFeatureMetadata { opacity: 1.0 }; metadata_count];
86
87 for feature in &layer.features {
88 let transform = coords.transform_for_zoom(view_state.zoom());
91
92 let pos_matrix = view_state
93 .view_projection()
94 .to_model_view_projection(transform);
95
96 let zoom_factor = view_state.zoom().scale_to_tile(&coords);
97
98 let font_scale = 6.0;
99 let scaling = Matrix3::from_cols(
100 Vector3::new(zoom_factor * font_scale, 0.0, 0.0),
101 Vector3::new(0.0, zoom_factor * font_scale, 0.0),
102 Vector3::new(0.0, 0.0, 1.0),
103 );
104
105 let vec3 = Vector3::new(
106 feature.bbox.max.x as f64,
107 feature.bbox.max.y as f64,
108 0.0f64,
109 );
110 let text_anchor = Vector3::new(
111 feature.text_anchor.x as f64,
112 feature.text_anchor.y as f64,
113 0.0f64,
114 );
115
116 let shader = pos_matrix.get()
117 * (scaling * (vec3 - text_anchor) + text_anchor).extend(1.0);
118 let window = view_state.clip_to_window(&shader);
119
120 let anchor_point =
123 Point2D::new(feature.bbox.min.x as f64, feature.bbox.min.y as f64); let boxes = vec![CollisionBox {
126 anchor: anchor_point,
127 x1: 0.0 * (EXTENT / TILE_SIZE),
128 y1: 0. * (EXTENT / TILE_SIZE),
129 x2: (feature.bbox.max.x - feature.bbox.min.x) as f64, y2: (feature.bbox.max.y - feature.bbox.min.y) as f64, signed_distance_from_anchor: 0.0,
132 }]; let mut projected_boxes = vec![];
135 let collision_feature = CollisionFeature {
136 boxes,
137 indexed_feature: IndexedSubfeature {
138 ref_: RefIndexedSubfeature {
139 index: 0,
140 sort_index: 0,
141 source_layer_name: "".to_string(),
142 bucket_leader_id: "".to_string(),
143 bucket_instance_id: 0,
144 collision_group_id: 0,
145 },
146 source_layer_name_copy: "".to_string(),
147 bucket_leader_idcopy: "".to_string(),
148 },
149 along_line: false, };
151 let (placed_text, is_offscreen) = collision_index.place_feature(
152 &collision_feature,
153 Point2D::zero(), &pos_matrix,
155 &pos_matrix.get(), 1.0,
158 &PlacedSymbol {
159 anchor_point,
160 segment: 0,
161 lower_size: 0.0,
162 upper_size: 0.0,
163 line_offset: [0., 0.],
164 writing_modes: Default::default(),
165 line: GeometryCoordinates(vec![anchor_point.cast()]), tile_distances: vec![], glyph_offsets: vec![0., 0.], hidden: false,
169 vertex_start_index: 0,
170 cross_tile_id: 0,
171 placed_orientation: None,
172 angle: 0.0,
173
174 placed_icon_index: None,
175 },
176 view_state.zoom().scale_to_zoom_level(coords.z),
177 6.0,
178 false,
179 false,
180 false,
181 None, Some(|f: &IndexedSubfeature| true), &mut projected_boxes, );
185 if feature.str.starts_with("Ette") {
186 }
190
191 if placed_text {
192 collision_index.insert_feature(
193 collision_feature,
194 &projected_boxes,
195 false,
196 55,
197 66,
198 );
199
200 for index in feature.indices.clone() {
201 let index = layer.new_buffer.buffer.indices[index] as usize;
202 feature_metadata[index].opacity = 1.0;
203 }
204 } else {
205 for index in feature.indices.clone() {
206 let index = layer.new_buffer.buffer.indices[index] as usize;
207 feature_metadata[index].opacity = 0.0;
208 }
209
210 }
212 }
213
214 if let Some(layer_at_coords) = symbol_buffer_pool.index().get_layers(coords) {
215 for entry in layer_at_coords {
216 debug_assert_eq!(entry.coords, coords);
217
218 let source_layer = entry.style_layer.source_layer.as_ref().unwrap();
219
220 if source_layer != &layer.source_layer {
221 continue;
222 }
223
224 symbol_buffer_pool.update_feature_metadata(
225 queue,
226 entry,
227 &feature_metadata,
228 );
229 }
230 }
231 }
232 }
233 }
234 Ok(())
235 }
236}