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,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
|
+
}
|