A fixture is used to attach a shape to a body for collision detection. A fixture inherits its Transform from its parent. Fixtures hold additional non-geometric data such as friction, collision filters, etc. Fixtures are created via Body.CreateFixture. @warning you cannot reuse fixtures.
Exemplo n.º 1
0
        public Projectile(Player creator, float x, float y, float width, float height)
            : base(creator, 0, 0)
        {
            /* Create New Projectile Body */
            BodyDef def = new BodyDef();
            def.IsBullet = true;
            def.Position = creator.body.GetPosition() + new Vec2(x, y);
            projectile = creator.body.GetWorld().CreateBody(def);

            /* Create a fixture for the projectile */
            PolygonDef fixdef = new PolygonDef();
            fixdef.Density = 1.0f;
            fixdef.SetAsBox(width / 2, height / 2);
            fixdef.Filter.GroupIndex = creator.ID;
            fixture = projectile.CreateFixture(fixdef);
            fixture.Filter.CategoryBits = 0x0004;
            fixture.Filter.MaskBits = 0xFFFF;

            /* Made a 2nd fixture, one to observe all collisions */
            fixdef.IsSensor = true;
            fix2 = projectile.CreateFixture(fixdef);
            fix2.UserData = this;

            /* Finally, give this projectile some mass */
            projectile.SetMassFromShapes();

            /* Also, make sure we destroy the projectile when it is time */
            this.OnDestroy += Cleanup;
        }
Exemplo n.º 2
0
		public PolygonContact(Fixture fixtureA, Fixture fixtureB)
			: base(fixtureA, fixtureB)
		{
			Box2DXDebug.Assert(fixtureA.ShapeType == ShapeType.PolygonShape);
			Box2DXDebug.Assert(fixtureB.ShapeType == ShapeType.PolygonShape);
			CollideShapeFunction = CollidePolygons;
		}
Exemplo n.º 3
0
		public CircleContact(Fixture fixtureA, Fixture fixtureB)
			: base(fixtureA, fixtureB)
		{
			Box2DXDebug.Assert(fixtureA.ShapeType == ShapeType.CircleShape);
			Box2DXDebug.Assert(fixtureB.ShapeType == ShapeType.CircleShape);
			CollideShapeFunction = CollideCircles;
		}
Exemplo n.º 4
0
        public Breakable()
        {
            // Ground body
            {
                BodyDef bd = new BodyDef();
                Body ground = _world.CreateBody(bd);

                PolygonShape shape = new PolygonShape();
                shape.SetAsEdge(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f));
                ground.CreateFixture(shape, 0);
            }

            // Breakable dynamic body
            {
                BodyDef bd = new BodyDef();
                bd.Position.Set(0.0f, 40.0f);
                bd.Angle = 0.25f * Box2DX.Common.Settings.PI;
                _body1 = _world.CreateBody(bd);

                _shape1.SetAsBox(0.5f, 0.5f, new Vec2(-0.5f, 0.0f), 0.0f);
                _piece1 = _body1.CreateFixture(_shape1, 1.0f);

                _shape2.SetAsBox(0.5f, 0.5f, new Vec2(0.5f, 0.0f), 0.0f);
                _piece2 = _body1.CreateFixture(_shape2, 1.0f);
            }

            _break = false;
            _broke = false;
        }
Exemplo n.º 5
0
        public override float ReportFixture(Fixture fixture, Vec2 point, Vec2 normal, float fraction)
        {
            _fixture = fixture;
            _point = point;
            _normal = normal;

            return fraction;
        }
Exemplo n.º 6
0
 public Fixture()
 {
     UserData = null;
     Body = null;
     _next = null;
     ProxyId = BroadPhase.NullProxy;
     Shape = null;
 }
Exemplo n.º 7
0
		public EdgeAndCircleContact(Fixture fixtureA, Fixture fixtureB)
			: base(fixtureA, fixtureB)
		{
			Box2DXDebug.Assert(fixtureA.ShapeType == ShapeType.EdgeShape);
			Box2DXDebug.Assert(fixtureB.ShapeType == ShapeType.CircleShape);
			_manifold.PointCount = 0;
			_manifold.Points[0].NormalImpulse = 0.0f;
			_manifold.Points[0].TangentImpulse = 0.0f;
			CollideShapeFunction = CollideEdgeAndCircle;
		}
