b2Body.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. /*
  2. * Copyright (c) 2006-2007 Erin Catto http://www.box2d.org
  3. * Copyright (c) 2013 Google, Inc.
  4. *
  5. * This software is provided 'as-is', without any express or implied
  6. * warranty. In no event will the authors be held liable for any damages
  7. * arising from the use of this software.
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. * 1. The origin of this software must not be misrepresented; you must not
  12. * claim that you wrote the original software. If you use this software
  13. * in a product, an acknowledgment in the product documentation would be
  14. * appreciated but is not required.
  15. * 2. Altered source versions must be plainly marked as such, and must not be
  16. * misrepresented as being the original software.
  17. * 3. This notice may not be removed or altered from any source distribution.
  18. */
  19. #include <Box2D/Dynamics/b2Body.h>
  20. #include <Box2D/Dynamics/b2Fixture.h>
  21. #include <Box2D/Dynamics/b2World.h>
  22. #include <Box2D/Dynamics/Contacts/b2Contact.h>
  23. #include <Box2D/Dynamics/Joints/b2Joint.h>
  24. b2Body::b2Body(const b2BodyDef* bd, b2World* world)
  25. {
  26. b2Assert(bd->position.IsValid());
  27. b2Assert(bd->linearVelocity.IsValid());
  28. b2Assert(b2IsValid(bd->angle));
  29. b2Assert(b2IsValid(bd->angularVelocity));
  30. b2Assert(b2IsValid(bd->angularDamping) && bd->angularDamping >= 0.0f);
  31. b2Assert(b2IsValid(bd->linearDamping) && bd->linearDamping >= 0.0f);
  32. m_flags = 0;
  33. if (bd->bullet)
  34. {
  35. m_flags |= e_bulletFlag;
  36. }
  37. if (bd->fixedRotation)
  38. {
  39. m_flags |= e_fixedRotationFlag;
  40. }
  41. if (bd->allowSleep)
  42. {
  43. m_flags |= e_autoSleepFlag;
  44. }
  45. if (bd->awake)
  46. {
  47. m_flags |= e_awakeFlag;
  48. }
  49. if (bd->active)
  50. {
  51. m_flags |= e_activeFlag;
  52. }
  53. m_world = world;
  54. m_xf.p = bd->position;
  55. m_xf.q.Set(bd->angle);
  56. m_xf0 = m_xf;
  57. m_sweep.localCenter.SetZero();
  58. m_sweep.c0 = m_xf.p;
  59. m_sweep.c = m_xf.p;
  60. m_sweep.a0 = bd->angle;
  61. m_sweep.a = bd->angle;
  62. m_sweep.alpha0 = 0.0f;
  63. m_jointList = NULL;
  64. m_contactList = NULL;
  65. m_prev = NULL;
  66. m_next = NULL;
  67. m_linearVelocity = bd->linearVelocity;
  68. m_angularVelocity = bd->angularVelocity;
  69. m_linearDamping = bd->linearDamping;
  70. m_angularDamping = bd->angularDamping;
  71. m_gravityScale = bd->gravityScale;
  72. m_force.SetZero();
  73. m_torque = 0.0f;
  74. m_sleepTime = 0.0f;
  75. m_type = bd->type;
  76. if (m_type == b2_dynamicBody)
  77. {
  78. m_mass = 1.0f;
  79. m_invMass = 1.0f;
  80. }
  81. else
  82. {
  83. m_mass = 0.0f;
  84. m_invMass = 0.0f;
  85. }
  86. m_I = 0.0f;
  87. m_invI = 0.0f;
  88. m_userData = bd->userData;
  89. m_fixtureList = NULL;
  90. m_fixtureCount = 0;
  91. }
  92. b2Body::~b2Body()
  93. {
  94. // shapes and joints are destroyed in b2World::Destroy
  95. }
  96. void b2Body::SetType(b2BodyType type)
  97. {
  98. b2Assert(m_world->IsLocked() == false);
  99. if (m_world->IsLocked() == true)
  100. {
  101. return;
  102. }
  103. if (m_type == type)
  104. {
  105. return;
  106. }
  107. m_type = type;
  108. ResetMassData();
  109. if (m_type == b2_staticBody)
  110. {
  111. m_linearVelocity.SetZero();
  112. m_angularVelocity = 0.0f;
  113. m_sweep.a0 = m_sweep.a;
  114. m_sweep.c0 = m_sweep.c;
  115. SynchronizeFixtures();
  116. }
  117. SetAwake(true);
  118. m_force.SetZero();
  119. m_torque = 0.0f;
  120. // Delete the attached contacts.
  121. b2ContactEdge* ce = m_contactList;
  122. while (ce)
  123. {
  124. b2ContactEdge* ce0 = ce;
  125. ce = ce->next;
  126. m_world->m_contactManager.Destroy(ce0->contact);
  127. }
  128. m_contactList = NULL;
  129. // Touch the proxies so that new contacts will be created (when appropriate)
  130. b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
  131. for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
  132. {
  133. int32 proxyCount = f->m_proxyCount;
  134. for (int32 i = 0; i < proxyCount; ++i)
  135. {
  136. broadPhase->TouchProxy(f->m_proxies[i].proxyId);
  137. }
  138. }
  139. }
  140. b2Fixture* b2Body::CreateFixture(const b2FixtureDef* def)
  141. {
  142. b2Assert(m_world->IsLocked() == false);
  143. if (m_world->IsLocked() == true)
  144. {
  145. return NULL;
  146. }
  147. b2BlockAllocator* allocator = &m_world->m_blockAllocator;
  148. void* memory = allocator->Allocate(sizeof(b2Fixture));
  149. b2Fixture* fixture = new (memory) b2Fixture;
  150. fixture->Create(allocator, this, def);
  151. if (m_flags & e_activeFlag)
  152. {
  153. b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
  154. fixture->CreateProxies(broadPhase, m_xf);
  155. }
  156. fixture->m_next = m_fixtureList;
  157. m_fixtureList = fixture;
  158. ++m_fixtureCount;
  159. fixture->m_body = this;
  160. // Adjust mass properties if needed.
  161. if (fixture->m_density > 0.0f)
  162. {
  163. ResetMassData();
  164. }
  165. // Let the world know we have a new fixture. This will cause new contacts
  166. // to be created at the beginning of the next time step.
  167. m_world->m_flags |= b2World::e_newFixture;
  168. return fixture;
  169. }
  170. b2Fixture* b2Body::CreateFixture(const b2Shape* shape, float32 density)
  171. {
  172. b2FixtureDef def;
  173. def.shape = shape;
  174. def.density = density;
  175. return CreateFixture(&def);
  176. }
  177. void b2Body::DestroyFixture(b2Fixture* fixture)
  178. {
  179. b2Assert(m_world->IsLocked() == false);
  180. if (m_world->IsLocked() == true)
  181. {
  182. return;
  183. }
  184. b2Assert(fixture->m_body == this);
  185. // Remove the fixture from this body's singly linked list.
  186. b2Assert(m_fixtureCount > 0);
  187. b2Fixture** node = &m_fixtureList;
  188. #if B2_ASSERT_ENABLED
  189. bool found = false;
  190. #endif // B2_ASSERT_ENABLED
  191. while (*node != NULL)
  192. {
  193. if (*node == fixture)
  194. {
  195. *node = fixture->m_next;
  196. #if B2_ASSERT_ENABLED
  197. found = true;
  198. #endif // B2_ASSERT_ENABLED
  199. break;
  200. }
  201. node = &(*node)->m_next;
  202. }
  203. // You tried to remove a shape that is not attached to this body.
  204. b2Assert(found);
  205. // Destroy any contacts associated with the fixture.
  206. b2ContactEdge* edge = m_contactList;
  207. while (edge)
  208. {
  209. b2Contact* c = edge->contact;
  210. edge = edge->next;
  211. b2Fixture* fixtureA = c->GetFixtureA();
  212. b2Fixture* fixtureB = c->GetFixtureB();
  213. if (fixture == fixtureA || fixture == fixtureB)
  214. {
  215. // This destroys the contact and removes it from
  216. // this body's contact list.
  217. m_world->m_contactManager.Destroy(c);
  218. }
  219. }
  220. b2BlockAllocator* allocator = &m_world->m_blockAllocator;
  221. if (m_flags & e_activeFlag)
  222. {
  223. b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
  224. fixture->DestroyProxies(broadPhase);
  225. }
  226. fixture->Destroy(allocator);
  227. fixture->m_body = NULL;
  228. fixture->m_next = NULL;
  229. fixture->~b2Fixture();
  230. allocator->Free(fixture, sizeof(b2Fixture));
  231. --m_fixtureCount;
  232. // Reset the mass data.
  233. ResetMassData();
  234. }
  235. void b2Body::ResetMassData()
  236. {
  237. // Compute mass data from shapes. Each shape has its own density.
  238. m_mass = 0.0f;
  239. m_invMass = 0.0f;
  240. m_I = 0.0f;
  241. m_invI = 0.0f;
  242. m_sweep.localCenter.SetZero();
  243. // Static and kinematic bodies have zero mass.
  244. if (m_type == b2_staticBody || m_type == b2_kinematicBody)
  245. {
  246. m_sweep.c0 = m_xf.p;
  247. m_sweep.c = m_xf.p;
  248. m_sweep.a0 = m_sweep.a;
  249. return;
  250. }
  251. b2Assert(m_type == b2_dynamicBody);
  252. // Accumulate mass over all fixtures.
  253. b2Vec2 localCenter = b2Vec2_zero;
  254. for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
  255. {
  256. if (f->m_density == 0.0f)
  257. {
  258. continue;
  259. }
  260. b2MassData massData;
  261. f->GetMassData(&massData);
  262. m_mass += massData.mass;
  263. localCenter += massData.mass * massData.center;
  264. m_I += massData.I;
  265. }
  266. // Compute center of mass.
  267. if (m_mass > 0.0f)
  268. {
  269. m_invMass = 1.0f / m_mass;
  270. localCenter *= m_invMass;
  271. }
  272. else
  273. {
  274. // Force all dynamic bodies to have a positive mass.
  275. m_mass = 1.0f;
  276. m_invMass = 1.0f;
  277. }
  278. if (m_I > 0.0f && (m_flags & e_fixedRotationFlag) == 0)
  279. {
  280. // Center the inertia about the center of mass.
  281. m_I -= m_mass * b2Dot(localCenter, localCenter);
  282. b2Assert(m_I > 0.0f);
  283. m_invI = 1.0f / m_I;
  284. }
  285. else
  286. {
  287. m_I = 0.0f;
  288. m_invI = 0.0f;
  289. }
  290. // Move center of mass.
  291. b2Vec2 oldCenter = m_sweep.c;
  292. m_sweep.localCenter = localCenter;
  293. m_sweep.c0 = m_sweep.c = b2Mul(m_xf, m_sweep.localCenter);
  294. // Update center of mass velocity.
  295. m_linearVelocity += b2Cross(m_angularVelocity, m_sweep.c - oldCenter);
  296. }
  297. void b2Body::SetMassData(const b2MassData* massData)
  298. {
  299. b2Assert(m_world->IsLocked() == false);
  300. if (m_world->IsLocked() == true)
  301. {
  302. return;
  303. }
  304. if (m_type != b2_dynamicBody)
  305. {
  306. return;
  307. }
  308. m_invMass = 0.0f;
  309. m_I = 0.0f;
  310. m_invI = 0.0f;
  311. m_mass = massData->mass;
  312. if (m_mass <= 0.0f)
  313. {
  314. m_mass = 1.0f;
  315. }
  316. m_invMass = 1.0f / m_mass;
  317. if (massData->I > 0.0f && (m_flags & b2Body::e_fixedRotationFlag) == 0)
  318. {
  319. m_I = massData->I - m_mass * b2Dot(massData->center, massData->center);
  320. b2Assert(m_I > 0.0f);
  321. m_invI = 1.0f / m_I;
  322. }
  323. // Move center of mass.
  324. b2Vec2 oldCenter = m_sweep.c;
  325. m_sweep.localCenter = massData->center;
  326. m_sweep.c0 = m_sweep.c = b2Mul(m_xf, m_sweep.localCenter);
  327. // Update center of mass velocity.
  328. m_linearVelocity += b2Cross(m_angularVelocity, m_sweep.c - oldCenter);
  329. }
  330. bool b2Body::ShouldCollide(const b2Body* other) const
  331. {
  332. // At least one body should be dynamic.
  333. if (m_type != b2_dynamicBody && other->m_type != b2_dynamicBody)
  334. {
  335. return false;
  336. }
  337. // Does a joint prevent collision?
  338. for (b2JointEdge* jn = m_jointList; jn; jn = jn->next)
  339. {
  340. if (jn->other == other)
  341. {
  342. if (jn->joint->m_collideConnected == false)
  343. {
  344. return false;
  345. }
  346. }
  347. }
  348. return true;
  349. }
  350. void b2Body::SetTransform(const b2Vec2& position, float32 angle)
  351. {
  352. b2Assert(m_world->IsLocked() == false);
  353. if (m_world->IsLocked() == true)
  354. {
  355. return;
  356. }
  357. m_xf.q.Set(angle);
  358. m_xf.p = position;
  359. m_xf0 = m_xf;
  360. m_sweep.c = b2Mul(m_xf, m_sweep.localCenter);
  361. m_sweep.a = angle;
  362. m_sweep.c0 = m_sweep.c;
  363. m_sweep.a0 = angle;
  364. b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
  365. for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
  366. {
  367. f->Synchronize(broadPhase, m_xf, m_xf);
  368. }
  369. }
  370. void b2Body::SynchronizeFixtures()
  371. {
  372. b2Transform xf1;
  373. xf1.q.Set(m_sweep.a0);
  374. xf1.p = m_sweep.c0 - b2Mul(xf1.q, m_sweep.localCenter);
  375. b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
  376. for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
  377. {
  378. f->Synchronize(broadPhase, xf1, m_xf);
  379. }
  380. }
  381. void b2Body::SetActive(bool flag)
  382. {
  383. b2Assert(m_world->IsLocked() == false);
  384. if (flag == IsActive())
  385. {
  386. return;
  387. }
  388. if (flag)
  389. {
  390. m_flags |= e_activeFlag;
  391. // Create all proxies.
  392. b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
  393. for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
  394. {
  395. f->CreateProxies(broadPhase, m_xf);
  396. }
  397. // Contacts are created the next time step.
  398. }
  399. else
  400. {
  401. m_flags &= ~e_activeFlag;
  402. // Destroy all proxies.
  403. b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase;
  404. for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
  405. {
  406. f->DestroyProxies(broadPhase);
  407. }
  408. // Destroy the attached contacts.
  409. b2ContactEdge* ce = m_contactList;
  410. while (ce)
  411. {
  412. b2ContactEdge* ce0 = ce;
  413. ce = ce->next;
  414. m_world->m_contactManager.Destroy(ce0->contact);
  415. }
  416. m_contactList = NULL;
  417. }
  418. }
  419. void b2Body::SetFixedRotation(bool flag)
  420. {
  421. bool status = (m_flags & e_fixedRotationFlag) == e_fixedRotationFlag;
  422. if (status == flag)
  423. {
  424. return;
  425. }
  426. if (flag)
  427. {
  428. m_flags |= e_fixedRotationFlag;
  429. }
  430. else
  431. {
  432. m_flags &= ~e_fixedRotationFlag;
  433. }
  434. m_angularVelocity = 0.0f;
  435. ResetMassData();
  436. }
  437. void b2Body::Dump()
  438. {
  439. int32 bodyIndex = m_islandIndex;
  440. b2Log("{\n");
  441. b2Log(" b2BodyDef bd;\n");
  442. b2Log(" bd.type = b2BodyType(%d);\n", m_type);
  443. b2Log(" bd.position.Set(%.15lef, %.15lef);\n", m_xf.p.x, m_xf.p.y);
  444. b2Log(" bd.angle = %.15lef;\n", m_sweep.a);
  445. b2Log(" bd.linearVelocity.Set(%.15lef, %.15lef);\n", m_linearVelocity.x, m_linearVelocity.y);
  446. b2Log(" bd.angularVelocity = %.15lef;\n", m_angularVelocity);
  447. b2Log(" bd.linearDamping = %.15lef;\n", m_linearDamping);
  448. b2Log(" bd.angularDamping = %.15lef;\n", m_angularDamping);
  449. b2Log(" bd.allowSleep = bool(%d);\n", m_flags & e_autoSleepFlag);
  450. b2Log(" bd.awake = bool(%d);\n", m_flags & e_awakeFlag);
  451. b2Log(" bd.fixedRotation = bool(%d);\n", m_flags & e_fixedRotationFlag);
  452. b2Log(" bd.bullet = bool(%d);\n", m_flags & e_bulletFlag);
  453. b2Log(" bd.active = bool(%d);\n", m_flags & e_activeFlag);
  454. b2Log(" bd.gravityScale = %.15lef;\n", m_gravityScale);
  455. b2Log(" bodies[%d] = m_world->CreateBody(&bd);\n", m_islandIndex);
  456. b2Log("\n");
  457. for (b2Fixture* f = m_fixtureList; f; f = f->m_next)
  458. {
  459. b2Log(" {\n");
  460. f->Dump(bodyIndex);
  461. b2Log(" }\n");
  462. }
  463. b2Log("}\n");
  464. }