b2World.cpp
上传用户:gb3593
上传日期:2022-01-07
资源大小:3028k
文件大小:24k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /*
  2. * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
  3. *
  4. * This software is provided 'as-is', without any express or implied
  5. * warranty.  In no event will the authors be held liable for any damages
  6. * arising from the use of this software.
  7. * Permission is granted to anyone to use this software for any purpose,
  8. * including commercial applications, and to alter it and redistribute it
  9. * freely, subject to the following restrictions:
  10. * 1. The origin of this software must not be misrepresented; you must not
  11. * claim that you wrote the original software. If you use this software
  12. * in a product, an acknowledgment in the product documentation would be
  13. * appreciated but is not required.
  14. * 2. Altered source versions must be plainly marked as such, and must not be
  15. * misrepresented as being the original software.
  16. * 3. This notice may not be removed or altered from any source distribution.
  17. */
  18. #include <Box2D/Dynamics/b2World.h>
  19. #include <Box2D/Dynamics/b2Body.h>
  20. #include <Box2D/Dynamics/b2Fixture.h>
  21. #include <Box2D/Dynamics/b2Island.h>
  22. #include <Box2D/Dynamics/Joints/b2PulleyJoint.h>
  23. #include <Box2D/Dynamics/Contacts/b2Contact.h>
  24. #include <Box2D/Dynamics/Contacts/b2ContactSolver.h>
  25. #include <Box2D/Dynamics/Contacts/b2TOISolver.h>
  26. #include <Box2D/Collision/b2Collision.h>
  27. #include <Box2D/Collision/b2BroadPhase.h>
  28. #include <Box2D/Collision/Shapes/b2CircleShape.h>
  29. #include <Box2D/Collision/Shapes/b2PolygonShape.h>
  30. #include <Box2D/Collision/b2TimeOfImpact.h>
  31. #include <new>
  32. b2World::b2World(const b2Vec2& gravity, bool doSleep)
  33. {
  34. m_destructionListener = NULL;
  35. m_debugDraw = NULL;
  36. m_bodyList = NULL;
  37. m_jointList = NULL;
  38. m_bodyCount = 0;
  39. m_jointCount = 0;
  40. m_warmStarting = true;
  41. m_continuousPhysics = true;
  42. m_allowSleep = doSleep;
  43. m_gravity = gravity;
  44. m_flags = e_clearForces;
  45. m_inv_dt0 = 0.0f;
  46. m_contactManager.m_allocator = &m_blockAllocator;
  47. }
  48. b2World::~b2World()
  49. {
  50. }
  51. void b2World::SetDestructionListener(b2DestructionListener* listener)
  52. {
  53. m_destructionListener = listener;
  54. }
  55. void b2World::SetContactFilter(b2ContactFilter* filter)
  56. {
  57. m_contactManager.m_contactFilter = filter;
  58. }
  59. void b2World::SetContactListener(b2ContactListener* listener)
  60. {
  61. m_contactManager.m_contactListener = listener;
  62. }
  63. void b2World::SetDebugDraw(b2DebugDraw* debugDraw)
  64. {
  65. m_debugDraw = debugDraw;
  66. }
  67. b2Body* b2World::CreateBody(const b2BodyDef* def)
  68. {
  69. b2Assert(IsLocked() == false);
  70. if (IsLocked())
  71. {
  72. return NULL;
  73. }
  74. void* mem = m_blockAllocator.Allocate(sizeof(b2Body));
  75. b2Body* b = new (mem) b2Body(def, this);
  76. // Add to world doubly linked list.
  77. b->m_prev = NULL;
  78. b->m_next = m_bodyList;
  79. if (m_bodyList)
  80. {
  81. m_bodyList->m_prev = b;
  82. }
  83. m_bodyList = b;
  84. ++m_bodyCount;
  85. return b;
  86. }
  87. void b2World::DestroyBody(b2Body* b)
  88. {
  89. b2Assert(m_bodyCount > 0);
  90. b2Assert(IsLocked() == false);
  91. if (IsLocked())
  92. {
  93. return;
  94. }
  95. // Delete the attached joints.
  96. b2JointEdge* je = b->m_jointList;
  97. while (je)
  98. {
  99. b2JointEdge* je0 = je;
  100. je = je->next;
  101. if (m_destructionListener)
  102. {
  103. m_destructionListener->SayGoodbye(je0->joint);
  104. }
  105. DestroyJoint(je0->joint);
  106. }
  107. b->m_jointList = NULL;
  108. // Delete the attached contacts.
  109. b2ContactEdge* ce = b->m_contactList;
  110. while (ce)
  111. {
  112. b2ContactEdge* ce0 = ce;
  113. ce = ce->next;
  114. m_contactManager.Destroy(ce0->contact);
  115. }
  116. b->m_contactList = NULL;
  117. // Delete the attached fixtures. This destroys broad-phase proxies.
  118. b2Fixture* f = b->m_fixtureList;
  119. while (f)
  120. {
  121. b2Fixture* f0 = f;
  122. f = f->m_next;
  123. if (m_destructionListener)
  124. {
  125. m_destructionListener->SayGoodbye(f0);
  126. }
  127. f0->DestroyProxy(&m_contactManager.m_broadPhase);
  128. f0->Destroy(&m_blockAllocator);
  129. f0->~b2Fixture();
  130. m_blockAllocator.Free(f0, sizeof(b2Fixture));
  131. }
  132. b->m_fixtureList = NULL;
  133. b->m_fixtureCount = 0;
  134. // Remove world body list.
  135. if (b->m_prev)
  136. {
  137. b->m_prev->m_next = b->m_next;
  138. }
  139. if (b->m_next)
  140. {
  141. b->m_next->m_prev = b->m_prev;
  142. }
  143. if (b == m_bodyList)
  144. {
  145. m_bodyList = b->m_next;
  146. }
  147. --m_bodyCount;
  148. b->~b2Body();
  149. m_blockAllocator.Free(b, sizeof(b2Body));
  150. }
  151. b2Joint* b2World::CreateJoint(const b2JointDef* def)
  152. {
  153. b2Assert(IsLocked() == false);
  154. if (IsLocked())
  155. {
  156. return NULL;
  157. }
  158. b2Joint* j = b2Joint::Create(def, &m_blockAllocator);
  159. // Connect to the world list.
  160. j->m_prev = NULL;
  161. j->m_next = m_jointList;
  162. if (m_jointList)
  163. {
  164. m_jointList->m_prev = j;
  165. }
  166. m_jointList = j;
  167. ++m_jointCount;
  168. // Connect to the bodies' doubly linked lists.
  169. j->m_edgeA.joint = j;
  170. j->m_edgeA.other = j->m_bodyB;
  171. j->m_edgeA.prev = NULL;
  172. j->m_edgeA.next = j->m_bodyA->m_jointList;
  173. if (j->m_bodyA->m_jointList) j->m_bodyA->m_jointList->prev = &j->m_edgeA;
  174. j->m_bodyA->m_jointList = &j->m_edgeA;
  175. j->m_edgeB.joint = j;
  176. j->m_edgeB.other = j->m_bodyA;
  177. j->m_edgeB.prev = NULL;
  178. j->m_edgeB.next = j->m_bodyB->m_jointList;
  179. if (j->m_bodyB->m_jointList) j->m_bodyB->m_jointList->prev = &j->m_edgeB;
  180. j->m_bodyB->m_jointList = &j->m_edgeB;
  181. b2Body* bodyA = def->bodyA;
  182. b2Body* bodyB = def->bodyB;
  183. // If the joint prevents collisions, then flag any contacts for filtering.
  184. if (def->collideConnected == false)
  185. {
  186. b2ContactEdge* edge = bodyB->GetContactList();
  187. while (edge)
  188. {
  189. if (edge->other == bodyA)
  190. {
  191. // Flag the contact for filtering at the next time step (where either
  192. // body is awake).
  193. edge->contact->FlagForFiltering();
  194. }
  195. edge = edge->next;
  196. }
  197. }
  198. // Note: creating a joint doesn't wake the bodies.
  199. return j;
  200. }
  201. void b2World::DestroyJoint(b2Joint* j)
  202. {
  203. b2Assert(IsLocked() == false);
  204. if (IsLocked())
  205. {
  206. return;
  207. }
  208. bool collideConnected = j->m_collideConnected;
  209. // Remove from the doubly linked list.
  210. if (j->m_prev)
  211. {
  212. j->m_prev->m_next = j->m_next;
  213. }
  214. if (j->m_next)
  215. {
  216. j->m_next->m_prev = j->m_prev;
  217. }
  218. if (j == m_jointList)
  219. {
  220. m_jointList = j->m_next;
  221. }
  222. // Disconnect from island graph.
  223. b2Body* bodyA = j->m_bodyA;
  224. b2Body* bodyB = j->m_bodyB;
  225. // Wake up connected bodies.
  226. bodyA->SetAwake(true);
  227. bodyB->SetAwake(true);
  228. // Remove from body 1.
  229. if (j->m_edgeA.prev)
  230. {
  231. j->m_edgeA.prev->next = j->m_edgeA.next;
  232. }
  233. if (j->m_edgeA.next)
  234. {
  235. j->m_edgeA.next->prev = j->m_edgeA.prev;
  236. }
  237. if (&j->m_edgeA == bodyA->m_jointList)
  238. {
  239. bodyA->m_jointList = j->m_edgeA.next;
  240. }
  241. j->m_edgeA.prev = NULL;
  242. j->m_edgeA.next = NULL;
  243. // Remove from body 2
  244. if (j->m_edgeB.prev)
  245. {
  246. j->m_edgeB.prev->next = j->m_edgeB.next;
  247. }
  248. if (j->m_edgeB.next)
  249. {
  250. j->m_edgeB.next->prev = j->m_edgeB.prev;
  251. }
  252. if (&j->m_edgeB == bodyB->m_jointList)
  253. {
  254. bodyB->m_jointList = j->m_edgeB.next;
  255. }
  256. j->m_edgeB.prev = NULL;
  257. j->m_edgeB.next = NULL;
  258. b2Joint::Destroy(j, &m_blockAllocator);
  259. b2Assert(m_jointCount > 0);
  260. --m_jointCount;
  261. // If the joint prevents collisions, then flag any contacts for filtering.
  262. if (collideConnected == false)
  263. {
  264. b2ContactEdge* edge = bodyB->GetContactList();
  265. while (edge)
  266. {
  267. if (edge->other == bodyA)
  268. {
  269. // Flag the contact for filtering at the next time step (where either
  270. // body is awake).
  271. edge->contact->FlagForFiltering();
  272. }
  273. edge = edge->next;
  274. }
  275. }
  276. }
  277. // Find islands, integrate and solve constraints, solve position constraints
  278. void b2World::Solve(const b2TimeStep& step)
  279. {
  280. // Size the island for the worst case.
  281. b2Island island(m_bodyCount,
  282. m_contactManager.m_contactCount,
  283. m_jointCount,
  284. &m_stackAllocator,
  285. m_contactManager.m_contactListener);
  286. // Clear all the island flags.
  287. for (b2Body* b = m_bodyList; b; b = b->m_next)
  288. {
  289. b->m_flags &= ~b2Body::e_islandFlag;
  290. }
  291. for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next)
  292. {
  293. c->m_flags &= ~b2Contact::e_islandFlag;
  294. }
  295. for (b2Joint* j = m_jointList; j; j = j->m_next)
  296. {
  297. j->m_islandFlag = false;
  298. }
  299. // Build and simulate all awake islands.
  300. int32 stackSize = m_bodyCount;
  301. b2Body** stack = (b2Body**)m_stackAllocator.Allocate(stackSize * sizeof(b2Body*));
  302. for (b2Body* seed = m_bodyList; seed; seed = seed->m_next)
  303. {
  304. if (seed->m_flags & b2Body::e_islandFlag)
  305. {
  306. continue;
  307. }
  308. if (seed->IsAwake() == false || seed->IsActive() == false)
  309. {
  310. continue;
  311. }
  312. // The seed can be dynamic or kinematic.
  313. if (seed->GetType() == b2_staticBody)
  314. {
  315. continue;
  316. }
  317. // Reset island and stack.
  318. island.Clear();
  319. int32 stackCount = 0;
  320. stack[stackCount++] = seed;
  321. seed->m_flags |= b2Body::e_islandFlag;
  322. // Perform a depth first search (DFS) on the constraint graph.
  323. while (stackCount > 0)
  324. {
  325. // Grab the next body off the stack and add it to the island.
  326. b2Body* b = stack[--stackCount];
  327. b2Assert(b->IsActive() == true);
  328. island.Add(b);
  329. // Make sure the body is awake.
  330. b->SetAwake(true);
  331. // To keep islands as small as possible, we don't
  332. // propagate islands across static bodies.
  333. if (b->GetType() == b2_staticBody)
  334. {
  335. continue;
  336. }
  337. // Search all contacts connected to this body.
  338. for (b2ContactEdge* ce = b->m_contactList; ce; ce = ce->next)
  339. {
  340. b2Contact* contact = ce->contact;
  341. // Has this contact already been added to an island?
  342. if (contact->m_flags & b2Contact::e_islandFlag)
  343. {
  344. continue;
  345. }
  346. // Is this contact solid and touching?
  347. if (contact->IsEnabled() == false ||
  348. contact->IsTouching() == false)
  349. {
  350. continue;
  351. }
  352. // Skip sensors.
  353. bool sensorA = contact->m_fixtureA->m_isSensor;
  354. bool sensorB = contact->m_fixtureB->m_isSensor;
  355. if (sensorA || sensorB)
  356. {
  357. continue;
  358. }
  359. island.Add(contact);
  360. contact->m_flags |= b2Contact::e_islandFlag;
  361. b2Body* other = ce->other;
  362. // Was the other body already added to this island?
  363. if (other->m_flags & b2Body::e_islandFlag)
  364. {
  365. continue;
  366. }
  367. b2Assert(stackCount < stackSize);
  368. stack[stackCount++] = other;
  369. other->m_flags |= b2Body::e_islandFlag;
  370. }
  371. // Search all joints connect to this body.
  372. for (b2JointEdge* je = b->m_jointList; je; je = je->next)
  373. {
  374. if (je->joint->m_islandFlag == true)
  375. {
  376. continue;
  377. }
  378. b2Body* other = je->other;
  379. // Don't simulate joints connected to inactive bodies.
  380. if (other->IsActive() == false)
  381. {
  382. continue;
  383. }
  384. island.Add(je->joint);
  385. je->joint->m_islandFlag = true;
  386. if (other->m_flags & b2Body::e_islandFlag)
  387. {
  388. continue;
  389. }
  390. b2Assert(stackCount < stackSize);
  391. stack[stackCount++] = other;
  392. other->m_flags |= b2Body::e_islandFlag;
  393. }
  394. }
  395. island.Solve(step, m_gravity, m_allowSleep);
  396. // Post solve cleanup.
  397. for (int32 i = 0; i < island.m_bodyCount; ++i)
  398. {
  399. // Allow static bodies to participate in other islands.
  400. b2Body* b = island.m_bodies[i];
  401. if (b->GetType() == b2_staticBody)
  402. {
  403. b->m_flags &= ~b2Body::e_islandFlag;
  404. }
  405. }
  406. }
  407. m_stackAllocator.Free(stack);
  408. // Synchronize fixtures, check for out of range bodies.
  409. for (b2Body* b = m_bodyList; b; b = b->GetNext())
  410. {
  411. // If a body was not in an island then it did not move.
  412. if ((b->m_flags & b2Body::e_islandFlag) == 0)
  413. {
  414. continue;
  415. }
  416. if (b->GetType() == b2_staticBody)
  417. {
  418. continue;
  419. }
  420. // Update fixtures (for broad-phase).
  421. b->SynchronizeFixtures();
  422. }
  423. // Look for new contacts.
  424. m_contactManager.FindNewContacts();
  425. }
  426. // Advance a dynamic body to its first time of contact
  427. // and adjust the position to ensure clearance.
  428. void b2World::SolveTOI(b2Body* body)
  429. {
  430. // Find the minimum contact.
  431. b2Contact* toiContact = NULL;
  432. float32 toi = 1.0f;
  433. b2Body* toiOther = NULL;
  434. bool found;
  435. int32 count;
  436. int32 iter = 0;
  437. bool bullet = body->IsBullet();
  438. // Iterate until all contacts agree on the minimum TOI. We have
  439. // to iterate because the TOI algorithm may skip some intermediate
  440. // collisions when objects rotate through each other.
  441. do
  442. {
  443. count = 0;
  444. found = false;
  445. for (b2ContactEdge* ce = body->m_contactList; ce; ce = ce->next)
  446. {
  447. if (ce->contact == toiContact)
  448. {
  449. continue;
  450. }
  451. b2Body* other = ce->other;
  452. b2BodyType type = other->GetType();
  453. // Only bullets perform TOI with dynamic bodies.
  454. if (bullet == true)
  455. {
  456. // Bullets only perform TOI with bodies that have their TOI resolved.
  457. if ((other->m_flags & b2Body::e_toiFlag) == 0)
  458. {
  459. continue;
  460. }
  461. // No repeated hits on non-static bodies
  462. if (type != b2_staticBody && (ce->contact->m_flags & b2Contact::e_bulletHitFlag) != 0)
  463. {
  464. continue;
  465. }
  466. }
  467. else if (type == b2_dynamicBody)
  468. {
  469. continue;
  470. }
  471. // Check for a disabled contact.
  472. b2Contact* contact = ce->contact;
  473. if (contact->IsEnabled() == false)
  474. {
  475. continue;
  476. }
  477. // Prevent infinite looping.
  478. if (contact->m_toiCount > 10)
  479. {
  480. continue;
  481. }
  482. b2Fixture* fixtureA = contact->m_fixtureA;
  483. b2Fixture* fixtureB = contact->m_fixtureB;
  484. // Cull sensors.
  485. if (fixtureA->IsSensor() || fixtureB->IsSensor())
  486. {
  487. continue;
  488. }
  489. b2Body* bodyA = fixtureA->m_body;
  490. b2Body* bodyB = fixtureB->m_body;
  491. // Compute the time of impact in interval [0, minTOI]
  492. b2TOIInput input;
  493. input.proxyA.Set(fixtureA->GetShape());
  494. input.proxyB.Set(fixtureB->GetShape());
  495. input.sweepA = bodyA->m_sweep;
  496. input.sweepB = bodyB->m_sweep;
  497. input.tMax = toi;
  498. b2TOIOutput output;
  499. b2TimeOfImpact(&output, &input);
  500. if (output.state == b2TOIOutput::e_touching && output.t < toi)
  501. {
  502. toiContact = contact;
  503. toi = output.t;
  504. toiOther = other;
  505. found = true;
  506. }
  507. ++count;
  508. }
  509. ++iter;
  510. } while (found && count > 1 && iter < 50);
  511. if (toiContact == NULL)
  512. {
  513. body->Advance(1.0f);
  514. return;
  515. }
  516. b2Sweep backup = body->m_sweep;
  517. body->Advance(toi);
  518. toiContact->Update(m_contactManager.m_contactListener);
  519. if (toiContact->IsEnabled() == false)
  520. {
  521. // Contact disabled. Backup and recurse.
  522. body->m_sweep = backup;
  523. SolveTOI(body);
  524. }
  525. ++toiContact->m_toiCount;
  526. // Update all the valid contacts on this body and build a contact island.
  527. b2Contact* contacts[b2_maxTOIContacts];
  528. count = 0;
  529. for (b2ContactEdge* ce = body->m_contactList; ce && count < b2_maxTOIContacts; ce = ce->next)
  530. {
  531. b2Body* other = ce->other;
  532. b2BodyType type = other->GetType();
  533. // Only perform correction with static bodies, so the
  534. // body won't get pushed out of the world.
  535. if (type == b2_dynamicBody)
  536. {
  537. continue;
  538. }
  539. // Check for a disabled contact.
  540. b2Contact* contact = ce->contact;
  541. if (contact->IsEnabled() == false)
  542. {
  543. continue;
  544. }
  545. b2Fixture* fixtureA = contact->m_fixtureA;
  546. b2Fixture* fixtureB = contact->m_fixtureB;
  547. // Cull sensors.
  548. if (fixtureA->IsSensor() || fixtureB->IsSensor())
  549. {
  550. continue;
  551. }
  552. // The contact likely has some new contact points. The listener
  553. // gives the user a chance to disable the contact.
  554. if (contact != toiContact)
  555. {
  556. contact->Update(m_contactManager.m_contactListener);
  557. }
  558. // Did the user disable the contact?
  559. if (contact->IsEnabled() == false)
  560. {
  561. // Skip this contact.
  562. continue;
  563. }
  564. if (contact->IsTouching() == false)
  565. {
  566. continue;
  567. }
  568. contacts[count] = contact;
  569. ++count;
  570. }
  571. // Reduce the TOI body's overlap with the contact island.
  572. b2TOISolver solver(&m_stackAllocator);
  573. solver.Initialize(contacts, count, body);
  574. const float32 k_toiBaumgarte = 0.75f;
  575. bool solved = false;
  576. for (int32 i = 0; i < 20; ++i)
  577. {
  578. bool contactsOkay = solver.Solve(k_toiBaumgarte);
  579. if (contactsOkay)
  580. {
  581. solved = true;
  582. break;
  583. }
  584. }
  585. if (toiOther->GetType() != b2_staticBody)
  586. {
  587. toiContact->m_flags |= b2Contact::e_bulletHitFlag;
  588. }
  589. }
  590. // Sequentially solve TOIs for each body. We bring each
  591. // body to the time of contact and perform some position correction.
  592. // Time is not conserved.
  593. void b2World::SolveTOI()
  594. {
  595. // Prepare all contacts.
  596. for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next)
  597. {
  598. // Enable the contact
  599. c->m_flags |= b2Contact::e_enabledFlag;
  600. // Set the number of TOI events for this contact to zero.
  601. c->m_toiCount = 0;
  602. }
  603. // Initialize the TOI flag.
  604. for (b2Body* body = m_bodyList; body; body = body->m_next)
  605. {
  606. // Kinematic, and static bodies will not be affected by the TOI event.
  607. // If a body was not in an island then it did not move.
  608. if ((body->m_flags & b2Body::e_islandFlag) == 0 || body->GetType() == b2_kinematicBody || body->GetType() == b2_staticBody)
  609. {
  610. body->m_flags |= b2Body::e_toiFlag;
  611. }
  612. else
  613. {
  614. body->m_flags &= ~b2Body::e_toiFlag;
  615. }
  616. }
  617. // Collide non-bullets.
  618. for (b2Body* body = m_bodyList; body; body = body->m_next)
  619. {
  620. if (body->m_flags & b2Body::e_toiFlag)
  621. {
  622. continue;
  623. }
  624. if (body->IsBullet() == true)
  625. {
  626. continue;
  627. }
  628. SolveTOI(body);
  629. body->m_flags |= b2Body::e_toiFlag;
  630. }
  631. // Collide bullets.
  632. for (b2Body* body = m_bodyList; body; body = body->m_next)
  633. {
  634. if (body->m_flags & b2Body::e_toiFlag)
  635. {
  636. continue;
  637. }
  638. if (body->IsBullet() == false)
  639. {
  640. continue;
  641. }
  642. SolveTOI(body);
  643. body->m_flags |= b2Body::e_toiFlag;
  644. }
  645. }
  646. void b2World::Step(float32 dt, int32 velocityIterations, int32 positionIterations)
  647. {
  648. // If new fixtures were added, we need to find the new contacts.
  649. if (m_flags & e_newFixture)
  650. {
  651. m_contactManager.FindNewContacts();
  652. m_flags &= ~e_newFixture;
  653. }
  654. m_flags |= e_locked;
  655. b2TimeStep step;
  656. step.dt = dt;
  657. step.velocityIterations = velocityIterations;
  658. step.positionIterations = positionIterations;
  659. if (dt > 0.0f)
  660. {
  661. step.inv_dt = 1.0f / dt;
  662. }
  663. else
  664. {
  665. step.inv_dt = 0.0f;
  666. }
  667. step.dtRatio = m_inv_dt0 * dt;
  668. step.warmStarting = m_warmStarting;
  669. // Update contacts. This is where some contacts are destroyed.
  670. m_contactManager.Collide();
  671. // Integrate velocities, solve velocity constraints, and integrate positions.
  672. if (step.dt > 0.0f)
  673. {
  674. Solve(step);
  675. }
  676. // Handle TOI events.
  677. if (m_continuousPhysics && step.dt > 0.0f)
  678. {
  679. SolveTOI();
  680. }
  681. if (step.dt > 0.0f)
  682. {
  683. m_inv_dt0 = step.inv_dt;
  684. }
  685. if (m_flags & e_clearForces)
  686. {
  687. ClearForces();
  688. }
  689. m_flags &= ~e_locked;
  690. }
  691. void b2World::ClearForces()
  692. {
  693. for (b2Body* body = m_bodyList; body; body = body->GetNext())
  694. {
  695. body->m_force.SetZero();
  696. body->m_torque = 0.0f;
  697. }
  698. }
  699. struct b2WorldQueryWrapper
  700. {
  701. bool QueryCallback(int32 proxyId)
  702. {
  703. b2Fixture* fixture = (b2Fixture*)broadPhase->GetUserData(proxyId);
  704. return callback->ReportFixture(fixture);
  705. }
  706. const b2BroadPhase* broadPhase;
  707. b2QueryCallback* callback;
  708. };
  709. void b2World::QueryAABB(b2QueryCallback* callback, const b2AABB& aabb) const
  710. {
  711. b2WorldQueryWrapper wrapper;
  712. wrapper.broadPhase = &m_contactManager.m_broadPhase;
  713. wrapper.callback = callback;
  714. m_contactManager.m_broadPhase.Query(&wrapper, aabb);
  715. }
  716. struct b2WorldRayCastWrapper
  717. {
  718. float32 RayCastCallback(const b2RayCastInput& input, int32 proxyId)
  719. {
  720. void* userData = broadPhase->GetUserData(proxyId);
  721. b2Fixture* fixture = (b2Fixture*)userData;
  722. b2RayCastOutput output;
  723. bool hit = fixture->RayCast(&output, input);
  724. if (hit)
  725. {
  726. float32 fraction = output.fraction;
  727. b2Vec2 point = (1.0f - fraction) * input.p1 + fraction * input.p2;
  728. return callback->ReportFixture(fixture, point, output.normal, fraction);
  729. }
  730. return input.maxFraction;
  731. }
  732. const b2BroadPhase* broadPhase;
  733. b2RayCastCallback* callback;
  734. };
  735. void b2World::RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const
  736. {
  737. b2WorldRayCastWrapper wrapper;
  738. wrapper.broadPhase = &m_contactManager.m_broadPhase;
  739. wrapper.callback = callback;
  740. b2RayCastInput input;
  741. input.maxFraction = 1.0f;
  742. input.p1 = point1;
  743. input.p2 = point2;
  744. m_contactManager.m_broadPhase.RayCast(&wrapper, input);
  745. }
  746. void b2World::DrawShape(b2Fixture* fixture, const b2Transform& xf, const b2Color& color)
  747. {
  748. switch (fixture->GetType())
  749. {
  750. case b2Shape::e_circle:
  751. {
  752. b2CircleShape* circle = (b2CircleShape*)fixture->GetShape();
  753. b2Vec2 center = b2Mul(xf, circle->m_p);
  754. float32 radius = circle->m_radius;
  755. b2Vec2 axis = xf.R.col1;
  756. m_debugDraw->DrawSolidCircle(center, radius, axis, color);
  757. }
  758. break;
  759. case b2Shape::e_polygon:
  760. {
  761. b2PolygonShape* poly = (b2PolygonShape*)fixture->GetShape();
  762. int32 vertexCount = poly->m_vertexCount;
  763. b2Assert(vertexCount <= b2_maxPolygonVertices);
  764. b2Vec2 vertices[b2_maxPolygonVertices];
  765. for (int32 i = 0; i < vertexCount; ++i)
  766. {
  767. vertices[i] = b2Mul(xf, poly->m_vertices[i]);
  768. }
  769. m_debugDraw->DrawSolidPolygon(vertices, vertexCount, color);
  770. }
  771. break;
  772. }
  773. }
  774. void b2World::DrawJoint(b2Joint* joint)
  775. {
  776. b2Body* bodyA = joint->GetBodyA();
  777. b2Body* bodyB = joint->GetBodyB();
  778. const b2Transform& xf1 = bodyA->GetTransform();
  779. const b2Transform& xf2 = bodyB->GetTransform();
  780. b2Vec2 x1 = xf1.position;
  781. b2Vec2 x2 = xf2.position;
  782. b2Vec2 p1 = joint->GetAnchorA();
  783. b2Vec2 p2 = joint->GetAnchorB();
  784. b2Color color(0.5f, 0.8f, 0.8f);
  785. switch (joint->GetType())
  786. {
  787. case e_distanceJoint:
  788. m_debugDraw->DrawSegment(p1, p2, color);
  789. break;
  790. case e_pulleyJoint:
  791. {
  792. b2PulleyJoint* pulley = (b2PulleyJoint*)joint;
  793. b2Vec2 s1 = pulley->GetGroundAnchorA();
  794. b2Vec2 s2 = pulley->GetGroundAnchorB();
  795. m_debugDraw->DrawSegment(s1, p1, color);
  796. m_debugDraw->DrawSegment(s2, p2, color);
  797. m_debugDraw->DrawSegment(s1, s2, color);
  798. }
  799. break;
  800. case e_mouseJoint:
  801. // don't draw this
  802. break;
  803. default:
  804. m_debugDraw->DrawSegment(x1, p1, color);
  805. m_debugDraw->DrawSegment(p1, p2, color);
  806. m_debugDraw->DrawSegment(x2, p2, color);
  807. }
  808. }
  809. void b2World::DrawDebugData()
  810. {
  811. if (m_debugDraw == NULL)
  812. {
  813. return;
  814. }
  815. uint32 flags = m_debugDraw->GetFlags();
  816. if (flags & b2DebugDraw::e_shapeBit)
  817. {
  818. for (b2Body* b = m_bodyList; b; b = b->GetNext())
  819. {
  820. const b2Transform& xf = b->GetTransform();
  821. for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext())
  822. {
  823. if (b->IsActive() == false)
  824. {
  825. DrawShape(f, xf, b2Color(0.5f, 0.5f, 0.3f));
  826. }
  827. else if (b->GetType() == b2_staticBody)
  828. {
  829. DrawShape(f, xf, b2Color(0.5f, 0.9f, 0.5f));
  830. }
  831. else if (b->GetType() == b2_kinematicBody)
  832. {
  833. DrawShape(f, xf, b2Color(0.5f, 0.5f, 0.9f));
  834. }
  835. else if (b->IsAwake() == false)
  836. {
  837. DrawShape(f, xf, b2Color(0.6f, 0.6f, 0.6f));
  838. }
  839. else
  840. {
  841. DrawShape(f, xf, b2Color(0.9f, 0.7f, 0.7f));
  842. }
  843. }
  844. }
  845. }
  846. if (flags & b2DebugDraw::e_jointBit)
  847. {
  848. for (b2Joint* j = m_jointList; j; j = j->GetNext())
  849. {
  850. DrawJoint(j);
  851. }
  852. }
  853. if (flags & b2DebugDraw::e_pairBit)
  854. {
  855. b2Color color(0.3f, 0.9f, 0.9f);
  856. for (b2Contact* c = m_contactManager.m_contactList; c; c = c->GetNext())
  857. {
  858. b2Fixture* fixtureA = c->GetFixtureA();
  859. b2Fixture* fixtureB = c->GetFixtureB();
  860. b2Vec2 cA = fixtureA->GetAABB().GetCenter();
  861. b2Vec2 cB = fixtureB->GetAABB().GetCenter();
  862. m_debugDraw->DrawSegment(cA, cB, color);
  863. }
  864. }
  865. if (flags & b2DebugDraw::e_aabbBit)
  866. {
  867. b2Color color(0.9f, 0.3f, 0.9f);
  868. b2BroadPhase* bp = &m_contactManager.m_broadPhase;
  869. for (b2Body* b = m_bodyList; b; b = b->GetNext())
  870. {
  871. if (b->IsActive() == false)
  872. {
  873. continue;
  874. }
  875. for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext())
  876. {
  877. b2AABB aabb = bp->GetFatAABB(f->m_proxyId);
  878. b2Vec2 vs[4];
  879. vs[0].Set(aabb.lowerBound.x, aabb.lowerBound.y);
  880. vs[1].Set(aabb.upperBound.x, aabb.lowerBound.y);
  881. vs[2].Set(aabb.upperBound.x, aabb.upperBound.y);
  882. vs[3].Set(aabb.lowerBound.x, aabb.upperBound.y);
  883. m_debugDraw->DrawPolygon(vs, 4, color);
  884. }
  885. }
  886. }
  887. if (flags & b2DebugDraw::e_centerOfMassBit)
  888. {
  889. for (b2Body* b = m_bodyList; b; b = b->GetNext())
  890. {
  891. b2Transform xf = b->GetTransform();
  892. xf.position = b->GetWorldCenter();
  893. m_debugDraw->DrawTransform(xf);
  894. }
  895. }
  896. }
  897. int32 b2World::GetProxyCount() const
  898. {
  899. return m_contactManager.m_broadPhase.GetProxyCount();
  900. }