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