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,534 @@
|
|
|
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 b2RevoluteJoint_EnableSpring( b2JointId jointId, bool enableSpring )
|
|
21
|
+
{
|
|
22
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
23
|
+
if ( enableSpring != joint->revoluteJoint.enableSpring )
|
|
24
|
+
{
|
|
25
|
+
joint->revoluteJoint.enableSpring = enableSpring;
|
|
26
|
+
joint->revoluteJoint.springImpulse = 0.0f;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
bool b2RevoluteJoint_IsSpringEnabled( b2JointId jointId )
|
|
31
|
+
{
|
|
32
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
33
|
+
return joint->revoluteJoint.enableSpring;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
void b2RevoluteJoint_SetSpringHertz( b2JointId jointId, float hertz )
|
|
37
|
+
{
|
|
38
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
39
|
+
joint->revoluteJoint.hertz = hertz;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
float b2RevoluteJoint_GetSpringHertz( b2JointId jointId )
|
|
43
|
+
{
|
|
44
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
45
|
+
return joint->revoluteJoint.hertz;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
void b2RevoluteJoint_SetSpringDampingRatio( b2JointId jointId, float dampingRatio )
|
|
49
|
+
{
|
|
50
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
51
|
+
joint->revoluteJoint.dampingRatio = dampingRatio;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
float b2RevoluteJoint_GetSpringDampingRatio( b2JointId jointId )
|
|
55
|
+
{
|
|
56
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
57
|
+
return joint->revoluteJoint.dampingRatio;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
float b2RevoluteJoint_GetAngle( b2JointId jointId )
|
|
61
|
+
{
|
|
62
|
+
b2World* world = b2GetWorld( jointId.world0 );
|
|
63
|
+
b2JointSim* jointSim = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
64
|
+
b2Transform transformA = b2GetBodyTransform( world, jointSim->bodyIdA );
|
|
65
|
+
b2Transform transformB = b2GetBodyTransform( world, jointSim->bodyIdB );
|
|
66
|
+
|
|
67
|
+
float angle = b2RelativeAngle( transformB.q, transformA.q ) - jointSim->revoluteJoint.referenceAngle;
|
|
68
|
+
angle = b2UnwindAngle( angle );
|
|
69
|
+
return angle;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
void b2RevoluteJoint_EnableLimit( b2JointId jointId, bool enableLimit )
|
|
73
|
+
{
|
|
74
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
75
|
+
if ( enableLimit != joint->revoluteJoint.enableLimit )
|
|
76
|
+
{
|
|
77
|
+
joint->revoluteJoint.enableLimit = enableLimit;
|
|
78
|
+
joint->revoluteJoint.lowerImpulse = 0.0f;
|
|
79
|
+
joint->revoluteJoint.upperImpulse = 0.0f;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
bool b2RevoluteJoint_IsLimitEnabled( b2JointId jointId )
|
|
84
|
+
{
|
|
85
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
86
|
+
return joint->revoluteJoint.enableLimit;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
float b2RevoluteJoint_GetLowerLimit( b2JointId jointId )
|
|
90
|
+
{
|
|
91
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
92
|
+
return joint->revoluteJoint.lowerAngle;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
float b2RevoluteJoint_GetUpperLimit( b2JointId jointId )
|
|
96
|
+
{
|
|
97
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
98
|
+
return joint->revoluteJoint.upperAngle;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
void b2RevoluteJoint_SetLimits( b2JointId jointId, float lower, float upper )
|
|
102
|
+
{
|
|
103
|
+
B2_ASSERT( lower <= upper );
|
|
104
|
+
B2_ASSERT( lower >= -0.95f * B2_PI );
|
|
105
|
+
B2_ASSERT( upper <= 0.95f * B2_PI );
|
|
106
|
+
|
|
107
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
108
|
+
if ( lower != joint->revoluteJoint.lowerAngle || upper != joint->revoluteJoint.upperAngle )
|
|
109
|
+
{
|
|
110
|
+
joint->revoluteJoint.lowerAngle = b2MinFloat( lower, upper );
|
|
111
|
+
joint->revoluteJoint.upperAngle = b2MaxFloat( lower, upper );
|
|
112
|
+
joint->revoluteJoint.lowerImpulse = 0.0f;
|
|
113
|
+
joint->revoluteJoint.upperImpulse = 0.0f;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
void b2RevoluteJoint_EnableMotor( b2JointId jointId, bool enableMotor )
|
|
118
|
+
{
|
|
119
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
120
|
+
if ( enableMotor != joint->revoluteJoint.enableMotor )
|
|
121
|
+
{
|
|
122
|
+
joint->revoluteJoint.enableMotor = enableMotor;
|
|
123
|
+
joint->revoluteJoint.motorImpulse = 0.0f;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
bool b2RevoluteJoint_IsMotorEnabled( b2JointId jointId )
|
|
128
|
+
{
|
|
129
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
130
|
+
return joint->revoluteJoint.enableMotor;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
void b2RevoluteJoint_SetMotorSpeed( b2JointId jointId, float motorSpeed )
|
|
134
|
+
{
|
|
135
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
136
|
+
joint->revoluteJoint.motorSpeed = motorSpeed;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
float b2RevoluteJoint_GetMotorSpeed( b2JointId jointId )
|
|
140
|
+
{
|
|
141
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
142
|
+
return joint->revoluteJoint.motorSpeed;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
float b2RevoluteJoint_GetMotorTorque( b2JointId jointId )
|
|
146
|
+
{
|
|
147
|
+
b2World* world = b2GetWorld( jointId.world0 );
|
|
148
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
149
|
+
return world->inv_h * joint->revoluteJoint.motorImpulse;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
void b2RevoluteJoint_SetMaxMotorTorque( b2JointId jointId, float torque )
|
|
153
|
+
{
|
|
154
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
155
|
+
joint->revoluteJoint.maxMotorTorque = torque;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
float b2RevoluteJoint_GetMaxMotorTorque( b2JointId jointId )
|
|
159
|
+
{
|
|
160
|
+
b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint );
|
|
161
|
+
return joint->revoluteJoint.maxMotorTorque;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
b2Vec2 b2GetRevoluteJointForce( b2World* world, b2JointSim* base )
|
|
165
|
+
{
|
|
166
|
+
b2Vec2 force = b2MulSV( world->inv_h, base->revoluteJoint.linearImpulse );
|
|
167
|
+
return force;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
float b2GetRevoluteJointTorque( b2World* world, b2JointSim* base )
|
|
171
|
+
{
|
|
172
|
+
const b2RevoluteJoint* revolute = &base->revoluteJoint;
|
|
173
|
+
float torque = world->inv_h * ( revolute->motorImpulse + revolute->lowerImpulse - revolute->upperImpulse );
|
|
174
|
+
return torque;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Point-to-point constraint
|
|
178
|
+
// C = p2 - p1
|
|
179
|
+
// Cdot = v2 - v1
|
|
180
|
+
// = v2 + cross(w2, r2) - v1 - cross(w1, r1)
|
|
181
|
+
// J = [-I -r1_skew I r2_skew ]
|
|
182
|
+
// Identity used:
|
|
183
|
+
// w k % (rx i + ry j) = w * (-ry i + rx j)
|
|
184
|
+
|
|
185
|
+
// Motor constraint
|
|
186
|
+
// Cdot = w2 - w1
|
|
187
|
+
// J = [0 0 -1 0 0 1]
|
|
188
|
+
// K = invI1 + invI2
|
|
189
|
+
|
|
190
|
+
void b2PrepareRevoluteJoint( b2JointSim* base, b2StepContext* context )
|
|
191
|
+
{
|
|
192
|
+
B2_ASSERT( base->type == b2_revoluteJoint );
|
|
193
|
+
|
|
194
|
+
// chase body id to the solver set where the body lives
|
|
195
|
+
int idA = base->bodyIdA;
|
|
196
|
+
int idB = base->bodyIdB;
|
|
197
|
+
|
|
198
|
+
b2World* world = context->world;
|
|
199
|
+
|
|
200
|
+
b2Body* bodyA = b2BodyArray_Get( &world->bodies, idA );
|
|
201
|
+
b2Body* bodyB = b2BodyArray_Get( &world->bodies, idB );
|
|
202
|
+
|
|
203
|
+
B2_ASSERT( bodyA->setIndex == b2_awakeSet || bodyB->setIndex == b2_awakeSet );
|
|
204
|
+
b2SolverSet* setA = b2SolverSetArray_Get( &world->solverSets, bodyA->setIndex );
|
|
205
|
+
b2SolverSet* setB = b2SolverSetArray_Get( &world->solverSets, bodyB->setIndex );
|
|
206
|
+
|
|
207
|
+
int localIndexA = bodyA->localIndex;
|
|
208
|
+
int localIndexB = bodyB->localIndex;
|
|
209
|
+
|
|
210
|
+
b2BodySim* bodySimA = b2BodySimArray_Get( &setA->bodySims, localIndexA );
|
|
211
|
+
b2BodySim* bodySimB = b2BodySimArray_Get( &setB->bodySims, localIndexB );
|
|
212
|
+
|
|
213
|
+
float mA = bodySimA->invMass;
|
|
214
|
+
float iA = bodySimA->invInertia;
|
|
215
|
+
float mB = bodySimB->invMass;
|
|
216
|
+
float iB = bodySimB->invInertia;
|
|
217
|
+
|
|
218
|
+
base->invMassA = mA;
|
|
219
|
+
base->invMassB = mB;
|
|
220
|
+
base->invIA = iA;
|
|
221
|
+
base->invIB = iB;
|
|
222
|
+
|
|
223
|
+
b2RevoluteJoint* joint = &base->revoluteJoint;
|
|
224
|
+
|
|
225
|
+
joint->indexA = bodyA->setIndex == b2_awakeSet ? localIndexA : B2_NULL_INDEX;
|
|
226
|
+
joint->indexB = bodyB->setIndex == b2_awakeSet ? localIndexB : B2_NULL_INDEX;
|
|
227
|
+
|
|
228
|
+
// initial anchors in world space
|
|
229
|
+
joint->anchorA = b2RotateVector( bodySimA->transform.q, b2Sub( base->localOriginAnchorA, bodySimA->localCenter ) );
|
|
230
|
+
joint->anchorB = b2RotateVector( bodySimB->transform.q, b2Sub( base->localOriginAnchorB, bodySimB->localCenter ) );
|
|
231
|
+
joint->deltaCenter = b2Sub( bodySimB->center, bodySimA->center );
|
|
232
|
+
joint->deltaAngle = b2RelativeAngle( bodySimB->transform.q, bodySimA->transform.q ) - joint->referenceAngle;
|
|
233
|
+
joint->deltaAngle = b2UnwindAngle( joint->deltaAngle );
|
|
234
|
+
|
|
235
|
+
float k = iA + iB;
|
|
236
|
+
joint->axialMass = k > 0.0f ? 1.0f / k : 0.0f;
|
|
237
|
+
|
|
238
|
+
joint->springSoftness = b2MakeSoft( joint->hertz, joint->dampingRatio, context->h );
|
|
239
|
+
|
|
240
|
+
if ( context->enableWarmStarting == false )
|
|
241
|
+
{
|
|
242
|
+
joint->linearImpulse = b2Vec2_zero;
|
|
243
|
+
joint->springImpulse = 0.0f;
|
|
244
|
+
joint->motorImpulse = 0.0f;
|
|
245
|
+
joint->lowerImpulse = 0.0f;
|
|
246
|
+
joint->upperImpulse = 0.0f;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
void b2WarmStartRevoluteJoint( b2JointSim* base, b2StepContext* context )
|
|
251
|
+
{
|
|
252
|
+
B2_ASSERT( base->type == b2_revoluteJoint );
|
|
253
|
+
|
|
254
|
+
float mA = base->invMassA;
|
|
255
|
+
float mB = base->invMassB;
|
|
256
|
+
float iA = base->invIA;
|
|
257
|
+
float iB = base->invIB;
|
|
258
|
+
|
|
259
|
+
// dummy state for static bodies
|
|
260
|
+
b2BodyState dummyState = b2_identityBodyState;
|
|
261
|
+
|
|
262
|
+
b2RevoluteJoint* joint = &base->revoluteJoint;
|
|
263
|
+
b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA;
|
|
264
|
+
b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB;
|
|
265
|
+
|
|
266
|
+
b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA );
|
|
267
|
+
b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB );
|
|
268
|
+
|
|
269
|
+
float axialImpulse = joint->springImpulse + joint->motorImpulse + joint->lowerImpulse - joint->upperImpulse;
|
|
270
|
+
|
|
271
|
+
stateA->linearVelocity = b2MulSub( stateA->linearVelocity, mA, joint->linearImpulse );
|
|
272
|
+
stateA->angularVelocity -= iA * ( b2Cross( rA, joint->linearImpulse ) + axialImpulse );
|
|
273
|
+
|
|
274
|
+
stateB->linearVelocity = b2MulAdd( stateB->linearVelocity, mB, joint->linearImpulse );
|
|
275
|
+
stateB->angularVelocity += iB * ( b2Cross( rB, joint->linearImpulse ) + axialImpulse );
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
void b2SolveRevoluteJoint( b2JointSim* base, b2StepContext* context, bool useBias )
|
|
279
|
+
{
|
|
280
|
+
B2_ASSERT( base->type == b2_revoluteJoint );
|
|
281
|
+
|
|
282
|
+
float mA = base->invMassA;
|
|
283
|
+
float mB = base->invMassB;
|
|
284
|
+
float iA = base->invIA;
|
|
285
|
+
float iB = base->invIB;
|
|
286
|
+
|
|
287
|
+
// dummy state for static bodies
|
|
288
|
+
b2BodyState dummyState = b2_identityBodyState;
|
|
289
|
+
|
|
290
|
+
b2RevoluteJoint* joint = &base->revoluteJoint;
|
|
291
|
+
|
|
292
|
+
b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA;
|
|
293
|
+
b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB;
|
|
294
|
+
|
|
295
|
+
b2Vec2 vA = stateA->linearVelocity;
|
|
296
|
+
float wA = stateA->angularVelocity;
|
|
297
|
+
b2Vec2 vB = stateB->linearVelocity;
|
|
298
|
+
float wB = stateB->angularVelocity;
|
|
299
|
+
|
|
300
|
+
bool fixedRotation = ( iA + iB == 0.0f );
|
|
301
|
+
// const float maxBias = context->maxBiasVelocity;
|
|
302
|
+
|
|
303
|
+
// Solve spring.
|
|
304
|
+
if ( joint->enableSpring && fixedRotation == false )
|
|
305
|
+
{
|
|
306
|
+
float C = b2RelativeAngle( stateB->deltaRotation, stateA->deltaRotation ) + joint->deltaAngle;
|
|
307
|
+
float bias = joint->springSoftness.biasRate * C;
|
|
308
|
+
float massScale = joint->springSoftness.massScale;
|
|
309
|
+
float impulseScale = joint->springSoftness.impulseScale;
|
|
310
|
+
|
|
311
|
+
float Cdot = wB - wA;
|
|
312
|
+
float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * joint->springImpulse;
|
|
313
|
+
joint->springImpulse += impulse;
|
|
314
|
+
|
|
315
|
+
wA -= iA * impulse;
|
|
316
|
+
wB += iB * impulse;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Solve motor constraint.
|
|
320
|
+
if ( joint->enableMotor && fixedRotation == false )
|
|
321
|
+
{
|
|
322
|
+
float Cdot = wB - wA - joint->motorSpeed;
|
|
323
|
+
float impulse = -joint->axialMass * Cdot;
|
|
324
|
+
float oldImpulse = joint->motorImpulse;
|
|
325
|
+
float maxImpulse = context->h * joint->maxMotorTorque;
|
|
326
|
+
joint->motorImpulse = b2ClampFloat( joint->motorImpulse + impulse, -maxImpulse, maxImpulse );
|
|
327
|
+
impulse = joint->motorImpulse - oldImpulse;
|
|
328
|
+
|
|
329
|
+
wA -= iA * impulse;
|
|
330
|
+
wB += iB * impulse;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if ( joint->enableLimit && fixedRotation == false )
|
|
334
|
+
{
|
|
335
|
+
float jointAngle = b2RelativeAngle( stateB->deltaRotation, stateA->deltaRotation ) + joint->deltaAngle;
|
|
336
|
+
jointAngle = b2UnwindAngle( jointAngle );
|
|
337
|
+
|
|
338
|
+
// Lower limit
|
|
339
|
+
{
|
|
340
|
+
float C = jointAngle - joint->lowerAngle;
|
|
341
|
+
float bias = 0.0f;
|
|
342
|
+
float massScale = 1.0f;
|
|
343
|
+
float impulseScale = 0.0f;
|
|
344
|
+
if ( C > 0.0f )
|
|
345
|
+
{
|
|
346
|
+
// speculation
|
|
347
|
+
bias = C * context->inv_h;
|
|
348
|
+
}
|
|
349
|
+
else if ( useBias )
|
|
350
|
+
{
|
|
351
|
+
bias = context->jointSoftness.biasRate * C;
|
|
352
|
+
massScale = context->jointSoftness.massScale;
|
|
353
|
+
impulseScale = context->jointSoftness.impulseScale;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
float Cdot = wB - wA;
|
|
357
|
+
float oldImpulse = joint->lowerImpulse;
|
|
358
|
+
float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * oldImpulse;
|
|
359
|
+
joint->lowerImpulse = b2MaxFloat( oldImpulse + impulse, 0.0f );
|
|
360
|
+
impulse = joint->lowerImpulse - oldImpulse;
|
|
361
|
+
|
|
362
|
+
wA -= iA * impulse;
|
|
363
|
+
wB += iB * impulse;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Upper limit
|
|
367
|
+
// Note: signs are flipped to keep C positive when the constraint is satisfied.
|
|
368
|
+
// This also keeps the impulse positive when the limit is active.
|
|
369
|
+
{
|
|
370
|
+
float C = joint->upperAngle - jointAngle;
|
|
371
|
+
float bias = 0.0f;
|
|
372
|
+
float massScale = 1.0f;
|
|
373
|
+
float impulseScale = 0.0f;
|
|
374
|
+
if ( C > 0.0f )
|
|
375
|
+
{
|
|
376
|
+
// speculation
|
|
377
|
+
bias = C * context->inv_h;
|
|
378
|
+
}
|
|
379
|
+
else if ( useBias )
|
|
380
|
+
{
|
|
381
|
+
bias = context->jointSoftness.biasRate * C;
|
|
382
|
+
massScale = context->jointSoftness.massScale;
|
|
383
|
+
impulseScale = context->jointSoftness.impulseScale;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// sign flipped on Cdot
|
|
387
|
+
float Cdot = wA - wB;
|
|
388
|
+
float oldImpulse = joint->upperImpulse;
|
|
389
|
+
float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * oldImpulse;
|
|
390
|
+
joint->upperImpulse = b2MaxFloat( oldImpulse + impulse, 0.0f );
|
|
391
|
+
impulse = joint->upperImpulse - oldImpulse;
|
|
392
|
+
|
|
393
|
+
// sign flipped on applied impulse
|
|
394
|
+
wA += iA * impulse;
|
|
395
|
+
wB -= iB * impulse;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Solve point-to-point constraint
|
|
400
|
+
{
|
|
401
|
+
// J = [-I -r1_skew I r2_skew]
|
|
402
|
+
// r_skew = [-ry; rx]
|
|
403
|
+
// K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x]
|
|
404
|
+
// [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB]
|
|
405
|
+
|
|
406
|
+
// current anchors
|
|
407
|
+
b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA );
|
|
408
|
+
b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB );
|
|
409
|
+
|
|
410
|
+
b2Vec2 Cdot = b2Sub( b2Add( vB, b2CrossSV( wB, rB ) ), b2Add( vA, b2CrossSV( wA, rA ) ) );
|
|
411
|
+
|
|
412
|
+
b2Vec2 bias = b2Vec2_zero;
|
|
413
|
+
float massScale = 1.0f;
|
|
414
|
+
float impulseScale = 0.0f;
|
|
415
|
+
if ( useBias )
|
|
416
|
+
{
|
|
417
|
+
b2Vec2 dcA = stateA->deltaPosition;
|
|
418
|
+
b2Vec2 dcB = stateB->deltaPosition;
|
|
419
|
+
|
|
420
|
+
b2Vec2 separation = b2Add( b2Add( b2Sub( dcB, dcA ), b2Sub( rB, rA ) ), joint->deltaCenter );
|
|
421
|
+
bias = b2MulSV( context->jointSoftness.biasRate, separation );
|
|
422
|
+
massScale = context->jointSoftness.massScale;
|
|
423
|
+
impulseScale = context->jointSoftness.impulseScale;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
b2Mat22 K;
|
|
427
|
+
K.cx.x = mA + mB + rA.y * rA.y * iA + rB.y * rB.y * iB;
|
|
428
|
+
K.cy.x = -rA.y * rA.x * iA - rB.y * rB.x * iB;
|
|
429
|
+
K.cx.y = K.cy.x;
|
|
430
|
+
K.cy.y = mA + mB + rA.x * rA.x * iA + rB.x * rB.x * iB;
|
|
431
|
+
b2Vec2 b = b2Solve22( K, b2Add( Cdot, bias ) );
|
|
432
|
+
|
|
433
|
+
b2Vec2 impulse;
|
|
434
|
+
impulse.x = -massScale * b.x - impulseScale * joint->linearImpulse.x;
|
|
435
|
+
impulse.y = -massScale * b.y - impulseScale * joint->linearImpulse.y;
|
|
436
|
+
joint->linearImpulse.x += impulse.x;
|
|
437
|
+
joint->linearImpulse.y += impulse.y;
|
|
438
|
+
|
|
439
|
+
vA = b2MulSub( vA, mA, impulse );
|
|
440
|
+
wA -= iA * b2Cross( rA, impulse );
|
|
441
|
+
vB = b2MulAdd( vB, mB, impulse );
|
|
442
|
+
wB += iB * b2Cross( rB, impulse );
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
stateA->linearVelocity = vA;
|
|
446
|
+
stateA->angularVelocity = wA;
|
|
447
|
+
stateB->linearVelocity = vB;
|
|
448
|
+
stateB->angularVelocity = wB;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
#if 0
|
|
452
|
+
void b2RevoluteJoint::Dump()
|
|
453
|
+
{
|
|
454
|
+
int32 indexA = joint->bodyA->joint->islandIndex;
|
|
455
|
+
int32 indexB = joint->bodyB->joint->islandIndex;
|
|
456
|
+
|
|
457
|
+
b2Dump(" b2RevoluteJointDef jd;\n");
|
|
458
|
+
b2Dump(" jd.bodyA = bodies[%d];\n", indexA);
|
|
459
|
+
b2Dump(" jd.bodyB = bodies[%d];\n", indexB);
|
|
460
|
+
b2Dump(" jd.collideConnected = bool(%d);\n", joint->collideConnected);
|
|
461
|
+
b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", joint->localAnchorA.x, joint->localAnchorA.y);
|
|
462
|
+
b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", joint->localAnchorB.x, joint->localAnchorB.y);
|
|
463
|
+
b2Dump(" jd.referenceAngle = %.9g;\n", joint->referenceAngle);
|
|
464
|
+
b2Dump(" jd.enableLimit = bool(%d);\n", joint->enableLimit);
|
|
465
|
+
b2Dump(" jd.lowerAngle = %.9g;\n", joint->lowerAngle);
|
|
466
|
+
b2Dump(" jd.upperAngle = %.9g;\n", joint->upperAngle);
|
|
467
|
+
b2Dump(" jd.enableMotor = bool(%d);\n", joint->enableMotor);
|
|
468
|
+
b2Dump(" jd.motorSpeed = %.9g;\n", joint->motorSpeed);
|
|
469
|
+
b2Dump(" jd.maxMotorTorque = %.9g;\n", joint->maxMotorTorque);
|
|
470
|
+
b2Dump(" joints[%d] = joint->world->CreateJoint(&jd);\n", joint->index);
|
|
471
|
+
}
|
|
472
|
+
#endif
|
|
473
|
+
|
|
474
|
+
void b2DrawRevoluteJoint( b2DebugDraw* draw, b2JointSim* base, b2Transform transformA, b2Transform transformB, float drawSize )
|
|
475
|
+
{
|
|
476
|
+
B2_ASSERT( base->type == b2_revoluteJoint );
|
|
477
|
+
|
|
478
|
+
b2RevoluteJoint* joint = &base->revoluteJoint;
|
|
479
|
+
|
|
480
|
+
b2Vec2 pA = b2TransformPoint( transformA, base->localOriginAnchorA );
|
|
481
|
+
b2Vec2 pB = b2TransformPoint( transformB, base->localOriginAnchorB );
|
|
482
|
+
|
|
483
|
+
b2HexColor c1 = b2_colorGray;
|
|
484
|
+
b2HexColor c2 = b2_colorGreen;
|
|
485
|
+
b2HexColor c3 = b2_colorRed;
|
|
486
|
+
|
|
487
|
+
const float L = drawSize;
|
|
488
|
+
// draw->drawPoint(pA, 3.0f, b2_colorGray40, draw->context);
|
|
489
|
+
// draw->drawPoint(pB, 3.0f, b2_colorLightBlue, draw->context);
|
|
490
|
+
draw->DrawCircleFcn( pB, L, c1, draw->context );
|
|
491
|
+
|
|
492
|
+
float angle = b2RelativeAngle( transformB.q, transformA.q );
|
|
493
|
+
|
|
494
|
+
b2Rot rot = b2MakeRot( angle );
|
|
495
|
+
b2Vec2 r = { L * rot.c, L * rot.s };
|
|
496
|
+
b2Vec2 pC = b2Add( pB, r );
|
|
497
|
+
draw->DrawSegmentFcn( pB, pC, c1, draw->context );
|
|
498
|
+
|
|
499
|
+
if ( draw->drawJointExtras )
|
|
500
|
+
{
|
|
501
|
+
float jointAngle = b2UnwindAngle( angle - joint->referenceAngle );
|
|
502
|
+
char buffer[32];
|
|
503
|
+
snprintf( buffer, 32, " %.1f deg", 180.0f * jointAngle / B2_PI );
|
|
504
|
+
draw->DrawStringFcn( pC, buffer, b2_colorWhite, draw->context );
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
float lowerAngle = joint->lowerAngle + joint->referenceAngle;
|
|
508
|
+
float upperAngle = joint->upperAngle + joint->referenceAngle;
|
|
509
|
+
|
|
510
|
+
if ( joint->enableLimit )
|
|
511
|
+
{
|
|
512
|
+
b2Rot rotLo = b2MakeRot( lowerAngle );
|
|
513
|
+
b2Vec2 rlo = { L * rotLo.c, L * rotLo.s };
|
|
514
|
+
|
|
515
|
+
b2Rot rotHi = b2MakeRot( upperAngle );
|
|
516
|
+
b2Vec2 rhi = { L * rotHi.c, L * rotHi.s };
|
|
517
|
+
|
|
518
|
+
draw->DrawSegmentFcn( pB, b2Add( pB, rlo ), c2, draw->context );
|
|
519
|
+
draw->DrawSegmentFcn( pB, b2Add( pB, rhi ), c3, draw->context );
|
|
520
|
+
|
|
521
|
+
b2Rot rotRef = b2MakeRot( joint->referenceAngle );
|
|
522
|
+
b2Vec2 ref = (b2Vec2){ L * rotRef.c, L * rotRef.s };
|
|
523
|
+
draw->DrawSegmentFcn( pB, b2Add( pB, ref ), b2_colorBlue, draw->context );
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
b2HexColor color = b2_colorGold;
|
|
527
|
+
draw->DrawSegmentFcn( transformA.p, pA, color, draw->context );
|
|
528
|
+
draw->DrawSegmentFcn( pA, pB, color, draw->context );
|
|
529
|
+
draw->DrawSegmentFcn( transformB.p, pB, color, draw->context );
|
|
530
|
+
|
|
531
|
+
// char buffer[32];
|
|
532
|
+
// sprintf(buffer, "%.1f", b2Length(joint->impulse));
|
|
533
|
+
// draw->DrawString(pA, buffer, draw->context);
|
|
534
|
+
}
|