File indexing completed on 2025-08-03 03:50:01
0001 /* 0002 * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com 0003 * 0004 * This software is provided 'as-is', without any express or implied 0005 * warranty. In no event will the authors be held liable for any damages 0006 * arising from the use of this software. 0007 * Permission is granted to anyone to use this software for any purpose, 0008 * including commercial applications, and to alter it and redistribute it 0009 * freely, subject to the following restrictions: 0010 * 1. The origin of this software must not be misrepresented; you must not 0011 * claim that you wrote the original software. If you use this software 0012 * in a product, an acknowledgment in the product documentation would be 0013 * appreciated but is not required. 0014 * 2. Altered source versions must be plainly marked as such, and must not be 0015 * misrepresented as being the original software. 0016 * 3. This notice may not be removed or altered from any source distribution. 0017 */ 0018 0019 #include <Box2D/Dynamics/b2Fixture.h> 0020 #include <Box2D/Dynamics/Contacts/b2Contact.h> 0021 #include <Box2D/Collision/Shapes/b2CircleShape.h> 0022 #include <Box2D/Collision/Shapes/b2EdgeShape.h> 0023 #include <Box2D/Collision/Shapes/b2PolygonShape.h> 0024 #include <Box2D/Collision/Shapes/b2LoopShape.h> 0025 #include <Box2D/Collision/b2BroadPhase.h> 0026 #include <Box2D/Common/b2BlockAllocator.h> 0027 0028 b2Fixture::b2Fixture() 0029 { 0030 m_userData = NULL; 0031 m_body = NULL; 0032 m_next = NULL; 0033 m_proxies = NULL; 0034 m_proxyCount = 0; 0035 m_shape = NULL; 0036 m_density = 0.0f; 0037 } 0038 0039 void b2Fixture::Create(b2BlockAllocator* allocator, b2Body* body, const b2FixtureDef* def) 0040 { 0041 m_userData = def->userData; 0042 m_friction = def->friction; 0043 m_restitution = def->restitution; 0044 0045 m_body = body; 0046 m_next = NULL; 0047 0048 m_filter = def->filter; 0049 0050 m_isSensor = def->isSensor; 0051 0052 m_shape = def->shape->Clone(allocator); 0053 0054 // Reserve proxy space 0055 int32 childCount = m_shape->GetChildCount(); 0056 m_proxies = (b2FixtureProxy*)allocator->Allocate(childCount * sizeof(b2FixtureProxy)); 0057 for (int32 i = 0; i < childCount; ++i) 0058 { 0059 m_proxies[i].fixture = NULL; 0060 m_proxies[i].proxyId = b2BroadPhase::e_nullProxy; 0061 } 0062 m_proxyCount = 0; 0063 0064 m_density = def->density; 0065 } 0066 0067 void b2Fixture::Destroy(b2BlockAllocator* allocator) 0068 { 0069 // The proxies must be destroyed before calling this. 0070 b2Assert(m_proxyCount == 0); 0071 0072 // Free the proxy array. 0073 int32 childCount = m_shape->GetChildCount(); 0074 allocator->Free(m_proxies, childCount * sizeof(b2FixtureProxy)); 0075 m_proxies = NULL; 0076 0077 // Free the child shape. 0078 switch (m_shape->m_type) 0079 { 0080 case b2Shape::e_circle: 0081 { 0082 b2CircleShape* s = (b2CircleShape*)m_shape; 0083 s->~b2CircleShape(); 0084 allocator->Free(s, sizeof(b2CircleShape)); 0085 } 0086 break; 0087 0088 case b2Shape::e_edge: 0089 { 0090 b2EdgeShape* s = (b2EdgeShape*)m_shape; 0091 s->~b2EdgeShape(); 0092 allocator->Free(s, sizeof(b2EdgeShape)); 0093 } 0094 break; 0095 0096 case b2Shape::e_polygon: 0097 { 0098 b2PolygonShape* s = (b2PolygonShape*)m_shape; 0099 s->~b2PolygonShape(); 0100 allocator->Free(s, sizeof(b2PolygonShape)); 0101 } 0102 break; 0103 0104 case b2Shape::e_loop: 0105 { 0106 b2LoopShape* s = (b2LoopShape*)m_shape; 0107 s->~b2LoopShape(); 0108 allocator->Free(s, sizeof(b2LoopShape)); 0109 } 0110 break; 0111 0112 default: 0113 b2Assert(false); 0114 break; 0115 } 0116 0117 m_shape = NULL; 0118 } 0119 0120 void b2Fixture::CreateProxies(b2BroadPhase* broadPhase, const b2Transform& xf) 0121 { 0122 b2Assert(m_proxyCount == 0); 0123 0124 // Create proxies in the broad-phase. 0125 m_proxyCount = m_shape->GetChildCount(); 0126 0127 for (int32 i = 0; i < m_proxyCount; ++i) 0128 { 0129 b2FixtureProxy* proxy = m_proxies + i; 0130 m_shape->ComputeAABB(&proxy->aabb, xf, i); 0131 proxy->proxyId = broadPhase->CreateProxy(proxy->aabb, proxy); 0132 proxy->fixture = this; 0133 proxy->childIndex = i; 0134 } 0135 } 0136 0137 void b2Fixture::DestroyProxies(b2BroadPhase* broadPhase) 0138 { 0139 // Destroy proxies in the broad-phase. 0140 for (int32 i = 0; i < m_proxyCount; ++i) 0141 { 0142 b2FixtureProxy* proxy = m_proxies + i; 0143 broadPhase->DestroyProxy(proxy->proxyId); 0144 proxy->proxyId = b2BroadPhase::e_nullProxy; 0145 } 0146 0147 m_proxyCount = 0; 0148 } 0149 0150 void b2Fixture::Synchronize(b2BroadPhase* broadPhase, const b2Transform& transform1, const b2Transform& transform2) 0151 { 0152 if (m_proxyCount == 0) 0153 { 0154 return; 0155 } 0156 0157 for (int32 i = 0; i < m_proxyCount; ++i) 0158 { 0159 b2FixtureProxy* proxy = m_proxies + i; 0160 0161 // Compute an AABB that covers the swept shape (may miss some rotation effect). 0162 b2AABB aabb1, aabb2; 0163 m_shape->ComputeAABB(&aabb1, transform1, proxy->childIndex); 0164 m_shape->ComputeAABB(&aabb2, transform2, proxy->childIndex); 0165 0166 proxy->aabb.Combine(aabb1, aabb2); 0167 0168 b2Vec2 displacement = transform2.position - transform1.position; 0169 0170 broadPhase->MoveProxy(proxy->proxyId, proxy->aabb, displacement); 0171 } 0172 } 0173 0174 void b2Fixture::SetFilterData(const b2Filter& filter) 0175 { 0176 m_filter = filter; 0177 0178 if (m_body == NULL) 0179 { 0180 return; 0181 } 0182 0183 // Flag associated contacts for filtering. 0184 b2ContactEdge* edge = m_body->GetContactList(); 0185 while (edge) 0186 { 0187 b2Contact* contact = edge->contact; 0188 b2Fixture* fixtureA = contact->GetFixtureA(); 0189 b2Fixture* fixtureB = contact->GetFixtureB(); 0190 if (fixtureA == this || fixtureB == this) 0191 { 0192 contact->FlagForFiltering(); 0193 } 0194 0195 edge = edge->next; 0196 } 0197 } 0198 0199 void b2Fixture::SetSensor(bool sensor) 0200 { 0201 m_isSensor = sensor; 0202 } 0203