Exemplo n.º 8
0
        /// <summary>
        /// Return true if the given shape should be considered for ray intersection.
        /// </summary>
        public bool RayCollide(object userData, Fixture fixture)
        {
            //By default, cast userData as a shape, and then collide if the shapes would collide
            if (userData == null)
            {
                return true;
            }

            return ShouldCollide((Fixture)userData, fixture);
        }
Exemplo n.º 9
0
		/// <summary>
		/// Return true if contact calculations should be performed between these two shapes.
		/// If you implement your own collision filter you may want to build from this implementation.
		/// @warning for performance reasons this is only called when the AABBs begin to overlap.
		/// </summary>
		public virtual bool ShouldCollide(Fixture fixtureA, Fixture fixtureB)
		{
			FilterData filterA = fixtureA.Filter;
			FilterData filterB = fixtureB.Filter;

			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;
		}
Exemplo n.º 10
0
        public SensorTest()
        {
            {
                BodyDef bd = new BodyDef();
                Body ground = _world.CreateBody(bd);

                {
                    PolygonShape shape = new PolygonShape();
                    shape.SetAsEdge(new Vec2(-40.0f, 0.0f), new Vec2(40.0f, 0.0f));
                    ground.CreateFixture(shape, 0);
                }

            #if false
            {
                b2FixtureDef sd;
                sd.SetAsBox(10.0f, 2.0f, b2Vec2(0.0f, 20.0f), 0.0f);
                sd.isSensor = true;
                m_sensor = ground->CreateFixture(&sd);
            }
            #else
                {
                    CircleShape shape = new CircleShape();
                    shape._radius = 5.0f;
                    shape._p.Set(0.0f, 10.0f);

                    FixtureDef fd = new FixtureDef();
                    fd.Shape = shape;
                    fd.IsSensor = true;
                    _sensor = ground.CreateFixture(fd);
                }
            #endif
            }

            {
                CircleShape shape = new CircleShape();
                shape._radius = 1.0f;

                for (int i = 0; i < _count; ++i)
                {
                    BodyDef bd = new BodyDef();
                    bd.Position.Set(-10.0f + 3.0f * i, 20.0f);
                    bd.UserData = false;

                    _bodies[i] = _world.CreateBody(bd);

                    _bodies[i].CreateFixture(shape, 1.0f);
                }
            }
        }
Exemplo n.º 11
0
 /// Called for each fixture found in the query AABB.
 /// @return false to terminate the query.
 public abstract bool ReportFixture(Fixture fixture);
Exemplo n.º 12
0
        public void Create(BroadPhase broadPhase, Body body, 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;

            _type = def.Type;

            // Allocate and initialize the child shape.
            switch (_type)
            {
                case ShapeType.CircleShape:
                    {
                        CircleShape circle = new CircleShape();
                        CircleDef circleDef = (CircleDef)def;
                        circle._position = circleDef.LocalPosition;
                        circle._radius = circleDef.Radius;
                        _shape = circle;
                    }
                    break;

                case ShapeType.PolygonShape:
                    {
                        PolygonShape polygon = new PolygonShape();
                        PolygonDef polygonDef = (PolygonDef)def;
                        polygon.Set(polygonDef.Vertices, polygonDef.VertexCount);
                        _shape = polygon;
                    }
                    break;

                case ShapeType.EdgeShape:
                    {
                        EdgeShape edge = new EdgeShape();
                        EdgeDef edgeDef = (EdgeDef)def;
                        edge.Set(edgeDef.Vertex1, edgeDef.Vertex2);
                        _shape = edge;
                    }
                    break;

                default:
                    Box2DXDebug.Assert(false);
                    break;
            }

            // Create proxy in the broad-phase.
            AABB aabb;
            _shape.ComputeAABB(out aabb, xf);

            bool inRange = broadPhase.InRange(aabb);

            // You are creating a shape outside the world box.
            Box2DXDebug.Assert(inRange);

            if (inRange)
            {
                _proxyId = broadPhase.CreateProxy(aabb, this);
            }
            else
            {
                _proxyId = PairManager.NullProxy;
            }
        }
