box2d-ruby 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +336 -0
  4. data/examples/contact_events.rb +22 -0
  5. data/examples/debug_draw.rb +15 -0
  6. data/examples/falling_ball.rb +19 -0
  7. data/examples/rugl_debug_draw.rb +68 -0
  8. data/examples/stagecraft_debug_draw.rb +64 -0
  9. data/examples/support/box2d_debug_lines.rb +125 -0
  10. data/ext/box2d/CMakeLists.txt +35 -0
  11. data/ext/box2d/extconf.rb +42 -0
  12. data/ext/box2d/native.c +9 -0
  13. data/ext/box2d/vendor/box2d/LICENSE +21 -0
  14. data/ext/box2d/vendor/box2d/VERSION +1 -0
  15. data/ext/box2d/vendor/box2d/include/box2d/base.h +131 -0
  16. data/ext/box2d/vendor/box2d/include/box2d/box2d.h +1222 -0
  17. data/ext/box2d/vendor/box2d/include/box2d/collision.h +830 -0
  18. data/ext/box2d/vendor/box2d/include/box2d/id.h +144 -0
  19. data/ext/box2d/vendor/box2d/include/box2d/math_functions.h +761 -0
  20. data/ext/box2d/vendor/box2d/include/box2d/types.h +1457 -0
  21. data/ext/box2d/vendor/box2d/src/CMakeLists.txt +223 -0
  22. data/ext/box2d/vendor/box2d/src/aabb.c +132 -0
  23. data/ext/box2d/vendor/box2d/src/aabb.h +56 -0
  24. data/ext/box2d/vendor/box2d/src/arena_allocator.c +112 -0
  25. data/ext/box2d/vendor/box2d/src/arena_allocator.h +48 -0
  26. data/ext/box2d/vendor/box2d/src/array.c +8 -0
  27. data/ext/box2d/vendor/box2d/src/array.h +179 -0
  28. data/ext/box2d/vendor/box2d/src/atomic.h +79 -0
  29. data/ext/box2d/vendor/box2d/src/bitset.c +67 -0
  30. data/ext/box2d/vendor/box2d/src/bitset.h +65 -0
  31. data/ext/box2d/vendor/box2d/src/body.c +1884 -0
  32. data/ext/box2d/vendor/box2d/src/body.h +194 -0
  33. data/ext/box2d/vendor/box2d/src/box2d.natvis +41 -0
  34. data/ext/box2d/vendor/box2d/src/broad_phase.c +524 -0
  35. data/ext/box2d/vendor/box2d/src/broad_phase.h +83 -0
  36. data/ext/box2d/vendor/box2d/src/constants.h +54 -0
  37. data/ext/box2d/vendor/box2d/src/constraint_graph.c +322 -0
  38. data/ext/box2d/vendor/box2d/src/constraint_graph.h +58 -0
  39. data/ext/box2d/vendor/box2d/src/contact.c +650 -0
  40. data/ext/box2d/vendor/box2d/src/contact.h +148 -0
  41. data/ext/box2d/vendor/box2d/src/contact_solver.c +2120 -0
  42. data/ext/box2d/vendor/box2d/src/contact_solver.h +54 -0
  43. data/ext/box2d/vendor/box2d/src/core.c +178 -0
  44. data/ext/box2d/vendor/box2d/src/core.h +149 -0
  45. data/ext/box2d/vendor/box2d/src/ctz.h +112 -0
  46. data/ext/box2d/vendor/box2d/src/distance.c +1415 -0
  47. data/ext/box2d/vendor/box2d/src/distance_joint.c +556 -0
  48. data/ext/box2d/vendor/box2d/src/dynamic_tree.c +1989 -0
  49. data/ext/box2d/vendor/box2d/src/geometry.c +1028 -0
  50. data/ext/box2d/vendor/box2d/src/hull.c +328 -0
  51. data/ext/box2d/vendor/box2d/src/id_pool.c +79 -0
  52. data/ext/box2d/vendor/box2d/src/id_pool.h +35 -0
  53. data/ext/box2d/vendor/box2d/src/island.c +977 -0
  54. data/ext/box2d/vendor/box2d/src/island.h +89 -0
  55. data/ext/box2d/vendor/box2d/src/joint.c +1272 -0
  56. data/ext/box2d/vendor/box2d/src/joint.h +335 -0
  57. data/ext/box2d/vendor/box2d/src/manifold.c +1726 -0
  58. data/ext/box2d/vendor/box2d/src/math_functions.c +159 -0
  59. data/ext/box2d/vendor/box2d/src/motor_joint.c +283 -0
  60. data/ext/box2d/vendor/box2d/src/mouse_joint.c +214 -0
  61. data/ext/box2d/vendor/box2d/src/mover.c +73 -0
  62. data/ext/box2d/vendor/box2d/src/prismatic_joint.c +656 -0
  63. data/ext/box2d/vendor/box2d/src/revolute_joint.c +534 -0
  64. data/ext/box2d/vendor/box2d/src/sensor.c +389 -0
  65. data/ext/box2d/vendor/box2d/src/sensor.h +36 -0
  66. data/ext/box2d/vendor/box2d/src/shape.c +1714 -0
  67. data/ext/box2d/vendor/box2d/src/shape.h +123 -0
  68. data/ext/box2d/vendor/box2d/src/solver.c +2038 -0
  69. data/ext/box2d/vendor/box2d/src/solver.h +155 -0
  70. data/ext/box2d/vendor/box2d/src/solver_set.c +613 -0
  71. data/ext/box2d/vendor/box2d/src/solver_set.h +57 -0
  72. data/ext/box2d/vendor/box2d/src/table.c +238 -0
  73. data/ext/box2d/vendor/box2d/src/table.h +37 -0
  74. data/ext/box2d/vendor/box2d/src/timer.c +185 -0
  75. data/ext/box2d/vendor/box2d/src/types.c +151 -0
  76. data/ext/box2d/vendor/box2d/src/weld_joint.c +310 -0
  77. data/ext/box2d/vendor/box2d/src/wheel_joint.c +551 -0
  78. data/ext/box2d/vendor/box2d/src/world.c +3301 -0
  79. data/ext/box2d/vendor/box2d/src/world.h +192 -0
  80. data/generator/generate.rb +316 -0
  81. data/generator/layout_probe.c +507 -0
  82. data/generator/verify_layouts.rb +32 -0
  83. data/lib/box2d/body.rb +172 -0
  84. data/lib/box2d/body_definition.rb +38 -0
  85. data/lib/box2d/body_shapes.rb +135 -0
  86. data/lib/box2d/chain.rb +61 -0
  87. data/lib/box2d/debug_draw.rb +118 -0
  88. data/lib/box2d/events.rb +103 -0
  89. data/lib/box2d/fixed_stepper.rb +39 -0
  90. data/lib/box2d/handle.rb +46 -0
  91. data/lib/box2d/hit.rb +5 -0
  92. data/lib/box2d/joint.rb +197 -0
  93. data/lib/box2d/native.rb +1462 -0
  94. data/lib/box2d/native_loader.rb +45 -0
  95. data/lib/box2d/pixel_scale.rb +29 -0
  96. data/lib/box2d/shape.rb +109 -0
  97. data/lib/box2d/shape_definition.rb +44 -0
  98. data/lib/box2d/value_conversion.rb +80 -0
  99. data/lib/box2d/version.rb +7 -0
  100. data/lib/box2d/world.rb +135 -0
  101. data/lib/box2d/world_joints.rb +156 -0
  102. data/lib/box2d/world_queries.rb +122 -0
  103. data/lib/box2d/world_registry.rb +95 -0
  104. data/lib/box2d.rb +31 -0
  105. data/script/build_platform_gem.rb +24 -0
  106. data/script/deterministic_scene.rb +56 -0
  107. data/script/update_deterministic_snapshot.rb +11 -0
  108. data/script/verify_platform_gem.rb +24 -0
  109. metadata +164 -0
