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,556 @@
1
+ // SPDX-FileCopyrightText: 2023 Erin Catto
2
+ // SPDX-License-Identifier: MIT
3
+
4
+ #if defined( _MSC_VER ) && !defined( _CRT_SECURE_NO_WARNINGS )
5
+ #define _CRT_SECURE_NO_WARNINGS
6
+ #endif
7
+
8
+ #include "body.h"
9
+ #include "core.h"
10
+ #include "joint.h"
11
+ #include "solver.h"
12
+ #include "solver_set.h"
13
+ #include "world.h"
14
+
15
+ // needed for dll export
16
+ #include "box2d/box2d.h"
17
+
18
+ #include <stdio.h>
19
+
20
+ void b2DistanceJoint_SetLength( b2JointId jointId, float length )
21
+ {
22
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
23
+ b2DistanceJoint* joint = &base->distanceJoint;
24
+
25
+ joint->length = b2ClampFloat( length, B2_LINEAR_SLOP, B2_HUGE );
26
+ joint->impulse = 0.0f;
27
+ joint->lowerImpulse = 0.0f;
28
+ joint->upperImpulse = 0.0f;
29
+ }
30
+
31
+ float b2DistanceJoint_GetLength( b2JointId jointId )
32
+ {
33
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
34
+ b2DistanceJoint* joint = &base->distanceJoint;
35
+ return joint->length;
36
+ }
37
+
38
+ void b2DistanceJoint_EnableLimit( b2JointId jointId, bool enableLimit )
39
+ {
40
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
41
+ b2DistanceJoint* joint = &base->distanceJoint;
42
+ joint->enableLimit = enableLimit;
43
+ }
44
+
45
+ bool b2DistanceJoint_IsLimitEnabled( b2JointId jointId )
46
+ {
47
+ b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint );
48
+ return joint->distanceJoint.enableLimit;
49
+ }
50
+
51
+ void b2DistanceJoint_SetLengthRange( b2JointId jointId, float minLength, float maxLength )
52
+ {
53
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
54
+ b2DistanceJoint* joint = &base->distanceJoint;
55
+
56
+ minLength = b2ClampFloat( minLength, B2_LINEAR_SLOP, B2_HUGE );
57
+ maxLength = b2ClampFloat( maxLength, B2_LINEAR_SLOP, B2_HUGE );
58
+ joint->minLength = b2MinFloat( minLength, maxLength );
59
+ joint->maxLength = b2MaxFloat( minLength, maxLength );
60
+ joint->impulse = 0.0f;
61
+ joint->lowerImpulse = 0.0f;
62
+ joint->upperImpulse = 0.0f;
63
+ }
64
+
65
+ float b2DistanceJoint_GetMinLength( b2JointId jointId )
66
+ {
67
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
68
+ b2DistanceJoint* joint = &base->distanceJoint;
69
+ return joint->minLength;
70
+ }
71
+
72
+ float b2DistanceJoint_GetMaxLength( b2JointId jointId )
73
+ {
74
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
75
+ b2DistanceJoint* joint = &base->distanceJoint;
76
+ return joint->maxLength;
77
+ }
78
+
79
+ float b2DistanceJoint_GetCurrentLength( b2JointId jointId )
80
+ {
81
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
82
+
83
+ b2World* world = b2GetWorld( jointId.world0 );
84
+ B2_ASSERT( world->locked == false );
85
+ if ( world->locked )
86
+ {
87
+ return 0.0f;
88
+ }
89
+
90
+ b2Transform transformA = b2GetBodyTransform( world, base->bodyIdA );
91
+ b2Transform transformB = b2GetBodyTransform( world, base->bodyIdB );
92
+
93
+ b2Vec2 pA = b2TransformPoint( transformA, base->localOriginAnchorA );
94
+ b2Vec2 pB = b2TransformPoint( transformB, base->localOriginAnchorB );
95
+ b2Vec2 d = b2Sub( pB, pA );
96
+ float length = b2Length( d );
97
+ return length;
98
+ }
99
+
100
+ void b2DistanceJoint_EnableSpring( b2JointId jointId, bool enableSpring )
101
+ {
102
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
103
+ base->distanceJoint.enableSpring = enableSpring;
104
+ }
105
+
106
+ bool b2DistanceJoint_IsSpringEnabled( b2JointId jointId )
107
+ {
108
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
109
+ return base->distanceJoint.enableSpring;
110
+ }
111
+
112
+ void b2DistanceJoint_SetSpringHertz( b2JointId jointId, float hertz )
113
+ {
114
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
115
+ base->distanceJoint.hertz = hertz;
116
+ }
117
+
118
+ void b2DistanceJoint_SetSpringDampingRatio( b2JointId jointId, float dampingRatio )
119
+ {
120
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
121
+ base->distanceJoint.dampingRatio = dampingRatio;
122
+ }
123
+
124
+ float b2DistanceJoint_GetSpringHertz( b2JointId jointId )
125
+ {
126
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
127
+ b2DistanceJoint* joint = &base->distanceJoint;
128
+ return joint->hertz;
129
+ }
130
+
131
+ float b2DistanceJoint_GetSpringDampingRatio( b2JointId jointId )
132
+ {
133
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
134
+ b2DistanceJoint* joint = &base->distanceJoint;
135
+ return joint->dampingRatio;
136
+ }
137
+
138
+ void b2DistanceJoint_EnableMotor( b2JointId jointId, bool enableMotor )
139
+ {
140
+ b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint );
141
+ if ( enableMotor != joint->distanceJoint.enableMotor )
142
+ {
143
+ joint->distanceJoint.enableMotor = enableMotor;
144
+ joint->distanceJoint.motorImpulse = 0.0f;
145
+ }
146
+ }
147
+
148
+ bool b2DistanceJoint_IsMotorEnabled( b2JointId jointId )
149
+ {
150
+ b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint );
151
+ return joint->distanceJoint.enableMotor;
152
+ }
153
+
154
+ void b2DistanceJoint_SetMotorSpeed( b2JointId jointId, float motorSpeed )
155
+ {
156
+ b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint );
157
+ joint->distanceJoint.motorSpeed = motorSpeed;
158
+ }
159
+
160
+ float b2DistanceJoint_GetMotorSpeed( b2JointId jointId )
161
+ {
162
+ b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint );
163
+ return joint->distanceJoint.motorSpeed;
164
+ }
165
+
166
+ float b2DistanceJoint_GetMotorForce( b2JointId jointId )
167
+ {
168
+ b2World* world = b2GetWorld( jointId.world0 );
169
+ b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint );
170
+ return world->inv_h * base->distanceJoint.motorImpulse;
171
+ }
172
+
173
+ void b2DistanceJoint_SetMaxMotorForce( b2JointId jointId, float force )
174
+ {
175
+ b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint );
176
+ joint->distanceJoint.maxMotorForce = force;
177
+ }
178
+
179
+ float b2DistanceJoint_GetMaxMotorForce( b2JointId jointId )
180
+ {
181
+ b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint );
182
+ return joint->distanceJoint.maxMotorForce;
183
+ }
184
+
185
+ b2Vec2 b2GetDistanceJointForce( b2World* world, b2JointSim* base )
186
+ {
187
+ b2DistanceJoint* joint = &base->distanceJoint;
188
+
189
+ b2Transform transformA = b2GetBodyTransform( world, base->bodyIdA );
190
+ b2Transform transformB = b2GetBodyTransform( world, base->bodyIdB );
191
+
192
+ b2Vec2 pA = b2TransformPoint( transformA, base->localOriginAnchorA );
193
+ b2Vec2 pB = b2TransformPoint( transformB, base->localOriginAnchorB );
194
+ b2Vec2 d = b2Sub( pB, pA );
195
+ b2Vec2 axis = b2Normalize( d );
196
+ float force = ( joint->impulse + joint->lowerImpulse - joint->upperImpulse + joint->motorImpulse ) * world->inv_h;
197
+ return b2MulSV( force, axis );
198
+ }
199
+
200
+ // 1-D constrained system
201
+ // m (v2 - v1) = lambda
202
+ // v2 + (beta/h) * x1 + gamma * lambda = 0, gamma has units of inverse mass.
203
+ // x2 = x1 + h * v2
204
+
205
+ // 1-D mass-damper-spring system
206
+ // m (v2 - v1) + h * d * v2 + h * k *
207
+
208
+ // C = norm(p2 - p1) - L
209
+ // u = (p2 - p1) / norm(p2 - p1)
210
+ // Cdot = dot(u, v2 + cross(w2, r2) - v1 - cross(w1, r1))
211
+ // J = [-u -cross(r1, u) u cross(r2, u)]
212
+ // K = J * invM * JT
213
+ // = invMass1 + invI1 * cross(r1, u)^2 + invMass2 + invI2 * cross(r2, u)^2
214
+
215
+ void b2PrepareDistanceJoint( b2JointSim* base, b2StepContext* context )
216
+ {
217
+ B2_ASSERT( base->type == b2_distanceJoint );
218
+
219
+ // chase body id to the solver set where the body lives
220
+ int idA = base->bodyIdA;
221
+ int idB = base->bodyIdB;
222
+
223
+ b2World* world = context->world;
224
+ b2Body* bodyA = b2BodyArray_Get( &world->bodies, idA );
225
+ b2Body* bodyB = b2BodyArray_Get( &world->bodies, idB );
226
+
227
+ B2_ASSERT( bodyA->setIndex == b2_awakeSet || bodyB->setIndex == b2_awakeSet );
228
+
229
+ b2SolverSet* setA = b2SolverSetArray_Get( &world->solverSets, bodyA->setIndex );
230
+ b2SolverSet* setB = b2SolverSetArray_Get( &world->solverSets, bodyB->setIndex );
231
+
232
+ int localIndexA = bodyA->localIndex;
233
+ int localIndexB = bodyB->localIndex;
234
+
235
+ b2BodySim* bodySimA = b2BodySimArray_Get( &setA->bodySims, localIndexA );
236
+ b2BodySim* bodySimB = b2BodySimArray_Get( &setB->bodySims, localIndexB );
237
+
238
+ float mA = bodySimA->invMass;
239
+ float iA = bodySimA->invInertia;
240
+ float mB = bodySimB->invMass;
241
+ float iB = bodySimB->invInertia;
242
+
243
+ base->invMassA = mA;
244
+ base->invMassB = mB;
245
+ base->invIA = iA;
246
+ base->invIB = iB;
247
+
248
+ b2DistanceJoint* joint = &base->distanceJoint;
249
+
250
+ joint->indexA = bodyA->setIndex == b2_awakeSet ? localIndexA : B2_NULL_INDEX;
251
+ joint->indexB = bodyB->setIndex == b2_awakeSet ? localIndexB : B2_NULL_INDEX;
252
+
253
+ // initial anchors in world space
254
+ joint->anchorA = b2RotateVector( bodySimA->transform.q, b2Sub( base->localOriginAnchorA, bodySimA->localCenter ) );
255
+ joint->anchorB = b2RotateVector( bodySimB->transform.q, b2Sub( base->localOriginAnchorB, bodySimB->localCenter ) );
256
+ joint->deltaCenter = b2Sub( bodySimB->center, bodySimA->center );
257
+
258
+ b2Vec2 rA = joint->anchorA;
259
+ b2Vec2 rB = joint->anchorB;
260
+ b2Vec2 separation = b2Add( b2Sub( rB, rA ), joint->deltaCenter );
261
+ b2Vec2 axis = b2Normalize( separation );
262
+
263
+ // compute effective mass
264
+ float crA = b2Cross( rA, axis );
265
+ float crB = b2Cross( rB, axis );
266
+ float k = mA + mB + iA * crA * crA + iB * crB * crB;
267
+ joint->axialMass = k > 0.0f ? 1.0f / k : 0.0f;
268
+
269
+ joint->distanceSoftness = b2MakeSoft( joint->hertz, joint->dampingRatio, context->h );
270
+
271
+ if ( context->enableWarmStarting == false )
272
+ {
273
+ joint->impulse = 0.0f;
274
+ joint->lowerImpulse = 0.0f;
275
+ joint->upperImpulse = 0.0f;
276
+ joint->motorImpulse = 0.0f;
277
+ }
278
+ }
279
+
280
+ void b2WarmStartDistanceJoint( b2JointSim* base, b2StepContext* context )
281
+ {
282
+ B2_ASSERT( base->type == b2_distanceJoint );
283
+
284
+ float mA = base->invMassA;
285
+ float mB = base->invMassB;
286
+ float iA = base->invIA;
287
+ float iB = base->invIB;
288
+
289
+ // dummy state for static bodies
290
+ b2BodyState dummyState = b2_identityBodyState;
291
+
292
+ b2DistanceJoint* joint = &base->distanceJoint;
293
+ b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA;
294
+ b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB;
295
+
296
+ b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA );
297
+ b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB );
298
+
299
+ b2Vec2 ds = b2Add( b2Sub( stateB->deltaPosition, stateA->deltaPosition ), b2Sub( rB, rA ) );
300
+ b2Vec2 separation = b2Add( joint->deltaCenter, ds );
301
+ b2Vec2 axis = b2Normalize( separation );
302
+
303
+ float axialImpulse = joint->impulse + joint->lowerImpulse - joint->upperImpulse + joint->motorImpulse;
304
+ b2Vec2 P = b2MulSV( axialImpulse, axis );
305
+
306
+ stateA->linearVelocity = b2MulSub( stateA->linearVelocity, mA, P );
307
+ stateA->angularVelocity -= iA * b2Cross( rA, P );
308
+ stateB->linearVelocity = b2MulAdd( stateB->linearVelocity, mB, P );
309
+ stateB->angularVelocity += iB * b2Cross( rB, P );
310
+ }
311
+
312
+ void b2SolveDistanceJoint( b2JointSim* base, b2StepContext* context, bool useBias )
313
+ {
314
+ B2_ASSERT( base->type == b2_distanceJoint );
315
+
316
+ float mA = base->invMassA;
317
+ float mB = base->invMassB;
318
+ float iA = base->invIA;
319
+ float iB = base->invIB;
320
+
321
+ // dummy state for static bodies
322
+ b2BodyState dummyState = b2_identityBodyState;
323
+
324
+ b2DistanceJoint* joint = &base->distanceJoint;
325
+ b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA;
326
+ b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB;
327
+
328
+ b2Vec2 vA = stateA->linearVelocity;
329
+ float wA = stateA->angularVelocity;
330
+ b2Vec2 vB = stateB->linearVelocity;
331
+ float wB = stateB->angularVelocity;
332
+
333
+ // current anchors
334
+ b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA );
335
+ b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB );
336
+
337
+ // current separation
338
+ b2Vec2 ds = b2Add( b2Sub( stateB->deltaPosition, stateA->deltaPosition ), b2Sub( rB, rA ) );
339
+ b2Vec2 separation = b2Add( joint->deltaCenter, ds );
340
+
341
+ float length = b2Length( separation );
342
+ b2Vec2 axis = b2Normalize( separation );
343
+
344
+ // joint is soft if
345
+ // - spring is enabled
346
+ // - and (joint limit is disabled or limits are not equal)
347
+ if ( joint->enableSpring && ( joint->minLength < joint->maxLength || joint->enableLimit == false ) )
348
+ {
349
+ // spring
350
+ if ( joint->hertz > 0.0f )
351
+ {
352
+ // Cdot = dot(u, v + cross(w, r))
353
+ b2Vec2 vr = b2Add( b2Sub( vB, vA ), b2Sub( b2CrossSV( wB, rB ), b2CrossSV( wA, rA ) ) );
354
+ float Cdot = b2Dot( axis, vr );
355
+ float C = length - joint->length;
356
+ float bias = joint->distanceSoftness.biasRate * C;
357
+
358
+ float m = joint->distanceSoftness.massScale * joint->axialMass;
359
+ float impulse = -m * ( Cdot + bias ) - joint->distanceSoftness.impulseScale * joint->impulse;
360
+ joint->impulse += impulse;
361
+
362
+ b2Vec2 P = b2MulSV( impulse, axis );
363
+ vA = b2MulSub( vA, mA, P );
364
+ wA -= iA * b2Cross( rA, P );
365
+ vB = b2MulAdd( vB, mB, P );
366
+ wB += iB * b2Cross( rB, P );
367
+ }
368
+
369
+ if ( joint->enableLimit )
370
+ {
371
+ // lower limit
372
+ {
373
+ b2Vec2 vr = b2Add( b2Sub( vB, vA ), b2Sub( b2CrossSV( wB, rB ), b2CrossSV( wA, rA ) ) );
374
+ float Cdot = b2Dot( axis, vr );
375
+
376
+ float C = length - joint->minLength;
377
+
378
+ float bias = 0.0f;
379
+ float massCoeff = 1.0f;
380
+ float impulseCoeff = 0.0f;
381
+ if ( C > 0.0f )
382
+ {
383
+ // speculative
384
+ bias = C * context->inv_h;
385
+ }
386
+ else if ( useBias )
387
+ {
388
+ bias = context->jointSoftness.biasRate * C;
389
+ massCoeff = context->jointSoftness.massScale;
390
+ impulseCoeff = context->jointSoftness.impulseScale;
391
+ }
392
+
393
+ float impulse = -massCoeff * joint->axialMass * ( Cdot + bias ) - impulseCoeff * joint->lowerImpulse;
394
+ float newImpulse = b2MaxFloat( 0.0f, joint->lowerImpulse + impulse );
395
+ impulse = newImpulse - joint->lowerImpulse;
396
+ joint->lowerImpulse = newImpulse;
397
+
398
+ b2Vec2 P = b2MulSV( impulse, axis );
399
+ vA = b2MulSub( vA, mA, P );
400
+ wA -= iA * b2Cross( rA, P );
401
+ vB = b2MulAdd( vB, mB, P );
402
+ wB += iB * b2Cross( rB, P );
403
+ }
404
+
405
+ // upper
406
+ {
407
+ b2Vec2 vr = b2Add( b2Sub( vA, vB ), b2Sub( b2CrossSV( wA, rA ), b2CrossSV( wB, rB ) ) );
408
+ float Cdot = b2Dot( axis, vr );
409
+
410
+ float C = joint->maxLength - length;
411
+
412
+ float bias = 0.0f;
413
+ float massScale = 1.0f;
414
+ float impulseScale = 0.0f;
415
+ if ( C > 0.0f )
416
+ {
417
+ // speculative
418
+ bias = C * context->inv_h;
419
+ }
420
+ else if ( useBias )
421
+ {
422
+ bias = context->jointSoftness.biasRate * C;
423
+ massScale = context->jointSoftness.massScale;
424
+ impulseScale = context->jointSoftness.impulseScale;
425
+ }
426
+
427
+ float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * joint->upperImpulse;
428
+ float newImpulse = b2MaxFloat( 0.0f, joint->upperImpulse + impulse );
429
+ impulse = newImpulse - joint->upperImpulse;
430
+ joint->upperImpulse = newImpulse;
431
+
432
+ b2Vec2 P = b2MulSV( -impulse, axis );
433
+ vA = b2MulSub( vA, mA, P );
434
+ wA -= iA * b2Cross( rA, P );
435
+ vB = b2MulAdd( vB, mB, P );
436
+ wB += iB * b2Cross( rB, P );
437
+ }
438
+ }
439
+
440
+ if ( joint->enableMotor )
441
+ {
442
+ b2Vec2 vr = b2Add( b2Sub( vB, vA ), b2Sub( b2CrossSV( wB, rB ), b2CrossSV( wA, rA ) ) );
443
+ float Cdot = b2Dot( axis, vr );
444
+ float impulse = joint->axialMass * ( joint->motorSpeed - Cdot );
445
+ float oldImpulse = joint->motorImpulse;
446
+ float maxImpulse = context->h * joint->maxMotorForce;
447
+ joint->motorImpulse = b2ClampFloat( joint->motorImpulse + impulse, -maxImpulse, maxImpulse );
448
+ impulse = joint->motorImpulse - oldImpulse;
449
+
450
+ b2Vec2 P = b2MulSV( impulse, axis );
451
+ vA = b2MulSub( vA, mA, P );
452
+ wA -= iA * b2Cross( rA, P );
453
+ vB = b2MulAdd( vB, mB, P );
454
+ wB += iB * b2Cross( rB, P );
455
+ }
456
+ }
457
+ else
458
+ {
459
+ // rigid constraint
460
+ b2Vec2 vr = b2Add( b2Sub( vB, vA ), b2Sub( b2CrossSV( wB, rB ), b2CrossSV( wA, rA ) ) );
461
+ float Cdot = b2Dot( axis, vr );
462
+
463
+ float C = length - joint->length;
464
+
465
+ float bias = 0.0f;
466
+ float massScale = 1.0f;
467
+ float impulseScale = 0.0f;
468
+ if ( useBias )
469
+ {
470
+ bias = context->jointSoftness.biasRate * C;
471
+ massScale = context->jointSoftness.massScale;
472
+ impulseScale = context->jointSoftness.impulseScale;
473
+ }
474
+
475
+ float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * joint->impulse;
476
+ joint->impulse += impulse;
477
+
478
+ b2Vec2 P = b2MulSV( impulse, axis );
479
+ vA = b2MulSub( vA, mA, P );
480
+ wA -= iA * b2Cross( rA, P );
481
+ vB = b2MulAdd( vB, mB, P );
482
+ wB += iB * b2Cross( rB, P );
483
+ }
484
+
485
+ stateA->linearVelocity = vA;
486
+ stateA->angularVelocity = wA;
487
+ stateB->linearVelocity = vB;
488
+ stateB->angularVelocity = wB;
489
+ }
490
+
491
+ #if 0
492
+ void b2DistanceJoint::Dump()
493
+ {
494
+ int32 indexA = m_bodyA->m_islandIndex;
495
+ int32 indexB = m_bodyB->m_islandIndex;
496
+
497
+ b2Dump(" b2DistanceJointDef jd;\n");
498
+ b2Dump(" jd.bodyA = sims[%d];\n", indexA);
499
+ b2Dump(" jd.bodyB = sims[%d];\n", indexB);
500
+ b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected);
501
+ b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y);
502
+ b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y);
503
+ b2Dump(" jd.length = %.9g;\n", m_length);
504
+ b2Dump(" jd.minLength = %.9g;\n", m_minLength);
505
+ b2Dump(" jd.maxLength = %.9g;\n", m_maxLength);
506
+ b2Dump(" jd.stiffness = %.9g;\n", m_stiffness);
507
+ b2Dump(" jd.damping = %.9g;\n", m_damping);
508
+ b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
509
+ }
510
+ #endif
511
+
512
+ void b2DrawDistanceJoint( b2DebugDraw* draw, b2JointSim* base, b2Transform transformA, b2Transform transformB )
513
+ {
514
+ B2_ASSERT( base->type == b2_distanceJoint );
515
+
516
+ b2DistanceJoint* joint = &base->distanceJoint;
517
+
518
+ b2Vec2 pA = b2TransformPoint( transformA, base->localOriginAnchorA );
519
+ b2Vec2 pB = b2TransformPoint( transformB, base->localOriginAnchorB );
520
+
521
+ b2Vec2 axis = b2Normalize( b2Sub( pB, pA ) );
522
+
523
+ if ( joint->minLength < joint->maxLength && joint->enableLimit )
524
+ {
525
+ b2Vec2 pMin = b2MulAdd( pA, joint->minLength, axis );
526
+ b2Vec2 pMax = b2MulAdd( pA, joint->maxLength, axis );
527
+ b2Vec2 offset = b2MulSV( 0.05f * b2_lengthUnitsPerMeter, b2RightPerp( axis ) );
528
+
529
+ if ( joint->minLength > B2_LINEAR_SLOP )
530
+ {
531
+ // draw->DrawPoint(pMin, 4.0f, c2, draw->context);
532
+ draw->DrawSegmentFcn( b2Sub( pMin, offset ), b2Add( pMin, offset ), b2_colorLightGreen, draw->context );
533
+ }
534
+
535
+ if ( joint->maxLength < B2_HUGE )
536
+ {
537
+ // draw->DrawPoint(pMax, 4.0f, c3, draw->context);
538
+ draw->DrawSegmentFcn( b2Sub( pMax, offset ), b2Add( pMax, offset ), b2_colorRed, draw->context );
539
+ }
540
+
541
+ if ( joint->minLength > B2_LINEAR_SLOP && joint->maxLength < B2_HUGE )
542
+ {
543
+ draw->DrawSegmentFcn( pMin, pMax, b2_colorGray, draw->context );
544
+ }
545
+ }
546
+
547
+ draw->DrawSegmentFcn( pA, pB, b2_colorWhite, draw->context );
548
+ draw->DrawPointFcn( pA, 4.0f, b2_colorWhite, draw->context );
549
+ draw->DrawPointFcn( pB, 4.0f, b2_colorWhite, draw->context );
550
+
551
+ if ( joint->hertz > 0.0f && joint->enableSpring )
552
+ {
553
+ b2Vec2 pRest = b2MulAdd( pA, joint->length, axis );
554
+ draw->DrawPointFcn( pRest, 4.0f, b2_colorBlue, draw->context );
555
+ }
556
+ }