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
27class b2Body;
28class b2Contact;
29class b2Fixture;
30class b2World;
31class b2BlockAllocator;
32class b2StackAllocator;
33class 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.
37inline 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.
44inline float32 b2MixRestitution(float32 restitution1, float32 restitution2)
45{
46	return restitution1 > restitution2 ? restitution1 : restitution2;
47}
48
49typedef b2Contact* b2ContactCreateFcn(	b2Fixture* fixtureA, int32 indexA,
50										b2Fixture* fixtureB, int32 indexB,
51										b2BlockAllocator* allocator);
52typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator);
53
54struct 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.
66struct 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.
77class b2Contact
78{
79public:
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
147protected:
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
186	b2Contact() : m_fixtureA(NULL), m_fixtureB(NULL) {}
187	b2Contact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB);
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
222inline b2Manifold* b2Contact::GetManifold()
223{
224	return &m_manifold;
225}
226
227inline const b2Manifold* b2Contact::GetManifold() const
228{
229	return &m_manifold;
230}
231
232inline 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
242inline 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
254inline bool b2Contact::IsEnabled() const
255{
256	return (m_flags & e_enabledFlag) == e_enabledFlag;
257}
258
259inline bool b2Contact::IsTouching() const
260{
261	return (m_flags & e_touchingFlag) == e_touchingFlag;
262}
263
264inline b2Contact* b2Contact::GetNext()
265{
266	return m_next;
267}
268
269inline const b2Contact* b2Contact::GetNext() const
270{
271	return m_next;
272}
273
274inline b2Fixture* b2Contact::GetFixtureA()
275{
276	return m_fixtureA;
277}
278
279inline const b2Fixture* b2Contact::GetFixtureA() const
280{
281	return m_fixtureA;
282}
283
284inline b2Fixture* b2Contact::GetFixtureB()
285{
286	return m_fixtureB;
287}
288
289inline int32 b2Contact::GetChildIndexA() const
290{
291	return m_indexA;
292}
293
294inline const b2Fixture* b2Contact::GetFixtureB() const
295{
296	return m_fixtureB;
297}
298
299inline int32 b2Contact::GetChildIndexB() const
300{
301	return m_indexB;
302}
303
304inline void b2Contact::FlagForFiltering()
305{
306	m_flags |= e_filterFlag;
307}
308
309inline void b2Contact::SetFriction(float32 friction)
310{
311	m_friction = friction;
312}
313
314inline float32 b2Contact::GetFriction() const
315{
316	return m_friction;
317}
318
319inline void b2Contact::ResetFriction()
320{
321	m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction);
322}
323
324inline void b2Contact::SetRestitution(float32 restitution)
325{
326	m_restitution = restitution;
327}
328
329inline float32 b2Contact::GetRestitution() const
330{
331	return m_restitution;
332}
333
334inline void b2Contact::ResetRestitution()
335{
336	m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution);
337}
338
339inline void b2Contact::SetTangentSpeed(float32 speed)
340{
341	m_tangentSpeed = speed;
342}
343
344inline float32 b2Contact::GetTangentSpeed() const
345{
346	return m_tangentSpeed;
347}
348
349#endif
350