View difference between Paste ID: d6fn0mLd and RqNmfEVq
SHOW: | | - or go back to the newest paste.
1
/*
2
* Copyright (c) 2006-2011 Erin Catto http://www.box2d.org
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 <Box2D/Dynamics/b2World.h>
20
#include <Box2D/Dynamics/b2Body.h>
21
#include <Box2D/Dynamics/b2Fixture.h>
22
#include <Box2D/Dynamics/b2Island.h>
23
#include <Box2D/Dynamics/Joints/b2PulleyJoint.h>
24
#include <Box2D/Dynamics/Contacts/b2Contact.h>
25
#include <Box2D/Dynamics/Contacts/b2ContactSolver.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/b2EdgeShape.h>
30
#include <Box2D/Collision/Shapes/b2ChainShape.h>
31
#include <Box2D/Collision/Shapes/b2PolygonShape.h>
32
#include <Box2D/Collision/b2TimeOfImpact.h>
33
#include <Box2D/Common/b2Draw.h>
34
#include <Box2D/Common/b2Timer.h>
35
#include <new>
36
37
#include <string>
38
#include <stdio.h>
39
40
b2World::b2World(const b2Vec2& gravity)
41
{
42
	m_destructionListener = NULL;
43
	g_debugDraw = NULL;
44
45
	m_bodyList = NULL;
46
	m_jointList = NULL;
47
48
	m_bodyCount = 0;
49
	m_jointCount = 0;
50
51
	m_warmStarting = true;
52
	m_continuousPhysics = true;
53
	m_subStepping = false;
54
55
	m_stepComplete = true;
56
57
	m_allowSleep = true;
58
	m_gravity = gravity;
59
60
	m_flags = e_clearForces;
61
62
	m_inv_dt0 = 0.0f;
63
64
	m_contactManager.m_allocator = &m_blockAllocator;
65
66
	memset(&m_profile, 0, sizeof(b2Profile));
67
}
68
69
b2World::~b2World()
70
{
71
	// Some shapes allocate using b2Alloc.
72
	b2Body* b = m_bodyList;
73
	while (b)
74
	{
75
		b2Body* bNext = b->m_next;
76
77
		b2Fixture* f = b->m_fixtureList;
78
		while (f)
79
		{
80
			b2Fixture* fNext = f->m_next;
81
			f->m_proxyCount = 0;
82
			f->Destroy(&m_blockAllocator);
83
			f = fNext;
84
		}
85
86
		b = bNext;
87
	}
88
}
89
90
void b2World::SetDestructionListener(b2DestructionListener* listener)
91
{
92
	m_destructionListener = listener;
93
}
94
95
void b2World::SetContactFilter(b2ContactFilter* filter)
96
{
97
	m_contactManager.m_contactFilter = filter;
98
}
99
100
void b2World::SetContactListener(b2ContactListener* listener)
101
{
102
	m_contactManager.m_contactListener = listener;
103
}
104
105
void b2World::SetDebugDraw(b2Draw* debugDraw)
106
{
107
	g_debugDraw = debugDraw;
108
}
109
110
b2Body* b2World::CreateBody(const b2BodyDef* def)
111
{
112
	b2Assert(IsLocked() == false);
113
	if (IsLocked())
114
	{
115
		return NULL;
116
	}
117
118
	void* mem = m_blockAllocator.Allocate(sizeof(b2Body));
119
	b2Body* b = new (mem) b2Body(def, this);
120
121
	// Add to world doubly linked list.
122
	b->m_prev = NULL;
123
	b->m_next = m_bodyList;
124
	if (m_bodyList)
125
	{
126
		m_bodyList->m_prev = b;
127
	}
128
	m_bodyList = b;
129
	++m_bodyCount;
130
131
	return b;
132
}
133
134
void b2World::DestroyBody(b2Body* b)
135
{
136
	b2Assert(m_bodyCount > 0);
137
	b2Assert(IsLocked() == false);
138
	if (IsLocked())
139
	{
140
		return;
141
	}
142
143
	// Delete the attached joints.
144
	b2JointEdge* je = b->m_jointList;
145
	while (je)
146
	{
147
		b2JointEdge* je0 = je;
148
		je = je->next;
149
150
		if (m_destructionListener)
151
		{
152
			m_destructionListener->SayGoodbye(je0->joint);
153
		}
154
155
		DestroyJoint(je0->joint);
156
157
		b->m_jointList = je;
158
	}
159
	b->m_jointList = NULL;
160
161
	// Delete the attached contacts.
162
	b2ContactEdge* ce = b->m_contactList;
163
	while (ce)
164
	{
165
		b2ContactEdge* ce0 = ce;
166
		ce = ce->next;
167
		m_contactManager.Destroy(ce0->contact);
168
	}
169
	b->m_contactList = NULL;
170
171
	// Delete the attached fixtures. This destroys broad-phase proxies.
172
	b2Fixture* f = b->m_fixtureList;
173
	while (f)
174
	{
175
		b2Fixture* f0 = f;
176
		f = f->m_next;
177
178
		if (m_destructionListener)
179
		{
180
			m_destructionListener->SayGoodbye(f0);
181
		}
182
183
		f0->DestroyProxies(&m_contactManager.m_broadPhase);
184
		f0->Destroy(&m_blockAllocator);
185
		f0->~b2Fixture();
186
		m_blockAllocator.Free(f0, sizeof(b2Fixture));
187
188
		b->m_fixtureList = f;
189
		b->m_fixtureCount -= 1;
190
	}
191
	b->m_fixtureList = NULL;
192
	b->m_fixtureCount = 0;
193
194
	// Remove world body list.
195
	if (b->m_prev)
196
	{
197
		b->m_prev->m_next = b->m_next;
198
	}
199
200
	if (b->m_next)
201
	{
202
		b->m_next->m_prev = b->m_prev;
203
	}
204
205
	if (b == m_bodyList)
206
	{
207
		m_bodyList = b->m_next;
208
	}
209
210
	--m_bodyCount;
211
	b->~b2Body();
212
	m_blockAllocator.Free(b, sizeof(b2Body));
213
}
214
215
b2Joint* b2World::CreateJoint(const b2JointDef* def)
216
{
217
	b2Assert(IsLocked() == false);
218
	if (IsLocked())
219
	{
220
		return NULL;
221
	}
222
223
	b2Joint* j = b2Joint::Create(def, &m_blockAllocator);
224
225
	// Connect to the world list.
226
	j->m_prev = NULL;
227
	j->m_next = m_jointList;
228
	if (m_jointList)
229
	{
230
		m_jointList->m_prev = j;
231
	}
232
	m_jointList = j;
233
	++m_jointCount;
234
235
	// Connect to the bodies' doubly linked lists.
236
	j->m_edgeA.joint = j;
237
	j->m_edgeA.other = j->m_bodyB;
238
	j->m_edgeA.prev = NULL;
239
	j->m_edgeA.next = j->m_bodyA->m_jointList;
240
	if (j->m_bodyA->m_jointList) j->m_bodyA->m_jointList->prev = &j->m_edgeA;
241
	j->m_bodyA->m_jointList = &j->m_edgeA;
242
243
	j->m_edgeB.joint = j;
244
	j->m_edgeB.other = j->m_bodyA;
245
	j->m_edgeB.prev = NULL;
246
	j->m_edgeB.next = j->m_bodyB->m_jointList;
247
	if (j->m_bodyB->m_jointList) j->m_bodyB->m_jointList->prev = &j->m_edgeB;
248
	j->m_bodyB->m_jointList = &j->m_edgeB;
249
250
	b2Body* bodyA = def->bodyA;
251
	b2Body* bodyB = def->bodyB;
252
253
	// If the joint prevents collisions, then flag any contacts for filtering.
254
	if (def->collideConnected == false)
255
	{
256
		b2ContactEdge* edge = bodyB->GetContactList();
257
		while (edge)
258
		{
259
			if (edge->other == bodyA)
260
			{
261
				// Flag the contact for filtering at the next time step (where either
262
				// body is awake).
263
				edge->contact->FlagForFiltering();
264
			}
265
266
			edge = edge->next;
267
		}
268
	}
269
270
	// Note: creating a joint doesn't wake the bodies.
271
272
	return j;
273
}
274
275
void b2World::DestroyJoint(b2Joint* j)
276
{
277
	b2Assert(IsLocked() == false);
278
	if (IsLocked())
279
	{
280
		return;
281
	}
282
283
	bool collideConnected = j->m_collideConnected;
284
285
	// Remove from the doubly linked list.
286
	if (j->m_prev)
287
	{
288
		j->m_prev->m_next = j->m_next;
289
	}
290
291
	if (j->m_next)
292
	{
293
		j->m_next->m_prev = j->m_prev;
294
	}
295
296
	if (j == m_jointList)
297
	{
298
		m_jointList = j->m_next;
299
	}
300
301
	// Disconnect from island graph.
302
	b2Body* bodyA = j->m_bodyA;
303
	b2Body* bodyB = j->m_bodyB;
304
305
	// Wake up connected bodies.
306
	bodyA->SetAwake(true);
307
	bodyB->SetAwake(true);
308
309
	// Remove from body 1.
310
	if (j->m_edgeA.prev)
311
	{
312
		j->m_edgeA.prev->next = j->m_edgeA.next;
313
	}
314
315
	if (j->m_edgeA.next)
316
	{
317
		j->m_edgeA.next->prev = j->m_edgeA.prev;
318
	}
319
320
	if (&j->m_edgeA == bodyA->m_jointList)
321
	{
322
		bodyA->m_jointList = j->m_edgeA.next;
323
	}
324
325
	j->m_edgeA.prev = NULL;
326
	j->m_edgeA.next = NULL;
327
328
	// Remove from body 2
329
	if (j->m_edgeB.prev)
330
	{
331
		j->m_edgeB.prev->next = j->m_edgeB.next;
332
	}
333
334
	if (j->m_edgeB.next)
335
	{
336
		j->m_edgeB.next->prev = j->m_edgeB.prev;
337
	}
338
339
	if (&j->m_edgeB == bodyB->m_jointList)
340
	{
341
		bodyB->m_jointList = j->m_edgeB.next;
342
	}
343
344
	j->m_edgeB.prev = NULL;
345
	j->m_edgeB.next = NULL;
346
347
	b2Joint::Destroy(j, &m_blockAllocator);
348
349
	b2Assert(m_jointCount > 0);
350
	--m_jointCount;
351
352
	// If the joint prevents collisions, then flag any contacts for filtering.
353
	if (collideConnected == false)
354
	{
355
		b2ContactEdge* edge = bodyB->GetContactList();
356
		while (edge)
357
		{
358
			if (edge->other == bodyA)
359
			{
360
				// Flag the contact for filtering at the next time step (where either
361
				// body is awake).
362
				edge->contact->FlagForFiltering();
363
			}
364
365
			edge = edge->next;
366
		}
367
	}
368
}
369
370
//
371
void b2World::SetAllowSleeping(bool flag)
372
{
373
	if (flag == m_allowSleep)
374
	{
375
		return;
376
	}
377
378
	m_allowSleep = flag;
379
	if (m_allowSleep == false)
380
	{
381
		for (b2Body* b = m_bodyList; b; b = b->m_next)
382
		{
383
			b->SetAwake(true);
384
		}
385
	}
386
}
387
388
// Find islands, integrate and solve constraints, solve position constraints
389
void b2World::Solve(const b2TimeStep& step)
390
{
391
	m_profile.solveInit = 0.0f;
392
	m_profile.solveVelocity = 0.0f;
393
	m_profile.solvePosition = 0.0f;
394
395
	// Size the island for the worst case.
396
	b2Island island(m_bodyCount,
397
					m_contactManager.m_contactCount,
398
					m_jointCount,
399
					&m_stackAllocator,
400
					m_contactManager.m_contactListener);
401
402
	// Clear all the island flags.
403
	for (b2Body* b = m_bodyList; b; b = b->m_next)
404
	{
405
		b->m_flags &= ~b2Body::e_islandFlag;
406
	}
407
408
	for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next)
409
	{
410
		c->m_flags &= ~b2Contact::e_islandFlag;
411
	}
412
413
	for (b2Joint* j = m_jointList; j; j = j->m_next)
414
	{
415
		j->m_islandFlag = false;
416
	}
417
418
	// Build and simulate all awake islands.
419
	int32 stackSize = m_bodyCount;
420
	b2Body** stack = (b2Body**)m_stackAllocator.Allocate(stackSize * sizeof(b2Body*));
421
	for (b2Body* seed = m_bodyList; seed; seed = seed->m_next)
422
	{
423
		if (seed->m_flags & b2Body::e_islandFlag)
424
		{
425
			continue;
426
		}
427
428
		if (seed->IsAwake() == false || seed->IsActive() == false)
429
		{
430
			continue;
431
		}
432
433
		// The seed can be dynamic or kinematic.
434
		if (seed->GetType() == b2_staticBody)
435
		{
436
			continue;
437
		}
438
439
		//printf("{N}");
440
		//fflush(stdout);
441
		// Reset island and stack.
442
		island.Clear();
443
		int32 stackCount = 0;
444
		stack[stackCount++] = seed;
445
		seed->m_flags |= b2Body::e_islandFlag;
446
447
		// Perform a depth first search (DFS) on the constraint graph.
448
		while (stackCount > 0)
449
		{
450
			// Grab the next body off the stack and add it to the island.
451
			b2Body* b = stack[--stackCount];
452
			b2Assert(b->IsActive() == true);
453
			island.Add(b);
454
455
			// Make sure the body is awake.
456
			b->SetAwake(true);
457
458
			// To keep islands as small as possible, we don't
459
			// propagate islands across static bodies.
460
			if (b->GetType() == b2_staticBody)
461
			{
462
				continue;
463
			}
464
465
			// Search all contacts connected to this body.
466
			for (b2ContactEdge* ce = b->m_contactList; ce; ce = ce->next)
467
			{
468
				b2Contact* contact = ce->contact;
469
470
				// Has this contact already been added to an island?
471
				if (contact->m_flags & b2Contact::e_islandFlag)
472
				{
473
					continue;
474
				}
475
476
				// Is this contact solid and touching?
477
				if (contact->IsEnabled() == false ||
478
					contact->IsTouching() == false)
479
				{
480
					continue;
481
				}
482
483
				// Skip sensors.
484
				bool sensorA = contact->m_fixtureA->m_isSensor;
485
				bool sensorB = contact->m_fixtureB->m_isSensor;
486
				if (sensorA || sensorB)
487
				{
488
					continue;
489
				}
490
491
				island.Add(contact);
492
				contact->m_flags |= b2Contact::e_islandFlag;
493
494
				b2Body* other = ce->other;
495
496
				// Was the other body already added to this island?
497
				if (other->m_flags & b2Body::e_islandFlag)
498
				{
499
					continue;
500
				}
501
502
				b2Assert(stackCount < stackSize);
503
				stack[stackCount++] = other;
504
				other->m_flags |= b2Body::e_islandFlag;
505
			}
506
507
			// Search all joints connect to this body.
508
			for (b2JointEdge* je = b->m_jointList; je; je = je->next)
509
			{
510
				if (je->joint->m_islandFlag == true)
511
				{
512
					continue;
513
				}
514
515
				b2Body* other = je->other;
516
517
				// Don't simulate joints connected to inactive bodies.
518
				if (other->IsActive() == false)
519
				{
520
					continue;
521
				}
522
523
				island.Add(je->joint);
524
				je->joint->m_islandFlag = true;
525
526
				if (other->m_flags & b2Body::e_islandFlag)
527
				{
528
					continue;
529
				}
530
531
				b2Assert(stackCount < stackSize);
532
				stack[stackCount++] = other;
533
				other->m_flags |= b2Body::e_islandFlag;
534
			}
535
		}
536
537
		//printf("{M}");
538
		//fflush(stdout);
539
		b2Profile profile;
540
		island.Solve(&profile, step, m_gravity, m_allowSleep);
541
		m_profile.solveInit += profile.solveInit;
542
		m_profile.solveVelocity += profile.solveVelocity;
543
		m_profile.solvePosition += profile.solvePosition;
544
545
		//printf("{;}");
546
		//fflush(stdout);
547
		// Post solve cleanup.
548
		for (int32 i = 0; i < island.m_bodyCount; ++i)
549
		{
550
			// Allow static bodies to participate in other islands.
551
			b2Body* b = island.m_bodies[i];
552
			if (b->GetType() == b2_staticBody)
553
			{
554
				b->m_flags &= ~b2Body::e_islandFlag;
555
			}
556
		}
557
	}
558
559
	m_stackAllocator.Free(stack);
560
561
	{
562
		b2Timer timer;
563
		// Synchronize fixtures, check for out of range bodies.
564
		for (b2Body* b = m_bodyList; b; b = b->GetNext())
565
		{
566
			// If a body was not in an island then it did not move.
567
			if ((b->m_flags & b2Body::e_islandFlag) == 0)
568
			{
569
				continue;
570
			}
571
572
			if (b->GetType() == b2_staticBody)
573
			{
574
				continue;
575
			}
576
577
			// Update fixtures (for broad-phase).
578
			b->SynchronizeFixtures();
579
		}
580
581
		// Look for new contacts.
582
		m_contactManager.FindNewContacts();
583
		m_profile.broadphase = timer.GetMilliseconds();
584
	}
585
}
586
587
// Find TOI contacts and solve them.
588
void b2World::SolveTOI(const b2TimeStep& step)
589
{
590
591
	printf("\n");
592
	printf("{A}");
593
	fflush(stdout);
594
595
	b2Island island(2 * b2_maxTOIContacts, b2_maxTOIContacts, 0, &m_stackAllocator, m_contactManager.m_contactListener);
596
	printf("{B}");
597
	fflush(stdout);
598
599
	if (m_stepComplete)
600
	{
601
		for (b2Body* b = m_bodyList; b; b = b->m_next)
602
		{
603
			b->m_flags &= ~b2Body::e_islandFlag;
604
			b->m_sweep.alpha0 = 0.0f;
605
		}
606
		printf("{C}");
607
		fflush(stdout);
608
609
		for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next)
610
		{
611
			// Invalidate TOI
612
			c->m_flags &= ~(b2Contact::e_toiFlag | b2Contact::e_islandFlag);
613
			c->m_toiCount = 0;
614
			c->m_toi = 1.0f;
615
		}
616
	}
617
	printf("{D}");
618
	fflush(stdout);
619
620
	// Find TOI events and solve them.
621
	for (;;)
622
	{
623
		// Find the first TOI.
624
		b2Contact* minContact = NULL;
625
		float32 minAlpha = 1.0f;
626-
		int32 contactCount = 0;
626+
627-
		int32 contactProcessedCount = 0;
627+
628
		{
629
			// Is this contact disabled?
630
			if (c->IsEnabled() == false)
631-
			contactCount++;
631+
632
				continue;
633
			}
634
635
			// Prevent excessive sub-stepping.
636
			if (c->m_toiCount > b2_maxSubSteps)
637
			{
638
				continue;
639
			}
640
641
			float32 alpha = 1.0f;
642
			if (c->m_flags & b2Contact::e_toiFlag)
643
			{
644
				// This contact has a valid cached TOI.
645
				alpha = c->m_toi;
646
			}
647
			else
648
			{
649
				b2Fixture* fA = c->GetFixtureA();
650
				b2Fixture* fB = c->GetFixtureB();
651
652
				// Is there a sensor?
653
				if (fA->IsSensor() || fB->IsSensor())
654
				{
655
					continue;
656
				}
657
658
				b2Body* bA = fA->GetBody();
659
				b2Body* bB = fB->GetBody();
660
661
				b2BodyType typeA = bA->m_type;
662
				b2BodyType typeB = bB->m_type;
663
				b2Assert(typeA == b2_dynamicBody || typeB == b2_dynamicBody);
664
665
				bool activeA = bA->IsAwake() && typeA != b2_staticBody;
666
				bool activeB = bB->IsAwake() && typeB != b2_staticBody;
667
668
				// Is at least one body active (awake and dynamic or kinematic)?
669
				if (activeA == false && activeB == false)
670
				{
671
					continue;
672
				}
673
674
				bool collideA = bA->IsBullet() || typeA != b2_dynamicBody;
675
				bool collideB = bB->IsBullet() || typeB != b2_dynamicBody;
676
677
				// Are these two non-bullet dynamic bodies?
678
				if (collideA == false && collideB == false)
679
				{
680
					continue;
681
				}
682
683
				// Compute the TOI for this contact.
684
				// Put the sweeps onto the same time interval.
685
				float32 alpha0 = bA->m_sweep.alpha0;
686
687
				if (bA->m_sweep.alpha0 < bB->m_sweep.alpha0)
688
				{
689
					alpha0 = bB->m_sweep.alpha0;
690
					bA->m_sweep.Advance(alpha0);
691
				}
692
				else if (bB->m_sweep.alpha0 < bA->m_sweep.alpha0)
693
				{
694
					alpha0 = bA->m_sweep.alpha0;
695
					bB->m_sweep.Advance(alpha0);
696
				}
697
698
				b2Assert(alpha0 < 1.0f);
699
700
				int32 indexA = c->GetChildIndexA();
701
				int32 indexB = c->GetChildIndexB();
702
703
				// Compute the time of impact in interval [0, minTOI]
704
				b2TOIInput input;
705
				input.proxyA.Set(fA->GetShape(), indexA);
706
				input.proxyB.Set(fB->GetShape(), indexB);
707
				input.sweepA = bA->m_sweep;
708
				input.sweepB = bB->m_sweep;
709
				input.tMax = 1.0f;
710
711
				b2TOIOutput output;
712
				b2TimeOfImpact(&output, &input);
713
714
				// Beta is the fraction of the remaining portion of the .
715
				float32 beta = output.t;
716
				if (output.state == b2TOIOutput::e_touching)
717
				{
718
					alpha = b2Min(alpha0 + (1.0f - alpha0) * beta, 1.0f);
719
				}
720
				else
721
				{
722
					alpha = 1.0f;
723
				}
724
725
				c->m_toi = alpha;
726
				c->m_flags |= b2Contact::e_toiFlag;
727
			}
728
729
			if (alpha < minAlpha)
730-
				contactProcessedCount++;
730+
731
				// This is the minimum TOI found so far.
732
				minContact = c;
733
				minAlpha = alpha;
734
			}
735
		}
736
737
		if (minContact == NULL || 1.0f - 10.0f * b2_epsilon < minAlpha)
738
		{
739
			printf("{E2}");
740-
		printf("{c");
740+
741-
		printf("%d",contactProcessedCount);
741+
742-
		printf("/");
742+
743-
		printf("%d",contactCount);
743+
744-
		printf("}");
744+
745
			printf("{E1}");
746
			fflush(stdout);
747
		}
748
749
		// Advance the bodies to the TOI.
750
		b2Fixture* fA = minContact->GetFixtureA();
751
		b2Fixture* fB = minContact->GetFixtureB();
752
		b2Body* bA = fA->GetBody();
753
		b2Body* bB = fB->GetBody();
754
755
		b2Sweep backup1 = bA->m_sweep;
756
		b2Sweep backup2 = bB->m_sweep;
757
758
		bA->Advance(minAlpha);
759
		bB->Advance(minAlpha);
760
		printf("{F}");
761
		fflush(stdout);
762
763
		// The TOI contact likely has some new contact points.
764
		minContact->Update(m_contactManager.m_contactListener);
765
		minContact->m_flags &= ~b2Contact::e_toiFlag;
766
		++minContact->m_toiCount;
767
768
		printf("{G}");
769
		fflush(stdout);
770
		// Is the contact solid?
771
		if (minContact->IsEnabled() == false || minContact->IsTouching() == false)
772
		{
773
			// Restore the sweeps.
774
			minContact->SetEnabled(false);
775
			bA->m_sweep = backup1;
776
			bB->m_sweep = backup2;
777
			bA->SynchronizeTransform();
778
			bB->SynchronizeTransform();
779
			continue;
780
		}
781
782
		bA->SetAwake(true);
783
		bB->SetAwake(true);
784
785
		// Build the island
786
		island.Clear();
787
		island.Add(bA);
788
		island.Add(bB);
789
		island.Add(minContact);
790
791
		bA->m_flags |= b2Body::e_islandFlag;
792
		bB->m_flags |= b2Body::e_islandFlag;
793
		minContact->m_flags |= b2Contact::e_islandFlag;
794
795
		// Get contacts on bodyA and bodyB.
796
		b2Body* bodies[2] = {bA, bB};
797
		for (int32 i = 0; i < 2; ++i)
798
		{
799
			b2Body* body = bodies[i];
800
			if (body->m_type == b2_dynamicBody)
801
			{
802
				for (b2ContactEdge* ce = body->m_contactList; ce; ce = ce->next)
803
				{
804
					if (island.m_bodyCount == island.m_bodyCapacity)
805
					{
806
						break;
807
					}
808
809
					if (island.m_contactCount == island.m_contactCapacity)
810
					{
811
						break;
812
					}
813
814
					b2Contact* contact = ce->contact;
815
816
					// Has this contact already been added to the island?
817
					if (contact->m_flags & b2Contact::e_islandFlag)
818
					{
819
						continue;
820
					}
821
822
					// Only add static, kinematic, or bullet bodies.
823
					b2Body* other = ce->other;
824
					if (other->m_type == b2_dynamicBody &&
825
						body->IsBullet() == false && other->IsBullet() == false)
826
					{
827
						continue;
828
					}
829
830
					// Skip sensors.
831
					bool sensorA = contact->m_fixtureA->m_isSensor;
832
					bool sensorB = contact->m_fixtureB->m_isSensor;
833
					if (sensorA || sensorB)
834
					{
835
						continue;
836
					}
837
838
					// Tentatively advance the body to the TOI.
839
					b2Sweep backup = other->m_sweep;
840
					if ((other->m_flags & b2Body::e_islandFlag) == 0)
841
					{
842
						other->Advance(minAlpha);
843
					}
844
845
					// Update the contact points
846
					contact->Update(m_contactManager.m_contactListener);
847
848
					// Was the contact disabled by the user?
849
					if (contact->IsEnabled() == false)
850
					{
851
						other->m_sweep = backup;
852
						other->SynchronizeTransform();
853
						continue;
854
					}
855
856
					// Are there contact points?
857
					if (contact->IsTouching() == false)
858
					{
859
						other->m_sweep = backup;
860
						other->SynchronizeTransform();
861
						continue;
862
					}
863
864
					// Add the contact to the island
865
					contact->m_flags |= b2Contact::e_islandFlag;
866
					island.Add(contact);
867
868
					// Has the other body already been added to the island?
869
					if (other->m_flags & b2Body::e_islandFlag)
870
					{
871
						continue;
872
					}
873
					
874
					// Add the other body to the island.
875
					other->m_flags |= b2Body::e_islandFlag;
876
877
					if (other->m_type != b2_staticBody)
878
					{
879
						other->SetAwake(true);
880
					}
881
882
					island.Add(other);
883
				}
884
			}
885
		}
886
		printf("{H}");
887
		fflush(stdout);
888
889
		b2TimeStep subStep;
890
		subStep.dt = (1.0f - minAlpha) * step.dt;
891
		subStep.inv_dt = 1.0f / subStep.dt;
892
		subStep.dtRatio = 1.0f;
893
		subStep.positionIterations = 20;
894
		subStep.velocityIterations = step.velocityIterations;
895
		subStep.warmStarting = false;
896
		island.SolveTOI(subStep, bA->m_islandIndex, bB->m_islandIndex);
897
		printf("{I}");
898
		fflush(stdout);
899
900
		// Reset island flags and synchronize broad-phase proxies.
901
		for (int32 i = 0; i < island.m_bodyCount; ++i)
902
		{
903
			b2Body* body = island.m_bodies[i];
904
			body->m_flags &= ~b2Body::e_islandFlag;
905
906
			if (body->m_type != b2_dynamicBody)
907
			{
908
				continue;
909
			}
910
911
			body->SynchronizeFixtures();
912
913
			// Invalidate all contact TOIs on this displaced body.
914
			for (b2ContactEdge* ce = body->m_contactList; ce; ce = ce->next)
915
			{
916
				ce->contact->m_flags &= ~(b2Contact::e_toiFlag | b2Contact::e_islandFlag);
917
			}
918
		}
919
		printf("{J}");
920
		fflush(stdout);
921
922
		// Commit fixture proxy movements to the broad-phase so that new contacts are created.
923
		// Also, some contacts can be destroyed.
924
		m_contactManager.FindNewContacts();
925
		printf("{K}");
926
		fflush(stdout);
927
928
		if (m_subStepping)
929
		{
930
			m_stepComplete = false;
931
			break;
932
		}
933
	}
934
}
935
936
void b2World::Step(float32 dt, int32 velocityIterations, int32 positionIterations)
937
{
938
	b2Timer stepTimer;
939
940
	// If new fixtures were added, we need to find the new contacts.
941
	if (m_flags & e_newFixture)
942
	{
943
		m_contactManager.FindNewContacts();
944
		m_flags &= ~e_newFixture;
945
	}
946
947
	m_flags |= e_locked;
948
949
	b2TimeStep step;
950
	step.dt = dt;
951
	step.velocityIterations	= velocityIterations;
952
	step.positionIterations = positionIterations;
953
	if (dt > 0.0f)
954
	{
955
		step.inv_dt = 1.0f / dt;
956
	}
957
	else
958
	{
959
		step.inv_dt = 0.0f;
960
	}
961
962
	step.dtRatio = m_inv_dt0 * dt;
963
964
	step.warmStarting = m_warmStarting;
965
	
966
	// Update contacts. This is where some contacts are destroyed.
967
	{
968
		b2Timer timer;
969
		m_contactManager.Collide();
970
		m_profile.collide = timer.GetMilliseconds();
971
	}
972
973
	// Integrate velocities, solve velocity constraints, and integrate positions.
974
	if (m_stepComplete && step.dt > 0.0f)
975
	{
976
		b2Timer timer;
977
		Solve(step);
978
		m_profile.solve = timer.GetMilliseconds();
979
	}
980
981
	// Handle TOI events.
982
	if (m_continuousPhysics && step.dt > 0.0f)
983
	{
984
		b2Timer timer;
985
		SolveTOI(step);
986
		m_profile.solveTOI = timer.GetMilliseconds();
987
	}
988
989
	if (step.dt > 0.0f)
990
	{
991
		m_inv_dt0 = step.inv_dt;
992
	}
993
994
	if (m_flags & e_clearForces)
995
	{
996
		ClearForces();
997
	}
998
999
	m_flags &= ~e_locked;
1000
1001
	m_profile.step = stepTimer.GetMilliseconds();
1002
1003
	printf("\n");
1004
	printf("{PR|");
1005
	printf("%.2f", m_profile.step);
1006
	printf("|");
1007
	printf("%.2f", m_profile.collide);
1008
	printf("|");
1009
	printf("%.2f", m_profile.solve);
1010
	printf("|");
1011
	printf("%.2f", m_profile.solveInit);
1012
	printf("|");
1013
	printf("%.2f", m_profile.solveVelocity);
1014
	printf("|");
1015
	printf("%.2f", m_profile.solvePosition);
1016
	printf("|");
1017
	printf("%.2f", m_profile.solveTOI);
1018
	printf("|");
1019
	printf("%.2f", m_profile.broadphase);
1020
	printf("}");
1021
	fflush(stdout);
1022
1023
}
1024
1025
void b2World::ClearForces()
1026
{
1027
	for (b2Body* body = m_bodyList; body; body = body->GetNext())
1028
	{
1029
		body->m_force.SetZero();
1030
		body->m_torque = 0.0f;
1031
	}
1032
}
1033
1034
struct b2WorldQueryWrapper
1035
{
1036
	bool QueryCallback(int32 proxyId)
1037
	{
1038
		b2FixtureProxy* proxy = (b2FixtureProxy*)broadPhase->GetUserData(proxyId);
1039
		return callback->ReportFixture(proxy->fixture);
1040
	}
1041
1042
	const b2BroadPhase* broadPhase;
1043
	b2QueryCallback* callback;
1044
};
1045
1046
void b2World::QueryAABB(b2QueryCallback* callback, const b2AABB& aabb) const
1047
{
1048
	b2WorldQueryWrapper wrapper;
1049
	wrapper.broadPhase = &m_contactManager.m_broadPhase;
1050
	wrapper.callback = callback;
1051
	m_contactManager.m_broadPhase.Query(&wrapper, aabb);
1052
}
1053
1054
struct b2WorldRayCastWrapper
1055
{
1056
	float32 RayCastCallback(const b2RayCastInput& input, int32 proxyId)
1057
	{
1058
		void* userData = broadPhase->GetUserData(proxyId);
1059
		b2FixtureProxy* proxy = (b2FixtureProxy*)userData;
1060
		b2Fixture* fixture = proxy->fixture;
1061
		int32 index = proxy->childIndex;
1062
		b2RayCastOutput output;
1063
		bool hit = fixture->RayCast(&output, input, index);
1064
1065
		if (hit)
1066
		{
1067
			float32 fraction = output.fraction;
1068
			b2Vec2 point = (1.0f - fraction) * input.p1 + fraction * input.p2;
1069
			return callback->ReportFixture(fixture, point, output.normal, fraction);
1070
		}
1071
1072
		return input.maxFraction;
1073
	}
1074
1075
	const b2BroadPhase* broadPhase;
1076
	b2RayCastCallback* callback;
1077
};
1078
1079
void b2World::RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const
1080
{
1081
	b2WorldRayCastWrapper wrapper;
1082
	wrapper.broadPhase = &m_contactManager.m_broadPhase;
1083
	wrapper.callback = callback;
1084
	b2RayCastInput input;
1085
	input.maxFraction = 1.0f;
1086
	input.p1 = point1;
1087
	input.p2 = point2;
1088
	m_contactManager.m_broadPhase.RayCast(&wrapper, input);
1089
}
1090
1091
void b2World::DrawShape(b2Fixture* fixture, const b2Transform& xf, const b2Color& color)
1092
{
1093
	switch (fixture->GetType())
1094
	{
1095
	case b2Shape::e_circle:
1096
		{
1097
			b2CircleShape* circle = (b2CircleShape*)fixture->GetShape();
1098
1099
			b2Vec2 center = b2Mul(xf, circle->m_p);
1100
			float32 radius = circle->m_radius;
1101
			b2Vec2 axis = b2Mul(xf.q, b2Vec2(1.0f, 0.0f));
1102
1103
			g_debugDraw->DrawSolidCircle(center, radius, axis, color);
1104
		}
1105
		break;
1106
1107
	case b2Shape::e_edge:
1108
		{
1109
			b2EdgeShape* edge = (b2EdgeShape*)fixture->GetShape();
1110
			b2Vec2 v1 = b2Mul(xf, edge->m_vertex1);
1111
			b2Vec2 v2 = b2Mul(xf, edge->m_vertex2);
1112
			g_debugDraw->DrawSegment(v1, v2, color);
1113
		}
1114
		break;
1115
1116
	case b2Shape::e_chain:
1117
		{
1118
			b2ChainShape* chain = (b2ChainShape*)fixture->GetShape();
1119
			int32 count = chain->m_count;
1120
			const b2Vec2* vertices = chain->m_vertices;
1121
1122
			b2Vec2 v1 = b2Mul(xf, vertices[0]);
1123
			for (int32 i = 1; i < count; ++i)
1124
			{
1125
				b2Vec2 v2 = b2Mul(xf, vertices[i]);
1126
				g_debugDraw->DrawSegment(v1, v2, color);
1127
				g_debugDraw->DrawCircle(v1, 0.05f, color);
1128
				v1 = v2;
1129
			}
1130
		}
1131
		break;
1132
1133
	case b2Shape::e_polygon:
1134
		{
1135
			b2PolygonShape* poly = (b2PolygonShape*)fixture->GetShape();
1136
			int32 vertexCount = poly->m_count;
1137
			b2Assert(vertexCount <= b2_maxPolygonVertices);
1138
			b2Vec2 vertices[b2_maxPolygonVertices];
1139
1140
			for (int32 i = 0; i < vertexCount; ++i)
1141
			{
1142
				vertices[i] = b2Mul(xf, poly->m_vertices[i]);
1143
			}
1144
1145
			g_debugDraw->DrawSolidPolygon(vertices, vertexCount, color);
1146
		}
1147
		break;
1148
            
1149
    default:
1150
        break;
1151
	}
1152
}
1153
1154
void b2World::DrawJoint(b2Joint* joint)
1155
{
1156
	b2Body* bodyA = joint->GetBodyA();
1157
	b2Body* bodyB = joint->GetBodyB();
1158
	const b2Transform& xf1 = bodyA->GetTransform();
1159
	const b2Transform& xf2 = bodyB->GetTransform();
1160
	b2Vec2 x1 = xf1.p;
1161
	b2Vec2 x2 = xf2.p;
1162
	b2Vec2 p1 = joint->GetAnchorA();
1163
	b2Vec2 p2 = joint->GetAnchorB();
1164
1165
	b2Color color(0.5f, 0.8f, 0.8f);
1166
1167
	switch (joint->GetType())
1168
	{
1169
	case e_distanceJoint:
1170
		g_debugDraw->DrawSegment(p1, p2, color);
1171
		break;
1172
1173
	case e_pulleyJoint:
1174
		{
1175
			b2PulleyJoint* pulley = (b2PulleyJoint*)joint;
1176
			b2Vec2 s1 = pulley->GetGroundAnchorA();
1177
			b2Vec2 s2 = pulley->GetGroundAnchorB();
1178
			g_debugDraw->DrawSegment(s1, p1, color);
1179
			g_debugDraw->DrawSegment(s2, p2, color);
1180
			g_debugDraw->DrawSegment(s1, s2, color);
1181
		}
1182
		break;
1183
1184
	case e_mouseJoint:
1185
		// don't draw this
1186
		break;
1187
1188
	default:
1189
		g_debugDraw->DrawSegment(x1, p1, color);
1190
		g_debugDraw->DrawSegment(p1, p2, color);
1191
		g_debugDraw->DrawSegment(x2, p2, color);
1192
	}
1193
}
1194
1195
void b2World::DrawDebugData()
1196
{
1197
	if (g_debugDraw == NULL)
1198
	{
1199
		return;
1200
	}
1201
1202
	uint32 flags = g_debugDraw->GetFlags();
1203
1204
	if (flags & b2Draw::e_shapeBit)
1205
	{
1206
		for (b2Body* b = m_bodyList; b; b = b->GetNext())
1207
		{
1208
			const b2Transform& xf = b->GetTransform();
1209
			for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext())
1210
			{
1211
				if (b->IsActive() == false)
1212
				{
1213
					DrawShape(f, xf, b2Color(0.5f, 0.5f, 0.3f));
1214
				}
1215
				else if (b->GetType() == b2_staticBody)
1216
				{
1217
					DrawShape(f, xf, b2Color(0.5f, 0.9f, 0.5f));
1218
				}
1219
				else if (b->GetType() == b2_kinematicBody)
1220
				{
1221
					DrawShape(f, xf, b2Color(0.5f, 0.5f, 0.9f));
1222
				}
1223
				else if (b->IsAwake() == false)
1224
				{
1225
					DrawShape(f, xf, b2Color(0.6f, 0.6f, 0.6f));
1226
				}
1227
				else
1228
				{
1229
					DrawShape(f, xf, b2Color(0.9f, 0.7f, 0.7f));
1230
				}
1231
			}
1232
		}
1233
	}
1234
1235
	if (flags & b2Draw::e_jointBit)
1236
	{
1237
		for (b2Joint* j = m_jointList; j; j = j->GetNext())
1238
		{
1239
			DrawJoint(j);
1240
		}
1241
	}
1242
1243
	if (flags & b2Draw::e_pairBit)
1244
	{
1245
		b2Color color(0.3f, 0.9f, 0.9f);
1246
		for (b2Contact* c = m_contactManager.m_contactList; c; c = c->GetNext())
1247
		{
1248
			//b2Fixture* fixtureA = c->GetFixtureA();
1249
			//b2Fixture* fixtureB = c->GetFixtureB();
1250
1251
			//b2Vec2 cA = fixtureA->GetAABB().GetCenter();
1252
			//b2Vec2 cB = fixtureB->GetAABB().GetCenter();
1253
1254
			//g_debugDraw->DrawSegment(cA, cB, color);
1255
		}
1256
	}
1257
1258
	if (flags & b2Draw::e_aabbBit)
1259
	{
1260
		b2Color color(0.9f, 0.3f, 0.9f);
1261
		b2BroadPhase* bp = &m_contactManager.m_broadPhase;
1262
1263
		for (b2Body* b = m_bodyList; b; b = b->GetNext())
1264
		{
1265
			if (b->IsActive() == false)
1266
			{
1267
				continue;
1268
			}
1269
1270
			for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext())
1271
			{
1272
				for (int32 i = 0; i < f->m_proxyCount; ++i)
1273
				{
1274
					b2FixtureProxy* proxy = f->m_proxies + i;
1275
					b2AABB aabb = bp->GetFatAABB(proxy->proxyId);
1276
					b2Vec2 vs[4];
1277
					vs[0].Set(aabb.lowerBound.x, aabb.lowerBound.y);
1278
					vs[1].Set(aabb.upperBound.x, aabb.lowerBound.y);
1279
					vs[2].Set(aabb.upperBound.x, aabb.upperBound.y);
1280
					vs[3].Set(aabb.lowerBound.x, aabb.upperBound.y);
1281
1282
					g_debugDraw->DrawPolygon(vs, 4, color);
1283
				}
1284
			}
1285
		}
1286
	}
1287
1288
	if (flags & b2Draw::e_centerOfMassBit)
1289
	{
1290
		for (b2Body* b = m_bodyList; b; b = b->GetNext())
1291
		{
1292
			b2Transform xf = b->GetTransform();
1293
			xf.p = b->GetWorldCenter();
1294
			g_debugDraw->DrawTransform(xf);
1295
		}
1296
	}
1297
}
1298
1299
int32 b2World::GetProxyCount() const
1300
{
1301
	return m_contactManager.m_broadPhase.GetProxyCount();
1302
}
1303
1304
int32 b2World::GetTreeHeight() const
1305
{
1306
	return m_contactManager.m_broadPhase.GetTreeHeight();
1307
}
1308
1309
int32 b2World::GetTreeBalance() const
1310
{
1311
	return m_contactManager.m_broadPhase.GetTreeBalance();
1312
}
1313
1314
float32 b2World::GetTreeQuality() const
1315
{
1316
	return m_contactManager.m_broadPhase.GetTreeQuality();
1317
}
1318
1319
void b2World::ShiftOrigin(const b2Vec2& newOrigin)
1320
{
1321
	b2Assert((m_flags & e_locked) == 0);
1322
	if ((m_flags & e_locked) == e_locked)
1323
	{
1324
		return;
1325
	}
1326
1327
	for (b2Body* b = m_bodyList; b; b = b->m_next)
1328
	{
1329
		b->m_xf.p -= newOrigin;
1330
		b->m_sweep.c0 -= newOrigin;
1331
		b->m_sweep.c -= newOrigin;
1332
	}
1333
1334
	for (b2Joint* j = m_jointList; j; j = j->m_next)
1335
	{
1336
		j->ShiftOrigin(newOrigin);
1337
	}
1338
1339
	m_contactManager.m_broadPhase.ShiftOrigin(newOrigin);
1340
}
1341
1342
void b2World::Dump()
1343
{
1344
	if ((m_flags & e_locked) == e_locked)
1345
	{
1346
		return;
1347
	}
1348
1349
	b2Log("b2Vec2 g(%.15lef, %.15lef);\n", m_gravity.x, m_gravity.y);
1350
	b2Log("m_world->SetGravity(g);\n");
1351
1352
	b2Log("b2Body** bodies = (b2Body**)b2Alloc(%d * sizeof(b2Body*));\n", m_bodyCount);
1353
	b2Log("b2Joint** joints = (b2Joint**)b2Alloc(%d * sizeof(b2Joint*));\n", m_jointCount);
1354
	int32 i = 0;
1355
	for (b2Body* b = m_bodyList; b; b = b->m_next)
1356
	{
1357
		b->m_islandIndex = i;
1358
		b->Dump();
1359
		++i;
1360
	}
1361
1362
	i = 0;
1363
	for (b2Joint* j = m_jointList; j; j = j->m_next)
1364
	{
1365
		j->m_index = i;
1366
		++i;
1367
	}
1368
1369
	// First pass on joints, skip gear joints.
1370
	for (b2Joint* j = m_jointList; j; j = j->m_next)
1371
	{
1372
		if (j->m_type == e_gearJoint)
1373
		{
1374
			continue;
1375
		}
1376
1377
		b2Log("{\n");
1378
		j->Dump();
1379
		b2Log("}\n");
1380
	}
1381
1382
	// Second pass on joints, only gear joints.
1383
	for (b2Joint* j = m_jointList; j; j = j->m_next)
1384
	{
1385
		if (j->m_type != e_gearJoint)
1386
		{
1387
			continue;
1388
		}
1389
1390
		b2Log("{\n");
1391
		j->Dump();
1392
		b2Log("}\n");
1393
	}
1394
1395
	b2Log("b2Free(joints);\n");
1396
	b2Log("b2Free(bodies);\n");
1397
	b2Log("joints = NULL;\n");
1398
	b2Log("bodies = NULL;\n");
1399
}