1 /*
2 * Copyright (c) 2006-2009 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 #ifndef B2_CONTACT_H
20 #define B2_CONTACT_H
21 
22 #include <Box2D/Common/b2Math.h>
23 #include <Box2D/Collision/b2Collision.h>
24 #include <Box2D/Collision/Shapes/b2Shape.h>
25 #include <Box2D/Dynamics/b2Fixture.h>
26 
27 class b2Body;
28 class b2Contact;
29 class b2Fixture;
30 class b2World;
31 class b2BlockAllocator;
32 class b2StackAllocator;
33 class b2ContactListener;
34 
35 /// Friction mixing law. The idea is to allow either fixture to drive the restitution to zero.
36 /// For example, anything slides on ice.
b2MixFriction(float32 friction1,float32 friction2)37 inline float32 b2MixFriction(float32 friction1, float32 friction2)
38 {
39 	return b2Sqrt(friction1 * friction2);
40 }
41 
42 /// Restitution mixing law. The idea is allow for anything to bounce off an inelastic surface.
43 /// For example, a superball bounces on anything.
b2MixRestitution(float32 restitution1,float32 restitution2)44 inline float32 b2MixRestitution(float32 restitution1, float32 restitution2)
45 {
46 	return restitution1 > restitution2 ? restitution1 : restitution2;
47 }
48 
49 typedef b2Contact* b2ContactCreateFcn(	b2Fixture* fixtureA, int32 indexA,
50 										b2Fixture* fixtureB, int32 indexB,
51 										b2BlockAllocator* allocator);
52 typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator);
53 
54 struct b2ContactRegister
55 {
56 	b2ContactCreateFcn* createFcn;
57 	b2ContactDestroyFcn* destroyFcn;
58 	bool primary;
59 };
60 
61 /// A contact edge is used to connect bodies and contacts together
62 /// in a contact graph where each body is a node and each contact
63 /// is an edge. A contact edge belongs to a doubly linked list
64 /// maintained in each attached body. Each contact has two contact
65 /// nodes, one for each attached body.
66 struct b2ContactEdge
67 {
68 	b2Body* other;			///< provides quick access to the other body attached.
69 	b2Contact* contact;		///< the contact
70 	b2ContactEdge* prev;	///< the previous contact edge in the body's contact list
71 	b2ContactEdge* next;	///< the next contact edge in the body's contact list
72 };
73 
74 /// The class manages contact between two shapes. A contact exists for each overlapping
75 /// AABB in the broad-phase (except if filtered). Therefore a contact object may exist
76 /// that has no contact points.
77 class b2Contact
78 {
79 public:
80 
81 	/// Get the contact manifold. Do not modify the manifold unless you understand the
82 	/// internals of Box2D.
83 	b2Manifold* GetManifold();
84 	const b2Manifold* GetManifold() const;
85 
86 	/// Get the world manifold.
87 	void GetWorldManifold(b2WorldManifold* worldManifold) const;
88 
89 	/// Is this contact touching?
90 	bool IsTouching() const;
91 
92 	/// Enable/disable this contact. This can be used inside the pre-solve
93 	/// contact listener. The contact is only disabled for the current
94 	/// time step (or sub-step in continuous collisions).
95 	void SetEnabled(bool flag);
96 
97 	/// Has this contact been disabled?
98 	bool IsEnabled() const;
99 
100 	/// Get the next contact in the world's contact list.
101 	b2Contact* GetNext();
102 	const b2Contact* GetNext() const;
103 
104 	/// Get fixture A in this contact.
105 	b2Fixture* GetFixtureA();
106 	const b2Fixture* GetFixtureA() const;
107 
108 	/// Get the child primitive index for fixture A.
109 	int32 GetChildIndexA() const;
110 
111 	/// Get fixture B in this contact.
112 	b2Fixture* GetFixtureB();
113 	const b2Fixture* GetFixtureB() const;
114 
115 	/// Get the child primitive index for fixture B.
116 	int32 GetChildIndexB() const;
117 
118 	/// Override the default friction mixture. You can call this in b2ContactListener::PreSolve.
119 	/// This value persists until set or reset.
120 	void SetFriction(float32 friction);
121 
122 	/// Get the friction.
123 	float32 GetFriction() const;
124 
125 	/// Reset the friction mixture to the default value.
126 	void ResetFriction();
127 
128 	/// Override the default restitution mixture. You can call this in b2ContactListener::PreSolve.
129 	/// The value persists until you set or reset.
130 	void SetRestitution(float32 restitution);
131 
132 	/// Get the restitution.
133 	float32 GetRestitution() const;
134 
135 	/// Reset the restitution to the default value.
136 	void ResetRestitution();
137 
138 	/// Set the desired tangent speed for a conveyor belt behavior. In meters per second.
139 	void SetTangentSpeed(float32 speed);
140 
141 	/// Get the desired tangent speed. In meters per second.
142 	float32 GetTangentSpeed() const;
143 
144 	/// Evaluate this contact with your own manifold and transforms.
145 	virtual void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) = 0;
146 
147 protected:
148 	friend class b2ContactManager;
149 	friend class b2World;
150 	friend class b2ContactSolver;
151 	friend class b2Body;
152 	friend class b2Fixture;
153 
154 	// Flags stored in m_flags
155 	enum
156 	{
157 		// Used when crawling contact graph when forming islands.
158 		e_islandFlag		= 0x0001,
159 
160         // Set when the shapes are touching.
161 		e_touchingFlag		= 0x0002,
162 
163 		// This contact can be disabled (by user)
164 		e_enabledFlag		= 0x0004,
165 
166 		// This contact needs filtering because a fixture filter was changed.
167 		e_filterFlag		= 0x0008,
168 
169 		// This bullet contact had a TOI event
170 		e_bulletHitFlag		= 0x0010,
171 
172 		// This contact has a valid TOI in m_toi
173 		e_toiFlag			= 0x0020
174 	};
175 
176 	/// Flag this contact for filtering. Filtering will occur the next time step.
177 	void FlagForFiltering();
178 
179 	static void AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destroyFcn,
180 						b2Shape::Type typeA, b2Shape::Type typeB);
181 	static void InitializeRegisters();
182 	static b2Contact* Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator);
183 	static void Destroy(b2Contact* contact, b2Shape::Type typeA, b2Shape::Type typeB, b2BlockAllocator* allocator);
184 	static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
185 
b2Contact()186 	b2Contact() : m_fixtureA(NULL), m_fixtureB(NULL) {}
187 	b2Contact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB);
~b2Contact()188 	virtual ~b2Contact() {}
189 
190 	void Update(b2ContactListener* listener);
191 
192 	static b2ContactRegister s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount];
193 	static bool s_initialized;
194 
195 	uint32 m_flags;
196 
197 	// World pool and list pointers.
198 	b2Contact* m_prev;
199 	b2Contact* m_next;
200 
201 	// Nodes for connecting bodies.
202 	b2ContactEdge m_nodeA;
203 	b2ContactEdge m_nodeB;
204 
205 	b2Fixture* m_fixtureA;
206 	b2Fixture* m_fixtureB;
207 
208 	int32 m_indexA;
209 	int32 m_indexB;
210 
211 	b2Manifold m_manifold;
212 
213 	int32 m_toiCount;
214 	float32 m_toi;
215 
216 	float32 m_friction;
217 	float32 m_restitution;
218 
219 	float32 m_tangentSpeed;
220 };
221 
GetManifold()222 inline b2Manifold* b2Contact::GetManifold()
223 {
224 	return &m_manifold;
225 }
226 
GetManifold()227 inline const b2Manifold* b2Contact::GetManifold() const
228 {
229 	return &m_manifold;
230 }
231 
GetWorldManifold(b2WorldManifold * worldManifold)232 inline void b2Contact::GetWorldManifold(b2WorldManifold* worldManifold) const
233 {
234 	const b2Body* bodyA = m_fixtureA->GetBody();
235 	const b2Body* bodyB = m_fixtureB->GetBody();
236 	const b2Shape* shapeA = m_fixtureA->GetShape();
237 	const b2Shape* shapeB = m_fixtureB->GetShape();
238 
239 	worldManifold->Initialize(&m_manifold, bodyA->GetTransform(), shapeA->m_radius, bodyB->GetTransform(), shapeB->m_radius);
240 }
241 
SetEnabled(bool flag)242 inline void b2Contact::SetEnabled(bool flag)
243 {
244 	if (flag)
245 	{
246 		m_flags |= e_enabledFlag;
247 	}
248 	else
249 	{
250 		m_flags &= ~e_enabledFlag;
251 	}
252 }
253 
IsEnabled()254 inline bool b2Contact::IsEnabled() const
255 {
256 	return (m_flags & e_enabledFlag) == e_enabledFlag;
257 }
258 
IsTouching()259 inline bool b2Contact::IsTouching() const
260 {
261 	return (m_flags & e_touchingFlag) == e_touchingFlag;
262 }
263 
GetNext()264 inline b2Contact* b2Contact::GetNext()
265 {
266 	return m_next;
267 }
268 
GetNext()269 inline const b2Contact* b2Contact::GetNext() const
270 {
271 	return m_next;
272 }
273 
GetFixtureA()274 inline b2Fixture* b2Contact::GetFixtureA()
275 {
276 	return m_fixtureA;
277 }
278 
GetFixtureA()279 inline const b2Fixture* b2Contact::GetFixtureA() const
280 {
281 	return m_fixtureA;
282 }
283 
GetFixtureB()284 inline b2Fixture* b2Contact::GetFixtureB()
285 {
286 	return m_fixtureB;
287 }
288 
GetChildIndexA()289 inline int32 b2Contact::GetChildIndexA() const
290 {
291 	return m_indexA;
292 }
293 
GetFixtureB()294 inline const b2Fixture* b2Contact::GetFixtureB() const
295 {
296 	return m_fixtureB;
297 }
298 
GetChildIndexB()299 inline int32 b2Contact::GetChildIndexB() const
300 {
301 	return m_indexB;
302 }
303 
FlagForFiltering()304 inline void b2Contact::FlagForFiltering()
305 {
306 	m_flags |= e_filterFlag;
307 }
308 
SetFriction(float32 friction)309 inline void b2Contact::SetFriction(float32 friction)
310 {
311 	m_friction = friction;
312 }
313 
GetFriction()314 inline float32 b2Contact::GetFriction() const
315 {
316 	return m_friction;
317 }
318 
ResetFriction()319 inline void b2Contact::ResetFriction()
320 {
321 	m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction);
322 }
323 
SetRestitution(float32 restitution)324 inline void b2Contact::SetRestitution(float32 restitution)
325 {
326 	m_restitution = restitution;
327 }
328 
GetRestitution()329 inline float32 b2Contact::GetRestitution() const
330 {
331 	return m_restitution;
332 }
333 
ResetRestitution()334 inline void b2Contact::ResetRestitution()
335 {
336 	m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution);
337 }
338 
SetTangentSpeed(float32 speed)339 inline void b2Contact::SetTangentSpeed(float32 speed)
340 {
341 	m_tangentSpeed = speed;
342 }
343 
GetTangentSpeed()344 inline float32 b2Contact::GetTangentSpeed() const
345 {
346 	return m_tangentSpeed;
347 }
348 
349 #endif
350