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#include <Box2D/Dynamics/b2Fixture.h>
20#include <Box2D/Dynamics/Contacts/b2Contact.h>
21#include <Box2D/Dynamics/b2World.h>
22#include <Box2D/Collision/Shapes/b2CircleShape.h>
23#include <Box2D/Collision/Shapes/b2EdgeShape.h>
24#include <Box2D/Collision/Shapes/b2PolygonShape.h>
25#include <Box2D/Collision/Shapes/b2ChainShape.h>
26#include <Box2D/Collision/b2BroadPhase.h>
27#include <Box2D/Collision/b2Collision.h>
28#include <Box2D/Common/b2BlockAllocator.h>
29
30b2Fixture::b2Fixture()
31{
32 m_userData = NULL;
33 m_body = NULL;
34 m_next = NULL;
35 m_proxies = NULL;
36 m_proxyCount = 0;
37 m_shape = NULL;
38 m_density = 0.0f;
39}
40
41void b2Fixture::Create(b2BlockAllocator* allocator, b2Body* body, const b2FixtureDef* def)
42{
43 m_userData = def->userData;
44 m_friction = def->friction;
45 m_restitution = def->restitution;
46
47 m_body = body;
48 m_next = NULL;
49
50 m_filter = def->filter;
51
52 m_isSensor = def->isSensor;
53
54 m_shape = def->shape->Clone(allocator);
55
56 // Reserve proxy space
57 int32 childCount = m_shape->GetChildCount();
58 m_proxies = (b2FixtureProxy*)allocator->Allocate(childCount * sizeof(b2FixtureProxy));
59 for (int32 i = 0; i < childCount; ++i)
60 {
61 m_proxies[i].fixture = NULL;
62 m_proxies[i].proxyId = b2BroadPhase::e_nullProxy;
63 }
64 m_proxyCount = 0;
65
66 m_density = def->density;
67}
68
69void b2Fixture::Destroy(b2BlockAllocator* allocator)
70{
71 // The proxies must be destroyed before calling this.
72 b2Assert(m_proxyCount == 0);
73
74 // Free the proxy array.
75 int32 childCount = m_shape->GetChildCount();
76 allocator->Free(m_proxies, childCount * sizeof(b2FixtureProxy));
77 m_proxies = NULL;
78
79 // Free the child shape.
80 switch (m_shape->m_type)
81 {
82 case b2Shape::e_circle:
83 {
84 b2CircleShape* s = (b2CircleShape*)m_shape;
85 s->~b2CircleShape();
86 allocator->Free(s, sizeof(b2CircleShape));
87 }
88 break;
89
90 case b2Shape::e_edge:
91 {
92 b2EdgeShape* s = (b2EdgeShape*)m_shape;
93 s->~b2EdgeShape();
94 allocator->Free(s, sizeof(b2EdgeShape));
95 }
96 break;
97
98 case b2Shape::e_polygon:
99 {
100 b2PolygonShape* s = (b2PolygonShape*)m_shape;
101 s->~b2PolygonShape();
102 allocator->Free(s, sizeof(b2PolygonShape));
103 }
104 break;
105
106 case b2Shape::e_chain:
107 {
108 b2ChainShape* s = (b2ChainShape*)m_shape;
109 s->~b2ChainShape();
110 allocator->Free(s, sizeof(b2ChainShape));
111 }
112 break;
113
114 default:
115 b2Assert(false);
116 break;
117 }
118
119 m_shape = NULL;
120}
121
122void b2Fixture::CreateProxies(b2BroadPhase* broadPhase, const b2Transform& xf)
123{
124 b2Assert(m_proxyCount == 0);
125
126 // Create proxies in the broad-phase.
127 m_proxyCount = m_shape->GetChildCount();
128
129 for (int32 i = 0; i < m_proxyCount; ++i)
130 {
131 b2FixtureProxy* proxy = m_proxies + i;
132 m_shape->ComputeAABB(&proxy->aabb, xf, i);
133 proxy->proxyId = broadPhase->CreateProxy(proxy->aabb, proxy);
134 proxy->fixture = this;
135 proxy->childIndex = i;
136 }
137}
138
139void b2Fixture::DestroyProxies(b2BroadPhase* broadPhase)
140{
141 // Destroy proxies in the broad-phase.
142 for (int32 i = 0; i < m_proxyCount; ++i)
143 {
144 b2FixtureProxy* proxy = m_proxies + i;
145 broadPhase->DestroyProxy(proxy->proxyId);
146 proxy->proxyId = b2BroadPhase::e_nullProxy;
147 }
148
149 m_proxyCount = 0;
150}
151
152void b2Fixture::Synchronize(b2BroadPhase* broadPhase, const b2Transform& transform1, const b2Transform& transform2)
153{
154 if (m_proxyCount == 0)
155 {
156 return;
157 }
158
159 for (int32 i = 0; i < m_proxyCount; ++i)
160 {
161 b2FixtureProxy* proxy = m_proxies + i;
162
163 // Compute an AABB that covers the swept shape (may miss some rotation effect).
164 b2AABB aabb1, aabb2;
165 m_shape->ComputeAABB(&aabb1, transform1, proxy->childIndex);
166 m_shape->ComputeAABB(&aabb2, transform2, proxy->childIndex);
167
168 proxy->aabb.Combine(aabb1, aabb2);
169
170 b2Vec2 displacement = transform2.p - transform1.p;
171
172 broadPhase->MoveProxy(proxy->proxyId, proxy->aabb, displacement);
173 }
174}
175
176void b2Fixture::SetFilterData(const b2Filter& filter)
177{
178 m_filter = filter;
179
180 Refilter();
181}
182
183void b2Fixture::Refilter()
184{
185 if (m_body == NULL)
186 {
187 return;
188 }
189
190 // Flag associated contacts for filtering.
191 b2ContactEdge* edge = m_body->GetContactList();
192 while (edge)
193 {
194 b2Contact* contact = edge->contact;
195 b2Fixture* fixtureA = contact->GetFixtureA();
196 b2Fixture* fixtureB = contact->GetFixtureB();
197 if (fixtureA == this || fixtureB == this)
198 {
199 contact->FlagForFiltering();
200 }
201
202 edge = edge->next;
203 }
204
205 b2World* world = m_body->GetWorld();
206
207 if (world == NULL)
208 {
209 return;
210 }
211
212 // Touch each proxy so that new pairs may be created
213 b2BroadPhase* broadPhase = &world->m_contactManager.m_broadPhase;
214 for (int32 i = 0; i < m_proxyCount; ++i)
215 {
216 broadPhase->TouchProxy(m_proxies[i].proxyId);
217 }
218}
219
220void b2Fixture::SetSensor(bool sensor)
221{
222 if (sensor != m_isSensor)
223 {
224 m_body->SetAwake(true);
225 m_isSensor = sensor;
226 }
227}
228
229void b2Fixture::Dump(int32 bodyIndex)
230{
231 b2Log(" b2FixtureDef fd;\n");
232 b2Log(" fd.friction = %.15lef;\n", m_friction);
233 b2Log(" fd.restitution = %.15lef;\n", m_restitution);
234 b2Log(" fd.density = %.15lef;\n", m_density);
235 b2Log(" fd.isSensor = bool(%d);\n", m_isSensor);
236 b2Log(" fd.filter.categoryBits = uint16(%d);\n", m_filter.categoryBits);
237 b2Log(" fd.filter.maskBits = uint16(%d);\n", m_filter.maskBits);
238 b2Log(" fd.filter.groupIndex = int16(%d);\n", m_filter.groupIndex);
239
240 switch (m_shape->m_type)
241 {
242 case b2Shape::e_circle:
243 {
244 b2CircleShape* s = (b2CircleShape*)m_shape;
245 b2Log(" b2CircleShape shape;\n");
246 b2Log(" shape.m_radius = %.15lef;\n", s->m_radius);
247 b2Log(" shape.m_p.Set(%.15lef, %.15lef);\n", s->m_p.x, s->m_p.y);
248 }
249 break;
250
251 case b2Shape::e_edge:
252 {
253 b2EdgeShape* s = (b2EdgeShape*)m_shape;
254 b2Log(" b2EdgeShape shape;\n");
255 b2Log(" shape.m_radius = %.15lef;\n", s->m_radius);
256 b2Log(" shape.m_vertex0.Set(%.15lef, %.15lef);\n", s->m_vertex0.x, s->m_vertex0.y);
257 b2Log(" shape.m_vertex1.Set(%.15lef, %.15lef);\n", s->m_vertex1.x, s->m_vertex1.y);
258 b2Log(" shape.m_vertex2.Set(%.15lef, %.15lef);\n", s->m_vertex2.x, s->m_vertex2.y);
259 b2Log(" shape.m_vertex3.Set(%.15lef, %.15lef);\n", s->m_vertex3.x, s->m_vertex3.y);
260 b2Log(" shape.m_hasVertex0 = bool(%d);\n", s->m_hasVertex0);
261 b2Log(" shape.m_hasVertex3 = bool(%d);\n", s->m_hasVertex3);
262 }
263 break;
264
265 case b2Shape::e_polygon:
266 {
267 b2PolygonShape* s = (b2PolygonShape*)m_shape;
268 b2Log(" b2PolygonShape shape;\n");
269 b2Log(" b2Vec2 vs[%d];\n", b2_maxPolygonVertices);
270 for (int32 i = 0; i < s->m_count; ++i)
271 {
272 b2Log(" vs[%d].Set(%.15lef, %.15lef);\n", i, s->m_vertices[i].x, s->m_vertices[i].y);
273 }
274 b2Log(" shape.Set(vs, %d);\n", s->m_count);
275 }
276 break;
277
278 case b2Shape::e_chain:
279 {
280 b2ChainShape* s = (b2ChainShape*)m_shape;
281 b2Log(" b2ChainShape shape;\n");
282 b2Log(" b2Vec2 vs[%d];\n", s->m_count);
283 for (int32 i = 0; i < s->m_count; ++i)
284 {
285 b2Log(" vs[%d].Set(%.15lef, %.15lef);\n", i, s->m_vertices[i].x, s->m_vertices[i].y);
286 }
287 b2Log(" shape.CreateChain(vs, %d);\n", s->m_count);
288 b2Log(" shape.m_prevVertex.Set(%.15lef, %.15lef);\n", s->m_prevVertex.x, s->m_prevVertex.y);
289 b2Log(" shape.m_nextVertex.Set(%.15lef, %.15lef);\n", s->m_nextVertex.x, s->m_nextVertex.y);
290 b2Log(" shape.m_hasPrevVertex = bool(%d);\n", s->m_hasPrevVertex);
291 b2Log(" shape.m_hasNextVertex = bool(%d);\n", s->m_hasNextVertex);
292 }
293 break;
294
295 default:
296 return;
297 }
298
299 b2Log("\n");
300 b2Log(" fd.shape = &shape;\n");
301 b2Log("\n");
302 b2Log(" bodies[%d]->CreateFixture(&fd);\n", bodyIndex);
303}
304