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 
b2Fixture()30 b2Fixture::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 
Create(b2BlockAllocator * allocator,b2Body * body,const b2FixtureDef * def)41 void 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 
Destroy(b2BlockAllocator * allocator)69 void 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 
CreateProxies(b2BroadPhase * broadPhase,const b2Transform & xf)122 void 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 
DestroyProxies(b2BroadPhase * broadPhase)139 void 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 
Synchronize(b2BroadPhase * broadPhase,const b2Transform & transform1,const b2Transform & transform2)152 void 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 
SetFilterData(const b2Filter & filter)176 void b2Fixture::SetFilterData(const b2Filter& filter)
177 {
178 	m_filter = filter;
179 
180 	Refilter();
181 }
182 
Refilter()183 void 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 
SetSensor(bool sensor)220 void b2Fixture::SetSensor(bool sensor)
221 {
222 	if (sensor != m_isSensor)
223 	{
224 		m_body->SetAwake(true);
225 		m_isSensor = sensor;
226 	}
227 }
228 
Dump(int32 bodyIndex)229 void 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