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. |
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. |
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 | |
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 | |
222 | inline b2Manifold* b2Contact::GetManifold() |
223 | { |
224 | return &m_manifold; |
225 | } |
226 | |
227 | inline const b2Manifold* b2Contact::GetManifold() const |
228 | { |
229 | return &m_manifold; |
230 | } |
231 | |
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 | |
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 | |
254 | inline bool b2Contact::IsEnabled() const |
255 | { |
256 | return (m_flags & e_enabledFlag) == e_enabledFlag; |
257 | } |
258 | |
259 | inline bool b2Contact::IsTouching() const |
260 | { |
261 | return (m_flags & e_touchingFlag) == e_touchingFlag; |
262 | } |
263 | |
264 | inline b2Contact* b2Contact::GetNext() |
265 | { |
266 | return m_next; |
267 | } |
268 | |
269 | inline const b2Contact* b2Contact::GetNext() const |
270 | { |
271 | return m_next; |
272 | } |
273 | |
274 | inline b2Fixture* b2Contact::GetFixtureA() |
275 | { |
276 | return m_fixtureA; |
277 | } |
278 | |
279 | inline const b2Fixture* b2Contact::GetFixtureA() const |
280 | { |
281 | return m_fixtureA; |
282 | } |
283 | |
284 | inline b2Fixture* b2Contact::GetFixtureB() |
285 | { |
286 | return m_fixtureB; |
287 | } |
288 | |
289 | inline int32 b2Contact::GetChildIndexA() const |
290 | { |
291 | return m_indexA; |
292 | } |
293 | |
294 | inline const b2Fixture* b2Contact::GetFixtureB() const |
295 | { |
296 | return m_fixtureB; |
297 | } |
298 | |
299 | inline int32 b2Contact::GetChildIndexB() const |
300 | { |
301 | return m_indexB; |
302 | } |
303 | |
304 | inline void b2Contact::FlagForFiltering() |
305 | { |
306 | m_flags |= e_filterFlag; |
307 | } |
308 | |
309 | inline void b2Contact::SetFriction(float32 friction) |
310 | { |
311 | m_friction = friction; |
312 | } |
313 | |
314 | inline float32 b2Contact::GetFriction() const |
315 | { |
316 | return m_friction; |
317 | } |
318 | |
319 | inline void b2Contact::ResetFriction() |
320 | { |
321 | m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction); |
322 | } |
323 | |
324 | inline void b2Contact::SetRestitution(float32 restitution) |
325 | { |
326 | m_restitution = restitution; |
327 | } |
328 | |
329 | inline float32 b2Contact::GetRestitution() const |
330 | { |
331 | return m_restitution; |
332 | } |
333 | |
334 | inline void b2Contact::ResetRestitution() |
335 | { |
336 | m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution); |
337 | } |
338 | |
339 | inline void b2Contact::SetTangentSpeed(float32 speed) |
340 | { |
341 | m_tangentSpeed = speed; |
342 | } |
343 | |
344 | inline float32 b2Contact::GetTangentSpeed() const |
345 | { |
346 | return m_tangentSpeed; |
347 | } |
348 | |
349 | #endif |
350 | |