Exemplo n.º 13
0
        private void DrawFixture(Fixture fixture, Transform xf, Color color, bool core)
        {
            #warning "the core argument is not used, the coreColor variable is also not used"
            Color coreColor = new Color(0.9f, 0.6f, 0.6f);

            switch (fixture.ShapeType)
            {
                case ShapeType.CircleShape:
                    {
                        CircleShape circle = (CircleShape)fixture.Shape;

                        Vector2 center = xf.TransformPoint(circle._position);
                        float radius = circle._radius;
                        // [CHRISK] FIXME Vector2 axis = xf.R.Col1;

                        //_debugDraw.DrawSolidCircle(center, radius, axis, color);
                    }
                    break;

                case ShapeType.PolygonShape:
                    {
                        PolygonShape poly = (PolygonShape)fixture.Shape;
                        int vertexCount = poly._vertexCount;
                        Vector2[] localVertices = poly._vertices;

                        Box2DXDebug.Assert(vertexCount <= Settings.MaxPolygonVertices);
                        Vector2[] vertices = new Vector2[Settings.MaxPolygonVertices];

                        for (int i = 0; i < vertexCount; ++i)
                        {
                            vertices[i] = xf.TransformPoint(localVertices[i]);
                        }

                        _debugDraw.DrawSolidPolygon(vertices, vertexCount, color);
                    }
                    break;

                case ShapeType.EdgeShape:
                    {
                        EdgeShape edge = (EdgeShape)fixture.Shape;

                        _debugDraw.DrawSegment(xf.TransformPoint(edge.Vertex1), xf.TransformPoint(edge.Vertex2), color);
                    }
                    break;
            }
        }
 public PolyAndCircleContact(Fixture fixtureA, Fixture fixtureB)
     : base(fixtureA, fixtureB)
 {
     Box2DXDebug.Assert(_fixtureA.GetType() == ShapeType.PolygonShape);
     Box2DXDebug.Assert(_fixtureB.GetType() == ShapeType.CircleShape);
 }
Exemplo n.º 15
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(ref Fixture fixture)
        {
            Box2DXDebug.Assert(_world.IsLocked() == false);
            if (_world.IsLocked() == true)
            {
                return;
            }

            Box2DXDebug.Assert(fixture.Body == this);

            // Remove the fixture from this body's singly linked list.
            Box2DXDebug.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.
            Box2DXDebug.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);
                }
            }

            bool needMassUpdate = fixture._massData.Mass > 0.0f || fixture._massData.I > 0.0f;

            BroadPhase broadPhase = _world._contactManager._broadPhase;

            fixture.Destroy(broadPhase);
            fixture.Body = null;
            fixture._next = null;

            --_fixtureCount;

            // Adjust mass properties if needed.
            if (needMassUpdate)
            {
                ResetMass();
            }
        }
Exemplo n.º 16
0
        public static Contact Create(Fixture fixtureA, Fixture fixtureB)
        {
            if (Initialized == false)
            {
                InitializeRegisters();
                Initialized = true;
            }

            ShapeType type1 = fixtureA.GetType();
            ShapeType type2 = fixtureB.GetType();

            Box2DXDebug.Assert(ShapeType.UnknownShape < type1 && type1 < ShapeType.ShapeTypeCount);
            Box2DXDebug.Assert(ShapeType.UnknownShape < type2 && type2 < ShapeType.ShapeTypeCount);

            ContactCreateFcn createFcn = Registers[(int)type1][(int)type2].CreateFcn;
            if (createFcn != null)
            {
                if (Registers[(int)type1][(int)type2].Primary)
                {
                    return createFcn(fixtureA, fixtureB);
                }
                else
                {
                    return createFcn(fixtureB, fixtureA);
                }
            }
            else
            {
                return null;
            }
        }