@@ -0,0 +1,389 @@
1
+ // SPDX-FileCopyrightText: 2023 Erin Catto
2
+ // SPDX-License-Identifier: MIT
3
+
4
+ #include "sensor.h"
5
+
6
+ #include "array.h"
7
+ #include "body.h"
8
+ #include "contact.h"
9
+ #include "ctz.h"
10
+ #include "shape.h"
11
+ #include "world.h"
12
+
13
+ #include "box2d/collision.h"
14
+
15
+ #include <stddef.h>
16
+ #include <stdlib.h>
17
+
18
+ B2_ARRAY_SOURCE( b2ShapeRef, b2ShapeRef )
19
+ B2_ARRAY_SOURCE( b2Sensor, b2Sensor )
20
+ B2_ARRAY_SOURCE( b2SensorTaskContext, b2SensorTaskContext )
21
+
22
+ struct b2SensorQueryContext
23
+ {
24
+ b2World* world;
25
+ b2SensorTaskContext* taskContext;
26
+ b2Sensor* sensor;
27
+ b2Shape* sensorShape;
28
+ b2Transform transform;
29
+ };
30
+
31
+ // Sensor shapes need to
32
+ // - detect begin and end overlap events
33
+ // - events must be reported in deterministic order
34
+ // - maintain an active list of overlaps for query
35
+
36
+ // Assumption
37
+ // - sensors don't detect shapes on the same body
38
+
39
+ // Algorithm
40
+ // Query all sensors for overlaps
41
+ // Check against previous overlaps
42
+
43
+ // Data structures
44
+ // Each sensor has an double buffered array of overlaps
45
+ // These overlaps use a shape reference with index and generation
46
+
47
+ static bool b2SensorQueryCallback( int proxyId, uint64_t userData, void* context )
48
+ {
49
+ B2_UNUSED( proxyId );
50
+
51
+ int shapeId = (int)userData;
52
+
53
+ struct b2SensorQueryContext* queryContext = context;
54
+ b2Shape* sensorShape = queryContext->sensorShape;
55
+ int sensorShapeId = sensorShape->id;
56
+
57
+ if ( shapeId == sensorShapeId )
58
+ {
59
+ return true;
60
+ }
61
+
62
+ b2World* world = queryContext->world;
63
+ b2Shape* otherShape = b2ShapeArray_Get( &world->shapes, shapeId );
64
+
65
+ // Are sensor events enabled on the other shape?
66
+ if ( otherShape->enableSensorEvents == false )
67
+ {
68
+ return true;
69
+ }
70
+
71
+ // Skip shapes on the same body
72
+ if ( otherShape->bodyId == sensorShape->bodyId )
73
+ {
74
+ return true;
75
+ }
76
+
77
+ // Check filter
78
+ if ( b2ShouldShapesCollide( sensorShape->filter, otherShape->filter ) == false )
79
+ {
80
+ return true;
81
+ }
82
+
83
+ b2Transform otherTransform = b2GetBodyTransform( world, otherShape->bodyId );
84
+
85
+ b2DistanceInput input;
86
+ input.proxyA = b2MakeShapeDistanceProxy( sensorShape );
87
+ input.proxyB = b2MakeShapeDistanceProxy( otherShape );
88
+ input.transformA = queryContext->transform;
89
+ input.transformB = otherTransform;
90
+ input.useRadii = true;
91
+ b2SimplexCache cache = { 0 };
92
+ b2DistanceOutput output = b2ShapeDistance(&input, &cache, NULL, 0 );
93
+
94
+ bool overlaps = output.distance < 10.0f * FLT_EPSILON;
95
+ if ( overlaps == false )
96
+ {
97
+ return true;
98
+ }
99
+
100
+ // Record the overlap
101
+ b2Sensor* sensor = queryContext->sensor;
102
+ b2ShapeRef* shapeRef = b2ShapeRefArray_Add( &sensor->overlaps2 );
103
+ shapeRef->shapeId = shapeId;
104
+ shapeRef->generation = otherShape->generation;
105
+
106
+ return true;
107
+ }
108
+
109
+ static int b2CompareShapeRefs( const void* a, const void* b )
110
+ {
111
+ const b2ShapeRef* sa = a;
112
+ const b2ShapeRef* sb = b;
113
+
114
+ if ( sa->shapeId < sb->shapeId )
115
+ {
116
+ return -1;
117
+ }
118
+
119
+ if ( sa->shapeId == sb->shapeId )
120
+ {
121
+ if ( sa->generation < sb->generation )
122
+ {
123
+ return -1;
124
+ }
125
+
126
+ if ( sa->generation == sb->generation )
127
+ {
128
+ return 0;
129
+ }
130
+ }
131
+
132
+ return 1;
133
+ }
134
+
135
+ static void b2SensorTask( int startIndex, int endIndex, uint32_t threadIndex, void* context )
136
+ {
137
+ b2TracyCZoneNC( sensor_task, "Overlap", b2_colorBrown, true );
138
+
139
+ b2World* world = context;
140
+ B2_ASSERT( (int)threadIndex < world->workerCount );
141
+ b2SensorTaskContext* taskContext = world->sensorTaskContexts.data + threadIndex;
142
+
143
+ B2_ASSERT( startIndex < endIndex );
144
+
145
+ b2DynamicTree* trees = world->broadPhase.trees;
146
+ for ( int sensorIndex = startIndex; sensorIndex < endIndex; ++sensorIndex )
147
+ {
148
+ b2Sensor* sensor = b2SensorArray_Get( &world->sensors, sensorIndex );
149
+ b2Shape* sensorShape = b2ShapeArray_Get( &world->shapes, sensor->shapeId );
150
+
151
+ // swap overlap arrays
152
+ b2ShapeRefArray temp = sensor->overlaps1;
153
+ sensor->overlaps1 = sensor->overlaps2;
154
+ sensor->overlaps2 = temp;
155
+ b2ShapeRefArray_Clear( &sensor->overlaps2 );
156
+
157
+ b2Body* body = b2BodyArray_Get( &world->bodies, sensorShape->bodyId );
158
+ if ( body->setIndex == b2_disabledSet || sensorShape->enableSensorEvents == false )
159
+ {
160
+ if ( sensor->overlaps1.count != 0 )
161
+ {
162
+ b2SetBit( &taskContext->eventBits, sensorIndex );
163
+ }
164
+ continue;
165
+ }
166
+
167
+ b2Transform transform = b2GetBodyTransformQuick( world, body );
168
+
169
+ struct b2SensorQueryContext queryContext = {
170
+ .world = world,
171
+ .taskContext = taskContext,
172
+ .sensorShape = sensorShape,
173
+ .sensor = sensor,
174
+ .transform = transform,
175
+ };
176
+
177
+ B2_ASSERT( sensorShape->sensorIndex == sensorIndex );
178
+ b2AABB queryBounds = sensorShape->aabb;
179
+
180
+ // Query all trees
181
+ b2DynamicTree_Query( trees + 0, queryBounds, sensorShape->filter.maskBits, b2SensorQueryCallback, &queryContext );
182
+ b2DynamicTree_Query( trees + 1, queryBounds, sensorShape->filter.maskBits, b2SensorQueryCallback, &queryContext );
183
+ b2DynamicTree_Query( trees + 2, queryBounds, sensorShape->filter.maskBits, b2SensorQueryCallback, &queryContext );
184
+
185
+ // Sort the overlaps to enable finding begin and end events.
186
+ qsort( sensor->overlaps2.data, sensor->overlaps2.count, sizeof( b2ShapeRef ), b2CompareShapeRefs );
187
+
188
+ int count1 = sensor->overlaps1.count;
189
+ int count2 = sensor->overlaps2.count;
190
+ if ( count1 != count2 )
191
+ {
192
+ // something changed
193
+ b2SetBit( &taskContext->eventBits, sensorIndex );
194
+ }
195
+ else
196
+ {
197
+ for ( int i = 0; i < count1; ++i )
198
+ {
199
+ b2ShapeRef* s1 = sensor->overlaps1.data + i;
200
+ b2ShapeRef* s2 = sensor->overlaps2.data + i;
201
+
202
+ if ( s1->shapeId != s2->shapeId || s1->generation != s2->generation )
203
+ {
204
+ // something changed
205
+ b2SetBit( &taskContext->eventBits, sensorIndex );
206
+ break;
207
+ }
208
+ }
209
+ }
210
+ }
211
+
212
+ b2TracyCZoneEnd( sensor_task );
213
+ }
214
+
215
+ void b2OverlapSensors( b2World* world )
216
+ {
217
+ int sensorCount = world->sensors.count;
218
+ if ( sensorCount == 0 )
219
+ {
220
+ return;
221
+ }
222
+
223
+ B2_ASSERT( world->workerCount > 0 );
224
+
225
+ b2TracyCZoneNC( overlap_sensors, "Sensors", b2_colorMediumPurple, true );
226
+
227
+ for ( int i = 0; i < world->workerCount; ++i )
228
+ {
229
+ b2SetBitCountAndClear( &world->sensorTaskContexts.data[i].eventBits, sensorCount );
230
+ }
231
+
232
+ // Parallel-for sensors overlaps
233
+ int minRange = 16;
234
+ void* userSensorTask = world->enqueueTaskFcn( &b2SensorTask, sensorCount, minRange, world, world->userTaskContext );
235
+ world->taskCount += 1;
236
+ if ( userSensorTask != NULL )
237
+ {
238
+ world->finishTaskFcn( userSensorTask, world->userTaskContext );
239
+ }
240
+
241
+ b2TracyCZoneNC( sensor_state, "Events", b2_colorLightSlateGray, true );
242
+
243
+ b2BitSet* bitSet = &world->sensorTaskContexts.data[0].eventBits;
244
+ for ( int i = 1; i < world->workerCount; ++i )
245
+ {
246
+ b2InPlaceUnion( bitSet, &world->sensorTaskContexts.data[i].eventBits );
247
+ }
248
+
249
+ // Iterate sensors bits and publish events
250
+ // Process contact state changes. Iterate over set bits
251
+ uint64_t* bits = bitSet->bits;
252
+ uint32_t blockCount = bitSet->blockCount;
253
+
254
+ for ( uint32_t k = 0; k < blockCount; ++k )
255
+ {
256
+ uint64_t word = bits[k];
257
+ while ( word != 0 )
258
+ {
259
+ uint32_t ctz = b2CTZ64( word );
260
+ int sensorIndex = (int)( 64 * k + ctz );
261
+
262
+ b2Sensor* sensor = b2SensorArray_Get( &world->sensors, sensorIndex );
263
+ b2Shape* sensorShape = b2ShapeArray_Get( &world->shapes, sensor->shapeId );
264
+ b2ShapeId sensorId = { sensor->shapeId + 1, world->worldId, sensorShape->generation };
265
+
266
+ int count1 = sensor->overlaps1.count;
267
+ int count2 = sensor->overlaps2.count;
268
+ const b2ShapeRef* refs1 = sensor->overlaps1.data;
269
+ const b2ShapeRef* refs2 = sensor->overlaps2.data;
270
+
271
+ // overlaps1 can have overlaps that end
272
+ // overlaps2 can have overlaps that begin
273
+ int index1 = 0, index2 = 0;
274
+ while ( index1 < count1 && index2 < count2 )
275
+ {
276
+ const b2ShapeRef* r1 = refs1 + index1;
277
+ const b2ShapeRef* r2 = refs2 + index2;
278
+ if ( r1->shapeId == r2->shapeId )
279
+ {
280
+ if ( r1->generation < r2->generation )
281
+ {
282
+ // end
283
+ b2ShapeId visitorId = { r1->shapeId + 1, world->worldId, r1->generation };
284
+ b2SensorEndTouchEvent event = {
285
+ .sensorShapeId = sensorId,
286
+ .visitorShapeId = visitorId,
287
+ };
288
+ b2SensorEndTouchEventArray_Push( &world->sensorEndEvents[world->endEventArrayIndex], event );
289
+ index1 += 1;
290
+ }
291
+ else if ( r1->generation > r2->generation )
292
+ {
293
+ // begin
294
+ b2ShapeId visitorId = { r2->shapeId + 1, world->worldId, r2->generation };
295
+ b2SensorBeginTouchEvent event = { sensorId, visitorId };
296
+ b2SensorBeginTouchEventArray_Push( &world->sensorBeginEvents, event );
297
+ index2 += 1;
298
+ }
299
+ else
300
+ {
301
+ // persisted
302
+ index1 += 1;
303
+ index2 += 1;
304
+ }
305
+ }
306
+ else if ( r1->shapeId < r2->shapeId )
307
+ {
308
+ // end
309
+ b2ShapeId visitorId = { r1->shapeId + 1, world->worldId, r1->generation };
310
+ b2SensorEndTouchEvent event = { sensorId, visitorId };
311
+ b2SensorEndTouchEventArray_Push( &world->sensorEndEvents[world->endEventArrayIndex], event );
312
+ index1 += 1;
313
+ }
314
+ else
315
+ {
316
+ // begin
317
+ b2ShapeId visitorId = { r2->shapeId + 1, world->worldId, r2->generation };
318
+ b2SensorBeginTouchEvent event = { sensorId, visitorId };
319
+ b2SensorBeginTouchEventArray_Push( &world->sensorBeginEvents, event );
320
+ index2 += 1;
321
+ }
322
+ }
323
+
324
+ while ( index1 < count1 )
325
+ {
326
+ // end
327
+ const b2ShapeRef* r1 = refs1 + index1;
328
+ b2ShapeId visitorId = { r1->shapeId + 1, world->worldId, r1->generation };
329
+ b2SensorEndTouchEvent event = { sensorId, visitorId };
330
+ b2SensorEndTouchEventArray_Push( &world->sensorEndEvents[world->endEventArrayIndex], event );
331
+ index1 += 1;
332
+ }
333
+
334
+ while ( index2 < count2 )
335
+ {
336
+ // begin
337
+ const b2ShapeRef* r2 = refs2 + index2;
338
+ b2ShapeId visitorId = { r2->shapeId + 1, world->worldId, r2->generation };
339
+ b2SensorBeginTouchEvent event = { sensorId, visitorId };
340
+ b2SensorBeginTouchEventArray_Push( &world->sensorBeginEvents, event );
341
+ index2 += 1;
342
+ }
343
+
344
+ // Clear the smallest set bit
345
+ word = word & ( word - 1 );
346
+ }
347
+ }
348
+
349
+ b2TracyCZoneEnd( sensor_state );
350
+ b2TracyCZoneEnd( overlap_sensors );
351
+ }
352
+
353
+ void b2DestroySensor( b2World* world, b2Shape* sensorShape )
354
+ {
355
+ b2Sensor* sensor = b2SensorArray_Get( &world->sensors, sensorShape->sensorIndex );
356
+ for ( int i = 0; i < sensor->overlaps2.count; ++i )
357
+ {
358
+ b2ShapeRef* ref = sensor->overlaps2.data + i;
359
+ b2SensorEndTouchEvent event = {
360
+ .sensorShapeId =
361
+ {
362
+ .index1 = sensorShape->id + 1,
363
+ .generation = sensorShape->generation,
364
+ .world0 = world->worldId,
365
+ },
366
+ .visitorShapeId =
367
+ {
368
+ .index1 = ref->shapeId + 1,
369
+ .generation = ref->generation,
370
+ .world0 = world->worldId,
371
+ },
372
+ };
373
+
374
+ b2SensorEndTouchEventArray_Push( world->sensorEndEvents + world->endEventArrayIndex, event );
375
+ }
376
+
377
+ // Destroy sensor
378
+ b2ShapeRefArray_Destroy( &sensor->overlaps1 );
379
+ b2ShapeRefArray_Destroy( &sensor->overlaps2 );
380
+
381
+ int movedIndex = b2SensorArray_RemoveSwap( &world->sensors, sensorShape->sensorIndex );
382
+ if ( movedIndex != B2_NULL_INDEX )
383
+ {
384
+ // Fixup moved sensor
385
+ b2Sensor* movedSensor = b2SensorArray_Get( &world->sensors, sensorShape->sensorIndex );
386
+ b2Shape* otherSensorShape = b2ShapeArray_Get( &world->shapes, movedSensor->shapeId );
387
+ otherSensorShape->sensorIndex = sensorShape->sensorIndex;
388
+ }
389
+ }
@@ -0,0 +1,36 @@
1
+ // SPDX-FileCopyrightText: 2023 Erin Catto
2
+ // SPDX-License-Identifier: MIT
3
+
4
+ #pragma once
5
+
6
+ #include "array.h"
7
+ #include "bitset.h"
8
+
9
+ typedef struct b2Shape b2Shape;
10
+ typedef struct b2World b2World;
11
+
12
+ typedef struct b2ShapeRef
13
+ {
14
+ int shapeId;
15
+ uint16_t generation;
16
+ } b2ShapeRef;
17
+
18
+ typedef struct b2Sensor
19
+ {
20
+ b2ShapeRefArray overlaps1;
21
+ b2ShapeRefArray overlaps2;
22
+ int shapeId;
23
+ } b2Sensor;
24
+
25
+ typedef struct b2SensorTaskContext
26
+ {
27
+ b2BitSet eventBits;
28
+ } b2SensorTaskContext;
29
+
30
+ void b2OverlapSensors( b2World* world );
31
+
32
+ void b2DestroySensor( b2World* world, b2Shape* sensorShape );
33
+
34
+ B2_ARRAY_INLINE( b2ShapeRef, b2ShapeRef )
35
+ B2_ARRAY_INLINE( b2Sensor, b2Sensor )
36
+ B2_ARRAY_INLINE( b2SensorTaskContext, b2SensorTaskContext )