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