2 * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
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.
19 #include "b2Contact.h"
20 #include "b2CircleContact.h"
21 #include "b2PolyAndCircleContact.h"
22 #include "b2PolyContact.h"
23 #include "b2ContactSolver.h"
24 #include "../../Collision/b2Collision.h"
25 #include "../../Collision/Shapes/b2Shape.h"
26 #include "../../Common/b2BlockAllocator.h"
27 #include "../../Dynamics/b2World.h"
28 #include "../../Dynamics/b2Body.h"
30 b2ContactRegister b2Contact::s_registers[e_shapeTypeCount][e_shapeTypeCount];
31 bool b2Contact::s_initialized = false;
33 void b2Contact::InitializeRegisters()
35 AddType(b2CircleContact::Create, b2CircleContact::Destroy, e_circleShape, e_circleShape);
36 AddType(b2PolyAndCircleContact::Create, b2PolyAndCircleContact::Destroy, e_polygonShape, e_circleShape);
37 AddType(b2PolygonContact::Create, b2PolygonContact::Destroy, e_polygonShape, e_polygonShape);
40 void b2Contact::AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destoryFcn,
41 b2ShapeType type1, b2ShapeType type2)
43 b2Assert(e_unknownShape < type1 && type1 < e_shapeTypeCount);
44 b2Assert(e_unknownShape < type2 && type2 < e_shapeTypeCount);
46 s_registers[type1][type2].createFcn = createFcn;
47 s_registers[type1][type2].destroyFcn = destoryFcn;
48 s_registers[type1][type2].primary = true;
52 s_registers[type2][type1].createFcn = createFcn;
53 s_registers[type2][type1].destroyFcn = destoryFcn;
54 s_registers[type2][type1].primary = false;
58 b2Contact* b2Contact::Create(b2Shape* shape1, b2Shape* shape2, b2BlockAllocator* allocator)
60 if (s_initialized == false)
62 InitializeRegisters();
66 b2ShapeType type1 = shape1->GetType();
67 b2ShapeType type2 = shape2->GetType();
69 b2Assert(e_unknownShape < type1 && type1 < e_shapeTypeCount);
70 b2Assert(e_unknownShape < type2 && type2 < e_shapeTypeCount);
72 b2ContactCreateFcn* createFcn = s_registers[type1][type2].createFcn;
75 if (s_registers[type1][type2].primary)
77 return createFcn(shape1, shape2, allocator);
81 b2Contact* c = createFcn(shape2, shape1, allocator);
82 for (int32 i = 0; i < c->GetManifoldCount(); ++i)
84 b2Manifold* m = c->GetManifolds() + i;
85 m->normal = -m->normal;
96 void b2Contact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
98 b2Assert(s_initialized == true);
100 if (contact->GetManifoldCount() > 0)
102 contact->GetShape1()->GetBody()->WakeUp();
103 contact->GetShape2()->GetBody()->WakeUp();
106 b2ShapeType type1 = contact->GetShape1()->GetType();
107 b2ShapeType type2 = contact->GetShape2()->GetType();
109 b2Assert(e_unknownShape < type1 && type1 < e_shapeTypeCount);
110 b2Assert(e_unknownShape < type2 && type2 < e_shapeTypeCount);
112 b2ContactDestroyFcn* destroyFcn = s_registers[type1][type2].destroyFcn;
113 destroyFcn(contact, allocator);
116 b2Contact::b2Contact(b2Shape* s1, b2Shape* s2)
120 if (s1->IsSensor() || s2->IsSensor())
122 m_flags |= e_nonSolidFlag;
130 m_friction = b2MixFriction(m_shape1->GetFriction(), m_shape2->GetFriction());
131 m_restitution = b2MixRestitution(m_shape1->GetRestitution(), m_shape2->GetRestitution());
135 m_node1.contact = NULL;
138 m_node1.other = NULL;
140 m_node2.contact = NULL;
143 m_node2.other = NULL;
146 void b2Contact::Update(b2ContactListener* listener)
148 int32 oldCount = GetManifoldCount();
152 int32 newCount = GetManifoldCount();
154 b2Body* body1 = m_shape1->GetBody();
155 b2Body* body2 = m_shape2->GetBody();
157 if (newCount == 0 && oldCount > 0)
163 // Slow contacts don't generate TOI events.
164 if (body1->IsStatic() || body1->IsBullet() || body2->IsStatic() || body2->IsBullet())
166 m_flags &= ~e_slowFlag;
170 m_flags |= e_slowFlag;