b2_contact_manager.cpp
Go to the documentation of this file.
1 // MIT License
2 
3 // Copyright (c) 2019 Erin Catto
4 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 
23 #include "box2d/b2_body.h"
24 #include "box2d/b2_contact.h"
26 #include "box2d/b2_fixture.h"
28 
31 
33 {
34  m_contactList = nullptr;
35  m_contactCount = 0;
38  m_allocator = nullptr;
39 }
40 
42 {
43  b2Fixture* fixtureA = c->GetFixtureA();
44  b2Fixture* fixtureB = c->GetFixtureB();
45  b2Body* bodyA = fixtureA->GetBody();
46  b2Body* bodyB = fixtureB->GetBody();
47 
48  if (m_contactListener && c->IsTouching())
49  {
51  }
52 
53  // Remove from the world.
54  if (c->m_prev)
55  {
56  c->m_prev->m_next = c->m_next;
57  }
58 
59  if (c->m_next)
60  {
61  c->m_next->m_prev = c->m_prev;
62  }
63 
64  if (c == m_contactList)
65  {
66  m_contactList = c->m_next;
67  }
68 
69  // Remove from body 1
70  if (c->m_nodeA.prev)
71  {
72  c->m_nodeA.prev->next = c->m_nodeA.next;
73  }
74 
75  if (c->m_nodeA.next)
76  {
77  c->m_nodeA.next->prev = c->m_nodeA.prev;
78  }
79 
80  if (&c->m_nodeA == bodyA->m_contactList)
81  {
82  bodyA->m_contactList = c->m_nodeA.next;
83  }
84 
85  // Remove from body 2
86  if (c->m_nodeB.prev)
87  {
88  c->m_nodeB.prev->next = c->m_nodeB.next;
89  }
90 
91  if (c->m_nodeB.next)
92  {
93  c->m_nodeB.next->prev = c->m_nodeB.prev;
94  }
95 
96  if (&c->m_nodeB == bodyB->m_contactList)
97  {
98  bodyB->m_contactList = c->m_nodeB.next;
99  }
100 
101  // Call the factory.
103  --m_contactCount;
104 }
105 
106 // This is the top level collision call for the time step. Here
107 // all the narrow phase collision is processed for the world
108 // contact list.
110 {
111  // Update awake contacts.
113  while (c)
114  {
115  b2Fixture* fixtureA = c->GetFixtureA();
116  b2Fixture* fixtureB = c->GetFixtureB();
117  int32 indexA = c->GetChildIndexA();
118  int32 indexB = c->GetChildIndexB();
119  b2Body* bodyA = fixtureA->GetBody();
120  b2Body* bodyB = fixtureB->GetBody();
121 
122  // Is this contact flagged for filtering?
124  {
125  // Should these bodies collide?
126  if (bodyB->ShouldCollide(bodyA) == false)
127  {
128  b2Contact* cNuke = c;
129  c = cNuke->GetNext();
130  Destroy(cNuke);
131  continue;
132  }
133 
134  // Check user filtering.
135  if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false)
136  {
137  b2Contact* cNuke = c;
138  c = cNuke->GetNext();
139  Destroy(cNuke);
140  continue;
141  }
142 
143  // Clear the filtering flag.
144  c->m_flags &= ~b2Contact::e_filterFlag;
145  }
146 
147  bool activeA = bodyA->IsAwake() && bodyA->m_type != b2_staticBody;
148  bool activeB = bodyB->IsAwake() && bodyB->m_type != b2_staticBody;
149 
150  // At least one body must be awake and it must be dynamic or kinematic.
151  if (activeA == false && activeB == false)
152  {
153  c = c->GetNext();
154  continue;
155  }
156 
157  int32 proxyIdA = fixtureA->m_proxies[indexA].proxyId;
158  int32 proxyIdB = fixtureB->m_proxies[indexB].proxyId;
159  bool overlap = m_broadPhase.TestOverlap(proxyIdA, proxyIdB);
160 
161  // Here we destroy contacts that cease to overlap in the broad-phase.
162  if (overlap == false)
163  {
164  b2Contact* cNuke = c;
165  c = cNuke->GetNext();
166  Destroy(cNuke);
167  continue;
168  }
169 
170  // The contact persists.
172  c = c->GetNext();
173  }
174 }
175 
177 {
179 }
180 
181 void b2ContactManager::AddPair(void* proxyUserDataA, void* proxyUserDataB)
182 {
183  b2FixtureProxy* proxyA = (b2FixtureProxy*)proxyUserDataA;
184  b2FixtureProxy* proxyB = (b2FixtureProxy*)proxyUserDataB;
185 
186  b2Fixture* fixtureA = proxyA->fixture;
187  b2Fixture* fixtureB = proxyB->fixture;
188 
189  int32 indexA = proxyA->childIndex;
190  int32 indexB = proxyB->childIndex;
191 
192  b2Body* bodyA = fixtureA->GetBody();
193  b2Body* bodyB = fixtureB->GetBody();
194 
195  // Are the fixtures on the same body?
196  if (bodyA == bodyB)
197  {
198  return;
199  }
200 
201  // TODO_ERIN use a hash table to remove a potential bottleneck when both
202  // bodies have a lot of contacts.
203  // Does a contact already exist?
204  b2ContactEdge* edge = bodyB->GetContactList();
205  while (edge)
206  {
207  if (edge->other == bodyA)
208  {
209  b2Fixture* fA = edge->contact->GetFixtureA();
210  b2Fixture* fB = edge->contact->GetFixtureB();
211  int32 iA = edge->contact->GetChildIndexA();
212  int32 iB = edge->contact->GetChildIndexB();
213 
214  if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB)
215  {
216  // A contact already exists.
217  return;
218  }
219 
220  if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA)
221  {
222  // A contact already exists.
223  return;
224  }
225  }
226 
227  edge = edge->next;
228  }
229 
230  // Does a joint override collision? Is at least one body dynamic?
231  if (bodyB->ShouldCollide(bodyA) == false)
232  {
233  return;
234  }
235 
236  // Check user filtering.
237  if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false)
238  {
239  return;
240  }
241 
242  // Call the factory.
243  b2Contact* c = b2Contact::Create(fixtureA, indexA, fixtureB, indexB, m_allocator);
244  if (c == nullptr)
245  {
246  return;
247  }
248 
249  // Contact creation may swap fixtures.
250  fixtureA = c->GetFixtureA();
251  fixtureB = c->GetFixtureB();
252  indexA = c->GetChildIndexA();
253  indexB = c->GetChildIndexB();
254  bodyA = fixtureA->GetBody();
255  bodyB = fixtureB->GetBody();
256 
257  // Insert into the world.
258  c->m_prev = nullptr;
259  c->m_next = m_contactList;
260  if (m_contactList != nullptr)
261  {
262  m_contactList->m_prev = c;
263  }
264  m_contactList = c;
265 
266  // Connect to island graph.
267 
268  // Connect to body A
269  c->m_nodeA.contact = c;
270  c->m_nodeA.other = bodyB;
271 
272  c->m_nodeA.prev = nullptr;
273  c->m_nodeA.next = bodyA->m_contactList;
274  if (bodyA->m_contactList != nullptr)
275  {
276  bodyA->m_contactList->prev = &c->m_nodeA;
277  }
278  bodyA->m_contactList = &c->m_nodeA;
279 
280  // Connect to body B
281  c->m_nodeB.contact = c;
282  c->m_nodeB.other = bodyA;
283 
284  c->m_nodeB.prev = nullptr;
285  c->m_nodeB.next = bodyB->m_contactList;
286  if (bodyB->m_contactList != nullptr)
287  {
288  bodyB->m_contactList->prev = &c->m_nodeB;
289  }
290  bodyB->m_contactList = &c->m_nodeB;
291 
292  ++m_contactCount;
293 }
b2ContactListener * m_contactListener
b2ContactFilter b2_defaultFilter
void Update(b2ContactListener *listener)
Definition: b2_contact.cpp:166
virtual void EndContact(b2Contact *contact)
Called when two fixtures cease to touch.
void Destroy(b2Contact *c)
b2ContactFilter * m_contactFilter
b2Fixture * fixture
Definition: b2_fixture.h:106
b2Contact * GetNext()
Get the next contact in the world's contact list.
Definition: b2_contact.h:286
b2Fixture * GetFixtureB()
Get fixture B in this contact.
Definition: b2_contact.h:306
b2ContactEdge * GetContactList()
Definition: b2_body.h:714
b2ContactEdge * m_contactList
Definition: b2_body.h:458
This proxy is used internally to connect fixtures to the broad-phase.
Definition: b2_fixture.h:103
b2ContactEdge * next
the next contact edge in the body's contact list
Definition: b2_contact.h:82
void AddPair(void *proxyUserDataA, void *proxyUserDataB)
b2Contact * contact
the contact
Definition: b2_contact.h:80
signed int int32
Definition: b2_types.h:28
bool TestOverlap(int32 proxyIdA, int32 proxyIdB) const
Test overlap of fat AABBs.
virtual bool ShouldCollide(b2Fixture *fixtureA, b2Fixture *fixtureB)
A rigid body. These are created via b2World::CreateBody.
Definition: b2_body.h:128
int32 GetChildIndexA() const
Get the child primitive index for fixture A.
Definition: b2_contact.h:311
b2Contact * m_contactList
void UpdatePairs(T *callback)
Update the pairs. This results in pair callbacks. This can only add pairs.
bool IsAwake() const
Definition: b2_body.h:661
b2ContactListener b2_defaultListener
int32 GetChildIndexB() const
Get the child primitive index for fixture B.
Definition: b2_contact.h:321
b2Fixture * GetFixtureA()
Get fixture A in this contact.
Definition: b2_contact.h:296
b2ContactEdge m_nodeA
Definition: b2_contact.h:223
b2Body * other
provides quick access to the other body attached.
Definition: b2_contact.h:79
b2BlockAllocator * m_allocator
b2BroadPhase m_broadPhase
static b2Contact * Create(b2Fixture *fixtureA, int32 indexA, b2Fixture *fixtureB, int32 indexB, b2BlockAllocator *allocator)
Definition: b2_contact.cpp:73
b2Contact * m_prev
Definition: b2_contact.h:219
int32 childIndex
Definition: b2_fixture.h:107
b2ContactEdge m_nodeB
Definition: b2_contact.h:224
b2FixtureProxy * m_proxies
Definition: b2_fixture.h:243
bool ShouldCollide(const b2Body *other) const
Definition: b2_body.cpp:392
b2BodyType m_type
Definition: b2_body.h:435
uint32 m_flags
Definition: b2_contact.h:216
bool IsTouching() const
Is this contact touching?
Definition: b2_contact.h:281
b2Contact * m_next
Definition: b2_contact.h:220
b2Body * GetBody()
Definition: b2_fixture.h:283
b2ContactEdge * prev
the previous contact edge in the body's contact list
Definition: b2_contact.h:81
static void Destroy(b2Contact *contact, b2Shape::Type typeA, b2Shape::Type typeB, b2BlockAllocator *allocator)


mvsim
Author(s):
autogenerated on Tue Jul 4 2023 03:08:19