b2_contact.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 
25 #include "b2_circle_contact.h"
26 #include "b2_contact_solver.h"
27 #include "b2_edge_circle_contact.h"
30 #include "b2_polygon_contact.h"
31 
32 #include "box2d/b2_contact.h"
34 #include "box2d/b2_body.h"
35 #include "box2d/b2_collision.h"
36 #include "box2d/b2_fixture.h"
37 #include "box2d/b2_shape.h"
39 #include "box2d/b2_world.h"
40 
42 bool b2Contact::s_initialized = false;
43 
45 {
53 }
54 
56  b2Shape::Type type1, b2Shape::Type type2)
57 {
58  b2Assert(0 <= type1 && type1 < b2Shape::e_typeCount);
59  b2Assert(0 <= type2 && type2 < b2Shape::e_typeCount);
60 
61  s_registers[type1][type2].createFcn = createFcn;
62  s_registers[type1][type2].destroyFcn = destoryFcn;
63  s_registers[type1][type2].primary = true;
64 
65  if (type1 != type2)
66  {
67  s_registers[type2][type1].createFcn = createFcn;
68  s_registers[type2][type1].destroyFcn = destoryFcn;
69  s_registers[type2][type1].primary = false;
70  }
71 }
72 
73 b2Contact* b2Contact::Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator)
74 {
75  if (s_initialized == false)
76  {
78  s_initialized = true;
79  }
80 
81  b2Shape::Type type1 = fixtureA->GetType();
82  b2Shape::Type type2 = fixtureB->GetType();
83 
84  b2Assert(0 <= type1 && type1 < b2Shape::e_typeCount);
85  b2Assert(0 <= type2 && type2 < b2Shape::e_typeCount);
86 
87  b2ContactCreateFcn* createFcn = s_registers[type1][type2].createFcn;
88  if (createFcn)
89  {
90  if (s_registers[type1][type2].primary)
91  {
92  return createFcn(fixtureA, indexA, fixtureB, indexB, allocator);
93  }
94  else
95  {
96  return createFcn(fixtureB, indexB, fixtureA, indexA, allocator);
97  }
98  }
99  else
100  {
101  return nullptr;
102  }
103 }
104 
106 {
107  b2Assert(s_initialized == true);
108 
109  b2Fixture* fixtureA = contact->m_fixtureA;
110  b2Fixture* fixtureB = contact->m_fixtureB;
111 
112  if (contact->m_manifold.pointCount > 0 &&
113  fixtureA->IsSensor() == false &&
114  fixtureB->IsSensor() == false)
115  {
116  fixtureA->GetBody()->SetAwake(true);
117  fixtureB->GetBody()->SetAwake(true);
118  }
119 
120  b2Shape::Type typeA = fixtureA->GetType();
121  b2Shape::Type typeB = fixtureB->GetType();
122 
123  b2Assert(0 <= typeA && typeA < b2Shape::e_typeCount);
124  b2Assert(0 <= typeB && typeB < b2Shape::e_typeCount);
125 
126  b2ContactDestroyFcn* destroyFcn = s_registers[typeA][typeB].destroyFcn;
127  destroyFcn(contact, allocator);
128 }
129 
131 {
133 
134  m_fixtureA = fA;
135  m_fixtureB = fB;
136 
137  m_indexA = indexA;
138  m_indexB = indexB;
139 
141 
142  m_prev = nullptr;
143  m_next = nullptr;
144 
145  m_nodeA.contact = nullptr;
146  m_nodeA.prev = nullptr;
147  m_nodeA.next = nullptr;
148  m_nodeA.other = nullptr;
149 
150  m_nodeB.contact = nullptr;
151  m_nodeB.prev = nullptr;
152  m_nodeB.next = nullptr;
153  m_nodeB.other = nullptr;
154 
155  m_toiCount = 0;
156 
160 
161  m_tangentSpeed = 0.0f;
162 }
163 
164 // Update the contact manifold and touching status.
165 // Note: do not assume the fixture AABBs are overlapping or are valid.
167 {
168  b2Manifold oldManifold = m_manifold;
169 
170  // Re-enable this contact.
172 
173  bool touching = false;
174  bool wasTouching = (m_flags & e_touchingFlag) == e_touchingFlag;
175 
176  bool sensorA = m_fixtureA->IsSensor();
177  bool sensorB = m_fixtureB->IsSensor();
178  bool sensor = sensorA || sensorB;
179 
180  b2Body* bodyA = m_fixtureA->GetBody();
181  b2Body* bodyB = m_fixtureB->GetBody();
182  const b2Transform& xfA = bodyA->GetTransform();
183  const b2Transform& xfB = bodyB->GetTransform();
184 
185  // Is this contact a sensor?
186  if (sensor)
187  {
188  const b2Shape* shapeA = m_fixtureA->GetShape();
189  const b2Shape* shapeB = m_fixtureB->GetShape();
190  touching = b2TestOverlap(shapeA, m_indexA, shapeB, m_indexB, xfA, xfB);
191 
192  // Sensors don't generate manifolds.
194  }
195  else
196  {
197  Evaluate(&m_manifold, xfA, xfB);
198  touching = m_manifold.pointCount > 0;
199 
200  // Match old contact ids to new contact ids and copy the
201  // stored impulses to warm start the solver.
202  for (int32 i = 0; i < m_manifold.pointCount; ++i)
203  {
204  b2ManifoldPoint* mp2 = m_manifold.points + i;
205  mp2->normalImpulse = 0.0f;
206  mp2->tangentImpulse = 0.0f;
207  b2ContactID id2 = mp2->id;
208 
209  for (int32 j = 0; j < oldManifold.pointCount; ++j)
210  {
211  b2ManifoldPoint* mp1 = oldManifold.points + j;
212 
213  if (mp1->id.key == id2.key)
214  {
215  mp2->normalImpulse = mp1->normalImpulse;
216  mp2->tangentImpulse = mp1->tangentImpulse;
217  break;
218  }
219  }
220  }
221 
222  if (touching != wasTouching)
223  {
224  bodyA->SetAwake(true);
225  bodyB->SetAwake(true);
226  }
227  }
228 
229  if (touching)
230  {
232  }
233  else
234  {
236  }
237 
238  if (wasTouching == false && touching == true && listener)
239  {
240  listener->BeginContact(this);
241  }
242 
243  if (wasTouching == true && touching == false && listener)
244  {
245  listener->EndContact(this);
246  }
247 
248  if (sensor == false && touching && listener)
249  {
250  listener->PreSolve(this, &oldManifold);
251  }
252 }
const b2Transform & GetTransform() const
Definition: b2_body.h:479
b2Fixture * m_fixtureB
Definition: b2_contact.h:227
void Update(b2ContactListener *listener)
Definition: b2_contact.cpp:166
float m_friction
Definition: b2_fixture.h:239
static void Destroy(b2Contact *contact, b2BlockAllocator *allocator)
Contact ids to facilitate warm starting.
Definition: b2_collision.h:59
virtual void EndContact(b2Contact *contact)
Called when two fixtures cease to touch.
static void AddType(b2ContactCreateFcn *createFcn, b2ContactDestroyFcn *destroyFcn, b2Shape::Type typeA, b2Shape::Type typeB)
Definition: b2_contact.cpp:55
b2Fixture * m_fixtureA
Definition: b2_contact.h:226
static void Destroy(b2Contact *contact, b2BlockAllocator *allocator)
virtual void BeginContact(b2Contact *contact)
Called when two fixtures begin to touch.
float b2MixRestitution(float restitution1, float restitution2)
Definition: b2_contact.h:49
B2_API bool b2TestOverlap(const b2Shape *shapeA, int32 indexA, const b2Shape *shapeB, int32 indexB, const b2Transform &xfA, const b2Transform &xfB)
Determine if two generic shapes overlap.
static void Destroy(b2Contact *contact, b2BlockAllocator *allocator)
b2ContactID id
uniquely identifies a contact point between two shapes
Definition: b2_collision.h:80
void b2ContactDestroyFcn(b2Contact *contact, b2BlockAllocator *allocator)
Definition: b2_contact.h:63
static b2Contact * Create(b2Fixture *fixtureA, int32 indexA, b2Fixture *fixtureB, int32 indexB, b2BlockAllocator *allocator)
uint32 key
Used to quickly compare contact ids.
Definition: b2_collision.h:62
static b2Contact * Create(b2Fixture *fixtureA, int32 indexA, b2Fixture *fixtureB, int32 indexB, b2BlockAllocator *allocator)
static void Destroy(b2Contact *contact, b2BlockAllocator *allocator)
float m_tangentSpeed
Definition: b2_contact.h:241
static bool s_initialized
Definition: b2_contact.h:214
b2ContactEdge * next
the next contact edge in the body&#39;s contact list
Definition: b2_contact.h:82
b2Contact * contact
the contact
Definition: b2_contact.h:80
signed int int32
Definition: b2_types.h:28
A rigid body. These are created via b2World::CreateBody.
Definition: b2_body.h:128
float m_friction
Definition: b2_contact.h:237
static b2Contact * Create(b2Fixture *fixtureA, int32 indexA, b2Fixture *fixtureB, int32 indexB, b2BlockAllocator *allocator)
static void Destroy(b2Contact *contact, b2BlockAllocator *allocator)
float tangentImpulse
the friction impulse
Definition: b2_collision.h:79
static b2ContactRegister s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount]
Definition: b2_contact.h:213
float m_restitution
Definition: b2_contact.h:238
float b2MixRestitutionThreshold(float threshold1, float threshold2)
Restitution mixing law. This picks the lowest value.
Definition: b2_contact.h:55
float m_restitutionThreshold
Definition: b2_contact.h:239
static b2Contact * Create(b2Fixture *fixtureA, int32 indexA, b2Fixture *fixtureB, int32 indexB, b2BlockAllocator *allocator)
int32 m_indexB
Definition: b2_contact.h:230
static b2Contact * Create(b2Fixture *fixtureA, int32 indexA, b2Fixture *fixtureB, int32 indexB, b2BlockAllocator *allocator)
b2ContactCreateFcn * createFcn
Definition: b2_contact.h:67
int32 pointCount
the number of manifold points
Definition: b2_collision.h:112
float b2MixFriction(float friction1, float friction2)
Definition: b2_contact.h:42
virtual void Evaluate(b2Manifold *manifold, const b2Transform &xfA, const b2Transform &xfB)=0
Evaluate this contact with your own manifold and transforms.
int32 m_toiCount
Definition: b2_contact.h:234
static b2Contact * Create(b2Fixture *fixtureA, int32 indexA, b2Fixture *fixtureB, int32 indexB, b2BlockAllocator *allocator)
b2ContactDestroyFcn * destroyFcn
Definition: b2_contact.h:68
float normalImpulse
the non-penetration impulse
Definition: b2_collision.h:78
b2ContactEdge m_nodeA
Definition: b2_contact.h:223
static void Destroy(b2Contact *contact, b2BlockAllocator *allocator)
static b2Contact * Create(b2Fixture *fixtureA, int32 indexA, b2Fixture *fixtureB, int32 indexB, b2BlockAllocator *allocator)
bool IsSensor() const
Definition: b2_fixture.h:268
b2ManifoldPoint points[b2_maxManifoldPoints]
the points of contact
Definition: b2_collision.h:108
b2Body * other
provides quick access to the other body attached.
Definition: b2_contact.h:79
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
b2ContactEdge m_nodeB
Definition: b2_contact.h:224
int32 m_indexA
Definition: b2_contact.h:229
static void InitializeRegisters()
Definition: b2_contact.cpp:44
b2Shape * GetShape()
Definition: b2_fixture.h:258
b2Manifold m_manifold
Definition: b2_contact.h:232
uint32 m_flags
Definition: b2_contact.h:216
#define b2Assert(A)
Definition: b2_common.h:37
b2Contact * m_next
Definition: b2_contact.h:220
float m_restitutionThreshold
Definition: b2_fixture.h:241
void SetAwake(bool flag)
Definition: b2_body.h:638
virtual void PreSolve(b2Contact *contact, const b2Manifold *oldManifold)
b2Body * GetBody()
Definition: b2_fixture.h:283
b2Contact * b2ContactCreateFcn(b2Fixture *fixtureA, int32 indexA, b2Fixture *fixtureB, int32 indexB, b2BlockAllocator *allocator)
Definition: b2_contact.h:60
float m_restitution
Definition: b2_fixture.h:240
b2Shape::Type GetType() const
Definition: b2_fixture.h:253
b2ContactEdge * prev
the previous contact edge in the body&#39;s contact list
Definition: b2_contact.h:81
static void Destroy(b2Contact *contact, b2Shape::Type typeA, b2Shape::Type typeB, b2BlockAllocator *allocator)
static void Destroy(b2Contact *contact, b2BlockAllocator *allocator)


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