Esempio n. 1
0
        /// @see Shape.ComputeMass
        public override void ComputeMass(out MassData massData, float density)
        {
            massData.mass = density * Settings.b2_pi * _radius * _radius;
            massData.center = _p;

            // inertia about the local origin
            massData.i = massData.mass * (0.5f * _radius * _radius + Vector2.Dot(_p, _p));
        }
Esempio n. 2
0
 /// Compute the mass properties of this shape using its dimensions and density.
 /// The inertia tensor is computed about the local origin, not the centroid.
 /// @param massData returns the mass data for this shape.
 public void ComputeMass(out MassData massData)
 {
     _shape.ComputeMass(out massData, _density);
 }
Esempio n. 3
0
        /// @see Shape.ComputeMass
        public override void ComputeMass(out MassData massData, float density)
        {
            // Polygon mass, centroid, and inertia.
            // Let rho be the polygon density in mass per unit area.
            // Then:
            // mass = rho * int(dA)
            // centroid.X = (1/mass) * rho * int(x * dA)
            // centroid.Y = (1/mass) * rho * int(y * dA)
            // I = rho * int((x*x + y*y) * dA)
            //
            // We can compute these integrals by summing all the integrals
            // for each triangle of the polygon. To evaluate the integral
            // for a single triangle, we make a change of variables to
            // the (u,v) coordinates of the triangle:
            // x = x0 + e1x * u + e2x * v
            // y = y0 + e1y * u + e2y * v
            // where 0 <= u && 0 <= v && u + v <= 1.
            //
            // We integrate u from [0,1-v] and then v from [0,1].
            // We also need to use the Jacobian of the transformation:
            // D = cross(e1, e2)
            //
            // Simplification: triangle centroid = (1/3) * (p1 + p2 + p3)
            //
            // The rest of the derivation is handled by computer algebra.

            Debug.Assert(_vertexCount >= 3);

            Vector2 center = new Vector2(0.0f, 0.0f);
            float area = 0.0f;
            float I = 0.0f;

            // pRef is the reference point for forming triangles.
            // It's location doesn't change the result (except for rounding error).
            Vector2 pRef = new Vector2(0.0f, 0.0f);
            #if false
            // This code would put the reference point inside the polygon.
            for (int i = 0; i < _vertexCount; ++i)
            {
                pRef += _vertices[i];
            }
            pRef *= 1.0f / count;
            #endif

            float k_inv3 = 1.0f / 3.0f;

            for (int i = 0; i < _vertexCount; ++i)
            {
                // Triangle vertices.
                Vector2 p1 = pRef;
                Vector2 p2 = _vertices[i];
                Vector2 p3 = i + 1 < _vertexCount ? _vertices[i+1] : _vertices[0];

                Vector2 e1 = p2 - p1;
                Vector2 e2 = p3 - p1;

                float D = MathUtils.Cross(e1, e2);

                float triangleArea = 0.5f * D;
                area += triangleArea;

                // Area weighted centroid
                center += triangleArea * k_inv3 * (p1 + p2 + p3);

                float px = p1.X, py = p1.Y;
                float ex1 = e1.X, ey1 = e1.Y;
                float ex2 = e2.X, ey2 = e2.Y;

                float intx2 = k_inv3 * (0.25f * (ex1*ex1 + ex2*ex1 + ex2*ex2) + (px*ex1 + px*ex2)) + 0.5f*px*px;
                float inty2 = k_inv3 * (0.25f * (ey1*ey1 + ey2*ey1 + ey2*ey2) + (py*ey1 + py*ey2)) + 0.5f*py*py;

                I += D * (intx2 + inty2);
            }

            // Total mass
            massData.mass = density * area;

            // Center of mass
            Debug.Assert(area > Settings.b2_FLT_EPSILON);
            center *= 1.0f / area;
            massData.center = center;

            // Inertia tensor relative to the local origin.
            massData.i = density * I;
        }
Esempio n. 4
0
        /// Set the mass properties. Note that this changes the center of mass position.
        /// If you are not sure how to compute mass properties, use SetMassFromShapes.
        /// The inertia tensor is assumed to be relative to the center of mass.
        /// You can make the body static by using a zero mass.
        /// @param massData the mass properties.
        public void SetMassData(MassData massData)
        {
            Debug.Assert(_world.IsLocked == false);
            if (_world.IsLocked == true)
            {
                return;
            }

            _invMass = 0.0f;
            _I = 0.0f;
            _invI = 0.0f;

            _mass = massData.mass;

            if (_mass > 0.0f)
            {
                _invMass = 1.0f / _mass;
            }

            _I = massData.i;

            if (_I > 0.0f && (_flags & BodyFlags.FixedRotation) == BodyFlags.None)
            {
                _invI = 1.0f / _I;
            }

            // Move center of mass.
            _sweep.localCenter = massData.center;
            _sweep.c0 = _sweep.c = MathUtils.Multiply(ref _xf, _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 flag contacts for filtering.
            if (oldType != _type)
            {
                for (ContactEdge ce = _contactList; ce != null; ce = ce.Next)
                {
                    ce.Contact.FlagForFiltering();
                }
            }
        }
Esempio n. 5
0
 /// Compute the mass properties of this shape using its dimensions and density.
 /// The inertia tensor is computed about the local origin, not the centroid.
 /// @param massData returns the mass data for this shape.
 /// @param density the density in kilograms per meter squared.
 public abstract void ComputeMass(out MassData massData, float density);