public Fixture() { m_userData = null; m_body = null; m_next = null; m_proxies = null; m_proxyCount = 0; m_shape = null; m_filter = new Filter(); }
/// <summary> /// Return true if contact calculations should be performed between these two shapes. /// </summary> /// <warning> /// for performance reasons this is only called when the AABBs begin to overlap. /// </warning> /// <param name="fixtureA"></param> /// <param name="fixtureB"></param> /// <returns></returns> public virtual bool shouldCollide(Fixture fixtureA, Fixture fixtureB) { Filter filterA = fixtureA.FilterData; Filter filterB = fixtureB.FilterData; if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0) { return filterA.groupIndex > 0; } bool collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0; return collide; }
/// <summary> /// Return true if contact calculations should be performed between these two shapes. /// </summary> /// <warning> /// for performance reasons this is only called when the AABBs begin to overlap. /// </warning> /// <param name="fixtureA"></param> /// <param name="fixtureB"></param> /// <returns></returns> public bool ShouldCollide(Fixture fixtureA, Fixture fixtureB) { var filterA = fixtureA.FilterData; var filterB = fixtureB.FilterData; if (filterA.GroupIndex == filterB.GroupIndex && filterA.GroupIndex != 0) { return filterA.GroupIndex > 0; } bool collide = (filterA.MaskBits & filterB.CategoryBits) != 0 && (filterA.CategoryBits & filterB.MaskBits) != 0; return collide; }
public virtual Contact popContact(Fixture fixtureA, int indexA, Fixture fixtureB, int indexB) { ShapeType type1 = fixtureA.Type; ShapeType type2 = fixtureB.Type; ContactRegister reg = contactStacks[(int)type1][(int)type2]; IDynamicStack<Contact> creator = reg.creator; if (creator != null) { if (reg.primary) { Contact c = creator.pop(); c.init(fixtureA, indexA, fixtureB, indexB); return c; } else { Contact c = creator.pop(); c.init(fixtureB, indexB, fixtureA, indexA); return c; } } else { return null; } }
private void drawShape(Fixture fixture, Transform xf, Color3f color) { switch (fixture.Type) { case ShapeType.CIRCLE: { CircleShape circle = (CircleShape)fixture.Shape; // Vec2 center = Mul(xf, circle.m_p); Transform.mulToOutUnsafe(xf, circle.m_p, center); float radius = circle.m_radius; xf.q.getXAxis(axis); if (fixture.UserData != null && fixture.UserData.Equals(LIQUID_INT)) { Body b = fixture.Body; liquidOffset.set_Renamed(b.m_linearVelocity); float linVelLength = b.m_linearVelocity.length(); if (averageLinearVel == -1) { averageLinearVel = linVelLength; } else { averageLinearVel = .98f * averageLinearVel + .02f * linVelLength; } liquidOffset.mulLocal(liquidLength / averageLinearVel / 2); circCenterMoved.set_Renamed(center).addLocal(liquidOffset); center.subLocal(liquidOffset); m_debugDraw.drawSegment(center, circCenterMoved, liquidColor); return; } m_debugDraw.drawSolidCircle(center, radius, axis, color); } break; case ShapeType.POLYGON: { PolygonShape poly = (PolygonShape)fixture.Shape; int vertexCount = poly.m_count; Debug.Assert(vertexCount <= Settings.maxPolygonVertices); Vec2[] vertices = tlvertices.get_Renamed(Settings.maxPolygonVertices); for (int i = 0; i < vertexCount; ++i) { // vertices[i] = Mul(xf, poly.m_vertices[i]); Transform.mulToOutUnsafe(xf, poly.m_vertices[i], vertices[i]); } m_debugDraw.drawSolidPolygon(vertices, vertexCount, color); } break; case ShapeType.EDGE: { EdgeShape edge = (EdgeShape)fixture.Shape; Transform.mulToOutUnsafe(xf, edge.m_vertex1, v1); Transform.mulToOutUnsafe(xf, edge.m_vertex2, v2); m_debugDraw.drawSegment(v1, v2, color); } break; case ShapeType.CHAIN: { ChainShape chain = (ChainShape)fixture.Shape; int count = chain.m_count; Vec2[] vertices = chain.m_vertices; Transform.mulToOutUnsafe(xf, vertices[0], v1); for (int i = 1; i < count; ++i) { Transform.mulToOutUnsafe(xf, vertices[i], v2); m_debugDraw.drawSegment(v1, v2, color); m_debugDraw.drawCircle(v1, 0.05f, color); v1.set_Renamed(v2); } } break; default: break; } }
public Body(BodyDef bd, World world) { Debug.Assert(bd.position.Valid); Debug.Assert(bd.linearVelocity.Valid); Debug.Assert(bd.gravityScale >= 0.0f); Debug.Assert(bd.angularDamping >= 0.0f); Debug.Assert(bd.linearDamping >= 0.0f); m_flags = 0; if (bd.bullet) { m_flags |= e_bulletFlag; } if (bd.fixedRotation) { m_flags |= e_fixedRotationFlag; } if (bd.allowSleep) { m_flags |= e_autoSleepFlag; } if (bd.awake) { m_flags |= e_awakeFlag; } if (bd.active) { m_flags |= e_activeFlag; } m_world = world; m_xf.p.set_Renamed(bd.position); m_xf.q.set_Renamed(bd.angle); m_sweep.localCenter.setZero(); m_sweep.c0.set_Renamed(m_xf.p); m_sweep.c.set_Renamed(m_xf.p); m_sweep.a0 = bd.angle; m_sweep.a = bd.angle; m_sweep.alpha0 = 0.0f; m_jointList = null; m_contactList = null; m_prev = null; m_next = null; m_linearVelocity.set_Renamed(bd.linearVelocity); m_angularVelocity = bd.angularVelocity; m_linearDamping = bd.linearDamping; m_angularDamping = bd.angularDamping; m_gravityScale = bd.gravityScale; m_force.setZero(); m_torque = 0.0f; m_sleepTime = 0.0f; m_type = bd.type; if (m_type == BodyType.DYNAMIC) { m_mass = 1f; m_invMass = 1f; } else { m_mass = 0f; m_invMass = 0f; } m_I = 0.0f; m_invI = 0.0f; m_userData = bd.userData; m_fixtureList = null; m_fixtureCount = 0; }
/// <summary> /// Destroy a fixture. This removes the fixture from the broad-phase and destroys all contacts /// associated with this fixture. This will automatically adjust the mass of the body if the body /// is dynamic and the fixture has positive density. All fixtures attached to a body are implicitly /// destroyed when the body is destroyed. /// </summary> /// <param name="fixture">the fixture to be removed.</param> /// <warning>This function is locked during callbacks.</warning> public void destroyFixture(Fixture fixture) { Debug.Assert(m_world.Locked == false); if (m_world.Locked == true) { return; } Debug.Assert(fixture.m_body == this); // Remove the fixture from this body's singly linked list. Debug.Assert(m_fixtureCount > 0); Fixture node = m_fixtureList; Fixture last = null; // java change bool found = false; while (node != null) { if (node == fixture) { node = fixture.m_next; found = true; break; } last = node; node = node.m_next; } // You tried to remove a shape that is not attached to this body. Debug.Assert(found); // java change, remove it from the list if (last == null) { m_fixtureList = fixture.m_next; } else { last.m_next = fixture.m_next; } // Destroy any contacts associated with the fixture. ContactEdge edge = m_contactList; while (edge != null) { Contact c = edge.contact; edge = edge.next; Fixture fixtureA = c.FixtureA; Fixture fixtureB = c.FixtureB; if (fixture == fixtureA || fixture == fixtureB) { // This destroys the contact and removes it from // this body's contact list. m_world.m_contactManager.destroy(c); } } if ((m_flags & e_activeFlag) == e_activeFlag) { BroadPhase broadPhase = m_world.m_contactManager.m_broadPhase; fixture.destroyProxies(broadPhase); } fixture.destroy(); fixture.m_body = null; fixture.m_next = null; fixture = null; --m_fixtureCount; // Reset the mass data. resetMassData(); }
// TODO djm: check out about this new fixture here /// <summary> /// Creates a fixture and attach it to this body. Use this function if you need to set some fixture /// parameters, like friction. Otherwise you can create the fixture directly from a shape. If the /// density is non-zero, this function automatically updates the mass of the body. Contacts are not /// created until the next time step. /// </summary> /// <param name="def">the fixture definition.</param> /// <warning>This function is locked during callbacks.</warning> public Fixture createFixture(FixtureDef def) { Debug.Assert(m_world.Locked == false); if (m_world.Locked == true) { return null; } // djm TODO from pool? Fixture fixture = new Fixture(); fixture.create(this, def); if ((m_flags & e_activeFlag) == e_activeFlag) { BroadPhase broadPhase = m_world.m_contactManager.m_broadPhase; fixture.createProxies(broadPhase, m_xf); } fixture.m_next = m_fixtureList; m_fixtureList = fixture; ++m_fixtureCount; fixture.m_body = this; // Adjust mass properties if needed. if (fixture.m_density > 0.0f) { resetMassData(); } // Let the world know we have a new fixture. This will cause new contacts // to be created at the beginning of the next time step. m_world.m_flags |= World.NEW_FIXTURE; return fixture; }
private void DrawShape(Fixture fixture, Transform xf, Color3f color) { switch (fixture.Type) { case ShapeType.Circle: { CircleShape circle = (CircleShape)fixture.Shape; // Vec2 center = Mul(xf, circle.m_p); Transform.MulToOutUnsafe(xf, circle.P, center); float radius = circle.Radius; xf.Q.GetXAxis(axis); if (fixture.UserData != null && fixture.UserData.Equals(LIQUID_INT)) { Body b = fixture.Body; liquidOffset.Set(b.LinearVelocity); float linVelLength = b.LinearVelocity.Length(); if (averageLinearVel == -1) { averageLinearVel = linVelLength; } else { averageLinearVel = .98f * averageLinearVel + .02f * linVelLength; } liquidOffset.MulLocal(LIQUID_LENGTH / averageLinearVel / 2); circCenterMoved.Set(center).AddLocal(liquidOffset); center.SubLocal(liquidOffset); DebugDraw.DrawSegment(center, circCenterMoved, liquidColor); return; } DebugDraw.DrawSolidCircle(center, radius, axis, color); } break; case ShapeType.Polygon: { PolygonShape poly = (PolygonShape)fixture.Shape; int vertexCount = poly.VertexCount; Debug.Assert(vertexCount <= Settings.MAX_POLYGON_VERTICES); Vec2[] vertices = tlvertices.Get(Settings.MAX_POLYGON_VERTICES); for (int i = 0; i < vertexCount; ++i) { // vertices[i] = Mul(xf, poly.m_vertices[i]); Transform.MulToOutUnsafe(xf, poly.Vertices[i], vertices[i]); } DebugDraw.DrawSolidPolygon(vertices, vertexCount, color); } break; case ShapeType.Edge: { EdgeShape edge = (EdgeShape)fixture.Shape; Transform.MulToOutUnsafe(xf, edge.Vertex1, v1); Transform.MulToOutUnsafe(xf, edge.Vertex2, v2); DebugDraw.DrawSegment(v1, v2, color); } break; case ShapeType.Chain: { ChainShape chain = (ChainShape)fixture.Shape; int count = chain.Count; Vec2[] vertices = chain.Vertices; Transform.MulToOutUnsafe(xf, vertices[0], v1); for (int i = 1; i < count; ++i) { Transform.MulToOutUnsafe(xf, vertices[i], v2); DebugDraw.DrawSegment(v1, v2, color); DebugDraw.DrawCircle(v1, 0.05f, color); v1.Set(v2); } } break; } }
public virtual void destroy() { // The proxies must be destroyed before calling this. Debug.Assert(m_proxyCount == 0); // Free the child shape. m_shape = null; m_proxies = null; m_next = null; // TODO pool shapes // TODO pool fixtures }
// We need separation create/destroy functions from the constructor/destructor because // the destructor cannot access the allocator (no destructor arguments allowed by C++). public virtual void create(Body body, FixtureDef def) { m_userData = def.userData; m_friction = def.friction; m_restitution = def.restitution; m_body = body; m_next = null; m_filter.set_Renamed(def.filter); m_isSensor = def.isSensor; m_shape = def.shape.Clone(); // Reserve proxy space int childCount = m_shape.ChildCount; if (m_proxies == null) { m_proxies = new FixtureProxy[childCount]; for (int i = 0; i < childCount; i++) { m_proxies[i] = new FixtureProxy(); m_proxies[i].fixture = null; m_proxies[i].proxyId = BroadPhase.NULL_PROXY; } } if (m_proxies.Length < childCount) { FixtureProxy[] old = m_proxies; int newLen = MathUtils.max(old.Length * 2, childCount); m_proxies = new FixtureProxy[newLen]; Array.Copy(old, 0, m_proxies, 0, old.Length); for (int i = 0; i < newLen; i++) { if (i >= old.Length) { m_proxies[i] = new FixtureProxy(); } m_proxies[i].fixture = null; m_proxies[i].proxyId = BroadPhase.NULL_PROXY; } } m_proxyCount = 0; m_density = def.density; }
// TODO djm: check out about this new fixture here /// <summary> /// Creates a fixture and attach it to this body. Use this function if you need to set some fixture /// parameters, like friction. Otherwise you can create the fixture directly from a shape. If the /// density is non-zero, this function automatically updates the mass of the body. Contacts are not /// created until the next time step. /// </summary> /// <param name="def">the fixture definition.</param> /// <warning>This function is locked during callbacks.</warning> public Fixture CreateFixture(FixtureDef def) { Debug.Assert(World.Locked == false); if (World.Locked == true) { return null; } // djm TODO from pool? Fixture fixture = new Fixture(); fixture.Create(this, def); if ((Flags & TypeFlags.Active) == TypeFlags.Active) { BroadPhase broadPhase = World.ContactManager.BroadPhase; fixture.CreateProxies(broadPhase, Xf); } fixture.Next = FixtureList; FixtureList = fixture; ++FixtureCount; fixture.Body = this; // Adjust mass properties if needed. if (fixture.Density > 0.0f) { ResetMassData(); } // Let the world know we have a new fixture. This will cause new contacts // to be created at the beginning of the next time step. World.Flags |= World.NEW_FIXTURE; return fixture; }