b2_body.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_contact.h"
25 #include "box2d/b2_fixture.h"
26 #include "box2d/b2_joint.h"
27 #include "box2d/b2_world.h"
28 
29 #include <new>
30 
31 b2Body::b2Body(const b2BodyDef* bd, b2World* world)
32 {
33  b2Assert(bd->position.IsValid());
35  b2Assert(b2IsValid(bd->angle));
37  b2Assert(b2IsValid(bd->angularDamping) && bd->angularDamping >= 0.0f);
38  b2Assert(b2IsValid(bd->linearDamping) && bd->linearDamping >= 0.0f);
39 
40  m_flags = 0;
41 
42  if (bd->bullet)
43  {
45  }
46  if (bd->fixedRotation)
47  {
49  }
50  if (bd->allowSleep)
51  {
53  }
54  if (bd->awake && bd->type != b2_staticBody)
55  {
57  }
58  if (bd->enabled)
59  {
61  }
62 
63  m_world = world;
64 
65  m_xf.p = bd->position;
66  m_xf.q.Set(bd->angle);
67 
69  m_sweep.c0 = m_xf.p;
70  m_sweep.c = m_xf.p;
71  m_sweep.a0 = bd->angle;
72  m_sweep.a = bd->angle;
73  m_sweep.alpha0 = 0.0f;
74 
75  m_jointList = nullptr;
76  m_contactList = nullptr;
77  m_prev = nullptr;
78  m_next = nullptr;
79 
82 
86 
87  m_force.SetZero();
88  m_torque = 0.0f;
89 
90  m_sleepTime = 0.0f;
91 
92  m_type = bd->type;
93 
94  m_mass = 0.0f;
95  m_invMass = 0.0f;
96 
97  m_I = 0.0f;
98  m_invI = 0.0f;
99 
100  m_userData = bd->userData;
101 
102  m_fixtureList = nullptr;
103  m_fixtureCount = 0;
104 }
105 
107 {
108  // shapes and joints are destroyed in b2World::Destroy
109 }
110 
112 {
113  b2Assert(m_world->IsLocked() == false);
114  if (m_world->IsLocked() == true)
115  {
116  return;
117  }
118 
119  if (m_type == type)
120  {
121  return;
122  }
123 
124  m_type = type;
125 
126  ResetMassData();
127 
128  if (m_type == b2_staticBody)
129  {
131  m_angularVelocity = 0.0f;
132  m_sweep.a0 = m_sweep.a;
133  m_sweep.c0 = m_sweep.c;
134  m_flags &= ~e_awakeFlag;
136  }
137 
138  SetAwake(true);
139 
140  m_force.SetZero();
141  m_torque = 0.0f;
142 
143  // Delete the attached contacts.
145  while (ce)
146  {
147  b2ContactEdge* ce0 = ce;
148  ce = ce->next;
150  }
151  m_contactList = nullptr;
152 
153  // Touch the proxies so that new contacts will be created (when appropriate)
155  for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
156  {
157  int32 proxyCount = f->m_proxyCount;
158  for (int32 i = 0; i < proxyCount; ++i)
159  {
160  broadPhase->TouchProxy(f->m_proxies[i].proxyId);
161  }
162  }
163 }
164 
166 {
167  b2Assert(m_world->IsLocked() == false);
168  if (m_world->IsLocked() == true)
169  {
170  return nullptr;
171  }
172 
174 
175  void* memory = allocator->Allocate(sizeof(b2Fixture));
176  b2Fixture* fixture = new (memory) b2Fixture;
177  fixture->Create(allocator, this, def);
178 
179  if (m_flags & e_enabledFlag)
180  {
182  fixture->CreateProxies(broadPhase, m_xf);
183  }
184 
185  fixture->m_next = m_fixtureList;
186  m_fixtureList = fixture;
187  ++m_fixtureCount;
188 
189  fixture->m_body = this;
190 
191  // Adjust mass properties if needed.
192  if (fixture->m_density > 0.0f)
193  {
194  ResetMassData();
195  }
196 
197  // Let the world know we have a new fixture. This will cause new contacts
198  // to be created at the beginning of the next time step.
199  m_world->m_newContacts = true;
200 
201  return fixture;
202 }
203 
204 b2Fixture* b2Body::CreateFixture(const b2Shape* shape, float density)
205 {
206  b2FixtureDef def;
207  def.shape = shape;
208  def.density = density;
209 
210  return CreateFixture(&def);
211 }
212 
214 {
215  if (fixture == NULL)
216  {
217  return;
218  }
219 
220  b2Assert(m_world->IsLocked() == false);
221  if (m_world->IsLocked() == true)
222  {
223  return;
224  }
225 
226  b2Assert(fixture->m_body == this);
227 
228  // Remove the fixture from this body's singly linked list.
230  b2Fixture** node = &m_fixtureList;
231  bool found = false;
232  while (*node != nullptr)
233  {
234  if (*node == fixture)
235  {
236  *node = fixture->m_next;
237  found = true;
238  break;
239  }
240 
241  node = &(*node)->m_next;
242  }
243 
244  // You tried to remove a shape that is not attached to this body.
245  b2Assert(found);
246 
247  // Destroy any contacts associated with the fixture.
249  while (edge)
250  {
251  b2Contact* c = edge->contact;
252  edge = edge->next;
253 
254  b2Fixture* fixtureA = c->GetFixtureA();
255  b2Fixture* fixtureB = c->GetFixtureB();
256 
257  if (fixture == fixtureA || fixture == fixtureB)
258  {
259  // This destroys the contact and removes it from
260  // this body's contact list.
262  }
263  }
264 
266 
267  if (m_flags & e_enabledFlag)
268  {
270  fixture->DestroyProxies(broadPhase);
271  }
272 
273  fixture->m_body = nullptr;
274  fixture->m_next = nullptr;
275  fixture->Destroy(allocator);
276  fixture->~b2Fixture();
277  allocator->Free(fixture, sizeof(b2Fixture));
278 
279  --m_fixtureCount;
280 
281  // Reset the mass data.
282  ResetMassData();
283 }
284 
286 {
287  // Compute mass data from shapes. Each shape has its own density.
288  m_mass = 0.0f;
289  m_invMass = 0.0f;
290  m_I = 0.0f;
291  m_invI = 0.0f;
293 
294  // Static and kinematic bodies have zero mass.
296  {
297  m_sweep.c0 = m_xf.p;
298  m_sweep.c = m_xf.p;
299  m_sweep.a0 = m_sweep.a;
300  return;
301  }
302 
304 
305  // Accumulate mass over all fixtures.
306  b2Vec2 localCenter = b2Vec2_zero;
307  for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
308  {
309  if (f->m_density == 0.0f)
310  {
311  continue;
312  }
313 
314  b2MassData massData;
315  f->GetMassData(&massData);
316  m_mass += massData.mass;
317  localCenter += massData.mass * massData.center;
318  m_I += massData.I;
319  }
320 
321  // Compute center of mass.
322  if (m_mass > 0.0f)
323  {
324  m_invMass = 1.0f / m_mass;
325  localCenter *= m_invMass;
326  }
327 
328  if (m_I > 0.0f && (m_flags & e_fixedRotationFlag) == 0)
329  {
330  // Center the inertia about the center of mass.
331  m_I -= m_mass * b2Dot(localCenter, localCenter);
332  b2Assert(m_I > 0.0f);
333  m_invI = 1.0f / m_I;
334 
335  }
336  else
337  {
338  m_I = 0.0f;
339  m_invI = 0.0f;
340  }
341 
342  // Move center of mass.
343  b2Vec2 oldCenter = m_sweep.c;
344  m_sweep.localCenter = localCenter;
346 
347  // Update center of mass velocity.
349 }
350 
351 void b2Body::SetMassData(const b2MassData* massData)
352 {
353  b2Assert(m_world->IsLocked() == false);
354  if (m_world->IsLocked() == true)
355  {
356  return;
357  }
358 
359  if (m_type != b2_dynamicBody)
360  {
361  return;
362  }
363 
364  m_invMass = 0.0f;
365  m_I = 0.0f;
366  m_invI = 0.0f;
367 
368  m_mass = massData->mass;
369  if (m_mass <= 0.0f)
370  {
371  m_mass = 1.0f;
372  }
373 
374  m_invMass = 1.0f / m_mass;
375 
376  if (massData->I > 0.0f && (m_flags & b2Body::e_fixedRotationFlag) == 0)
377  {
378  m_I = massData->I - m_mass * b2Dot(massData->center, massData->center);
379  b2Assert(m_I > 0.0f);
380  m_invI = 1.0f / m_I;
381  }
382 
383  // Move center of mass.
384  b2Vec2 oldCenter = m_sweep.c;
385  m_sweep.localCenter = massData->center;
387 
388  // Update center of mass velocity.
390 }
391 
392 bool b2Body::ShouldCollide(const b2Body* other) const
393 {
394  // At least one body should be dynamic.
395  if (m_type != b2_dynamicBody && other->m_type != b2_dynamicBody)
396  {
397  return false;
398  }
399 
400  // Does a joint prevent collision?
401  for (b2JointEdge* jn = m_jointList; jn; jn = jn->next)
402  {
403  if (jn->other == other)
404  {
405  if (jn->joint->m_collideConnected == false)
406  {
407  return false;
408  }
409  }
410  }
411 
412  return true;
413 }
414 
415 void b2Body::SetTransform(const b2Vec2& position, float angle)
416 {
417  b2Assert(m_world->IsLocked() == false);
418  if (m_world->IsLocked() == true)
419  {
420  return;
421  }
422 
423  m_xf.q.Set(angle);
424  m_xf.p = position;
425 
427  m_sweep.a = angle;
428 
429  m_sweep.c0 = m_sweep.c;
430  m_sweep.a0 = angle;
431 
433  for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
434  {
435  f->Synchronize(broadPhase, m_xf, m_xf);
436  }
437 
438  // Check for new contacts the next step
439  m_world->m_newContacts = true;
440 }
441 
443 {
445 
447  {
448  b2Transform xf1;
449  xf1.q.Set(m_sweep.a0);
450  xf1.p = m_sweep.c0 - b2Mul(xf1.q, m_sweep.localCenter);
451 
452  for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
453  {
454  f->Synchronize(broadPhase, xf1, m_xf);
455  }
456  }
457  else
458  {
459  for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
460  {
461  f->Synchronize(broadPhase, m_xf, m_xf);
462  }
463  }
464 }
465 
466 void b2Body::SetEnabled(bool flag)
467 {
468  b2Assert(m_world->IsLocked() == false);
469 
470  if (flag == IsEnabled())
471  {
472  return;
473  }
474 
475  if (flag)
476  {
478 
479  // Create all proxies.
481  for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
482  {
483  f->CreateProxies(broadPhase, m_xf);
484  }
485 
486  // Contacts are created at the beginning of the next
487  m_world->m_newContacts = true;
488  }
489  else
490  {
492 
493  // Destroy all proxies.
495  for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
496  {
497  f->DestroyProxies(broadPhase);
498  }
499 
500  // Destroy the attached contacts.
502  while (ce)
503  {
504  b2ContactEdge* ce0 = ce;
505  ce = ce->next;
507  }
508  m_contactList = nullptr;
509  }
510 }
511 
513 {
514  bool status = (m_flags & e_fixedRotationFlag) == e_fixedRotationFlag;
515  if (status == flag)
516  {
517  return;
518  }
519 
520  if (flag)
521  {
523  }
524  else
525  {
527  }
528 
529  m_angularVelocity = 0.0f;
530 
531  ResetMassData();
532 }
533 
535 {
536  int32 bodyIndex = m_islandIndex;
537 
538  // %.9g is sufficient to save and load the same value using text
539  // FLT_DECIMAL_DIG == 9
540 
541  b2Dump("{\n");
542  b2Dump(" b2BodyDef bd;\n");
543  b2Dump(" bd.type = b2BodyType(%d);\n", m_type);
544  b2Dump(" bd.position.Set(%.9g, %.9g);\n", m_xf.p.x, m_xf.p.y);
545  b2Dump(" bd.angle = %.9g;\n", m_sweep.a);
546  b2Dump(" bd.linearVelocity.Set(%.9g, %.9g);\n", m_linearVelocity.x, m_linearVelocity.y);
547  b2Dump(" bd.angularVelocity = %.9g;\n", m_angularVelocity);
548  b2Dump(" bd.linearDamping = %.9g;\n", m_linearDamping);
549  b2Dump(" bd.angularDamping = %.9g;\n", m_angularDamping);
550  b2Dump(" bd.allowSleep = bool(%d);\n", m_flags & e_autoSleepFlag);
551  b2Dump(" bd.awake = bool(%d);\n", m_flags & e_awakeFlag);
552  b2Dump(" bd.fixedRotation = bool(%d);\n", m_flags & e_fixedRotationFlag);
553  b2Dump(" bd.bullet = bool(%d);\n", m_flags & e_bulletFlag);
554  b2Dump(" bd.enabled = bool(%d);\n", m_flags & e_enabledFlag);
555  b2Dump(" bd.gravityScale = %.9g;\n", m_gravityScale);
556  b2Dump(" bodies[%d] = m_world->CreateBody(&bd);\n", m_islandIndex);
557  b2Dump("\n");
558  for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
559  {
560  b2Dump(" {\n");
561  f->Dump(bodyIndex);
562  b2Dump(" }\n");
563  }
564  b2Dump("}\n");
565 }
const b2Shape * shape
Definition: b2_fixture.h:76
float mass
The mass of the shape, usually in kilograms.
Definition: b2_shape.h:36
int32 m_islandIndex
Definition: b2_body.h:439
void SynchronizeFixtures()
Definition: b2_body.cpp:442
float m_linearDamping
Definition: b2_body.h:465
float m_torque
Definition: b2_body.h:448
bool fixedRotation
Should this body be prevented from rotating? Useful for characters.
Definition: b2_body.h:109
b2Fixture * CreateFixture(const b2FixtureDef *def)
Definition: b2_body.cpp:165
b2Vec2 b2Mul(const b2Mat22 &A, const b2Vec2 &v)
Definition: b2_math.h:422
void Create(b2BlockAllocator *allocator, b2Body *body, const b2FixtureDef *def)
Definition: b2_fixture.cpp:44
float density
The density, usually in kg/m^2.
Definition: b2_fixture.h:92
b2Vec2 p
Definition: b2_math.h:360
bool m_newContacts
Definition: b2_world.h:250
b2ContactManager m_contactManager
Definition: b2_world.h:232
B2_API const b2Vec2 b2Vec2_zero
Useful constant.
b2Vec2 c0
Definition: b2_math.h:383
float b2Dot(const b2Vec2 &a, const b2Vec2 &b)
Perform the dot product on two vectors.
Definition: b2_math.h:395
void SetType(b2BodyType type)
Set the type of this body. This may alter the mass and velocity.
Definition: b2_body.cpp:111
void Destroy(b2Contact *c)
b2Rot q
Definition: b2_math.h:361
void ResetMassData()
Definition: b2_body.cpp:285
f
b2BodyUserData m_userData
Definition: b2_body.h:471
float m_sleepTime
Definition: b2_body.h:469
b2BodyType
Definition: b2_body.h:43
b2Vec2 m_linearVelocity
Definition: b2_body.h:444
float x
Definition: b2_math.h:128
void SetTransform(const b2Vec2 &position, float angle)
Definition: b2_body.cpp:415
float y
Definition: b2_math.h:128
float m_gravityScale
Definition: b2_body.h:467
b2Fixture * GetFixtureB()
Get fixture B in this contact.
Definition: b2_contact.h:306
b2Vec2 m_force
Definition: b2_body.h:447
b2Fixture * m_next
Definition: b2_fixture.h:234
b2ContactEdge * m_contactList
Definition: b2_body.h:458
void Free(void *p, int32 size)
Free memory. This will use b2Free if the size is larger than b2_maxBlockSize.
float angularDamping
Definition: b2_body.h:99
float angularVelocity
The angular velocity of the body.
Definition: b2_body.h:87
bool bullet
Definition: b2_body.h:115
b2Vec2 center
The position of the shape&#39;s centroid relative to the shape&#39;s origin.
Definition: b2_shape.h:39
b2ContactEdge * next
the next contact edge in the body&#39;s contact list
Definition: b2_contact.h:82
float m_mass
Definition: b2_body.h:460
void SetZero()
Set this vector to all zeros.
Definition: b2_math.h:50
A 2D column vector.
Definition: b2_math.h:41
b2Contact * contact
the contact
Definition: b2_contact.h:80
float a0
Definition: b2_math.h:384
b2Vec2 c
center world positions
Definition: b2_math.h:383
void SetFixedRotation(bool flag)
Definition: b2_body.cpp:512
signed int int32
Definition: b2_types.h:28
float m_invI
Definition: b2_body.h:463
b2Vec2 localCenter
local center of mass position
Definition: b2_math.h:382
b2Body(const b2BodyDef *bd, b2World *world)
Definition: b2_body.cpp:31
b2Vec2 linearVelocity
The linear velocity of the body&#39;s origin in world co-ordinates.
Definition: b2_body.h:84
b2JointEdge * m_jointList
Definition: b2_body.h:457
b2BodyType type
Definition: b2_body.h:74
A rigid body. These are created via b2World::CreateBody.
Definition: b2_body.h:128
b2Body * m_prev
Definition: b2_body.h:451
bool IsLocked() const
Is the world locked (in the middle of a time step).
Definition: b2_world.h:319
void * Allocate(int32 size)
Allocate memory. This will use b2Alloc if the size is larger than b2_maxBlockSize.
void DestroyFixture(b2Fixture *fixture)
Definition: b2_body.cpp:213
bool IsValid() const
Does this vector contain finite coordinates?
Definition: b2_math.h:117
b2World * m_world
Definition: b2_body.h:450
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
int32 m_fixtureCount
Definition: b2_body.h:455
float m_density
Definition: b2_fixture.h:232
void Destroy(b2BlockAllocator *allocator)
Definition: b2_fixture.cpp:73
~b2Body()
Definition: b2_body.cpp:106
bool enabled
Does this body start out enabled?
Definition: b2_body.h:118
bool awake
Is this body initially awake or sleeping?
Definition: b2_body.h:106
bool b2IsValid(float x)
This function is used to ensure that a floating point number is not a NaN or infinity.
Definition: b2_math.h:32
b2BodyUserData userData
Use this to store application specific body data.
Definition: b2_body.h:121
void SetEnabled(bool flag)
Definition: b2_body.cpp:466
float angle
The world angle of the body in radians.
Definition: b2_body.h:81
float I
The rotational inertia of the shape about the local origin.
Definition: b2_shape.h:42
void SetMassData(const b2MassData *data)
Definition: b2_body.cpp:351
b2Fixture * GetFixtureA()
Get fixture A in this contact.
Definition: b2_contact.h:296
void Dump()
Dump this body to a file.
Definition: b2_body.cpp:534
b2Vec2 position
Definition: b2_body.h:78
b2BroadPhase m_broadPhase
float m_invMass
Definition: b2_body.h:460
float gravityScale
Scale the gravity applied to this body.
Definition: b2_body.h:124
b2Body * m_body
Definition: b2_fixture.h:235
void TouchProxy(int32 proxyId)
Call to trigger a re-processing of it&#39;s pairs on the next call to UpdatePairs.
void b2Dump(const char *string,...)
Definition: b2_settings.cpp:57
void DestroyProxies(b2BroadPhase *broadPhase)
Definition: b2_fixture.cpp:143
float a
world angles
Definition: b2_math.h:384
void CreateProxies(b2BroadPhase *broadPhase, const b2Transform &xf)
Definition: b2_fixture.cpp:126
float m_angularDamping
Definition: b2_body.h:466
uint16 m_flags
Definition: b2_body.h:437
bool ShouldCollide(const b2Body *other) const
Definition: b2_body.cpp:392
b2Transform m_xf
Definition: b2_body.h:441
b2BlockAllocator m_blockAllocator
Definition: b2_world.h:229
bool allowSleep
Definition: b2_body.h:103
float m_I
Definition: b2_body.h:463
bool IsEnabled() const
Get the active state of the body.
Definition: b2_body.h:666
b2BodyType m_type
Definition: b2_body.h:435
This holds the mass data computed for a shape.
Definition: b2_shape.h:33
#define b2Assert(A)
Definition: b2_common.h:37
float linearDamping
Definition: b2_body.h:93
float m_angularVelocity
Definition: b2_body.h:445
void SetAwake(bool flag)
Definition: b2_body.h:638
b2JointEdge * next
the next joint edge in the body&#39;s joint list
Definition: b2_joint.h:68
b2Sweep m_sweep
Definition: b2_body.h:442
float alpha0
Definition: b2_math.h:388
void Set(float angle)
Set using an angle in radians.
Definition: b2_math.h:300
GLenum type
Definition: gl.h:1033
b2Fixture * m_fixtureList
Definition: b2_body.h:454
b2Body * m_next
Definition: b2_body.h:452


mvsim
Author(s):
autogenerated on Tue Jul 4 2023 03:08:19