Exemplo n.º 17
0
		public void MouseDown(Vec2 p)
		{
			if (_mouseJoint != null)
			{
				return;
			}

			// Make a small box.
			AABB aabb = new AABB();
			Vec2 d = new Vec2();
			d.Set(0.001f, 0.001f);
			aabb.LowerBound = p - d;
			aabb.UpperBound = p + d;

			// Query the world for overlapping shapes.
			int k_maxCount = 10;
			Fixture[] shapes = new Fixture[k_maxCount];
			int count = _world.Query(aabb, shapes, k_maxCount);
			Body body = null;
			for (int i = 0; i < count; ++i)
			{
				Body shapeBody = shapes[i].Body;
				if (shapeBody.IsStatic() == false && shapeBody.GetMass() > 0.0f)
				{
					bool inside = shapes[i].TestPoint(p);
					if (inside)
					{
						body = shapes[i].Body;
						break;
					}
				}
			}

			if (body != null)
			{
				MouseJointDef md = new MouseJointDef();
				md.Body1 = _world.GetGroundBody();
				md.Body2 = body;
				md.Target = p;
#if TARGET_FLOAT32_IS_FIXED
				md.MaxForce = (body.GetMass() < 16.0f)? 
					(1000.0f * body.GetMass()) : 16000.0f;
#else
				md.MaxForce = 1000.0f * body.GetMass();
#endif
				_mouseJoint = (MouseJoint)_world.CreateJoint(md);
				body.WakeUp();
			}
		}
Exemplo n.º 18
0
        // We need separation create/destroy functions from the constructor/destructor because
        // the destructor cannot access the allocator or broad-phase (no destructor arguments allowed by C++).
        public void Create(BroadPhase broadPhase, Body body, Transform xf, FixtureDef def)
        {
            UserData = def.UserData;
            Friction = def.Friction;
            Restitution = def.Restitution;

            Body = body;
            _next = null;

            Filter = def.Filter;

            IsSensor = def.IsSensor;

            Shape = def.Shape.Clone();

            Shape.ComputeMass(out _massData, def.Density);

            // Create proxy in the broad-phase.
            Shape.ComputeAABB(out Aabb, ref xf);

            ProxyId = broadPhase.CreateProxy(Aabb, this);
        }
Exemplo n.º 19
0
 /// <summary>
 /// Called when any shape is about to be destroyed due
 /// to the destruction of its parent body.
 /// </summary>
 public abstract void SayGoodbye(Fixture fixture);
Exemplo n.º 20
0
		public override void SayGoodbye(Fixture shape) { ; }
Exemplo n.º 21
0
 /// Called for each fixture found in the query. You control how the ray proceeds
 /// by returning a float that indicates the fractional length of the ray. By returning
 /// 0, you set the ray length to zero. By returning the current fraction, you proceed
 /// to find the closest point. By returning 1, you continue with the original ray
 /// clipping.
 /// @param fixture the fixture hit by the ray
 /// @param point the point of initial intersection
 /// @param normal the normal vector at the point of intersection
 /// @return 0 to terminate, fraction to clip the ray for
 /// closest hit, 1 to continue
 public abstract float ReportFixture(Fixture fixture, Vec2 point, Vec2 normal, float fraction);
Exemplo n.º 22
0
        void Break()
        {
            // Create two bodies from one.
            Body body1 = _piece1.GetBody();
            Vec2 center = body1.GetWorldCenter();

            body1.DestroyFixture(ref _piece2);
            _piece2 = null;

            BodyDef bd = new BodyDef();
            bd.Position = body1.GetPosition();
            bd.Angle = body1.GetAngle();

            Body body2 = _world.CreateBody(bd);
            _piece2 = body2.CreateFixture(_shape2, 1.0f);

            // Compute consistent velocities for new bodies based on
            // cached velocity.
            Vec2 center1 = body1.GetWorldCenter();
            Vec2 center2 = body2.GetWorldCenter();

            Vec2 velocity1 = _velocity + Vec2.Cross(_angularVelocity, center1 - center);
            Vec2 velocity2 = _velocity + Vec2.Cross(_angularVelocity, center2 - center);

            body1.SetAngularVelocity(_angularVelocity);
            body1.SetLinearVelocity(velocity1);

            body2.SetAngularVelocity(_angularVelocity);
            body2.SetLinearVelocity(velocity2);
        }
