/// @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)); }
/// 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); }
/// @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; }
/// 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(); } } }
/// 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);