b2_distance_joint.cpp
Go to the documentation of this file.
1 // MIT License
2 
3 // Copyright (c) 2019 Erin Catto
4 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 
23 #include "box2d/b2_body.h"
24 #include "box2d/b2_draw.h"
26 #include "box2d/b2_time_step.h"
27 
28 // 1-D constrained system
29 // m (v2 - v1) = lambda
30 // v2 + (beta/h) * x1 + gamma * lambda = 0, gamma has units of inverse mass.
31 // x2 = x1 + h * v2
32 
33 // 1-D mass-damper-spring system
34 // m (v2 - v1) + h * d * v2 + h * k *
35 
36 // C = norm(p2 - p1) - L
37 // u = (p2 - p1) / norm(p2 - p1)
38 // Cdot = dot(u, v2 + cross(w2, r2) - v1 - cross(w1, r1))
39 // J = [-u -cross(r1, u) u cross(r2, u)]
40 // K = J * invM * JT
41 // = invMass1 + invI1 * cross(r1, u)^2 + invMass2 + invI2 * cross(r2, u)^2
42 
43 
45  const b2Vec2& anchor1, const b2Vec2& anchor2)
46 {
47  bodyA = b1;
48  bodyB = b2;
49  localAnchorA = bodyA->GetLocalPoint(anchor1);
50  localAnchorB = bodyB->GetLocalPoint(anchor2);
51  b2Vec2 d = anchor2 - anchor1;
52  length = b2Max(d.Length(), b2_linearSlop);
53  minLength = length;
54  maxLength = length;
55 }
56 
58 : b2Joint(def)
59 {
65  m_stiffness = def->stiffness;
66  m_damping = def->damping;
67 
68  m_gamma = 0.0f;
69  m_bias = 0.0f;
70  m_impulse = 0.0f;
71  m_lowerImpulse = 0.0f;
72  m_upperImpulse = 0.0f;
73  m_currentLength = 0.0f;
74 }
75 
77 {
86 
87  b2Vec2 cA = data.positions[m_indexA].c;
88  float aA = data.positions[m_indexA].a;
89  b2Vec2 vA = data.velocities[m_indexA].v;
90  float wA = data.velocities[m_indexA].w;
91 
92  b2Vec2 cB = data.positions[m_indexB].c;
93  float aB = data.positions[m_indexB].a;
94  b2Vec2 vB = data.velocities[m_indexB].v;
95  float wB = data.velocities[m_indexB].w;
96 
97  b2Rot qA(aA), qB(aB);
98 
101  m_u = cB + m_rB - cA - m_rA;
102 
103  // Handle singularity.
106  {
107  m_u *= 1.0f / m_currentLength;
108  }
109  else
110  {
111  m_u.Set(0.0f, 0.0f);
112  m_mass = 0.0f;
113  m_impulse = 0.0f;
114  m_lowerImpulse = 0.0f;
115  m_upperImpulse = 0.0f;
116  }
117 
118  float crAu = b2Cross(m_rA, m_u);
119  float crBu = b2Cross(m_rB, m_u);
120  float invMass = m_invMassA + m_invIA * crAu * crAu + m_invMassB + m_invIB * crBu * crBu;
121  m_mass = invMass != 0.0f ? 1.0f / invMass : 0.0f;
122 
123  if (m_stiffness > 0.0f && m_minLength < m_maxLength)
124  {
125  // soft
126  float C = m_currentLength - m_length;
127 
128  float d = m_damping;
129  float k = m_stiffness;
130 
131  // magic formulas
132  float h = data.step.dt;
133 
134  // gamma = 1 / (h * (d + h * k))
135  // the extra factor of h in the denominator is since the lambda is an impulse, not a force
136  m_gamma = h * (d + h * k);
137  m_gamma = m_gamma != 0.0f ? 1.0f / m_gamma : 0.0f;
138  m_bias = C * h * k * m_gamma;
139 
140  invMass += m_gamma;
141  m_softMass = invMass != 0.0f ? 1.0f / invMass : 0.0f;
142  }
143  else
144  {
145  // rigid
146  m_gamma = 0.0f;
147  m_bias = 0.0f;
148  m_softMass = m_mass;
149  }
150 
151  if (data.step.warmStarting)
152  {
153  // Scale the impulse to support a variable time step.
154  m_impulse *= data.step.dtRatio;
155  m_lowerImpulse *= data.step.dtRatio;
156  m_upperImpulse *= data.step.dtRatio;
157 
159  vA -= m_invMassA * P;
160  wA -= m_invIA * b2Cross(m_rA, P);
161  vB += m_invMassB * P;
162  wB += m_invIB * b2Cross(m_rB, P);
163  }
164  else
165  {
166  m_impulse = 0.0f;
167  }
168 
169  data.velocities[m_indexA].v = vA;
170  data.velocities[m_indexA].w = wA;
171  data.velocities[m_indexB].v = vB;
172  data.velocities[m_indexB].w = wB;
173 }
174 
176 {
177  b2Vec2 vA = data.velocities[m_indexA].v;
178  float wA = data.velocities[m_indexA].w;
179  b2Vec2 vB = data.velocities[m_indexB].v;
180  float wB = data.velocities[m_indexB].w;
181 
182  if (m_minLength < m_maxLength)
183  {
184  if (m_stiffness > 0.0f)
185  {
186  // Cdot = dot(u, v + cross(w, r))
187  b2Vec2 vpA = vA + b2Cross(wA, m_rA);
188  b2Vec2 vpB = vB + b2Cross(wB, m_rB);
189  float Cdot = b2Dot(m_u, vpB - vpA);
190 
191  float impulse = -m_softMass * (Cdot + m_bias + m_gamma * m_impulse);
192  m_impulse += impulse;
193 
194  b2Vec2 P = impulse * m_u;
195  vA -= m_invMassA * P;
196  wA -= m_invIA * b2Cross(m_rA, P);
197  vB += m_invMassB * P;
198  wB += m_invIB * b2Cross(m_rB, P);
199  }
200 
201  // lower
202  {
203  float C = m_currentLength - m_minLength;
204  float bias = b2Max(0.0f, C) * data.step.inv_dt;
205 
206  b2Vec2 vpA = vA + b2Cross(wA, m_rA);
207  b2Vec2 vpB = vB + b2Cross(wB, m_rB);
208  float Cdot = b2Dot(m_u, vpB - vpA);
209 
210  float impulse = -m_mass * (Cdot + bias);
211  float oldImpulse = m_lowerImpulse;
212  m_lowerImpulse = b2Max(0.0f, m_lowerImpulse + impulse);
213  impulse = m_lowerImpulse - oldImpulse;
214  b2Vec2 P = impulse * m_u;
215 
216  vA -= m_invMassA * P;
217  wA -= m_invIA * b2Cross(m_rA, P);
218  vB += m_invMassB * P;
219  wB += m_invIB * b2Cross(m_rB, P);
220  }
221 
222  // upper
223  {
224  float C = m_maxLength - m_currentLength;
225  float bias = b2Max(0.0f, C) * data.step.inv_dt;
226 
227  b2Vec2 vpA = vA + b2Cross(wA, m_rA);
228  b2Vec2 vpB = vB + b2Cross(wB, m_rB);
229  float Cdot = b2Dot(m_u, vpA - vpB);
230 
231  float impulse = -m_mass * (Cdot + bias);
232  float oldImpulse = m_upperImpulse;
233  m_upperImpulse = b2Max(0.0f, m_upperImpulse + impulse);
234  impulse = m_upperImpulse - oldImpulse;
235  b2Vec2 P = -impulse * m_u;
236 
237  vA -= m_invMassA * P;
238  wA -= m_invIA * b2Cross(m_rA, P);
239  vB += m_invMassB * P;
240  wB += m_invIB * b2Cross(m_rB, P);
241  }
242  }
243  else
244  {
245  // Equal limits
246 
247  // Cdot = dot(u, v + cross(w, r))
248  b2Vec2 vpA = vA + b2Cross(wA, m_rA);
249  b2Vec2 vpB = vB + b2Cross(wB, m_rB);
250  float Cdot = b2Dot(m_u, vpB - vpA);
251 
252  float impulse = -m_mass * Cdot;
253  m_impulse += impulse;
254 
255  b2Vec2 P = impulse * m_u;
256  vA -= m_invMassA * P;
257  wA -= m_invIA * b2Cross(m_rA, P);
258  vB += m_invMassB * P;
259  wB += m_invIB * b2Cross(m_rB, P);
260  }
261 
262  data.velocities[m_indexA].v = vA;
263  data.velocities[m_indexA].w = wA;
264  data.velocities[m_indexB].v = vB;
265  data.velocities[m_indexB].w = wB;
266 }
267 
269 {
270  b2Vec2 cA = data.positions[m_indexA].c;
271  float aA = data.positions[m_indexA].a;
272  b2Vec2 cB = data.positions[m_indexB].c;
273  float aB = data.positions[m_indexB].a;
274 
275  b2Rot qA(aA), qB(aB);
276 
279  b2Vec2 u = cB + rB - cA - rA;
280 
281  float length = u.Normalize();
282  float C;
283  if (m_minLength == m_maxLength)
284  {
285  C = length - m_minLength;
286  }
287  else if (length < m_minLength)
288  {
289  C = length - m_minLength;
290  }
291  else if (m_maxLength < length)
292  {
293  C = length - m_maxLength;
294  }
295  else
296  {
297  return true;
298  }
299 
300  float impulse = -m_mass * C;
301  b2Vec2 P = impulse * u;
302 
303  cA -= m_invMassA * P;
304  aA -= m_invIA * b2Cross(rA, P);
305  cB += m_invMassB * P;
306  aB += m_invIB * b2Cross(rB, P);
307 
308  data.positions[m_indexA].c = cA;
309  data.positions[m_indexA].a = aA;
310  data.positions[m_indexB].c = cB;
311  data.positions[m_indexB].a = aB;
312 
313  return b2Abs(C) < b2_linearSlop;
314 }
315 
317 {
319 }
320 
322 {
324 }
325 
327 {
328  b2Vec2 F = inv_dt * (m_impulse + m_lowerImpulse - m_upperImpulse) * m_u;
329  return F;
330 }
331 
332 float b2DistanceJoint::GetReactionTorque(float inv_dt) const
333 {
334  B2_NOT_USED(inv_dt);
335  return 0.0f;
336 }
337 
339 {
340  m_impulse = 0.0f;
342  return m_length;
343 }
344 
345 float b2DistanceJoint::SetMinLength(float minLength)
346 {
347  m_lowerImpulse = 0.0f;
349  return m_minLength;
350 }
351 
352 float b2DistanceJoint::SetMaxLength(float maxLength)
353 {
354  m_upperImpulse = 0.0f;
355  m_maxLength = b2Max(maxLength, m_minLength);
356  return m_maxLength;
357 }
358 
360 {
363  b2Vec2 d = pB - pA;
364  float length = d.Length();
365  return length;
366 }
367 
369 {
370  int32 indexA = m_bodyA->m_islandIndex;
371  int32 indexB = m_bodyB->m_islandIndex;
372 
373  b2Dump(" b2DistanceJointDef jd;\n");
374  b2Dump(" jd.bodyA = bodies[%d];\n", indexA);
375  b2Dump(" jd.bodyB = bodies[%d];\n", indexB);
376  b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected);
377  b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y);
378  b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y);
379  b2Dump(" jd.length = %.9g;\n", m_length);
380  b2Dump(" jd.minLength = %.9g;\n", m_minLength);
381  b2Dump(" jd.maxLength = %.9g;\n", m_maxLength);
382  b2Dump(" jd.stiffness = %.9g;\n", m_stiffness);
383  b2Dump(" jd.damping = %.9g;\n", m_damping);
384  b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index);
385 }
386 
387 void b2DistanceJoint::Draw(b2Draw* draw) const
388 {
389  const b2Transform& xfA = m_bodyA->GetTransform();
390  const b2Transform& xfB = m_bodyB->GetTransform();
391  b2Vec2 pA = b2Mul(xfA, m_localAnchorA);
392  b2Vec2 pB = b2Mul(xfB, m_localAnchorB);
393 
394  b2Vec2 axis = pB - pA;
395  float length = axis.Normalize();
396 
397  b2Color c1(0.7f, 0.7f, 0.7f);
398  b2Color c2(0.3f, 0.9f, 0.3f);
399  b2Color c3(0.9f, 0.3f, 0.3f);
400  b2Color c4(0.4f, 0.4f, 0.4f);
401 
402  draw->DrawSegment(pA, pB, c4);
403 
404  b2Vec2 pRest = pA + m_length * axis;
405  draw->DrawPoint(pRest, 8.0f, c1);
406 
407  if (m_minLength != m_maxLength)
408  {
410  {
411  b2Vec2 pMin = pA + m_minLength * axis;
412  draw->DrawPoint(pMin, 4.0f, c2);
413  }
414 
415  if (m_maxLength < FLT_MAX)
416  {
417  b2Vec2 pMax = pA + m_maxLength * axis;
418  draw->DrawPoint(pMax, 4.0f, c3);
419  }
420  }
421 }
b2DistanceJoint::m_localAnchorB
b2Vec2 m_localAnchorB
Definition: b2_distance_joint.h:153
b2Cross
float b2Cross(const b2Vec2 &a, const b2Vec2 &b)
Perform the cross product on two vectors. In 2D this produces a scalar.
Definition: b2_math.h:401
b2Joint::m_index
int32 m_index
Definition: b2_joint.h:185
b2DistanceJoint::GetCurrentLength
float GetCurrentLength() const
Get the current length.
Definition: b2_distance_joint.cpp:359
b2DistanceJoint::m_localCenterA
b2Vec2 m_localCenterA
Definition: b2_distance_joint.h:165
b2Vec2::y
float y
Definition: b2_math.h:128
B2_NOT_USED
#define B2_NOT_USED(x)
Definition: b2_common.h:36
b2DistanceJoint::GetReactionTorque
float GetReactionTorque(float inv_dt) const override
Definition: b2_distance_joint.cpp:332
b2DistanceJoint::m_invMassA
float m_invMassA
Definition: b2_distance_joint.h:168
b2DistanceJoint::m_invIB
float m_invIB
Definition: b2_distance_joint.h:171
b2Position::c
b2Vec2 c
Definition: b2_time_step.h:55
b2DistanceJoint::m_mass
float m_mass
Definition: b2_distance_joint.h:173
b2DistanceJointDef::localAnchorB
b2Vec2 localAnchorB
The local anchor point relative to bodyB's origin.
Definition: b2_distance_joint.h:56
b2Sweep::localCenter
b2Vec2 localCenter
local center of mass position
Definition: b2_math.h:382
b2Vec2::Normalize
float Normalize()
Convert this vector into a unit vector. Returns the length.
Definition: b2_math.h:102
b2SolverData
Solver Data.
Definition: b2_time_step.h:67
b2Body::m_invMass
float m_invMass
Definition: b2_body.h:460
b2Draw::DrawSegment
virtual void DrawSegment(const b2Vec2 &p1, const b2Vec2 &p2, const b2Color &color)=0
Draw a line segment.
b2DistanceJointDef::damping
float damping
The linear damping in N*s/m.
Definition: b2_distance_joint.h:71
b2_distance_joint.h
b2DistanceJointDef::length
float length
The rest length of this joint. Clamped to a stable minimum value.
Definition: b2_distance_joint.h:59
b2Body
A rigid body. These are created via b2World::CreateBody.
Definition: b2_body.h:128
b2DistanceJoint::m_lowerImpulse
float m_lowerImpulse
Definition: b2_distance_joint.h:156
b2Mul
b2Vec2 b2Mul(const b2Mat22 &A, const b2Vec2 &v)
Definition: b2_math.h:422
b2Dump
void b2Dump(const char *string,...)
Definition: b2_settings.cpp:57
b2Velocity::v
b2Vec2 v
Definition: b2_time_step.h:62
b2DistanceJoint::m_u
b2Vec2 m_u
Definition: b2_distance_joint.h:162
b2Vec2::Set
void Set(float x_, float y_)
Set this vector to some specified coordinates.
Definition: b2_math.h:53
b2DistanceJoint::SetMaxLength
float SetMaxLength(float maxLength)
Definition: b2_distance_joint.cpp:352
b2DistanceJoint::m_length
float m_length
Definition: b2_distance_joint.h:147
b2Vec2
A 2D column vector.
Definition: b2_math.h:41
b2DistanceJoint::GetAnchorA
b2Vec2 GetAnchorA() const override
Get the anchor point on bodyA in world coordinates.
Definition: b2_distance_joint.cpp:316
f
f
b2Max
T b2Max(T a, T b)
Definition: b2_math.h:637
b2DistanceJointDef::maxLength
float maxLength
Maximum length. Must be greater than or equal to the minimum length.
Definition: b2_distance_joint.h:65
b2DistanceJoint::m_rB
b2Vec2 m_rB
Definition: b2_distance_joint.h:164
b2Draw::DrawPoint
virtual void DrawPoint(const b2Vec2 &p, float size, const b2Color &color)=0
Draw a point.
b2SolverData::positions
b2Position * positions
Definition: b2_time_step.h:70
b2DistanceJoint::m_softMass
float m_softMass
Definition: b2_distance_joint.h:172
b2DistanceJointDef::stiffness
float stiffness
The linear stiffness in N/m.
Definition: b2_distance_joint.h:68
b2Joint
Definition: b2_joint.h:110
b2Draw
Definition: b2_draw.h:48
b2Clamp
T b2Clamp(T a, T low, T high)
Definition: b2_math.h:648
b2DistanceJoint::GetAnchorB
b2Vec2 GetAnchorB() const override
Get the anchor point on bodyB in world coordinates.
Definition: b2_distance_joint.cpp:321
b2DistanceJoint::m_maxLength
float m_maxLength
Definition: b2_distance_joint.h:149
b2DistanceJoint::SolveVelocityConstraints
void SolveVelocityConstraints(const b2SolverData &data) override
Definition: b2_distance_joint.cpp:175
b2Transform
Definition: b2_math.h:338
b2SolverData::step
b2TimeStep step
Definition: b2_time_step.h:69
b2DistanceJoint::m_invMassB
float m_invMassB
Definition: b2_distance_joint.h:169
length
GLenum GLuint GLenum GLsizei length
Definition: gl.h:1033
b2DistanceJoint::Dump
void Dump() override
Dump joint to dmLog.
Definition: b2_distance_joint.cpp:368
b2DistanceJoint::SolvePositionConstraints
bool SolvePositionConstraints(const b2SolverData &data) override
Definition: b2_distance_joint.cpp:268
b2DistanceJoint::m_currentLength
float m_currentLength
Definition: b2_distance_joint.h:167
b2DistanceJoint::m_impulse
float m_impulse
Definition: b2_distance_joint.h:155
b2SolverData::velocities
b2Velocity * velocities
Definition: b2_time_step.h:71
b2_draw.h
b2Dot
float b2Dot(const b2Vec2 &a, const b2Vec2 &b)
Perform the dot product on two vectors.
Definition: b2_math.h:395
b2Joint::m_collideConnected
bool m_collideConnected
Definition: b2_joint.h:188
b2Color
Color for debug drawing. Each value has the range [0,1].
Definition: b2_draw.h:30
b2TimeStep::dt
float dt
Definition: b2_time_step.h:44
d
d
b2DistanceJoint::m_localAnchorA
b2Vec2 m_localAnchorA
Definition: b2_distance_joint.h:152
b2DistanceJoint::m_localCenterB
b2Vec2 m_localCenterB
Definition: b2_distance_joint.h:166
b2DistanceJoint::Draw
void Draw(b2Draw *draw) const override
Debug draw this joint.
Definition: b2_distance_joint.cpp:387
b2DistanceJoint::m_damping
float m_damping
Definition: b2_distance_joint.h:145
b2TimeStep::inv_dt
float inv_dt
Definition: b2_time_step.h:45
b2DistanceJointDef::minLength
float minLength
Minimum length. Clamped to a stable minimum value.
Definition: b2_distance_joint.h:62
b2Body::GetLocalPoint
b2Vec2 GetLocalPoint(const b2Vec2 &worldPoint) const
Definition: b2_body.h:571
b2Vec2::x
float x
Definition: b2_math.h:128
b2DistanceJointDef::Initialize
void Initialize(b2Body *bodyA, b2Body *bodyB, const b2Vec2 &anchorA, const b2Vec2 &anchorB)
Definition: b2_distance_joint.cpp:44
b2Body::m_islandIndex
int32 m_islandIndex
Definition: b2_body.h:439
b2DistanceJoint::m_stiffness
float m_stiffness
Definition: b2_distance_joint.h:144
b2Velocity::w
float w
Definition: b2_time_step.h:63
b2DistanceJoint::b2DistanceJoint
b2DistanceJoint(const b2DistanceJointDef *data)
Definition: b2_distance_joint.cpp:57
b2DistanceJoint::m_invIA
float m_invIA
Definition: b2_distance_joint.h:170
b2DistanceJoint::SetLength
float SetLength(float length)
Definition: b2_distance_joint.cpp:338
b2Joint::m_bodyA
b2Body * m_bodyA
Definition: b2_joint.h:182
b2Position::a
float a
Definition: b2_time_step.h:56
b2DistanceJoint::m_rA
b2Vec2 m_rA
Definition: b2_distance_joint.h:163
b2DistanceJoint::GetReactionForce
b2Vec2 GetReactionForce(float inv_dt) const override
Definition: b2_distance_joint.cpp:326
b2DistanceJoint::m_gamma
float m_gamma
Definition: b2_distance_joint.h:154
b2TimeStep::warmStarting
bool warmStarting
Definition: b2_time_step.h:49
b2_time_step.h
b2DistanceJoint::m_minLength
float m_minLength
Definition: b2_distance_joint.h:148
int32
signed int int32
Definition: b2_types.h:28
b2DistanceJoint::m_indexB
int32 m_indexB
Definition: b2_distance_joint.h:161
b2DistanceJoint::m_bias
float m_bias
Definition: b2_distance_joint.h:146
b2DistanceJointDef
Definition: b2_distance_joint.h:33
b2DistanceJoint::InitVelocityConstraints
void InitVelocityConstraints(const b2SolverData &data) override
Definition: b2_distance_joint.cpp:76
b2Body::m_sweep
b2Sweep m_sweep
Definition: b2_body.h:442
b2Rot
Rotation.
Definition: b2_math.h:287
b2DistanceJoint::m_indexA
int32 m_indexA
Definition: b2_distance_joint.h:160
b2Body::GetWorldPoint
b2Vec2 GetWorldPoint(const b2Vec2 &localPoint) const
Definition: b2_body.h:561
b2DistanceJoint::m_upperImpulse
float m_upperImpulse
Definition: b2_distance_joint.h:157
b2Joint::m_bodyB
b2Body * m_bodyB
Definition: b2_joint.h:183
b2DistanceJoint::SetMinLength
float SetMinLength(float minLength)
Definition: b2_distance_joint.cpp:345
b2Body::GetTransform
const b2Transform & GetTransform() const
Definition: b2_body.h:479
b2_linearSlop
#define b2_linearSlop
Definition: b2_common.h:65
b2Vec2::Length
float Length() const
Get the length of this vector (the norm).
Definition: b2_math.h:89
b2Body::m_invI
float m_invI
Definition: b2_body.h:463
b2JointDef::bodyA
b2Body * bodyA
The first attached body.
Definition: b2_joint.h:89
b2DistanceJointDef::localAnchorA
b2Vec2 localAnchorA
The local anchor point relative to bodyA's origin.
Definition: b2_distance_joint.h:53
b2Abs
T b2Abs(T a)
Definition: b2_math.h:610
b2TimeStep::dtRatio
float dtRatio
Definition: b2_time_step.h:46
b2JointDef::bodyB
b2Body * bodyB
The second attached body.
Definition: b2_joint.h:92
b2_body.h


mvsim
Author(s):
autogenerated on Wed May 28 2025 02:13:07