Exemplo n.º 23
0
        /// <summary>
        /// Return true if contact calculations should be performed between these two shapes.
        /// If you implement your own collision filter you may want to build from this implementation.
        /// @warning for performance reasons this is only called when the AABBs begin to overlap.
        /// </summary>
        public virtual bool ShouldCollide(Fixture fixtureA, Fixture fixtureB)
        {
            Filter filter1 = fixtureA.GetFilterData();
            Filter filter2 = fixtureB.GetFilterData();

            if (filter1.GroupIndex == filter2.GroupIndex && filter1.GroupIndex != 0)
            {
                return filter1.GroupIndex > 0;
            }

            bool collide = (filter1.MaskBits & filter2.CategoryBits) != 0 && (filter1.CategoryBits & filter2.MaskBits) != 0;
            return collide;
        }
Exemplo n.º 24
0
        /// 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.
        /// This function automatically updates the mass of the body.
        /// @param def the fixture definition.
        /// @warning This function is locked during callbacks.
        public Fixture CreateFixture(FixtureDef def)
        {
            Box2DXDebug.Assert(_world.IsLocked() == false);
            if (_world.IsLocked() == true)
            {
                return null;
            }

            BroadPhase broadPhase = _world._contactManager._broadPhase;

            Fixture fixture = new Fixture();
            fixture.Create(broadPhase, this, _xf, def);

            fixture._next = _fixtureList;
            _fixtureList = fixture;
            ++_fixtureCount;

            fixture.Body = this;

            bool needMassUpdate = fixture._massData.Mass > 0.0f || fixture._massData.I > 0.0f;

            // Adjust mass properties if needed.
            if (needMassUpdate)
            {
                ResetMass();
            }

            // 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.WorldFlags.NewFixture;

            return fixture;
        }
Exemplo n.º 25
0
        /// Query the world for all shapes that potentially overlap the
        /// provided AABB. You provide a shape pointer buffer of specified
        /// size. The number of shapes found is returned.
        /// @param aabb the query box.
        /// @param shapes a user allocated shape pointer array of size maxCount (or greater).
        /// @param maxCount the capacity of the shapes array.
        /// @return the number of shapes found in aabb.
        public int Query(AABB aabb, Fixture[] fixtures, int maxCount)
        {
            //using (object[] results = new object[maxCount])
            {
                object[] results = new object[maxCount];

                int count = _broadPhase.Query(aabb, results, maxCount);

                for (int i = 0; i < count; ++i)
                {
                    fixtures[i] = (Fixture)results[i];
                }

                results = null;
                return count;
            }
        }
Exemplo n.º 26
0
        private Transform _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.SetZero();
            _sweep.T0 = 1.0f;
            _sweep.A0 = _sweep.A = bd.Angle;
            _sweep.C0 = _sweep.C = Math.Mul(_xf, _sweep.LocalCenter);

            _jointList = null;
            _contactList = null;
            _prev = null;
            _next = null;

            _linearVelocity = bd.LinearVelocity;
            _angularVelocity = bd.AngularVelocity;

            _linearDamping = bd.LinearDamping;
            _angularDamping = bd.AngularDamping;

            _force.Set(0.0f, 0.0f);
            _torque = 0.0f;

            _sleepTime = 0.0f;

            _mass = 0;
            _invMass = 0.0f;
            _I = 0.0f;
            _invI = 0.0f;

            _type = BodyType.Static;

            _userData = bd.UserData;

            _fixtureList = null;
            _fixtureCount = 0;
        }
