/// <summary> /// Compute the mass properties of this shape using its dimensions and density. /// The inertia tensor is computed about the local origin, not the centroid. /// </summary> /// <param name="massData">Returns the mass data for this shape.</param> /// <param name="density">The density in kilograms per meter squared.</param> public abstract void ComputeMass(out MassData massData, float density);
/// <summary> /// Chains have zero mass. /// </summary> /// <param name="massData">Returns the mass data for this shape.</param> /// <param name="density">The density in kilograms per meter squared.</param> public override void ComputeMass(out MassData massData, float density) { massData = new MassData(); massData.Mass = 0.0f; massData.Center = Vector2.Zero; massData.Inertia = 0.0f; }
/// <summary> /// Compute the mass properties of this shape using its dimensions and density. /// The inertia tensor is computed about the local origin, not the centroid. /// </summary> /// <param name="massData">Returns the mass data for this shape.</param> /// <param name="density">The density in kilograms per meter squared.</param> public override void ComputeMass(out MassData massData, float density) { massData.Mass = density * Settings.Pi * Radius * Radius; massData.Center = Position; // inertia about the local origin massData.Inertia = massData.Mass * (0.5f * Radius * Radius + Vector2.Dot(Position, Position)); }
/// <summary> /// Compute the mass properties of this shape using its dimensions and density. /// The inertia tensor is computed about the local origin, not the centroid. /// </summary> /// <param name="massData">Returns the mass data for this shape.</param> /// <param name="density">The density in kilograms per meter squared.</param> 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(Vertices.Count >= 2); // A line segment has zero mass. if (Vertices.Count == 2) { massData.Center = 0.5f * (Vertices[0] + Vertices[1]); massData.Mass = 0.0f; massData.Inertia = 0.0f; return; } 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); const float inv3 = 1.0f / 3.0f; for (int i = 0; i < Vertices.Count; ++i) { // Triangle vertices. Vector2 p1 = pRef; Vector2 p2 = Vertices[i]; Vector2 p3 = i + 1 < Vertices.Count ? Vertices[i + 1] : Vertices[0]; Vector2 e1 = p2 - p1; Vector2 e2 = p3 - p1; float d; MathUtils.Cross(ref e1, ref e2, out d); float triangleArea = 0.5f * d; area += triangleArea; // Area weighted centroid center += triangleArea * 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 = inv3 * (0.25f * (ex1 * ex1 + ex2 * ex1 + ex2 * ex2) + (px * ex1 + px * ex2)) + 0.5f * px * px; float inty2 = 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.Epsilon); center *= 1.0f / area; massData.Center = center; // Inertia tensor relative to the local origin. massData.Inertia = density * I; }
/// <summary> /// Compute the mass properties of this shape using its dimensions and density. /// The inertia tensor is computed about the local origin, not the centroid. /// </summary> /// <param name="massData">Returns the mass data for this shape.</param> /// <param name="density">The density in kilograms per meter squared.</param> public override void ComputeMass(out MassData massData, float density) { massData = new MassData(); massData.Mass = 0.0f; massData.Center = 0.5f * (Vertex1 + Vertex2); massData.Inertia = 0.0f; }
/// <summary> /// Get the mass data for this fixture. The mass data is based on the density and /// the Shape. The rotational inertia is about the Shape's origin. /// </summary> /// <param name="massData">The mass data.</param> public void GetMassData(out MassData massData) { Shape.ComputeMass(out massData, Density); }
/// <summary> /// Compute the mass properties of this shape using its dimensions and density. /// The inertia tensor is computed about the local origin, not the centroid. /// </summary> /// <param name="massData">Returns the mass data for this shape.</param> /// <param name="density">The density in kilograms per meter squared.</param> public abstract void ComputeMass(out MassData massData, float density);
/// <summary> /// Compute the mass properties of this shape using its dimensions and density. /// The inertia tensor is computed about the local origin, not the centroid. /// </summary> /// <param name="massData">Returns the mass data for this shape.</param> /// <param name="density">The density in kilograms per meter squared.</param> 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(Vertices.Count >= 2); // A line segment has zero mass. if (Vertices.Count == 2) { massData.Center = 0.5f * (Vertices[0] + Vertices[1]); massData.Mass = 0.0f; massData.Inertia = 0.0f; return; } 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); const float inv3 = 1.0f / 3.0f; for (int i = 0; i < Vertices.Count; ++i) { // Triangle vertices. Vector2 p1 = pRef; Vector2 p2 = Vertices[i]; Vector2 p3 = i + 1 < Vertices.Count ? Vertices[i + 1] : Vertices[0]; Vector2 e1 = p2 - p1; Vector2 e2 = p3 - p1; float d; MathUtils.Cross(ref e1, ref e2, out d); float triangleArea = 0.5f * d; area += triangleArea; // Area weighted centroid center += triangleArea * 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 = inv3 * (0.25f * (ex1 * ex1 + ex2 * ex1 + ex2 * ex2) + (px * ex1 + px * ex2)) + 0.5f * px * px; float inty2 = 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.Epsilon); center *= 1.0f / area; massData.Center = center; // Inertia tensor relative to the local origin. massData.Inertia = density * I; }