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.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +336 -0
- data/examples/contact_events.rb +22 -0
- data/examples/debug_draw.rb +15 -0
- data/examples/falling_ball.rb +19 -0
- data/examples/rugl_debug_draw.rb +68 -0
- data/examples/stagecraft_debug_draw.rb +64 -0
- data/examples/support/box2d_debug_lines.rb +125 -0
- data/ext/box2d/CMakeLists.txt +35 -0
- data/ext/box2d/extconf.rb +42 -0
- data/ext/box2d/native.c +9 -0
- data/ext/box2d/vendor/box2d/LICENSE +21 -0
- data/ext/box2d/vendor/box2d/VERSION +1 -0
- data/ext/box2d/vendor/box2d/include/box2d/base.h +131 -0
- data/ext/box2d/vendor/box2d/include/box2d/box2d.h +1222 -0
- data/ext/box2d/vendor/box2d/include/box2d/collision.h +830 -0
- data/ext/box2d/vendor/box2d/include/box2d/id.h +144 -0
- data/ext/box2d/vendor/box2d/include/box2d/math_functions.h +761 -0
- data/ext/box2d/vendor/box2d/include/box2d/types.h +1457 -0
- data/ext/box2d/vendor/box2d/src/CMakeLists.txt +223 -0
- data/ext/box2d/vendor/box2d/src/aabb.c +132 -0
- data/ext/box2d/vendor/box2d/src/aabb.h +56 -0
- data/ext/box2d/vendor/box2d/src/arena_allocator.c +112 -0
- data/ext/box2d/vendor/box2d/src/arena_allocator.h +48 -0
- data/ext/box2d/vendor/box2d/src/array.c +8 -0
- data/ext/box2d/vendor/box2d/src/array.h +179 -0
- data/ext/box2d/vendor/box2d/src/atomic.h +79 -0
- data/ext/box2d/vendor/box2d/src/bitset.c +67 -0
- data/ext/box2d/vendor/box2d/src/bitset.h +65 -0
- data/ext/box2d/vendor/box2d/src/body.c +1884 -0
- data/ext/box2d/vendor/box2d/src/body.h +194 -0
- data/ext/box2d/vendor/box2d/src/box2d.natvis +41 -0
- data/ext/box2d/vendor/box2d/src/broad_phase.c +524 -0
- data/ext/box2d/vendor/box2d/src/broad_phase.h +83 -0
- data/ext/box2d/vendor/box2d/src/constants.h +54 -0
- data/ext/box2d/vendor/box2d/src/constraint_graph.c +322 -0
- data/ext/box2d/vendor/box2d/src/constraint_graph.h +58 -0
- data/ext/box2d/vendor/box2d/src/contact.c +650 -0
- data/ext/box2d/vendor/box2d/src/contact.h +148 -0
- data/ext/box2d/vendor/box2d/src/contact_solver.c +2120 -0
- data/ext/box2d/vendor/box2d/src/contact_solver.h +54 -0
- data/ext/box2d/vendor/box2d/src/core.c +178 -0
- data/ext/box2d/vendor/box2d/src/core.h +149 -0
- data/ext/box2d/vendor/box2d/src/ctz.h +112 -0
- data/ext/box2d/vendor/box2d/src/distance.c +1415 -0
- data/ext/box2d/vendor/box2d/src/distance_joint.c +556 -0
- data/ext/box2d/vendor/box2d/src/dynamic_tree.c +1989 -0
- data/ext/box2d/vendor/box2d/src/geometry.c +1028 -0
- data/ext/box2d/vendor/box2d/src/hull.c +328 -0
- data/ext/box2d/vendor/box2d/src/id_pool.c +79 -0
- data/ext/box2d/vendor/box2d/src/id_pool.h +35 -0
- data/ext/box2d/vendor/box2d/src/island.c +977 -0
- data/ext/box2d/vendor/box2d/src/island.h +89 -0
- data/ext/box2d/vendor/box2d/src/joint.c +1272 -0
- data/ext/box2d/vendor/box2d/src/joint.h +335 -0
- data/ext/box2d/vendor/box2d/src/manifold.c +1726 -0
- data/ext/box2d/vendor/box2d/src/math_functions.c +159 -0
- data/ext/box2d/vendor/box2d/src/motor_joint.c +283 -0
- data/ext/box2d/vendor/box2d/src/mouse_joint.c +214 -0
- data/ext/box2d/vendor/box2d/src/mover.c +73 -0
- data/ext/box2d/vendor/box2d/src/prismatic_joint.c +656 -0
- data/ext/box2d/vendor/box2d/src/revolute_joint.c +534 -0
- data/ext/box2d/vendor/box2d/src/sensor.c +389 -0
- data/ext/box2d/vendor/box2d/src/sensor.h +36 -0
- data/ext/box2d/vendor/box2d/src/shape.c +1714 -0
- data/ext/box2d/vendor/box2d/src/shape.h +123 -0
- data/ext/box2d/vendor/box2d/src/solver.c +2038 -0
- data/ext/box2d/vendor/box2d/src/solver.h +155 -0
- data/ext/box2d/vendor/box2d/src/solver_set.c +613 -0
- data/ext/box2d/vendor/box2d/src/solver_set.h +57 -0
- data/ext/box2d/vendor/box2d/src/table.c +238 -0
- data/ext/box2d/vendor/box2d/src/table.h +37 -0
- data/ext/box2d/vendor/box2d/src/timer.c +185 -0
- data/ext/box2d/vendor/box2d/src/types.c +151 -0
- data/ext/box2d/vendor/box2d/src/weld_joint.c +310 -0
- data/ext/box2d/vendor/box2d/src/wheel_joint.c +551 -0
- data/ext/box2d/vendor/box2d/src/world.c +3301 -0
- data/ext/box2d/vendor/box2d/src/world.h +192 -0
- data/generator/generate.rb +316 -0
- data/generator/layout_probe.c +507 -0
- data/generator/verify_layouts.rb +32 -0
- data/lib/box2d/body.rb +172 -0
- data/lib/box2d/body_definition.rb +38 -0
- data/lib/box2d/body_shapes.rb +135 -0
- data/lib/box2d/chain.rb +61 -0
- data/lib/box2d/debug_draw.rb +118 -0
- data/lib/box2d/events.rb +103 -0
- data/lib/box2d/fixed_stepper.rb +39 -0
- data/lib/box2d/handle.rb +46 -0
- data/lib/box2d/hit.rb +5 -0
- data/lib/box2d/joint.rb +197 -0
- data/lib/box2d/native.rb +1462 -0
- data/lib/box2d/native_loader.rb +45 -0
- data/lib/box2d/pixel_scale.rb +29 -0
- data/lib/box2d/shape.rb +109 -0
- data/lib/box2d/shape_definition.rb +44 -0
- data/lib/box2d/value_conversion.rb +80 -0
- data/lib/box2d/version.rb +7 -0
- data/lib/box2d/world.rb +135 -0
- data/lib/box2d/world_joints.rb +156 -0
- data/lib/box2d/world_queries.rb +122 -0
- data/lib/box2d/world_registry.rb +95 -0
- data/lib/box2d.rb +31 -0
- data/script/build_platform_gem.rb +24 -0
- data/script/deterministic_scene.rb +56 -0
- data/script/update_deterministic_snapshot.rb +11 -0
- data/script/verify_platform_gem.rb +24 -0
- metadata +164 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2023 Erin Catto
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
#include "constraint_graph.h"
|
|
5
|
+
|
|
6
|
+
#include "array.h"
|
|
7
|
+
#include "bitset.h"
|
|
8
|
+
#include "body.h"
|
|
9
|
+
#include "contact.h"
|
|
10
|
+
#include "joint.h"
|
|
11
|
+
#include "solver_set.h"
|
|
12
|
+
#include "world.h"
|
|
13
|
+
|
|
14
|
+
#include <string.h>
|
|
15
|
+
|
|
16
|
+
// Solver using graph coloring. Islands are only used for sleep.
|
|
17
|
+
// High-Performance Physical Simulations on Next-Generation Architecture with Many Cores
|
|
18
|
+
// http://web.eecs.umich.edu/~msmelyan/papers/physsim_onmanycore_itj.pdf
|
|
19
|
+
|
|
20
|
+
// Kinematic bodies have to be treated like dynamic bodies in graph coloring. Unlike static bodies, we cannot use a dummy solver
|
|
21
|
+
// body for kinematic bodies. We cannot access a kinematic body from multiple threads efficiently because the SIMD solver body
|
|
22
|
+
// scatter would write to the same kinematic body from multiple threads. Even if these writes don't modify the body, they will
|
|
23
|
+
// cause horrible cache stalls. To make this feasible I would need a way to block these writes.
|
|
24
|
+
|
|
25
|
+
// This is used for debugging by making all constraints be assigned to overflow.
|
|
26
|
+
#define B2_FORCE_OVERFLOW 0
|
|
27
|
+
|
|
28
|
+
_Static_assert( B2_GRAPH_COLOR_COUNT == 12, "graph color count assumed to be 12" );
|
|
29
|
+
|
|
30
|
+
void b2CreateGraph( b2ConstraintGraph* graph, int bodyCapacity )
|
|
31
|
+
{
|
|
32
|
+
_Static_assert( B2_GRAPH_COLOR_COUNT >= 2, "must have at least two constraint graph colors" );
|
|
33
|
+
_Static_assert( B2_OVERFLOW_INDEX == B2_GRAPH_COLOR_COUNT - 1, "bad over flow index" );
|
|
34
|
+
|
|
35
|
+
*graph = ( b2ConstraintGraph ){ 0 };
|
|
36
|
+
|
|
37
|
+
bodyCapacity = b2MaxInt( bodyCapacity, 8 );
|
|
38
|
+
|
|
39
|
+
// Initialize graph color bit set.
|
|
40
|
+
// No bitset for overflow color.
|
|
41
|
+
for ( int i = 0; i < B2_OVERFLOW_INDEX; ++i )
|
|
42
|
+
{
|
|
43
|
+
b2GraphColor* color = graph->colors + i;
|
|
44
|
+
color->bodySet = b2CreateBitSet( bodyCapacity );
|
|
45
|
+
b2SetBitCountAndClear( &color->bodySet, bodyCapacity );
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
void b2DestroyGraph( b2ConstraintGraph* graph )
|
|
50
|
+
{
|
|
51
|
+
for ( int i = 0; i < B2_GRAPH_COLOR_COUNT; ++i )
|
|
52
|
+
{
|
|
53
|
+
b2GraphColor* color = graph->colors + i;
|
|
54
|
+
|
|
55
|
+
// The bit set should never be used on the overflow color
|
|
56
|
+
B2_ASSERT( i != B2_OVERFLOW_INDEX || color->bodySet.bits == NULL );
|
|
57
|
+
|
|
58
|
+
b2DestroyBitSet( &color->bodySet );
|
|
59
|
+
|
|
60
|
+
b2ContactSimArray_Destroy( &color->contactSims );
|
|
61
|
+
b2JointSimArray_Destroy( &color->jointSims );
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Contacts are always created as non-touching. They get cloned into the constraint
|
|
66
|
+
// graph once they are found to be touching.
|
|
67
|
+
// todo maybe kinematic bodies should not go into graph
|
|
68
|
+
void b2AddContactToGraph( b2World* world, b2ContactSim* contactSim, b2Contact* contact )
|
|
69
|
+
{
|
|
70
|
+
B2_ASSERT( contactSim->manifold.pointCount > 0 );
|
|
71
|
+
B2_ASSERT( contactSim->simFlags & b2_simTouchingFlag );
|
|
72
|
+
B2_ASSERT( contact->flags & b2_contactTouchingFlag );
|
|
73
|
+
|
|
74
|
+
b2ConstraintGraph* graph = &world->constraintGraph;
|
|
75
|
+
int colorIndex = B2_OVERFLOW_INDEX;
|
|
76
|
+
|
|
77
|
+
int bodyIdA = contact->edges[0].bodyId;
|
|
78
|
+
int bodyIdB = contact->edges[1].bodyId;
|
|
79
|
+
b2Body* bodyA = b2BodyArray_Get( &world->bodies, bodyIdA );
|
|
80
|
+
b2Body* bodyB = b2BodyArray_Get( &world->bodies, bodyIdB );
|
|
81
|
+
bool staticA = bodyA->setIndex == b2_staticSet;
|
|
82
|
+
bool staticB = bodyB->setIndex == b2_staticSet;
|
|
83
|
+
B2_ASSERT( staticA == false || staticB == false );
|
|
84
|
+
|
|
85
|
+
#if B2_FORCE_OVERFLOW == 0
|
|
86
|
+
if ( staticA == false && staticB == false )
|
|
87
|
+
{
|
|
88
|
+
for ( int i = 0; i < B2_OVERFLOW_INDEX; ++i )
|
|
89
|
+
{
|
|
90
|
+
b2GraphColor* color = graph->colors + i;
|
|
91
|
+
if ( b2GetBit( &color->bodySet, bodyIdA ) || b2GetBit( &color->bodySet, bodyIdB ) )
|
|
92
|
+
{
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
b2SetBitGrow( &color->bodySet, bodyIdA );
|
|
97
|
+
b2SetBitGrow( &color->bodySet, bodyIdB );
|
|
98
|
+
colorIndex = i;
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else if ( staticA == false )
|
|
103
|
+
{
|
|
104
|
+
// No static contacts in color 0
|
|
105
|
+
for ( int i = 1; i < B2_OVERFLOW_INDEX; ++i )
|
|
106
|
+
{
|
|
107
|
+
b2GraphColor* color = graph->colors + i;
|
|
108
|
+
if ( b2GetBit( &color->bodySet, bodyIdA ) )
|
|
109
|
+
{
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
b2SetBitGrow( &color->bodySet, bodyIdA );
|
|
114
|
+
colorIndex = i;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else if ( staticB == false )
|
|
119
|
+
{
|
|
120
|
+
// No static contacts in color 0
|
|
121
|
+
for ( int i = 1; i < B2_OVERFLOW_INDEX; ++i )
|
|
122
|
+
{
|
|
123
|
+
b2GraphColor* color = graph->colors + i;
|
|
124
|
+
if ( b2GetBit( &color->bodySet, bodyIdB ) )
|
|
125
|
+
{
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
b2SetBitGrow( &color->bodySet, bodyIdB );
|
|
130
|
+
colorIndex = i;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
#endif
|
|
135
|
+
|
|
136
|
+
b2GraphColor* color = graph->colors + colorIndex;
|
|
137
|
+
contact->colorIndex = colorIndex;
|
|
138
|
+
contact->localIndex = color->contactSims.count;
|
|
139
|
+
|
|
140
|
+
b2ContactSim* newContact = b2ContactSimArray_Add( &color->contactSims );
|
|
141
|
+
memcpy( newContact, contactSim, sizeof( b2ContactSim ) );
|
|
142
|
+
|
|
143
|
+
// todo perhaps skip this if the contact is already awake
|
|
144
|
+
|
|
145
|
+
if ( staticA )
|
|
146
|
+
{
|
|
147
|
+
newContact->bodySimIndexA = B2_NULL_INDEX;
|
|
148
|
+
newContact->invMassA = 0.0f;
|
|
149
|
+
newContact->invIA = 0.0f;
|
|
150
|
+
}
|
|
151
|
+
else
|
|
152
|
+
{
|
|
153
|
+
B2_ASSERT( bodyA->setIndex == b2_awakeSet );
|
|
154
|
+
b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet );
|
|
155
|
+
|
|
156
|
+
int localIndex = bodyA->localIndex;
|
|
157
|
+
newContact->bodySimIndexA = localIndex;
|
|
158
|
+
|
|
159
|
+
b2BodySim* bodySimA = b2BodySimArray_Get( &awakeSet->bodySims, localIndex );
|
|
160
|
+
newContact->invMassA = bodySimA->invMass;
|
|
161
|
+
newContact->invIA = bodySimA->invInertia;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if ( staticB )
|
|
165
|
+
{
|
|
166
|
+
newContact->bodySimIndexB = B2_NULL_INDEX;
|
|
167
|
+
newContact->invMassB = 0.0f;
|
|
168
|
+
newContact->invIB = 0.0f;
|
|
169
|
+
}
|
|
170
|
+
else
|
|
171
|
+
{
|
|
172
|
+
B2_ASSERT( bodyB->setIndex == b2_awakeSet );
|
|
173
|
+
b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet );
|
|
174
|
+
|
|
175
|
+
int localIndex = bodyB->localIndex;
|
|
176
|
+
newContact->bodySimIndexB = localIndex;
|
|
177
|
+
|
|
178
|
+
b2BodySim* bodySimB = b2BodySimArray_Get( &awakeSet->bodySims, localIndex );
|
|
179
|
+
newContact->invMassB = bodySimB->invMass;
|
|
180
|
+
newContact->invIB = bodySimB->invInertia;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
void b2RemoveContactFromGraph( b2World* world, int bodyIdA, int bodyIdB, int colorIndex, int localIndex )
|
|
185
|
+
{
|
|
186
|
+
b2ConstraintGraph* graph = &world->constraintGraph;
|
|
187
|
+
|
|
188
|
+
B2_ASSERT( 0 <= colorIndex && colorIndex < B2_GRAPH_COLOR_COUNT );
|
|
189
|
+
b2GraphColor* color = graph->colors + colorIndex;
|
|
190
|
+
|
|
191
|
+
if ( colorIndex != B2_OVERFLOW_INDEX )
|
|
192
|
+
{
|
|
193
|
+
// might clear a bit for a static body, but this has no effect
|
|
194
|
+
b2ClearBit( &color->bodySet, bodyIdA );
|
|
195
|
+
b2ClearBit( &color->bodySet, bodyIdB );
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
int movedIndex = b2ContactSimArray_RemoveSwap( &color->contactSims, localIndex );
|
|
199
|
+
if ( movedIndex != B2_NULL_INDEX )
|
|
200
|
+
{
|
|
201
|
+
// Fix index on swapped contact
|
|
202
|
+
b2ContactSim* movedContactSim = color->contactSims.data + localIndex;
|
|
203
|
+
|
|
204
|
+
// Fix moved contact
|
|
205
|
+
int movedId = movedContactSim->contactId;
|
|
206
|
+
b2Contact* movedContact = b2ContactArray_Get( &world->contacts, movedId );
|
|
207
|
+
B2_ASSERT( movedContact->setIndex == b2_awakeSet );
|
|
208
|
+
B2_ASSERT( movedContact->colorIndex == colorIndex );
|
|
209
|
+
B2_ASSERT( movedContact->localIndex == movedIndex );
|
|
210
|
+
movedContact->localIndex = localIndex;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
static int b2AssignJointColor( b2ConstraintGraph* graph, int bodyIdA, int bodyIdB, bool staticA, bool staticB )
|
|
215
|
+
{
|
|
216
|
+
B2_ASSERT( staticA == false || staticB == false );
|
|
217
|
+
|
|
218
|
+
#if B2_FORCE_OVERFLOW == 0
|
|
219
|
+
if ( staticA == false && staticB == false )
|
|
220
|
+
{
|
|
221
|
+
for ( int i = 0; i < B2_OVERFLOW_INDEX; ++i )
|
|
222
|
+
{
|
|
223
|
+
b2GraphColor* color = graph->colors + i;
|
|
224
|
+
if ( b2GetBit( &color->bodySet, bodyIdA ) || b2GetBit( &color->bodySet, bodyIdB ) )
|
|
225
|
+
{
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
b2SetBitGrow( &color->bodySet, bodyIdA );
|
|
230
|
+
b2SetBitGrow( &color->bodySet, bodyIdB );
|
|
231
|
+
return i;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
else if ( staticA == false )
|
|
235
|
+
{
|
|
236
|
+
for ( int i = 0; i < B2_OVERFLOW_INDEX; ++i )
|
|
237
|
+
{
|
|
238
|
+
b2GraphColor* color = graph->colors + i;
|
|
239
|
+
if ( b2GetBit( &color->bodySet, bodyIdA ) )
|
|
240
|
+
{
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
b2SetBitGrow( &color->bodySet, bodyIdA );
|
|
245
|
+
return i;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else if ( staticB == false )
|
|
249
|
+
{
|
|
250
|
+
for ( int i = 0; i < B2_OVERFLOW_INDEX; ++i )
|
|
251
|
+
{
|
|
252
|
+
b2GraphColor* color = graph->colors + i;
|
|
253
|
+
if ( b2GetBit( &color->bodySet, bodyIdB ) )
|
|
254
|
+
{
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
b2SetBitGrow( &color->bodySet, bodyIdB );
|
|
259
|
+
return i;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
#else
|
|
263
|
+
B2_UNUSED( graph, bodyIdA, bodyIdB, staticA, staticB );
|
|
264
|
+
#endif
|
|
265
|
+
|
|
266
|
+
return B2_OVERFLOW_INDEX;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
b2JointSim* b2CreateJointInGraph( b2World* world, b2Joint* joint )
|
|
270
|
+
{
|
|
271
|
+
b2ConstraintGraph* graph = &world->constraintGraph;
|
|
272
|
+
|
|
273
|
+
int bodyIdA = joint->edges[0].bodyId;
|
|
274
|
+
int bodyIdB = joint->edges[1].bodyId;
|
|
275
|
+
b2Body* bodyA = b2BodyArray_Get( &world->bodies, bodyIdA );
|
|
276
|
+
b2Body* bodyB = b2BodyArray_Get( &world->bodies, bodyIdB );
|
|
277
|
+
bool staticA = bodyA->setIndex == b2_staticSet;
|
|
278
|
+
bool staticB = bodyB->setIndex == b2_staticSet;
|
|
279
|
+
|
|
280
|
+
int colorIndex = b2AssignJointColor( graph, bodyIdA, bodyIdB, staticA, staticB );
|
|
281
|
+
|
|
282
|
+
b2JointSim* jointSim = b2JointSimArray_Add( &graph->colors[colorIndex].jointSims );
|
|
283
|
+
memset( jointSim, 0, sizeof( b2JointSim ) );
|
|
284
|
+
|
|
285
|
+
joint->colorIndex = colorIndex;
|
|
286
|
+
joint->localIndex = graph->colors[colorIndex].jointSims.count - 1;
|
|
287
|
+
return jointSim;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
void b2AddJointToGraph( b2World* world, b2JointSim* jointSim, b2Joint* joint )
|
|
291
|
+
{
|
|
292
|
+
b2JointSim* jointDst = b2CreateJointInGraph( world, joint );
|
|
293
|
+
memcpy( jointDst, jointSim, sizeof( b2JointSim ) );
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
void b2RemoveJointFromGraph( b2World* world, int bodyIdA, int bodyIdB, int colorIndex, int localIndex )
|
|
297
|
+
{
|
|
298
|
+
b2ConstraintGraph* graph = &world->constraintGraph;
|
|
299
|
+
|
|
300
|
+
B2_ASSERT( 0 <= colorIndex && colorIndex < B2_GRAPH_COLOR_COUNT );
|
|
301
|
+
b2GraphColor* color = graph->colors + colorIndex;
|
|
302
|
+
|
|
303
|
+
if ( colorIndex != B2_OVERFLOW_INDEX )
|
|
304
|
+
{
|
|
305
|
+
// May clear static bodies, no effect
|
|
306
|
+
b2ClearBit( &color->bodySet, bodyIdA );
|
|
307
|
+
b2ClearBit( &color->bodySet, bodyIdB );
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
int movedIndex = b2JointSimArray_RemoveSwap( &color->jointSims, localIndex );
|
|
311
|
+
if ( movedIndex != B2_NULL_INDEX )
|
|
312
|
+
{
|
|
313
|
+
// Fix moved joint
|
|
314
|
+
b2JointSim* movedJointSim = color->jointSims.data + localIndex;
|
|
315
|
+
int movedId = movedJointSim->jointId;
|
|
316
|
+
b2Joint* movedJoint = b2JointArray_Get( &world->joints, movedId );
|
|
317
|
+
B2_ASSERT( movedJoint->setIndex == b2_awakeSet );
|
|
318
|
+
B2_ASSERT( movedJoint->colorIndex == colorIndex );
|
|
319
|
+
B2_ASSERT( movedJoint->localIndex == movedIndex );
|
|
320
|
+
movedJoint->localIndex = localIndex;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
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
|
+
#include "constants.h"
|
|
9
|
+
|
|
10
|
+
typedef struct b2Body b2Body;
|
|
11
|
+
typedef struct b2ContactSim b2ContactSim;
|
|
12
|
+
typedef struct b2Contact b2Contact;
|
|
13
|
+
typedef struct b2ContactConstraint b2ContactConstraint;
|
|
14
|
+
typedef struct b2ContactConstraintSIMD b2ContactConstraintSIMD;
|
|
15
|
+
typedef struct b2JointSim b2JointSim;
|
|
16
|
+
typedef struct b2Joint b2Joint;
|
|
17
|
+
typedef struct b2StepContext b2StepContext;
|
|
18
|
+
typedef struct b2World b2World;
|
|
19
|
+
|
|
20
|
+
// This holds constraints that cannot fit the graph color limit. This happens when a single dynamic body
|
|
21
|
+
// is touching many other bodies.
|
|
22
|
+
#define B2_OVERFLOW_INDEX (B2_GRAPH_COLOR_COUNT - 1)
|
|
23
|
+
|
|
24
|
+
typedef struct b2GraphColor
|
|
25
|
+
{
|
|
26
|
+
// This bitset is indexed by bodyId so this is over-sized to encompass static bodies
|
|
27
|
+
// however I never traverse these bits or use the bit count for anything
|
|
28
|
+
// This bitset is unused on the overflow color.
|
|
29
|
+
// todo consider having a uint_16 per body that tracks the graph color membership
|
|
30
|
+
b2BitSet bodySet;
|
|
31
|
+
|
|
32
|
+
// cache friendly arrays
|
|
33
|
+
b2ContactSimArray contactSims;
|
|
34
|
+
b2JointSimArray jointSims;
|
|
35
|
+
|
|
36
|
+
// transient
|
|
37
|
+
union
|
|
38
|
+
{
|
|
39
|
+
b2ContactConstraintSIMD* simdConstraints;
|
|
40
|
+
b2ContactConstraint* overflowConstraints;
|
|
41
|
+
};
|
|
42
|
+
} b2GraphColor;
|
|
43
|
+
|
|
44
|
+
typedef struct b2ConstraintGraph
|
|
45
|
+
{
|
|
46
|
+
// including overflow at the end
|
|
47
|
+
b2GraphColor colors[B2_GRAPH_COLOR_COUNT];
|
|
48
|
+
} b2ConstraintGraph;
|
|
49
|
+
|
|
50
|
+
void b2CreateGraph( b2ConstraintGraph* graph, int bodyCapacity );
|
|
51
|
+
void b2DestroyGraph( b2ConstraintGraph* graph );
|
|
52
|
+
|
|
53
|
+
void b2AddContactToGraph( b2World* world, b2ContactSim* contactSim, b2Contact* contact );
|
|
54
|
+
void b2RemoveContactFromGraph( b2World* world, int bodyIdA, int bodyIdB, int colorIndex, int localIndex );
|
|
55
|
+
|
|
56
|
+
b2JointSim* b2CreateJointInGraph( b2World* world, b2Joint* joint );
|
|
57
|
+
void b2AddJointToGraph( b2World* world, b2JointSim* jointSim, b2Joint* joint );
|
|
58
|
+
void b2RemoveJointFromGraph( b2World* world, int bodyIdA, int bodyIdB, int colorIndex, int localIndex );
|