Exemplo n.º 27
0
        /// <summary>
        /// Query the world for all shapes that intersect a given segment. You provide a shap
        /// pointer buffer of specified size. The number of shapes found is returned, and the buffer
        /// is filled in order of intersection.
        /// </summary>
        /// <param name="segment">Defines the begin and end point of the ray cast, from p1 to p2.
        /// Use Segment.Extend to create (semi-)infinite rays.</param>
        /// <param name="shapes">A user allocated shape pointer array of size maxCount (or greater).</param>
        /// <param name="maxCount">The capacity of the shapes array.</param>
        /// <param name="solidShapes">Determines if shapes that the ray starts in are counted as hits.</param>
        /// <param name="userData">Passed through the worlds contact filter, with method RayCollide. This can be used to filter valid shapes.</param>
        /// <returns>The number of shapes found</returns>
        public int Raycast(Segment segment, out Fixture[] fixtures, int maxCount, bool solidShapes, object userData)
        {
            #warning "PTR"
            _raycastSegment = segment;
            _raycastUserData = userData;
            _raycastSolidShape = solidShapes;

            object[] results = new object[maxCount];
            fixtures = new Fixture[maxCount];
            int count = _broadPhase.QuerySegment(segment, results, maxCount, RaycastSortKey);

            for (int i = 0; i < count; ++i)
            {
                fixtures[i] = (Fixture)results[i];
            }

            return count;
        }
Exemplo n.º 28
0
		new public static Contact Create(Fixture fixtureA, Fixture fixtureB)
		{
			return new CircleContact(fixtureA, fixtureB);
		}
Exemplo n.º 29
0
 /// <summary>
 /// Re-filter a fixture. This re-runs contact filtering on a fixture.
 /// </summary>		
 public void Refilter(Fixture fixture)
 {
     Box2DXDebug.Assert(_lock == false);
     fixture.RefilterProxy(_broadPhase, fixture.Body.GetTransform());
 }
 public static new Contact Create(Fixture fixtureA, Fixture fixtureB)
 {
     return new PolyAndCircleContact(fixtureA, fixtureB);
 }
Exemplo n.º 31
0
        // TODO_ERIN adjust linear velocity and torque to account for movement of center.
        /// <summary>
        /// Compute the mass properties from the attached shapes. You typically call this
        /// after adding all the shapes. If you add or remove shapes later, you may want
        /// to call this again. Note that this changes the center of mass position.
        /// </summary>
        public void SetMassFromShapes()
        {
            Box2DXDebug.Assert(_world._lock == false);
            if (_world._lock == true)
            {
                return;
            }

            // Compute mass data from shapes. Each shape has its own density.
            _mass    = 0.0f;
            _invMass = 0.0f;
            _I       = 0.0f;
            _invI    = 0.0f;

            Vector2 center = Vector2.zero;

            for (Fixture f = _fixtureList; f != null; f = f.Next)
            {
                MassData massData;
                f.ComputeMass(out massData);
                _mass  += massData.Mass;
                center += massData.Mass * massData.Center;
                _I     += massData.I;
            }

            // Compute center of mass, and shift the origin to the COM.
            if (_mass > 0.0f)
            {
                _invMass = 1.0f / _mass;
                center  *= _invMass;
            }

            if (_I > 0.0f && (_flags & BodyFlags.FixedRotation) == 0)
            {
                // Center the inertia about the center of mass.
                _I -= _mass * Vector2.Dot(center, center);
                Box2DXDebug.Assert(_I > 0.0f);
                _invI = 1.0f / _I;
            }
            else
            {
                _I    = 0.0f;
                _invI = 0.0f;
            }

            // Move center of mass.
            _sweep.LocalCenter = center;
            _sweep.C0          = _sweep.C = _xf.TransformPoint(_sweep.LocalCenter);

            BodyType oldType = _type;

            if (_invMass == 0.0f && _invI == 0.0f)
            {
                _type = BodyType.Static;
            }
            else
            {
                _type = BodyType.Dynamic;
            }

            // If the body type changed, we need to refilter the broad-phase proxies.
            if (oldType != _type)
            {
                for (Fixture f = _fixtureList; f != null; f = f.Next)
                {
                    f.RefilterProxy(_world._broadPhase, _xf);
                }
            }
        }