public override void computeMass(MassData massData, float density) { massData.mass = density*Settings.PI*m_radius*m_radius; massData.center.x = m_p.x; massData.center.y = m_p.y; // inertia about the local origin // massData.I = massData.mass * (0.5f * m_radius * m_radius + Vec2.dot(m_p, m_p)); massData.I = massData.mass*(0.5f*m_radius*m_radius + (m_p.x*m_p.x + m_p.y*m_p.y)); }
/** * Compute the mass properties of this shape using its dimensions and density. The inertia tensor * is computed about the local origin. * * @param massData returns the mass data for this shape. * @param density the density in kilograms per meter squared. */ public abstract void computeMass(MassData massData, float density);
/** * 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. * * @return */ public void getMassData(MassData massData) { m_shape.computeMass(massData, m_density); }
/** * Set the mass properties to override the mass properties of the fixtures. Note that this changes * the center of mass position. Note that creating or destroying fixtures can also alter the mass. * This function has no effect if the body isn't dynamic. * * @param massData the mass properties. */ public void setMassData(MassData massData) { // TODO_ERIN adjust linear velocity and torque to account for movement of center. Debug.Assert(m_world.isLocked() == false); if (m_world.isLocked() == true) { return; } if (m_type != BodyType.DYNAMIC) { return; } m_invMass = 0.0f; m_I = 0.0f; m_invI = 0.0f; m_mass = massData.mass; if (m_mass <= 0.0f) { m_mass = 1f; } m_invMass = 1.0f/m_mass; if (massData.I > 0.0f && (m_flags & BodyFlags.FixedRotation) == 0) { m_I = massData.I - m_mass*Vec2.dot(massData.center, massData.center); Debug.Assert(m_I > 0.0f); m_invI = 1.0f/m_I; } Vec2 oldCenter = m_world.getPool().popVec2(); // Move center of mass. oldCenter.set(m_sweep.c); m_sweep.localCenter.set(massData.center); // m_sweep.c0 = m_sweep.c = Mul(m_xf, m_sweep.localCenter); Transform.mulToOutUnsafe(m_xf, m_sweep.localCenter, ref m_sweep.c0); m_sweep.c.set(m_sweep.c0); // Update center of mass velocity. // m_linearVelocity += Cross(m_angularVelocity, m_sweep.c - oldCenter); Vec2 temp = m_world.getPool().popVec2(); temp.set(m_sweep.c); temp.subLocal(oldCenter); Vec2.crossToOut(m_angularVelocity, temp, ref temp); m_linearVelocity.addLocal(temp); m_world.getPool().pushVec2(2); }
/** * Get the mass data of the body. The rotational inertia is relative to the center of mass. * * @return a struct containing the mass, inertia and center of the body. */ public void getMassData(MassData data) { // data.mass = m_mass; // data.I = m_I + m_mass * Vec2.dot(m_sweep.localCenter, m_sweep.localCenter); // data.center.set(m_sweep.localCenter); data.mass = m_mass; data.I = m_I + m_mass *(m_sweep.localCenter.x*m_sweep.localCenter.x + m_sweep.localCenter.y *m_sweep.localCenter.y); data.center.x = m_sweep.localCenter.x; data.center.y = m_sweep.localCenter.y; }
public override void computeMass(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(m_count >= 3); Vec2 center = pool1; center.setZero(); 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). Vec2 s = pool2; s.setZero(); // This code would put the reference point inside the polygon. for (int i = 0; i < m_count; ++i) { s.addLocal(m_vertices[i]); } s.mulLocal(1.0f/m_count); float k_inv3 = 1.0f/3.0f; Vec2 e1 = pool3; Vec2 e2 = pool4; for (int i = 0; i < m_count; ++i) { // Triangle vertices. e1.set(m_vertices[i]); e1.subLocal(s); e2.set(s); e2.negateLocal(); e2.addLocal(i + 1 < m_count ? m_vertices[i + 1] : m_vertices[0]); float D = Vec2.cross(e1, e2); float triangleArea = 0.5f*D; area += triangleArea; // Area weighted centroid center.x += triangleArea*k_inv3*(e1.x + e2.x); center.y += triangleArea*k_inv3*(e1.y + e2.y); float ex1 = e1.x, ey1 = e1.y; float ex2 = e2.x, ey2 = e2.y; float intx2 = ex1*ex1 + ex2*ex1 + ex2*ex2; float inty2 = ey1*ey1 + ey2*ey1 + ey2*ey2; I += (0.25f*k_inv3*D)*(intx2 + inty2); } // Total mass massData.mass = density*area; // Center of mass Debug.Assert(area > Settings.EPSILON); center.mulLocal(1.0f/area); massData.center.set(center); massData.center.addLocal(s); // Inertia tensor relative to the local origin (point s) massData.I = I*density; // Shift to center of mass then to original body origin. massData.I += massData.mass*(Vec2.dot(massData.center, massData.center)); }
public override void computeMass(MassData massData, float density) { massData.mass = 0.0f; massData.center.set(m_vertex1); massData.center.addLocal(m_vertex2); massData.center.mulLocal(0.5f); massData.I = 0.0f; }
public override void computeMass(MassData massData, float density) { massData.mass = 0.0f; massData.center.setZero(); massData.I = 0.0f; }
/** * Copies from the given mass data * * @param md * mass data to copy from */ public MassData(MassData md) { mass = md.mass; I = md.I; center = md.center.clone(); }
public void set(MassData md) { mass = md.mass; I = md.I; center.set(md.center); }