File indexing completed on 2025-08-03 03:50:01
0001 /* 0002 * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com 0003 * 0004 * This software is provided 'as-is', without any express or implied 0005 * warranty. In no event will the authors be held liable for any damages 0006 * arising from the use of this software. 0007 * Permission is granted to anyone to use this software for any purpose, 0008 * including commercial applications, and to alter it and redistribute it 0009 * freely, subject to the following restrictions: 0010 * 1. The origin of this software must not be misrepresented; you must not 0011 * claim that you wrote the original software. If you use this software 0012 * in a product, an acknowledgment in the product documentation would be 0013 * appreciated but is not required. 0014 * 2. Altered source versions must be plainly marked as such, and must not be 0015 * misrepresented as being the original software. 0016 * 3. This notice may not be removed or altered from any source distribution. 0017 */ 0018 0019 #include <Box2D/Dynamics/b2World.h> 0020 #include <Box2D/Dynamics/b2Body.h> 0021 #include <Box2D/Dynamics/b2Fixture.h> 0022 #include <Box2D/Dynamics/b2Island.h> 0023 #include <Box2D/Dynamics/Joints/b2PulleyJoint.h> 0024 #include <Box2D/Dynamics/Contacts/b2Contact.h> 0025 #include <Box2D/Dynamics/Contacts/b2ContactSolver.h> 0026 #include <Box2D/Collision/b2Collision.h> 0027 #include <Box2D/Collision/b2BroadPhase.h> 0028 #include <Box2D/Collision/Shapes/b2CircleShape.h> 0029 #include <Box2D/Collision/Shapes/b2EdgeShape.h> 0030 #include <Box2D/Collision/Shapes/b2LoopShape.h> 0031 #include <Box2D/Collision/Shapes/b2PolygonShape.h> 0032 #include <Box2D/Collision/b2TimeOfImpact.h> 0033 #include <new> 0034 0035 b2World::b2World(const b2Vec2& gravity, bool doSleep) 0036 { 0037 m_destructionListener = NULL; 0038 m_debugDraw = NULL; 0039 0040 m_bodyList = NULL; 0041 m_jointList = NULL; 0042 0043 m_bodyCount = 0; 0044 m_jointCount = 0; 0045 0046 m_warmStarting = true; 0047 m_continuousPhysics = true; 0048 m_subStepping = false; 0049 0050 m_stepComplete = true; 0051 0052 m_allowSleep = doSleep; 0053 m_gravity = gravity; 0054 0055 m_flags = e_clearForces; 0056 0057 m_inv_dt0 = 0.0f; 0058 0059 m_contactManager.m_allocator = &m_blockAllocator; 0060 } 0061 0062 b2World::~b2World() 0063 { 0064 // Some shapes allocate using b2Alloc. 0065 b2Body* b = m_bodyList; 0066 while (b) 0067 { 0068 b2Body* bNext = b->m_next; 0069 0070 b2Fixture* f = b->m_fixtureList; 0071 while (f) 0072 { 0073 b2Fixture* fNext = f->m_next; 0074 f->m_proxyCount = 0; 0075 f->Destroy(&m_blockAllocator); 0076 f = fNext; 0077 } 0078 0079 b = bNext; 0080 } 0081 } 0082 0083 void b2World::SetDestructionListener(b2DestructionListener* listener) 0084 { 0085 m_destructionListener = listener; 0086 } 0087 0088 void b2World::SetContactFilter(b2ContactFilter* filter) 0089 { 0090 m_contactManager.m_contactFilter = filter; 0091 } 0092 0093 void b2World::SetContactListener(b2ContactListener* listener) 0094 { 0095 m_contactManager.m_contactListener = listener; 0096 } 0097 0098 void b2World::SetDebugDraw(b2DebugDraw* debugDraw) 0099 { 0100 m_debugDraw = debugDraw; 0101 } 0102 0103 b2Body* b2World::CreateBody(const b2BodyDef* def) 0104 { 0105 b2Assert(IsLocked() == false); 0106 if (IsLocked()) 0107 { 0108 return NULL; 0109 } 0110 0111 void* mem = m_blockAllocator.Allocate(sizeof(b2Body)); 0112 b2Body* b = new (mem) b2Body(def, this); 0113 0114 // Add to world doubly linked list. 0115 b->m_prev = NULL; 0116 b->m_next = m_bodyList; 0117 if (m_bodyList) 0118 { 0119 m_bodyList->m_prev = b; 0120 } 0121 m_bodyList = b; 0122 ++m_bodyCount; 0123 0124 return b; 0125 } 0126 0127 void b2World::DestroyBody(b2Body* b) 0128 { 0129 b2Assert(m_bodyCount > 0); 0130 b2Assert(IsLocked() == false); 0131 if (IsLocked()) 0132 { 0133 return; 0134 } 0135 0136 // Delete the attached joints. 0137 b2JointEdge* je = b->m_jointList; 0138 while (je) 0139 { 0140 b2JointEdge* je0 = je; 0141 je = je->next; 0142 0143 if (m_destructionListener) 0144 { 0145 m_destructionListener->SayGoodbye(je0->joint); 0146 } 0147 0148 DestroyJoint(je0->joint); 0149 0150 b->m_jointList = je; 0151 } 0152 b->m_jointList = NULL; 0153 0154 // Delete the attached contacts. 0155 b2ContactEdge* ce = b->m_contactList; 0156 while (ce) 0157 { 0158 b2ContactEdge* ce0 = ce; 0159 ce = ce->next; 0160 m_contactManager.Destroy(ce0->contact); 0161 } 0162 b->m_contactList = NULL; 0163 0164 // Delete the attached fixtures. This destroys broad-phase proxies. 0165 b2Fixture* f = b->m_fixtureList; 0166 while (f) 0167 { 0168 b2Fixture* f0 = f; 0169 f = f->m_next; 0170 0171 if (m_destructionListener) 0172 { 0173 m_destructionListener->SayGoodbye(f0); 0174 } 0175 0176 f0->DestroyProxies(&m_contactManager.m_broadPhase); 0177 f0->Destroy(&m_blockAllocator); 0178 f0->~b2Fixture(); 0179 m_blockAllocator.Free(f0, sizeof(b2Fixture)); 0180 0181 b->m_fixtureList = f; 0182 b->m_fixtureCount -= 1; 0183 } 0184 b->m_fixtureList = NULL; 0185 b->m_fixtureCount = 0; 0186 0187 // Remove world body list. 0188 if (b->m_prev) 0189 { 0190 b->m_prev->m_next = b->m_next; 0191 } 0192 0193 if (b->m_next) 0194 { 0195 b->m_next->m_prev = b->m_prev; 0196 } 0197 0198 if (b == m_bodyList) 0199 { 0200 m_bodyList = b->m_next; 0201 } 0202 0203 --m_bodyCount; 0204 b->~b2Body(); 0205 m_blockAllocator.Free(b, sizeof(b2Body)); 0206 } 0207 0208 b2Joint* b2World::CreateJoint(const b2JointDef* def) 0209 { 0210 b2Assert(IsLocked() == false); 0211 if (IsLocked()) 0212 { 0213 return NULL; 0214 } 0215 0216 b2Joint* j = b2Joint::Create(def, &m_blockAllocator); 0217 0218 // Connect to the world list. 0219 j->m_prev = NULL; 0220 j->m_next = m_jointList; 0221 if (m_jointList) 0222 { 0223 m_jointList->m_prev = j; 0224 } 0225 m_jointList = j; 0226 ++m_jointCount; 0227 0228 // Connect to the bodies' doubly linked lists. 0229 j->m_edgeA.joint = j; 0230 j->m_edgeA.other = j->m_bodyB; 0231 j->m_edgeA.prev = NULL; 0232 j->m_edgeA.next = j->m_bodyA->m_jointList; 0233 if (j->m_bodyA->m_jointList) j->m_bodyA->m_jointList->prev = &j->m_edgeA; 0234 j->m_bodyA->m_jointList = &j->m_edgeA; 0235 0236 j->m_edgeB.joint = j; 0237 j->m_edgeB.other = j->m_bodyA; 0238 j->m_edgeB.prev = NULL; 0239 j->m_edgeB.next = j->m_bodyB->m_jointList; 0240 if (j->m_bodyB->m_jointList) j->m_bodyB->m_jointList->prev = &j->m_edgeB; 0241 j->m_bodyB->m_jointList = &j->m_edgeB; 0242 0243 b2Body* bodyA = def->bodyA; 0244 b2Body* bodyB = def->bodyB; 0245 0246 // If the joint prevents collisions, then flag any contacts for filtering. 0247 if (def->collideConnected == false) 0248 { 0249 b2ContactEdge* edge = bodyB->GetContactList(); 0250 while (edge) 0251 { 0252 if (edge->other == bodyA) 0253 { 0254 // Flag the contact for filtering at the next time step (where either 0255 // body is awake). 0256 edge->contact->FlagForFiltering(); 0257 } 0258 0259 edge = edge->next; 0260 } 0261 } 0262 0263 // Note: creating a joint doesn't wake the bodies. 0264 0265 return j; 0266 } 0267 0268 void b2World::DestroyJoint(b2Joint* j) 0269 { 0270 b2Assert(IsLocked() == false); 0271 if (IsLocked()) 0272 { 0273 return; 0274 } 0275 0276 bool collideConnected = j->m_collideConnected; 0277 0278 // Remove from the doubly linked list. 0279 if (j->m_prev) 0280 { 0281 j->m_prev->m_next = j->m_next; 0282 } 0283 0284 if (j->m_next) 0285 { 0286 j->m_next->m_prev = j->m_prev; 0287 } 0288 0289 if (j == m_jointList) 0290 { 0291 m_jointList = j->m_next; 0292 } 0293 0294 // Disconnect from island graph. 0295 b2Body* bodyA = j->m_bodyA; 0296 b2Body* bodyB = j->m_bodyB; 0297 0298 // Wake up connected bodies. 0299 bodyA->SetAwake(true); 0300 bodyB->SetAwake(true); 0301 0302 // Remove from body 1. 0303 if (j->m_edgeA.prev) 0304 { 0305 j->m_edgeA.prev->next = j->m_edgeA.next; 0306 } 0307 0308 if (j->m_edgeA.next) 0309 { 0310 j->m_edgeA.next->prev = j->m_edgeA.prev; 0311 } 0312 0313 if (&j->m_edgeA == bodyA->m_jointList) 0314 { 0315 bodyA->m_jointList = j->m_edgeA.next; 0316 } 0317 0318 j->m_edgeA.prev = NULL; 0319 j->m_edgeA.next = NULL; 0320 0321 // Remove from body 2 0322 if (j->m_edgeB.prev) 0323 { 0324 j->m_edgeB.prev->next = j->m_edgeB.next; 0325 } 0326 0327 if (j->m_edgeB.next) 0328 { 0329 j->m_edgeB.next->prev = j->m_edgeB.prev; 0330 } 0331 0332 if (&j->m_edgeB == bodyB->m_jointList) 0333 { 0334 bodyB->m_jointList = j->m_edgeB.next; 0335 } 0336 0337 j->m_edgeB.prev = NULL; 0338 j->m_edgeB.next = NULL; 0339 0340 b2Joint::Destroy(j, &m_blockAllocator); 0341 0342 b2Assert(m_jointCount > 0); 0343 --m_jointCount; 0344 0345 // If the joint prevents collisions, then flag any contacts for filtering. 0346 if (collideConnected == false) 0347 { 0348 b2ContactEdge* edge = bodyB->GetContactList(); 0349 while (edge) 0350 { 0351 if (edge->other == bodyA) 0352 { 0353 // Flag the contact for filtering at the next time step (where either 0354 // body is awake). 0355 edge->contact->FlagForFiltering(); 0356 } 0357 0358 edge = edge->next; 0359 } 0360 } 0361 } 0362 0363 // Find islands, integrate and solve constraints, solve position constraints 0364 void b2World::Solve(const b2TimeStep& step) 0365 { 0366 // Size the island for the worst case. 0367 b2Island island(m_bodyCount, 0368 m_contactManager.m_contactCount, 0369 m_jointCount, 0370 &m_stackAllocator, 0371 m_contactManager.m_contactListener); 0372 0373 // Clear all the island flags. 0374 for (b2Body* b = m_bodyList; b; b = b->m_next) 0375 { 0376 b->m_flags &= ~b2Body::e_islandFlag; 0377 } 0378 for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) 0379 { 0380 c->m_flags &= ~b2Contact::e_islandFlag; 0381 } 0382 for (b2Joint* j = m_jointList; j; j = j->m_next) 0383 { 0384 j->m_islandFlag = false; 0385 } 0386 0387 // Build and simulate all awake islands. 0388 int32 stackSize = m_bodyCount; 0389 b2Body** stack = (b2Body**)m_stackAllocator.Allocate(stackSize * sizeof(b2Body*)); 0390 for (b2Body* seed = m_bodyList; seed; seed = seed->m_next) 0391 { 0392 if (seed->m_flags & b2Body::e_islandFlag) 0393 { 0394 continue; 0395 } 0396 0397 if (seed->IsAwake() == false || seed->IsActive() == false) 0398 { 0399 continue; 0400 } 0401 0402 // The seed can be dynamic or kinematic. 0403 if (seed->GetType() == b2_staticBody) 0404 { 0405 continue; 0406 } 0407 0408 // Reset island and stack. 0409 island.Clear(); 0410 int32 stackCount = 0; 0411 stack[stackCount++] = seed; 0412 seed->m_flags |= b2Body::e_islandFlag; 0413 0414 // Perform a depth first search (DFS) on the constraint graph. 0415 while (stackCount > 0) 0416 { 0417 // Grab the next body off the stack and add it to the island. 0418 b2Body* b = stack[--stackCount]; 0419 b2Assert(b->IsActive() == true); 0420 island.Add(b); 0421 0422 // Make sure the body is awake. 0423 b->SetAwake(true); 0424 0425 // To keep islands as small as possible, we don't 0426 // propagate islands across static bodies. 0427 if (b->GetType() == b2_staticBody) 0428 { 0429 continue; 0430 } 0431 0432 // Search all contacts connected to this body. 0433 for (b2ContactEdge* ce = b->m_contactList; ce; ce = ce->next) 0434 { 0435 b2Contact* contact = ce->contact; 0436 0437 // Has this contact already been added to an island? 0438 if (contact->m_flags & b2Contact::e_islandFlag) 0439 { 0440 continue; 0441 } 0442 0443 // Is this contact solid and touching? 0444 if (contact->IsEnabled() == false || 0445 contact->IsTouching() == false) 0446 { 0447 continue; 0448 } 0449 0450 // Skip sensors. 0451 bool sensorA = contact->m_fixtureA->m_isSensor; 0452 bool sensorB = contact->m_fixtureB->m_isSensor; 0453 if (sensorA || sensorB) 0454 { 0455 continue; 0456 } 0457 0458 island.Add(contact); 0459 contact->m_flags |= b2Contact::e_islandFlag; 0460 0461 b2Body* other = ce->other; 0462 0463 // Was the other body already added to this island? 0464 if (other->m_flags & b2Body::e_islandFlag) 0465 { 0466 continue; 0467 } 0468 0469 b2Assert(stackCount < stackSize); 0470 stack[stackCount++] = other; 0471 other->m_flags |= b2Body::e_islandFlag; 0472 } 0473 0474 // Search all joints connect to this body. 0475 for (b2JointEdge* je = b->m_jointList; je; je = je->next) 0476 { 0477 if (je->joint->m_islandFlag == true) 0478 { 0479 continue; 0480 } 0481 0482 b2Body* other = je->other; 0483 0484 // Don't simulate joints connected to inactive bodies. 0485 if (other->IsActive() == false) 0486 { 0487 continue; 0488 } 0489 0490 island.Add(je->joint); 0491 je->joint->m_islandFlag = true; 0492 0493 if (other->m_flags & b2Body::e_islandFlag) 0494 { 0495 continue; 0496 } 0497 0498 b2Assert(stackCount < stackSize); 0499 stack[stackCount++] = other; 0500 other->m_flags |= b2Body::e_islandFlag; 0501 } 0502 } 0503 0504 island.Solve(step, m_gravity, m_allowSleep); 0505 0506 // Post solve cleanup. 0507 for (int32 i = 0; i < island.m_bodyCount; ++i) 0508 { 0509 // Allow static bodies to participate in other islands. 0510 b2Body* b = island.m_bodies[i]; 0511 if (b->GetType() == b2_staticBody) 0512 { 0513 b->m_flags &= ~b2Body::e_islandFlag; 0514 } 0515 } 0516 } 0517 0518 m_stackAllocator.Free(stack); 0519 0520 // Synchronize fixtures, check for out of range bodies. 0521 for (b2Body* b = m_bodyList; b; b = b->GetNext()) 0522 { 0523 // If a body was not in an island then it did not move. 0524 if ((b->m_flags & b2Body::e_islandFlag) == 0) 0525 { 0526 continue; 0527 } 0528 0529 if (b->GetType() == b2_staticBody) 0530 { 0531 continue; 0532 } 0533 0534 // Update fixtures (for broad-phase). 0535 b->SynchronizeFixtures(); 0536 } 0537 0538 // Look for new contacts. 0539 m_contactManager.FindNewContacts(); 0540 } 0541 0542 // Find TOI contacts and solve them. 0543 void b2World::SolveTOI(const b2TimeStep& step) 0544 { 0545 b2Island island(2 * b2_maxTOIContacts, b2_maxTOIContacts, 0, &m_stackAllocator, m_contactManager.m_contactListener); 0546 0547 if (m_stepComplete) 0548 { 0549 for (b2Body* b = m_bodyList; b; b = b->m_next) 0550 { 0551 b->m_flags &= ~b2Body::e_islandFlag; 0552 b->m_sweep.alpha0 = 0.0f; 0553 } 0554 0555 for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) 0556 { 0557 // Invalidate TOI 0558 c->m_flags &= ~(b2Contact::e_toiFlag | b2Contact::e_islandFlag); 0559 c->m_toiCount = 0; 0560 c->m_toi = 1.0f; 0561 } 0562 } 0563 0564 // Find TOI events and solve them. 0565 for (;;) 0566 { 0567 // Find the first TOI. 0568 b2Contact* minContact = NULL; 0569 qreal minAlpha = 1.0f; 0570 0571 for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) 0572 { 0573 // Is this contact disabled? 0574 if (c->IsEnabled() == false) 0575 { 0576 continue; 0577 } 0578 0579 // Prevent excessive sub-stepping. 0580 if (c->m_toiCount > b2_maxSubSteps) 0581 { 0582 continue; 0583 } 0584 0585 qreal alpha = 1.0f; 0586 if (c->m_flags & b2Contact::e_toiFlag) 0587 { 0588 // This contact has a valid cached TOI. 0589 alpha = c->m_toi; 0590 } 0591 else 0592 { 0593 b2Fixture* fA = c->GetFixtureA(); 0594 b2Fixture* fB = c->GetFixtureB(); 0595 0596 // Is there a sensor? 0597 if (fA->IsSensor() || fB->IsSensor()) 0598 { 0599 continue; 0600 } 0601 0602 b2Body* bA = fA->GetBody(); 0603 b2Body* bB = fB->GetBody(); 0604 0605 b2BodyType typeA = bA->GetType(); 0606 b2BodyType typeB = bB->GetType(); 0607 b2Assert(typeA == b2_dynamicBody || typeB == b2_dynamicBody); 0608 0609 bool awakeA = bA->IsAwake() && typeA != b2_staticBody; 0610 bool awakeB = bB->IsAwake() && typeB != b2_staticBody; 0611 0612 // Is at least one body awake? 0613 if (awakeA == false && awakeB == false) 0614 { 0615 continue; 0616 } 0617 0618 bool collideA = bA->IsBullet() || typeA != b2_dynamicBody; 0619 bool collideB = bB->IsBullet() || typeB != b2_dynamicBody; 0620 0621 // Are these two non-bullet dynamic bodies? 0622 if (collideA == false && collideB == false) 0623 { 0624 continue; 0625 } 0626 0627 // Compute the TOI for this contact. 0628 // Put the sweeps onto the same time interval. 0629 qreal alpha0 = bA->m_sweep.alpha0; 0630 0631 if (bA->m_sweep.alpha0 < bB->m_sweep.alpha0) 0632 { 0633 alpha0 = bB->m_sweep.alpha0; 0634 bA->m_sweep.Advance(alpha0); 0635 } 0636 else if (bB->m_sweep.alpha0 < bA->m_sweep.alpha0) 0637 { 0638 alpha0 = bA->m_sweep.alpha0; 0639 bB->m_sweep.Advance(alpha0); 0640 } 0641 0642 b2Assert(alpha0 < 1.0f); 0643 0644 int32 indexA = c->GetChildIndexA(); 0645 int32 indexB = c->GetChildIndexB(); 0646 0647 // Compute the time of impact in interval [0, minTOI] 0648 b2TOIInput input; 0649 input.proxyA.Set(fA->GetShape(), indexA); 0650 input.proxyB.Set(fB->GetShape(), indexB); 0651 input.sweepA = bA->m_sweep; 0652 input.sweepB = bB->m_sweep; 0653 input.tMax = 1.0f; 0654 0655 b2TOIOutput output; 0656 b2TimeOfImpact(&output, &input); 0657 0658 // Beta is the fraction of the remaining portion of the . 0659 qreal beta = output.t; 0660 if (output.state == b2TOIOutput::e_touching) 0661 { 0662 alpha = b2Min(alpha0 + (1.0f - alpha0) * beta, 1.0f); 0663 } 0664 else 0665 { 0666 alpha = 1.0f; 0667 } 0668 0669 c->m_toi = alpha; 0670 c->m_flags |= b2Contact::e_toiFlag; 0671 } 0672 0673 if (alpha < minAlpha) 0674 { 0675 // This is the minimum TOI found so far. 0676 minContact = c; 0677 minAlpha = alpha; 0678 } 0679 } 0680 0681 if (minContact == NULL || 1.0f - 10.0f * b2_epsilon < minAlpha) 0682 { 0683 // No more TOI events. Done! 0684 m_stepComplete = true; 0685 break; 0686 } 0687 0688 // Advance the bodies to the TOI. 0689 b2Fixture* fA = minContact->GetFixtureA(); 0690 b2Fixture* fB = minContact->GetFixtureB(); 0691 b2Body* bA = fA->GetBody(); 0692 b2Body* bB = fB->GetBody(); 0693 0694 b2Sweep backup1 = bA->m_sweep; 0695 b2Sweep backup2 = bB->m_sweep; 0696 0697 bA->Advance(minAlpha); 0698 bB->Advance(minAlpha); 0699 0700 // The TOI contact likely has some new contact points. 0701 minContact->Update(m_contactManager.m_contactListener); 0702 minContact->m_flags &= ~b2Contact::e_toiFlag; 0703 ++minContact->m_toiCount; 0704 0705 // Is the contact solid? 0706 if (minContact->IsEnabled() == false || minContact->IsTouching() == false) 0707 { 0708 // Restore the sweeps. 0709 minContact->SetEnabled(false); 0710 bA->m_sweep = backup1; 0711 bB->m_sweep = backup2; 0712 bA->SynchronizeTransform(); 0713 bB->SynchronizeTransform(); 0714 continue; 0715 } 0716 0717 bA->SetAwake(true); 0718 bB->SetAwake(true); 0719 0720 // Build the island 0721 island.Clear(); 0722 island.Add(bA); 0723 island.Add(bB); 0724 island.Add(minContact); 0725 0726 bA->m_flags |= b2Body::e_islandFlag; 0727 bB->m_flags |= b2Body::e_islandFlag; 0728 minContact->m_flags |= b2Contact::e_islandFlag; 0729 0730 // Get contacts on bodyA and bodyB. 0731 b2Body* bodies[2] = {bA, bB}; 0732 for (int32 i = 0; i < 2; ++i) 0733 { 0734 b2Body* body = bodies[i]; 0735 if (body->m_type == b2_dynamicBody) 0736 { 0737 for (b2ContactEdge* ce = body->m_contactList; ce && island.m_bodyCount < b2_maxTOIContacts; ce = ce->next) 0738 { 0739 b2Contact* contact = ce->contact; 0740 0741 // Has this contact already been added to the island? 0742 if (contact->m_flags & b2Contact::e_islandFlag) 0743 { 0744 continue; 0745 } 0746 0747 // Only add static, kinematic, or bullet bodies. 0748 b2Body* other = ce->other; 0749 if (other->m_type == b2_dynamicBody && 0750 body->IsBullet() == false && other->IsBullet() == false) 0751 { 0752 continue; 0753 } 0754 0755 // Skip sensors. 0756 bool sensorA = contact->m_fixtureA->m_isSensor; 0757 bool sensorB = contact->m_fixtureB->m_isSensor; 0758 if (sensorA || sensorB) 0759 { 0760 continue; 0761 } 0762 0763 // Tentatively advance the body to the TOI. 0764 b2Sweep backup = other->m_sweep; 0765 if ((other->m_flags & b2Body::e_islandFlag) == 0) 0766 { 0767 other->Advance(minAlpha); 0768 } 0769 0770 // Update the contact points 0771 contact->Update(m_contactManager.m_contactListener); 0772 0773 // Was the contact disabled by the user? 0774 if (contact->IsEnabled() == false) 0775 { 0776 other->m_sweep = backup; 0777 other->SynchronizeTransform(); 0778 continue; 0779 } 0780 0781 // Are there contact points? 0782 if (contact->IsTouching() == false) 0783 { 0784 other->m_sweep = backup; 0785 other->SynchronizeTransform(); 0786 continue; 0787 } 0788 0789 // Add the contact to the island 0790 contact->m_flags |= b2Contact::e_islandFlag; 0791 island.Add(contact); 0792 0793 // Has the other body already been added to the island? 0794 if (other->m_flags & b2Body::e_islandFlag) 0795 { 0796 continue; 0797 } 0798 0799 // Add the other body to the island. 0800 other->m_flags |= b2Body::e_islandFlag; 0801 0802 if (other->m_type != b2_staticBody) 0803 { 0804 other->SetAwake(true); 0805 } 0806 0807 island.Add(other); 0808 } 0809 } 0810 } 0811 0812 b2TimeStep subStep; 0813 subStep.dt = (1.0f - minAlpha) * step.dt; 0814 subStep.inv_dt = 1.0f / subStep.dt; 0815 subStep.dtRatio = 1.0f; 0816 subStep.positionIterations = 20; 0817 subStep.velocityIterations = step.velocityIterations; 0818 subStep.warmStarting = false; 0819 island.SolveTOI(subStep, bA, bB); 0820 0821 // Reset island flags and synchronize broad-phase proxies. 0822 for (int32 i = 0; i < island.m_bodyCount; ++i) 0823 { 0824 b2Body* body = island.m_bodies[i]; 0825 body->m_flags &= ~b2Body::e_islandFlag; 0826 0827 if (body->m_type != b2_dynamicBody) 0828 { 0829 continue; 0830 } 0831 0832 body->SynchronizeFixtures(); 0833 0834 // Invalidate all contact TOIs on this displaced body. 0835 for (b2ContactEdge* ce = body->m_contactList; ce; ce = ce->next) 0836 { 0837 ce->contact->m_flags &= ~(b2Contact::e_toiFlag | b2Contact::e_islandFlag); 0838 } 0839 } 0840 0841 // Commit fixture proxy movements to the broad-phase so that new contacts are created. 0842 // Also, some contacts can be destroyed. 0843 m_contactManager.FindNewContacts(); 0844 0845 if (m_subStepping) 0846 { 0847 m_stepComplete = false; 0848 break; 0849 } 0850 } 0851 } 0852 0853 void b2World::Step(qreal dt, int32 velocityIterations, int32 positionIterations) 0854 { 0855 // If new fixtures were added, we need to find the new contacts. 0856 if (m_flags & e_newFixture) 0857 { 0858 m_contactManager.FindNewContacts(); 0859 m_flags &= ~e_newFixture; 0860 } 0861 0862 m_flags |= e_locked; 0863 0864 b2TimeStep step; 0865 step.dt = dt; 0866 step.velocityIterations = velocityIterations; 0867 step.positionIterations = positionIterations; 0868 if (dt > 0.0f) 0869 { 0870 step.inv_dt = 1.0f / dt; 0871 } 0872 else 0873 { 0874 step.inv_dt = 0.0f; 0875 } 0876 0877 step.dtRatio = m_inv_dt0 * dt; 0878 0879 step.warmStarting = m_warmStarting; 0880 0881 // Update contacts. This is where some contacts are destroyed. 0882 m_contactManager.Collide(); 0883 0884 // Integrate velocities, solve velocity constraints, and integrate positions. 0885 if (m_stepComplete && step.dt > 0.0f) 0886 { 0887 Solve(step); 0888 } 0889 0890 // Handle TOI events. 0891 if (m_continuousPhysics && step.dt > 0.0f) 0892 { 0893 SolveTOI(step); 0894 } 0895 0896 if (step.dt > 0.0f) 0897 { 0898 m_inv_dt0 = step.inv_dt; 0899 } 0900 0901 if (m_flags & e_clearForces) 0902 { 0903 ClearForces(); 0904 } 0905 0906 m_flags &= ~e_locked; 0907 } 0908 0909 void b2World::ClearForces() 0910 { 0911 for (b2Body* body = m_bodyList; body; body = body->GetNext()) 0912 { 0913 body->m_force.SetZero(); 0914 body->m_torque = 0.0f; 0915 } 0916 } 0917 0918 struct b2WorldQueryWrapper 0919 { 0920 bool QueryCallback(int32 proxyId) 0921 { 0922 b2FixtureProxy* proxy = (b2FixtureProxy*)broadPhase->GetUserData(proxyId); 0923 return callback->ReportFixture(proxy->fixture); 0924 } 0925 0926 const b2BroadPhase* broadPhase; 0927 b2QueryCallback* callback; 0928 }; 0929 0930 void b2World::QueryAABB(b2QueryCallback* callback, const b2AABB& aabb) const 0931 { 0932 b2WorldQueryWrapper wrapper; 0933 wrapper.broadPhase = &m_contactManager.m_broadPhase; 0934 wrapper.callback = callback; 0935 m_contactManager.m_broadPhase.Query(&wrapper, aabb); 0936 } 0937 0938 struct b2WorldRayCastWrapper 0939 { 0940 qreal RayCastCallback(const b2RayCastInput& input, int32 proxyId) 0941 { 0942 void* userData = broadPhase->GetUserData(proxyId); 0943 b2FixtureProxy* proxy = (b2FixtureProxy*)userData; 0944 b2Fixture* fixture = proxy->fixture; 0945 int32 index = proxy->childIndex; 0946 b2RayCastOutput output; 0947 bool hit = fixture->RayCast(&output, input, index); 0948 0949 if (hit) 0950 { 0951 qreal fraction = output.fraction; 0952 b2Vec2 point = (1.0f - fraction) * input.p1 + fraction * input.p2; 0953 return callback->ReportFixture(fixture, point, output.normal, fraction); 0954 } 0955 0956 return input.maxFraction; 0957 } 0958 0959 const b2BroadPhase* broadPhase; 0960 b2RayCastCallback* callback; 0961 }; 0962 0963 void b2World::RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const 0964 { 0965 b2WorldRayCastWrapper wrapper; 0966 wrapper.broadPhase = &m_contactManager.m_broadPhase; 0967 wrapper.callback = callback; 0968 b2RayCastInput input; 0969 input.maxFraction = 1.0f; 0970 input.p1 = point1; 0971 input.p2 = point2; 0972 m_contactManager.m_broadPhase.RayCast(&wrapper, input); 0973 } 0974 0975 void b2World::DrawShape(b2Fixture* fixture, const b2Transform& xf, const b2Color& color) 0976 { 0977 switch (fixture->GetType()) 0978 { 0979 case b2Shape::e_circle: 0980 { 0981 b2CircleShape* circle = (b2CircleShape*)fixture->GetShape(); 0982 0983 b2Vec2 center = b2Mul(xf, circle->m_p); 0984 qreal radius = circle->m_radius; 0985 b2Vec2 axis = xf.R.col1; 0986 0987 m_debugDraw->DrawSolidCircle(center, radius, axis, color); 0988 } 0989 break; 0990 0991 case b2Shape::e_edge: 0992 { 0993 b2EdgeShape* edge = (b2EdgeShape*)fixture->GetShape(); 0994 b2Vec2 v1 = b2Mul(xf, edge->m_vertex1); 0995 b2Vec2 v2 = b2Mul(xf, edge->m_vertex2); 0996 m_debugDraw->DrawSegment(v1, v2, color); 0997 } 0998 break; 0999 1000 case b2Shape::e_loop: 1001 { 1002 b2LoopShape* loop = (b2LoopShape*)fixture->GetShape(); 1003 int32 count = loop->GetCount(); 1004 const b2Vec2* vertices = loop->GetVertices(); 1005 1006 b2Vec2 v1 = b2Mul(xf, vertices[count - 1]); 1007 for (int32 i = 0; i < count; ++i) 1008 { 1009 b2Vec2 v2 = b2Mul(xf, vertices[i]); 1010 m_debugDraw->DrawSegment(v1, v2, color); 1011 v1 = v2; 1012 } 1013 } 1014 break; 1015 1016 case b2Shape::e_polygon: 1017 { 1018 b2PolygonShape* poly = (b2PolygonShape*)fixture->GetShape(); 1019 int32 vertexCount = poly->m_vertexCount; 1020 b2Assert(vertexCount <= b2_maxPolygonVertices); 1021 b2Vec2 vertices[b2_maxPolygonVertices]; 1022 1023 for (int32 i = 0; i < vertexCount; ++i) 1024 { 1025 vertices[i] = b2Mul(xf, poly->m_vertices[i]); 1026 } 1027 1028 m_debugDraw->DrawSolidPolygon(vertices, vertexCount, color); 1029 } 1030 break; 1031 default: 1032 break; 1033 } 1034 } 1035 1036 void b2World::DrawJoint(b2Joint* joint) 1037 { 1038 b2Body* bodyA = joint->GetBodyA(); 1039 b2Body* bodyB = joint->GetBodyB(); 1040 const b2Transform& xf1 = bodyA->GetTransform(); 1041 const b2Transform& xf2 = bodyB->GetTransform(); 1042 b2Vec2 x1 = xf1.position; 1043 b2Vec2 x2 = xf2.position; 1044 b2Vec2 p1 = joint->GetAnchorA(); 1045 b2Vec2 p2 = joint->GetAnchorB(); 1046 1047 b2Color color(0.5f, 0.8f, 0.8f); 1048 1049 switch (joint->GetType()) 1050 { 1051 case e_distanceJoint: 1052 m_debugDraw->DrawSegment(p1, p2, color); 1053 break; 1054 1055 case e_pulleyJoint: 1056 { 1057 b2PulleyJoint* pulley = (b2PulleyJoint*)joint; 1058 b2Vec2 s1 = pulley->GetGroundAnchorA(); 1059 b2Vec2 s2 = pulley->GetGroundAnchorB(); 1060 m_debugDraw->DrawSegment(s1, p1, color); 1061 m_debugDraw->DrawSegment(s2, p2, color); 1062 m_debugDraw->DrawSegment(s1, s2, color); 1063 } 1064 break; 1065 1066 case e_mouseJoint: 1067 // don't draw this 1068 break; 1069 1070 default: 1071 m_debugDraw->DrawSegment(x1, p1, color); 1072 m_debugDraw->DrawSegment(p1, p2, color); 1073 m_debugDraw->DrawSegment(x2, p2, color); 1074 } 1075 } 1076 1077 void b2World::DrawDebugData() 1078 { 1079 if (m_debugDraw == NULL) 1080 { 1081 return; 1082 } 1083 1084 uint32 flags = m_debugDraw->GetFlags(); 1085 1086 if (flags & b2DebugDraw::e_shapeBit) 1087 { 1088 for (b2Body* b = m_bodyList; b; b = b->GetNext()) 1089 { 1090 const b2Transform& xf = b->GetTransform(); 1091 for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext()) 1092 { 1093 if (b->IsActive() == false) 1094 { 1095 DrawShape(f, xf, b2Color(0.5f, 0.5f, 0.3f)); 1096 } 1097 else if (b->GetType() == b2_staticBody) 1098 { 1099 DrawShape(f, xf, b2Color(0.5f, 0.9f, 0.5f)); 1100 } 1101 else if (b->GetType() == b2_kinematicBody) 1102 { 1103 DrawShape(f, xf, b2Color(0.5f, 0.5f, 0.9f)); 1104 } 1105 else if (b->IsAwake() == false) 1106 { 1107 DrawShape(f, xf, b2Color(0.6f, 0.6f, 0.6f)); 1108 } 1109 else 1110 { 1111 DrawShape(f, xf, b2Color(0.9f, 0.7f, 0.7f)); 1112 } 1113 } 1114 } 1115 } 1116 1117 if (flags & b2DebugDraw::e_jointBit) 1118 { 1119 for (b2Joint* j = m_jointList; j; j = j->GetNext()) 1120 { 1121 DrawJoint(j); 1122 } 1123 } 1124 1125 if (flags & b2DebugDraw::e_pairBit) 1126 { 1127 b2Color color(0.3f, 0.9f, 0.9f); 1128 for (b2Contact* c = m_contactManager.m_contactList; c; c = c->GetNext()) 1129 { 1130 //b2Fixture* fixtureA = c->GetFixtureA(); 1131 //b2Fixture* fixtureB = c->GetFixtureB(); 1132 1133 //b2Vec2 cA = fixtureA->GetAABB().GetCenter(); 1134 //b2Vec2 cB = fixtureB->GetAABB().GetCenter(); 1135 1136 //m_debugDraw->DrawSegment(cA, cB, color); 1137 } 1138 } 1139 1140 if (flags & b2DebugDraw::e_aabbBit) 1141 { 1142 b2Color color(0.9f, 0.3f, 0.9f); 1143 b2BroadPhase* bp = &m_contactManager.m_broadPhase; 1144 1145 for (b2Body* b = m_bodyList; b; b = b->GetNext()) 1146 { 1147 if (b->IsActive() == false) 1148 { 1149 continue; 1150 } 1151 1152 for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext()) 1153 { 1154 for (int32 i = 0; i < f->m_proxyCount; ++i) 1155 { 1156 b2FixtureProxy* proxy = f->m_proxies + i; 1157 b2AABB aabb = bp->GetFatAABB(proxy->proxyId); 1158 b2Vec2 vs[4]; 1159 vs[0].Set(aabb.lowerBound.x, aabb.lowerBound.y); 1160 vs[1].Set(aabb.upperBound.x, aabb.lowerBound.y); 1161 vs[2].Set(aabb.upperBound.x, aabb.upperBound.y); 1162 vs[3].Set(aabb.lowerBound.x, aabb.upperBound.y); 1163 1164 m_debugDraw->DrawPolygon(vs, 4, color); 1165 } 1166 } 1167 } 1168 } 1169 1170 if (flags & b2DebugDraw::e_centerOfMassBit) 1171 { 1172 for (b2Body* b = m_bodyList; b; b = b->GetNext()) 1173 { 1174 b2Transform xf = b->GetTransform(); 1175 xf.position = b->GetWorldCenter(); 1176 m_debugDraw->DrawTransform(xf); 1177 } 1178 } 1179 } 1180 1181 int32 b2World::GetProxyCount() const 1182 { 1183 return m_contactManager.m_broadPhase.GetProxyCount(); 1184 }