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