Home | History | Annotate | Download | only in Dynamics
      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 
     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 
     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 
     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 
    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 
    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 
    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 
    176 void b2Fixture::SetFilterData(const b2Filter& filter)
    177 {
    178 	m_filter = filter;
    179 
    180 	Refilter();
    181 }
    182 
    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 
    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 
    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