internal Fixture() { _userData = null; _body = null; _next = null; _proxyId = BroadPhase.NullProxy; _shape = null; }
internal PolygonAndCircleContact(Fixture fixtureA, Fixture fixtureB) : base(fixtureA, fixtureB) { Debug.Assert(_fixtureA.ShapeType == ShapeType.Polygon); Debug.Assert(_fixtureB.ShapeType == ShapeType.Circle); }
// Broad-phase callback. internal void AddPair(Fixture proxyUserDataA, Fixture proxyUserDataB) { Fixture fixtureA = proxyUserDataA; Fixture fixtureB = proxyUserDataB; Body bodyA = fixtureA.GetBody(); Body bodyB = fixtureB.GetBody(); // Are the fixtures on the same body? if (bodyA == bodyB) { return; } // Are both bodies static? if (bodyA.IsStatic && bodyB.IsStatic) { return; } // Does a contact already exist? ContactEdge edge = bodyB.GetConactList(); while (edge != null) { if (edge.Other == bodyA) { Fixture fA = edge.Contact.GetFixtureA(); Fixture fB = edge.Contact.GetFixtureB(); if (fA == fixtureA && fB == fixtureB) { // A contact already exists. return; } if (fA == fixtureB && fB == fixtureA) { // A contact already exists. return; } } edge = edge.Next; } // Does a joint override collision? if (bodyB.IsConnected(bodyA)) { return; } // Check user filtering. if (ContactFilter.ShouldCollide(fixtureA, fixtureB) == false) { return; } // Call the factory. Contact c = Contact.Create(fixtureA, fixtureB); // Contact creation may swap fixtures. fixtureA = c.GetFixtureA(); fixtureB = c.GetFixtureB(); bodyA = fixtureA.GetBody(); bodyB = fixtureB.GetBody(); // Insert into the world. c._prev = null; c._next = _contactList; if (_contactList != null) { _contactList._prev = c; } _contactList = c; // Connect to island graph. // Connect to body A c._nodeA.Contact = c; c._nodeA.Other = bodyB; c._nodeA.Prev = null; c._nodeA.Next = bodyA._contactList; if (bodyA._contactList != null) { bodyA._contactList.Prev = c._nodeA; } bodyA._contactList = c._nodeA; // Connect to body B c._nodeB.Contact = c; c._nodeB.Other = bodyA; c._nodeB.Prev = null; c._nodeB.Next = bodyB._contactList; if (bodyB._contactList != null) { bodyB._contactList.Prev = c._nodeB; } bodyB._contactList = c._nodeB; ++_contactCount; }
// We need separation create/destroy functions from the ructor/destructor because // the destructor cannot access the allocator or broad-phase (no destructor arguments allowed by C++). internal void Create(BroadPhase broadPhase, Body body, ref XForm xf, FixtureDef def) { _userData = def.userData; _friction = def.friction; _restitution = def.restitution; _density = def.density; _body = body; _next = null; _filter = def.filter; _isSensor = def.isSensor; _shape = def.shape.Clone(); // Create proxy in the broad-phase. AABB aabb; _shape.ComputeAABB(out aabb, ref xf); _proxyId = broadPhase.CreateProxy(ref aabb, this); }
internal XForm _xf; // the body origin transform #endregion Fields #region Constructors internal Body(BodyDef bd, World world) { _flags = 0; if (bd.isBullet) { _flags |= BodyFlags.Bullet; } if (bd.fixedRotation) { _flags |= BodyFlags.FixedRotation; } if (bd.allowSleep) { _flags |= BodyFlags.AllowSleep; } if (bd.isSleeping) { _flags |= BodyFlags.Sleep; } _world = world; _xf.Position = bd.position; _xf.R.Set(bd.angle); _sweep.localCenter = bd.massData.center; _sweep.t0 = 1.0f; _sweep.a0 = _sweep.a = bd.angle; _sweep.c0 = _sweep.c = MathUtils.Multiply(ref _xf, _sweep.localCenter); _jointList = null; _contactList = null; _prev = null; _next = null; _linearVelocity = bd.linearVelocity; _angularVelocity = bd.angularVelocity; _linearDamping = bd.linearDamping; _angularDamping = bd.angularDamping; _force = new Vector2(0.0f, 0.0f); _torque = 0.0f; _linearVelocity = Vector2.Zero; _angularVelocity = 0.0f; _sleepTime = 0.0f; _invMass = 0.0f; _I = 0.0f; _invI = 0.0f; _mass = bd.massData.mass; if (_mass > 0.0f) { _invMass = 1.0f / _mass; } _I = bd.massData.i; if (_I > 0.0f && (_flags & BodyFlags.FixedRotation) == 0) { _invI = 1.0f / _I; } if (_invMass == 0.0f && _invI == 0.0f) { _type = BodyType.Static; } else { _type = BodyType.Dynamic; } _userData = bd.userData; _fixtureList = null; _fixtureCount = 0; }
/// Destroy a fixture. This removes the fixture from the broad-phase and /// therefore destroys any contacts associated with this fixture. All fixtures /// attached to a body are implicitly destroyed when the body is destroyed. /// @param fixture the fixture to be removed. /// @warning This function is locked during callbacks. public void DestroyFixture(Fixture fixture) { Debug.Assert(_world.IsLocked == false); if (_world.IsLocked == true) { return; } Debug.Assert(fixture._body == this); // Remove the fixture from this body's singly linked list. Debug.Assert(_fixtureCount > 0); Fixture node = _fixtureList; bool found = false; while (node != null) { if (node == fixture) { _fixtureList = fixture._next; found = true; break; } node = node._next; } // You tried to remove a shape that is not attached to this body. Debug.Assert(found); // Destroy any contacts associated with the fixture. ContactEdge edge = _contactList; while (edge != null) { Contact c = edge.Contact; edge = edge.Next; Fixture fixtureA = c.GetFixtureA(); Fixture fixtureB = c.GetFixtureB(); if (fixture == fixtureA || fixture == fixtureB) { // This destroys the contact and removes it from // this body's contact list. _world._contactManager.Destroy(c); } } BroadPhase broadPhase = _world._contactManager._broadPhase; fixture.Destroy(broadPhase); fixture._body = null; fixture._next = null; --_fixtureCount; }
/// Creates a fixture from a shape and attach it to this body. /// This is a convenience function. Use FixtureDef if you need to set parameters /// like friction, restitution, user data, or filtering. /// @param shape the shape to be cloned. /// @param density the shape density (set to zero for static bodies). /// @warning This function is locked during callbacks. public Fixture CreateFixture(Shape shape, float density) { Debug.Assert(_world.IsLocked == false); if (_world.IsLocked == true) { return null; } BroadPhase broadPhase = _world._contactManager._broadPhase; FixtureDef def = new FixtureDef(); def.shape = shape; def.density = density; Fixture fixture = new Fixture(); fixture.Create(broadPhase, this, ref _xf, def); fixture._next = _fixtureList; _fixtureList = fixture; ++_fixtureCount; fixture._body = this; // Let the world know we have a new fixture. _world._flags |= WorldFlags.NewFixture; return fixture; }
void DrawShape(Fixture fixture, XForm xf, Color color) { Color coreColor = ColorEx.FromScRgb(0.9f, 0.6f, 0.6f); switch (fixture.ShapeType) { case ShapeType.Circle: { CircleShape circle = (CircleShape)fixture.GetShape(); Vector2 center = MathUtils.Multiply(ref xf, circle._p); float radius = circle._radius; Vector2 axis = xf.R.col1; DebugDraw.DrawSolidCircle(center, radius, axis, color); } break; case ShapeType.Polygon: { PolygonShape poly = (PolygonShape)fixture.GetShape(); int vertexCount = poly._vertexCount; Debug.Assert(vertexCount <= Settings.b2_maxPolygonVertices); FixedArray8<Vector2> vertices = new FixedArray8<Vector2>(); for (int i = 0; i < vertexCount; ++i) { vertices[i] = MathUtils.Multiply(ref xf, poly._vertices[i]); } DebugDraw.DrawSolidPolygon(ref vertices, vertexCount, color); } break; } }