Warning, file /education/gcompris/external/qml-box2d/Box2D/Dynamics/b2ContactManager.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 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/b2ContactManager.h> 0020 #include <Box2D/Dynamics/b2Body.h> 0021 #include <Box2D/Dynamics/b2Fixture.h> 0022 #include <Box2D/Dynamics/b2WorldCallbacks.h> 0023 #include <Box2D/Dynamics/Contacts/b2Contact.h> 0024 0025 b2ContactFilter b2_defaultFilter; 0026 b2ContactListener b2_defaultListener; 0027 0028 b2ContactManager::b2ContactManager() 0029 { 0030 m_contactList = NULL; 0031 m_contactCount = 0; 0032 m_contactFilter = &b2_defaultFilter; 0033 m_contactListener = &b2_defaultListener; 0034 m_allocator = NULL; 0035 } 0036 0037 void b2ContactManager::Destroy(b2Contact* c) 0038 { 0039 b2Fixture* fixtureA = c->GetFixtureA(); 0040 b2Fixture* fixtureB = c->GetFixtureB(); 0041 b2Body* bodyA = fixtureA->GetBody(); 0042 b2Body* bodyB = fixtureB->GetBody(); 0043 0044 if (m_contactListener && c->IsTouching()) 0045 { 0046 m_contactListener->EndContact(c); 0047 } 0048 0049 // Remove from the world. 0050 if (c->m_prev) 0051 { 0052 c->m_prev->m_next = c->m_next; 0053 } 0054 0055 if (c->m_next) 0056 { 0057 c->m_next->m_prev = c->m_prev; 0058 } 0059 0060 if (c == m_contactList) 0061 { 0062 m_contactList = c->m_next; 0063 } 0064 0065 // Remove from body 1 0066 if (c->m_nodeA.prev) 0067 { 0068 c->m_nodeA.prev->next = c->m_nodeA.next; 0069 } 0070 0071 if (c->m_nodeA.next) 0072 { 0073 c->m_nodeA.next->prev = c->m_nodeA.prev; 0074 } 0075 0076 if (&c->m_nodeA == bodyA->m_contactList) 0077 { 0078 bodyA->m_contactList = c->m_nodeA.next; 0079 } 0080 0081 // Remove from body 2 0082 if (c->m_nodeB.prev) 0083 { 0084 c->m_nodeB.prev->next = c->m_nodeB.next; 0085 } 0086 0087 if (c->m_nodeB.next) 0088 { 0089 c->m_nodeB.next->prev = c->m_nodeB.prev; 0090 } 0091 0092 if (&c->m_nodeB == bodyB->m_contactList) 0093 { 0094 bodyB->m_contactList = c->m_nodeB.next; 0095 } 0096 0097 // Call the factory. 0098 b2Contact::Destroy(c, m_allocator); 0099 --m_contactCount; 0100 } 0101 0102 // This is the top level collision call for the time step. Here 0103 // all the narrow phase collision is processed for the world 0104 // contact list. 0105 void b2ContactManager::Collide() 0106 { 0107 // Update awake contacts. 0108 b2Contact* c = m_contactList; 0109 while (c) 0110 { 0111 b2Fixture* fixtureA = c->GetFixtureA(); 0112 b2Fixture* fixtureB = c->GetFixtureB(); 0113 int32 indexA = c->GetChildIndexA(); 0114 int32 indexB = c->GetChildIndexB(); 0115 b2Body* bodyA = fixtureA->GetBody(); 0116 b2Body* bodyB = fixtureB->GetBody(); 0117 0118 // Is this contact flagged for filtering? 0119 if (c->m_flags & b2Contact::e_filterFlag) 0120 { 0121 // Should these bodies collide? 0122 if (bodyB->ShouldCollide(bodyA) == false) 0123 { 0124 b2Contact* cNuke = c; 0125 c = cNuke->GetNext(); 0126 Destroy(cNuke); 0127 continue; 0128 } 0129 0130 // Check user filtering. 0131 if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false) 0132 { 0133 b2Contact* cNuke = c; 0134 c = cNuke->GetNext(); 0135 Destroy(cNuke); 0136 continue; 0137 } 0138 0139 // Clear the filtering flag. 0140 c->m_flags &= ~b2Contact::e_filterFlag; 0141 } 0142 0143 bool activeA = bodyA->IsAwake() && bodyA->m_type != b2_staticBody; 0144 bool activeB = bodyB->IsAwake() && bodyB->m_type != b2_staticBody; 0145 0146 // At least one body must be awake and it must be dynamic or kinematic. 0147 if (activeA == false && activeB == false) 0148 { 0149 c = c->GetNext(); 0150 continue; 0151 } 0152 0153 int32 proxyIdA = fixtureA->m_proxies[indexA].proxyId; 0154 int32 proxyIdB = fixtureB->m_proxies[indexB].proxyId; 0155 bool overlap = m_broadPhase.TestOverlap(proxyIdA, proxyIdB); 0156 0157 // Here we destroy contacts that cease to overlap in the broad-phase. 0158 if (overlap == false) 0159 { 0160 b2Contact* cNuke = c; 0161 c = cNuke->GetNext(); 0162 Destroy(cNuke); 0163 continue; 0164 } 0165 0166 // The contact persists. 0167 c->Update(m_contactListener); 0168 c = c->GetNext(); 0169 } 0170 } 0171 0172 void b2ContactManager::FindNewContacts() 0173 { 0174 m_broadPhase.UpdatePairs(this); 0175 } 0176 0177 void b2ContactManager::AddPair(void* proxyUserDataA, void* proxyUserDataB) 0178 { 0179 b2FixtureProxy* proxyA = (b2FixtureProxy*)proxyUserDataA; 0180 b2FixtureProxy* proxyB = (b2FixtureProxy*)proxyUserDataB; 0181 0182 b2Fixture* fixtureA = proxyA->fixture; 0183 b2Fixture* fixtureB = proxyB->fixture; 0184 0185 int32 indexA = proxyA->childIndex; 0186 int32 indexB = proxyB->childIndex; 0187 0188 b2Body* bodyA = fixtureA->GetBody(); 0189 b2Body* bodyB = fixtureB->GetBody(); 0190 0191 // Are the fixtures on the same body? 0192 if (bodyA == bodyB) 0193 { 0194 return; 0195 } 0196 0197 // TODO_ERIN use a hash table to remove a potential bottleneck when both 0198 // bodies have a lot of contacts. 0199 // Does a contact already exist? 0200 b2ContactEdge* edge = bodyB->GetContactList(); 0201 while (edge) 0202 { 0203 if (edge->other == bodyA) 0204 { 0205 b2Fixture* fA = edge->contact->GetFixtureA(); 0206 b2Fixture* fB = edge->contact->GetFixtureB(); 0207 int32 iA = edge->contact->GetChildIndexA(); 0208 int32 iB = edge->contact->GetChildIndexB(); 0209 0210 if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB) 0211 { 0212 // A contact already exists. 0213 return; 0214 } 0215 0216 if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA) 0217 { 0218 // A contact already exists. 0219 return; 0220 } 0221 } 0222 0223 edge = edge->next; 0224 } 0225 0226 // Does a joint override collision? Is at least one body dynamic? 0227 if (bodyB->ShouldCollide(bodyA) == false) 0228 { 0229 return; 0230 } 0231 0232 // Check user filtering. 0233 if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false) 0234 { 0235 return; 0236 } 0237 0238 // Call the factory. 0239 b2Contact* c = b2Contact::Create(fixtureA, indexA, fixtureB, indexB, m_allocator); 0240 if (c == NULL) 0241 { 0242 return; 0243 } 0244 0245 // Contact creation may swap fixtures. 0246 fixtureA = c->GetFixtureA(); 0247 fixtureB = c->GetFixtureB(); 0248 indexA = c->GetChildIndexA(); 0249 indexB = c->GetChildIndexB(); 0250 bodyA = fixtureA->GetBody(); 0251 bodyB = fixtureB->GetBody(); 0252 0253 // Insert into the world. 0254 c->m_prev = NULL; 0255 c->m_next = m_contactList; 0256 if (m_contactList != NULL) 0257 { 0258 m_contactList->m_prev = c; 0259 } 0260 m_contactList = c; 0261 0262 // Connect to island graph. 0263 0264 // Connect to body A 0265 c->m_nodeA.contact = c; 0266 c->m_nodeA.other = bodyB; 0267 0268 c->m_nodeA.prev = NULL; 0269 c->m_nodeA.next = bodyA->m_contactList; 0270 if (bodyA->m_contactList != NULL) 0271 { 0272 bodyA->m_contactList->prev = &c->m_nodeA; 0273 } 0274 bodyA->m_contactList = &c->m_nodeA; 0275 0276 // Connect to body B 0277 c->m_nodeB.contact = c; 0278 c->m_nodeB.other = bodyA; 0279 0280 c->m_nodeB.prev = NULL; 0281 c->m_nodeB.next = bodyB->m_contactList; 0282 if (bodyB->m_contactList != NULL) 0283 { 0284 bodyB->m_contactList->prev = &c->m_nodeB; 0285 } 0286 bodyB->m_contactList = &c->m_nodeB; 0287 0288 // Wake up the bodies 0289 if (fixtureA->IsSensor() == false && fixtureB->IsSensor() == false) 0290 { 0291 bodyA->SetAwake(true); 0292 bodyB->SetAwake(true); 0293 } 0294 0295 ++m_contactCount; 0296 }