1use crate::bitset::BitSet;
9use crate::core::NULL_INDEX;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct SensorHit {
14 pub sensor_id: i32,
15 pub visitor_id: i32,
16}
17
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub struct Visitor {
21 pub shape_id: i32,
22 pub generation: u16,
23}
24
25#[derive(Debug, Clone, Default)]
30pub struct Sensor {
31 pub hits: Vec<Visitor>,
32 pub overlaps1: Vec<Visitor>,
33 pub overlaps2: Vec<Visitor>,
34 pub shape_id: i32,
35}
36
37impl Sensor {
38 pub fn new(shape_id: i32) -> Sensor {
39 Sensor {
40 hits: Vec::new(),
41 overlaps1: Vec::new(),
42 overlaps2: Vec::new(),
43 shape_id,
44 }
45 }
46}
47
48#[derive(Debug, Clone, Default)]
50pub struct SensorTaskContext {
51 pub event_bits: BitSet,
52}
53
54#[derive(Debug, Clone, Default)]
56pub struct SensorOverlaps {
57 pub overlaps: Vec<i32>,
58}
59
60impl Default for SensorHit {
61 fn default() -> Self {
62 SensorHit {
63 sensor_id: NULL_INDEX,
64 visitor_id: NULL_INDEX,
65 }
66 }
67}
68
69pub fn destroy_sensor(world: &mut crate::world::World, sensor_shape_id: i32) {
73 use crate::events::SensorEndTouchEvent;
74 use crate::id::ShapeId;
75
76 let sensor_index = world.shapes[sensor_shape_id as usize].sensor_index;
77 let sensor_generation = world.shapes[sensor_shape_id as usize].generation;
78
79 let overlaps2 = std::mem::take(&mut world.sensors[sensor_index as usize].overlaps2);
80 for visitor in &overlaps2 {
81 let event = SensorEndTouchEvent {
82 sensor_shape_id: ShapeId {
83 index1: sensor_shape_id + 1,
84 world0: world.world_id,
85 generation: sensor_generation,
86 },
87 visitor_shape_id: ShapeId {
88 index1: visitor.shape_id + 1,
89 world0: world.world_id,
90 generation: visitor.generation,
91 },
92 };
93
94 world.sensor_end_events[world.end_event_array_index as usize].push(event);
95 }
96
97 let moved_index = world.sensors.len() as i32 - 1;
99 world.sensors.swap_remove(sensor_index as usize);
100 if moved_index != sensor_index {
101 let moved_shape_id = world.sensors[sensor_index as usize].shape_id;
103 world.shapes[moved_shape_id as usize].sensor_index = sensor_index;
104 }
105}
106
107pub fn overlap_sensors(world: &mut crate::world::World) {
110 use crate::distance::{shape_distance, DistanceInput, SimplexCache};
111 use crate::events::{SensorBeginTouchEvent, SensorEndTouchEvent};
112 use crate::id::ShapeId;
113 use crate::math_functions::inv_mul_world_transforms;
114 use crate::shape::{make_shape_distance_proxy, should_shapes_collide};
115 use crate::solver_set::DISABLED_SET;
116
117 let sensor_count = world.sensors.len();
118 if sensor_count == 0 {
119 return;
120 }
121
122 world.sensor_task_contexts[0]
123 .event_bits
124 .set_bit_count_and_clear(sensor_count as u32);
125
126 for sensor_index in 0..sensor_count {
128 {
130 let sensor = &mut world.sensors[sensor_index];
131 std::mem::swap(&mut sensor.overlaps1, &mut sensor.overlaps2);
132 sensor.overlaps2.clear();
133
134 let hits = std::mem::take(&mut sensor.hits);
136 sensor.overlaps2.extend_from_slice(&hits);
137 }
138
139 let sensor_shape_id = world.sensors[sensor_index].shape_id;
140 let (sensor_body_id, sensor_enabled) = {
141 let shape = &world.shapes[sensor_shape_id as usize];
142 (shape.body_id, shape.enable_sensor_events)
143 };
144
145 if world.bodies[sensor_body_id as usize].set_index == DISABLED_SET || !sensor_enabled {
146 if !world.sensors[sensor_index].overlaps1.is_empty() {
147 world.sensor_task_contexts[0]
150 .event_bits
151 .set_bit(sensor_index as u32);
152 }
153 continue;
154 }
155
156 let transform = crate::body::get_body_transform(world, sensor_body_id);
157
158 debug_assert!(world.shapes[sensor_shape_id as usize].sensor_index == sensor_index as i32);
159 let query_bounds = world.shapes[sensor_shape_id as usize].aabb;
160 let mask_bits = world.shapes[sensor_shape_id as usize].filter.mask_bits;
161
162 let mut new_overlaps: Vec<Visitor> = Vec::new();
165 {
166 let world_ref: &crate::world::World = world;
167 let sensor_shape = &world_ref.shapes[sensor_shape_id as usize];
168
169 let mut callback = |_proxy_id: i32, user_data: u64| -> bool {
170 let shape_id = user_data as i32;
171
172 if shape_id == sensor_shape_id {
173 return true;
174 }
175
176 let other_shape = &world_ref.shapes[shape_id as usize];
177
178 if !other_shape.enable_sensor_events {
180 return true;
181 }
182
183 if other_shape.body_id == sensor_shape.body_id {
185 return true;
186 }
187
188 if !should_shapes_collide(sensor_shape.filter, other_shape.filter) {
190 return true;
191 }
192
193 if sensor_shape.enable_custom_filtering || other_shape.enable_custom_filtering {
195 if let Some(custom_filter_fcn) = world_ref.custom_filter_fcn {
196 let id_a = ShapeId {
197 index1: sensor_shape_id + 1,
198 world0: world_ref.world_id,
199 generation: sensor_shape.generation,
200 };
201 let id_b = ShapeId {
202 index1: shape_id + 1,
203 world0: world_ref.world_id,
204 generation: other_shape.generation,
205 };
206 if !custom_filter_fcn(id_a, id_b, world_ref.custom_filter_context) {
207 return true;
208 }
209 }
210 }
211
212 let other_transform =
215 crate::body::get_body_transform(world_ref, other_shape.body_id);
216
217 let input = DistanceInput {
218 proxy_a: make_shape_distance_proxy(sensor_shape),
219 proxy_b: make_shape_distance_proxy(other_shape),
220 transform: inv_mul_world_transforms(transform, other_transform),
221 use_radii: true,
222 };
223 let mut cache = SimplexCache::default();
224 let output = shape_distance(&input, &mut cache, None);
225
226 let overlaps = output.distance < 10.0 * f32::EPSILON;
227 if !overlaps {
228 return true;
229 }
230
231 new_overlaps.push(Visitor {
233 shape_id,
234 generation: other_shape.generation,
235 });
236
237 true
238 };
239
240 for tree in &world_ref.broad_phase.trees {
241 tree.query(query_bounds, mask_bits, &mut callback);
242 }
243 }
244
245 let sensor = &mut world.sensors[sensor_index];
246 sensor.overlaps2.extend_from_slice(&new_overlaps);
247
248 sensor.overlaps2.sort_by_key(|visitor| visitor.shape_id);
252
253 sensor.overlaps2.dedup_by_key(|visitor| visitor.shape_id);
256
257 let count1 = sensor.overlaps1.len();
258 let count2 = sensor.overlaps2.len();
259 if count1 != count2 {
260 world.sensor_task_contexts[0]
262 .event_bits
263 .set_bit(sensor_index as u32);
264 } else {
265 for i in 0..count1 {
266 let s1 = sensor.overlaps1[i];
267 let s2 = sensor.overlaps2[i];
268
269 if s1.shape_id != s2.shape_id || s1.generation != s2.generation {
270 world.sensor_task_contexts[0]
272 .event_bits
273 .set_bit(sensor_index as u32);
274 break;
275 }
276 }
277 }
278 }
279
280 let world_id = world.world_id;
282 let end_event_array_index = world.end_event_array_index as usize;
283
284 let block_count = world.sensor_task_contexts[0].event_bits.block_count();
285 for k in 0..block_count {
286 let mut word = world.sensor_task_contexts[0].event_bits.block(k);
287 while word != 0 {
288 let ctz = word.trailing_zeros();
289 let sensor_index = (64 * k + ctz) as usize;
290
291 let sensor_shape_id = world.sensors[sensor_index].shape_id;
292 let sensor_generation = world.shapes[sensor_shape_id as usize].generation;
293 let sensor_id = ShapeId {
294 index1: sensor_shape_id + 1,
295 world0: world_id,
296 generation: sensor_generation,
297 };
298
299 let count1 = world.sensors[sensor_index].overlaps1.len();
300 let count2 = world.sensors[sensor_index].overlaps2.len();
301
302 let mut index1 = 0;
305 let mut index2 = 0;
306 while index1 < count1 && index2 < count2 {
307 let r1 = world.sensors[sensor_index].overlaps1[index1];
308 let r2 = world.sensors[sensor_index].overlaps2[index2];
309 if r1.shape_id == r2.shape_id {
310 match r1.generation.cmp(&r2.generation) {
311 std::cmp::Ordering::Less => {
312 let visitor_id = ShapeId {
314 index1: r1.shape_id + 1,
315 world0: world_id,
316 generation: r1.generation,
317 };
318 world.sensor_end_events[end_event_array_index].push(
319 SensorEndTouchEvent {
320 sensor_shape_id: sensor_id,
321 visitor_shape_id: visitor_id,
322 },
323 );
324 index1 += 1;
325 }
326 std::cmp::Ordering::Greater => {
327 let visitor_id = ShapeId {
329 index1: r2.shape_id + 1,
330 world0: world_id,
331 generation: r2.generation,
332 };
333 world.sensor_begin_events.push(SensorBeginTouchEvent {
334 sensor_shape_id: sensor_id,
335 visitor_shape_id: visitor_id,
336 });
337 index2 += 1;
338 }
339 std::cmp::Ordering::Equal => {
340 index1 += 1;
342 index2 += 1;
343 }
344 }
345 } else if r1.shape_id < r2.shape_id {
346 let visitor_id = ShapeId {
348 index1: r1.shape_id + 1,
349 world0: world_id,
350 generation: r1.generation,
351 };
352 world.sensor_end_events[end_event_array_index].push(SensorEndTouchEvent {
353 sensor_shape_id: sensor_id,
354 visitor_shape_id: visitor_id,
355 });
356 index1 += 1;
357 } else {
358 let visitor_id = ShapeId {
360 index1: r2.shape_id + 1,
361 world0: world_id,
362 generation: r2.generation,
363 };
364 world.sensor_begin_events.push(SensorBeginTouchEvent {
365 sensor_shape_id: sensor_id,
366 visitor_shape_id: visitor_id,
367 });
368 index2 += 1;
369 }
370 }
371
372 while index1 < count1 {
373 let r1 = world.sensors[sensor_index].overlaps1[index1];
375 let visitor_id = ShapeId {
376 index1: r1.shape_id + 1,
377 world0: world_id,
378 generation: r1.generation,
379 };
380 world.sensor_end_events[end_event_array_index].push(SensorEndTouchEvent {
381 sensor_shape_id: sensor_id,
382 visitor_shape_id: visitor_id,
383 });
384 index1 += 1;
385 }
386
387 while index2 < count2 {
388 let r2 = world.sensors[sensor_index].overlaps2[index2];
390 let visitor_id = ShapeId {
391 index1: r2.shape_id + 1,
392 world0: world_id,
393 generation: r2.generation,
394 };
395 world.sensor_begin_events.push(SensorBeginTouchEvent {
396 sensor_shape_id: sensor_id,
397 visitor_shape_id: visitor_id,
398 });
399 index2 += 1;
400 }
401
402 word &= word - 1;
404 }
405 }
406}