public override void GetMassProperties(PrimitiveProperties primitiveProperties, out float mass, out Vector3 centerOfMass, out Matrix inertiaTensor) { if (primitiveProperties.MassType == PrimitiveProperties.MassTypeEnum.Mass) { mass = primitiveProperties.MassOrDensity; } else { if (primitiveProperties.MassDistribution == PrimitiveProperties.MassDistributionEnum.Solid) mass = GetVolume() * primitiveProperties.MassOrDensity; else mass = GetSurfaceArea() * primitiveProperties.MassOrDensity; } centerOfMass = this.transform.Position; float Ixx; if (primitiveProperties.MassDistribution == PrimitiveProperties.MassDistributionEnum.Solid) Ixx = 0.4f * mass * radius; else Ixx = (2.0f / 3.0f) * mass * radius; inertiaTensor = Matrix.Identity; inertiaTensor.M11 = inertiaTensor.M22 = inertiaTensor.M33 = Ixx; // Transfer of axe theorem inertiaTensor.M11 = inertiaTensor.M11 + mass * (centerOfMass.Y * centerOfMass.Y + centerOfMass.Z * centerOfMass.Z); inertiaTensor.M22 = inertiaTensor.M22 + mass * (centerOfMass.Z * centerOfMass.Z + centerOfMass.X * centerOfMass.X); inertiaTensor.M33 = inertiaTensor.M33 + mass * (centerOfMass.X * centerOfMass.X + centerOfMass.Y * centerOfMass.Y); inertiaTensor.M12 = inertiaTensor.M21 = inertiaTensor.M12 - mass * centerOfMass.X * centerOfMass.Y; inertiaTensor.M23 = inertiaTensor.M32 = inertiaTensor.M23 - mass * centerOfMass.Y * centerOfMass.Z; inertiaTensor.M31 = inertiaTensor.M13 = inertiaTensor.M31 - mass * centerOfMass.Z * centerOfMass.X; }
/// <summary> /// GetMassPropertiees /// </summary> /// <param name="primitiveProperties"></param> /// <param name="mass"></param> /// <param name="centerOfMass"></param> /// <param name="inertiaTensor"></param> public override void GetMassProperties(PrimitiveProperties primitiveProperties, out float mass, out Vector3 centerOfMass, out Matrix4 inertiaTensor) { if (primitiveProperties.MassType == PrimitiveProperties.MassTypeEnum.Mass) { mass = primitiveProperties.MassOrDensity; } else { if (primitiveProperties.MassDistribution == PrimitiveProperties.MassDistributionEnum.Solid) { mass = GetVolume() * primitiveProperties.MassOrDensity; } else { mass = GetSurfaceArea() * primitiveProperties.MassOrDensity; } } centerOfMass = transform.Position + 0.5f * length * transform.Orientation.Backward(); // todo check solid/shell // first cylinder float cylinderMass = mass * MathHelper.Pi * radius * radius * length / GetVolume(); float Ixx = 0.5f * cylinderMass * radius * radius; float Iyy = 0.25f * cylinderMass * radius * radius + (1.0f / 12.0f) * cylinderMass * length * length; float Izz = Iyy; // add ends float endMass = mass - cylinderMass; Ixx += 0.4f * endMass * radius * radius; Iyy += 0.4f * endMass * radius * radius + endMass * (0.5f * length) * (0.5f * length); Izz += 0.4f * endMass * radius * radius + endMass * (0.5f * length) * (0.5f * length); inertiaTensor = Matrix4.Identity; inertiaTensor.M11 = Ixx; inertiaTensor.M22 = Iyy; inertiaTensor.M33 = Izz; // transform - e.g. see p664 of Physics-Based Animation // todo is the order correct here? Does it matter? // Calculate the tensor in a frame at the CoM, but aligned with the world axes inertiaTensor = transform.Orientation * inertiaTensor * Matrix4.Transpose(transform.Orientation); // Transfer of axe theorem inertiaTensor.M11 = inertiaTensor.M11 + mass * (centerOfMass.Y * centerOfMass.Y + centerOfMass.Z * centerOfMass.Z); inertiaTensor.M22 = inertiaTensor.M22 + mass * (centerOfMass.Z * centerOfMass.Z + centerOfMass.X * centerOfMass.X); inertiaTensor.M33 = inertiaTensor.M33 + mass * (centerOfMass.X * centerOfMass.X + centerOfMass.Y * centerOfMass.Y); inertiaTensor.M12 = inertiaTensor.M21 = inertiaTensor.M12 - mass * centerOfMass.X * centerOfMass.Y; inertiaTensor.M23 = inertiaTensor.M32 = inertiaTensor.M23 - mass * centerOfMass.Y * centerOfMass.Z; inertiaTensor.M31 = inertiaTensor.M13 = inertiaTensor.M31 - mass * centerOfMass.Z * centerOfMass.X; }
protected Vector3 SetMass(float mass) { PrimitiveProperties primitiveProperties = new PrimitiveProperties(PrimitiveProperties.MassDistributionEnum.Solid, PrimitiveProperties.MassTypeEnum.Density, mass); float junk; Vector3 com; Matrix it, itCoM; collision.GetMassProperties(primitiveProperties, out junk, out com, out it, out itCoM); body.BodyInertia = itCoM; body.Mass = junk; return com; }
public override void GetMassProperties(PrimitiveProperties primitiveProperties, out float mass, out Vector3 centerOfMass, out Matrix inertiaTensor) { if (primitiveProperties.MassType == PrimitiveProperties.MassTypeEnum.Mass) { mass = primitiveProperties.MassOrDensity; } else { if (primitiveProperties.MassDistribution == PrimitiveProperties.MassDistributionEnum.Solid) mass = GetVolume() * primitiveProperties.MassOrDensity; else mass = GetSurfaceArea() * primitiveProperties.MassOrDensity; } centerOfMass = transform.Position + 0.5f * length * transform.Orientation.Backward; /// todo check solid/shell // first cylinder float cylinderMass = mass * MathHelper.Pi * radius * radius * length / GetVolume(); float Ixx = 0.5f * cylinderMass * radius * radius; float Iyy = 0.25f * cylinderMass * radius * radius + (1.0f / 12.0f) * cylinderMass * length * length; float Izz = Iyy; // add ends float endMass = mass - cylinderMass; Ixx += 0.2f * endMass * radius * radius; Iyy += 0.4f * endMass * radius * radius + endMass * (0.5f * length) * (0.5f * length); Izz += 0.4f * endMass * radius * radius + endMass * (0.5f * length) * (0.5f * length); inertiaTensor = Matrix.Identity; inertiaTensor.M11 = Ixx; inertiaTensor.M22 = Iyy; inertiaTensor.M33 = Izz; // transform - e.g. see p664 of Physics-Based Animation // todo is the order correct here? Does it matter? // Calculate the tensor in a frame at the CoM, but aligned with the world axes inertiaTensor = transform.Orientation * inertiaTensor * Matrix.Transpose(transform.Orientation); // Transfer of axe theorem inertiaTensor.M11 = inertiaTensor.M11 + mass * (centerOfMass.Y * centerOfMass.Y + centerOfMass.Z * centerOfMass.Z); inertiaTensor.M22 = inertiaTensor.M22 + mass * (centerOfMass.Z * centerOfMass.Z + centerOfMass.X * centerOfMass.X); inertiaTensor.M33 = inertiaTensor.M33 + mass * (centerOfMass.X * centerOfMass.X + centerOfMass.Y * centerOfMass.Y); inertiaTensor.M12 = inertiaTensor.M21 = inertiaTensor.M12 - mass * centerOfMass.X * centerOfMass.Y; inertiaTensor.M23 = inertiaTensor.M32 = inertiaTensor.M23 - mass * centerOfMass.Y * centerOfMass.Z; inertiaTensor.M31 = inertiaTensor.M13 = inertiaTensor.M31 - mass * centerOfMass.Z * centerOfMass.X; }
/// <summary> /// GetMassProperties /// </summary> /// <param name="primitiveProperties"></param> /// <param name="mass"></param> /// <param name="centerOfMass"></param> /// <param name="inertiaTensor"></param> public override void GetMassProperties(PrimitiveProperties primitiveProperties, out float mass, out Vector3 centerOfMass, out Matrix inertiaTensor) { if (primitiveProperties.MassType == PrimitiveProperties.MassTypeEnum.Mass) { mass = primitiveProperties.MassOrDensity; } else { if (primitiveProperties.MassDistribution == PrimitiveProperties.MassDistributionEnum.Solid) { mass = GetVolume() * primitiveProperties.MassOrDensity; } else { mass = GetSurfaceArea() * primitiveProperties.MassOrDensity; } } centerOfMass = GetCentre(); // First calculate inertia in local frame, then shift to origin Vector3 sides = sideLengths; // todo check solid/shell float Ixx = (1.0f / 12.0f) * mass * (sides.Y * sides.Y + sides.Z * sides.Z); float Iyy = (1.0f / 12.0f) * mass * (sides.X * sides.X + sides.Z * sides.Z); float Izz = (1.0f / 12.0f) * mass * (sides.X * sides.X + sides.Y * sides.Y); inertiaTensor = Matrix.Identity; inertiaTensor.M11 = Ixx; inertiaTensor.M22 = Iyy; inertiaTensor.M33 = Izz; // transform - e.g. see p664 of Physics-Based Animation // todo is the order correct here? Does it matter? // Calculate the tensor in a frame at the CoM, but aligned with the world axes inertiaTensor = Matrix.Transpose(transform.Orientation) * inertiaTensor * transform.Orientation; // Transfer of axe theorem inertiaTensor.M11 = inertiaTensor.M11 + mass * (centerOfMass.Y * centerOfMass.Y + centerOfMass.Z * centerOfMass.Z); inertiaTensor.M22 = inertiaTensor.M22 + mass * (centerOfMass.Z * centerOfMass.Z + centerOfMass.X * centerOfMass.X); inertiaTensor.M33 = inertiaTensor.M33 + mass * (centerOfMass.X * centerOfMass.X + centerOfMass.Y * centerOfMass.Y); inertiaTensor.M12 = inertiaTensor.M21 = inertiaTensor.M12 - mass * centerOfMass.X * centerOfMass.Y; inertiaTensor.M23 = inertiaTensor.M32 = inertiaTensor.M23 - mass * centerOfMass.Y * centerOfMass.Z; inertiaTensor.M31 = inertiaTensor.M13 = inertiaTensor.M31 - mass * centerOfMass.Z * centerOfMass.X; }
public override void GetMassProperties(PrimitiveProperties primitiveProperties, out float mass, out Vector3 centerOfMass, out Matrix inertiaTensor) { if (primitiveProperties.MassType == PrimitiveProperties.MassTypeEnum.Mass) { mass = primitiveProperties.MassOrDensity; } else { if (primitiveProperties.MassDistribution == PrimitiveProperties.MassDistributionEnum.Solid) { mass = GetVolume() * primitiveProperties.MassOrDensity; } else { mass = GetSurfaceArea() * primitiveProperties.MassOrDensity; } } centerOfMass = this.transform.Position; float Ixx; if (primitiveProperties.MassDistribution == PrimitiveProperties.MassDistributionEnum.Solid) { Ixx = 0.4f * mass * radius; } else { Ixx = (2.0f / 3.0f) * mass * radius; } inertiaTensor = Matrix.Identity; inertiaTensor.M11 = inertiaTensor.M22 = inertiaTensor.M33 = Ixx; // Transfer of axe theorem inertiaTensor.M11 = inertiaTensor.M11 + mass * (centerOfMass.Y * centerOfMass.Y + centerOfMass.Z * centerOfMass.Z); inertiaTensor.M22 = inertiaTensor.M22 + mass * (centerOfMass.Z * centerOfMass.Z + centerOfMass.X * centerOfMass.X); inertiaTensor.M33 = inertiaTensor.M33 + mass * (centerOfMass.X * centerOfMass.X + centerOfMass.Y * centerOfMass.Y); inertiaTensor.M12 = inertiaTensor.M21 = inertiaTensor.M12 - mass * centerOfMass.X * centerOfMass.Y; inertiaTensor.M23 = inertiaTensor.M32 = inertiaTensor.M23 - mass * centerOfMass.Y * centerOfMass.Z; inertiaTensor.M31 = inertiaTensor.M13 = inertiaTensor.M31 - mass * centerOfMass.Z * centerOfMass.X; }
private Vector3 SetMass(float mass) { PrimitiveProperties primitiveProperties = new PrimitiveProperties( PrimitiveProperties.MassDistributionEnum.Solid, PrimitiveProperties.MassTypeEnum.Mass, mass); float junk = 0.0f; Vector3 com = Vector3.Zero; Matrix it = Matrix.Identity; Matrix itCom = Matrix.Identity; if (m_Skin != null) m_Skin.GetMassProperties(primitiveProperties, out junk, out com, out it, out itCom); if (m_Body != null) { m_Body.BodyInertia = itCom; m_Body.Mass = junk; } return com; }
/// <summary> /// Helper to calculate the combined mass, centre of mass, and /// inertia tensor about the origin and the CoM (for the local /// primitives) primitiveProperties is an array of properties - /// must be the same number as there are primitives /// </summary> /// <param name="primitiveProperties"></param> /// <param name="mass"></param> /// <param name="centerOfMass"></param> /// <param name="inertiaTensor"></param> /// <param name="inertiaTensorCoM"></param> public void GetMassProperties(PrimitiveProperties[] primitiveProperties, out float mass, out Vector3 centerOfMass, out Matrix inertiaTensor, out Matrix inertiaTensorCoM) { mass = 0.0f; centerOfMass = Vector3.Zero; inertiaTensor = Matrix.Identity; inertiaTensorCoM = Matrix.Identity; for (int prim = primitivesLocal.Count; prim-- != 0; ) { float m; Vector3 com; Matrix it; primitivesLocal[prim].GetMassProperties(primitiveProperties[prim], out m, out com, out it); mass += m; centerOfMass += m * com; inertiaTensor += it; } if (mass > 0.0f) { centerOfMass /= mass; // Transfer of axe theorem inertiaTensorCoM.M11 = inertiaTensor.M11 - mass * (centerOfMass.Y * centerOfMass.Y + centerOfMass.Z * centerOfMass.Z); inertiaTensorCoM.M22 = inertiaTensor.M22 - mass * (centerOfMass.Z * centerOfMass.Z + centerOfMass.X * centerOfMass.X); inertiaTensorCoM.M33 = inertiaTensor.M33 - mass * (centerOfMass.X * centerOfMass.X + centerOfMass.Y * centerOfMass.Y); // CHECK THIS. seems strange for me inertiaTensorCoM.M12 = inertiaTensorCoM.M21 = inertiaTensor.M12 + mass * centerOfMass.X * centerOfMass.Y; inertiaTensorCoM.M23 = inertiaTensorCoM.M32 = inertiaTensor.M23 + mass * centerOfMass.Y * centerOfMass.Z; inertiaTensorCoM.M31 = inertiaTensorCoM.M13 = inertiaTensor.M31 + mass * centerOfMass.Z * centerOfMass.X; } }
/// <summary> /// Helper to calculate the combined mass, centre of mass, and /// inertia tensor about the origin and the CoM (for the local /// primitives) primitiveProperties indicates the properties used /// for all primitives - so the mass is the total mass /// </summary> /// <param name="primitiveProperties"></param> /// <param name="mass"></param> /// <param name="centerOfMass"></param> /// <param name="inertiaTensor"></param> /// <param name="inertiaTensorCoM"></param> public void GetMassProperties(PrimitiveProperties primitiveProperties, out float mass, out Vector3 centerOfMass, out Matrix inertiaTensor, out Matrix inertiaTensorCoM) { mass = 0.0f; centerOfMass = Vector3.Zero; inertiaTensor = new Matrix(); float totalWeighting = 0.0f; if (primitiveProperties.MassType == PrimitiveProperties.MassTypeEnum.Mass) { for (int prim = primitivesLocal.Count; prim-- != 0; ) { if (primitiveProperties.MassDistribution == PrimitiveProperties.MassDistributionEnum.Solid) totalWeighting += primitivesLocal[prim].GetVolume(); else totalWeighting += primitivesLocal[prim].GetSurfaceArea(); } } for (int prim = primitivesLocal.Count; prim-- != 0; ) { float m; Vector3 com; Matrix it; PrimitiveProperties primProperties = primitiveProperties; if (primitiveProperties.MassType == PrimitiveProperties.MassTypeEnum.Mass) { float weighting = 0.0f; if (primitiveProperties.MassDistribution == PrimitiveProperties.MassDistributionEnum.Solid) weighting = primitivesLocal[prim].GetVolume(); else weighting = primitivesLocal[prim].GetSurfaceArea(); primProperties.MassOrDensity *= weighting / totalWeighting; } primitivesLocal[prim].GetMassProperties(primProperties, out m, out com, out it); mass += m; centerOfMass += m * com; inertiaTensor += it; } inertiaTensorCoM = Matrix.Identity; if (mass > 0.0f) { centerOfMass /= mass; // Transfer of axe theorem inertiaTensorCoM.M11 = inertiaTensor.M11 - mass * (centerOfMass.Y * centerOfMass.Y + centerOfMass.Z * centerOfMass.Z); inertiaTensorCoM.M22 = inertiaTensor.M22 - mass * (centerOfMass.Z * centerOfMass.Z + centerOfMass.X * centerOfMass.X); inertiaTensorCoM.M33 = inertiaTensor.M33 - mass * (centerOfMass.X * centerOfMass.X + centerOfMass.Y * centerOfMass.Y); // CHECK THIS. seems strange for me inertiaTensorCoM.M12 = inertiaTensorCoM.M21 = inertiaTensor.M12 + mass * centerOfMass.X * centerOfMass.Y; inertiaTensorCoM.M23 = inertiaTensorCoM.M32 = inertiaTensor.M23 + mass * centerOfMass.Y * centerOfMass.Z; inertiaTensorCoM.M31 = inertiaTensorCoM.M13 = inertiaTensor.M31 + mass * centerOfMass.Z * centerOfMass.X; } if (primitiveProperties.MassType == PrimitiveProperties.MassTypeEnum.Mass) mass = primitiveProperties.MassOrDensity; }
public override void GetMassProperties(PrimitiveProperties primitiveProperties, out float mass, out Vector3 centerOfMass, out Matrix inertiaTensor) { mass = 0.0f; centerOfMass = Vector3.Zero; inertiaTensor = Matrix.Identity; }
private void SetupProperty(Vector3 position, Matrix orientation ) { PrimitiveProperties primitiveProp = new PrimitiveProperties( PrimitiveProperties.MassDistributionEnum.Solid, PrimitiveProperties.MassTypeEnum.Density, mass); float outMass; Vector3 outCenterOfMass; Matrix outInertiaTensor; Matrix outInertiaTensorCoM; CollisionSkin.GetMassProperties( primitiveProp, out outMass, out outCenterOfMass, out outInertiaTensor, out outInertiaTensorCoM); CollisionSkin.ApplyLocalTransform( new Transform(-outCenterOfMass, orientation)); this.centerOfMass = outCenterOfMass; body.BodyInertia = outInertiaTensorCoM; body.Mass = outMass; body.MoveTo(position, orientation); body.CollisionSkin = CollisionSkin; body.EnableBody(); }
/// <summary> /// Returns the mass, center of mass, and intertia tensor around the origin /// </summary> /// <param name="primitiveProperties"></param> /// <param name="mass"></param> /// <param name="centerOfMass"></param> /// <param name="inertiaTensor"></param> public abstract void GetMassProperties(PrimitiveProperties primitiveProperties, out float mass, out Vector3 centerOfMass, out Matrix4 inertiaTensor);
private Vector3 ApplyMass(float mass) { float junk; Vector3 com; Microsoft.Xna.Framework.Matrix it; Microsoft.Xna.Framework.Matrix itCoM; var primitiveProperties = new PrimitiveProperties(PrimitiveProperties.MassDistributionEnum.Solid, PrimitiveProperties.MassTypeEnum.Mass, mass); collisionSkin.GetMassProperties(primitiveProperties, out junk, out com, out it, out itCoM); PhysicsBody.BodyInertia = itCoM; PhysicsBody.Mass = junk; return com; }
private static Vector3 SetMass(float mass, CollisionSkin skin, Body body) { PrimitiveProperties primitiveProperties = new PrimitiveProperties( PrimitiveProperties.MassDistributionEnum.Solid, PrimitiveProperties.MassTypeEnum.Mass, mass); float junk; Vector3 com; Matrix4 it; Matrix4 itCoM; skin.GetMassProperties(primitiveProperties, out junk, out com, out it, out itCoM); body.BodyInertia = itCoM; body.Mass = junk; return com; }
private Vector3 SetMass(float mass) { PrimitiveProperties primitiveProperties = new PrimitiveProperties( PrimitiveProperties.MassDistributionEnum.Solid, PrimitiveProperties.MassTypeEnum.Mass, mass); float junk; Vector3 com; Matrix it; Matrix itCoM; Skin.GetMassProperties(primitiveProperties, out junk, out com, out it, out itCoM); Body.BodyInertia = itCoM; Body.Mass = junk; return com; }
public override void GetMassProperties(PrimitiveProperties primitiveProperties, out float mass, out Vector3 centerOfMass, out Matrix inertiaTensor) { if (primitiveProperties.MassType == PrimitiveProperties.MassTypeEnum.Mass) { mass = primitiveProperties.MassOrDensity; } else { if (primitiveProperties.MassDistribution == PrimitiveProperties.MassDistributionEnum.Solid) mass = GetVolume() * primitiveProperties.MassOrDensity; else mass = GetSurfaceArea() * primitiveProperties.MassOrDensity; } centerOfMass = GetCentre(); // First calculate inertia in local frame, then shift to origin Vector3 sides = sideLengths; // todo check solid/shell float Ixx = (1.0f / 12.0f) * mass * (sides.Y * sides.Y + sides.Z * sides.Z); float Iyy = (1.0f / 12.0f) * mass * (sides.X * sides.X + sides.Z * sides.Z); float Izz = (1.0f / 12.0f) * mass * (sides.X * sides.X + sides.Y * sides.Y); inertiaTensor = Matrix.Identity; inertiaTensor.M11 = Ixx; inertiaTensor.M22 = Iyy; inertiaTensor.M33 = Izz; // transform - e.g. see p664 of Physics-Based Animation // todo is the order correct here? Does it matter? // Calculate the tensor in a frame at the CoM, but aligned with the world axes inertiaTensor = Matrix.Transpose(transform.Orientation) * inertiaTensor * transform.Orientation; // Transfer of axe theorem inertiaTensor.M11 = inertiaTensor.M11 + mass * (centerOfMass.Y * centerOfMass.Y + centerOfMass.Z * centerOfMass.Z); inertiaTensor.M22 = inertiaTensor.M22 + mass * (centerOfMass.Z * centerOfMass.Z + centerOfMass.X * centerOfMass.X); inertiaTensor.M33 = inertiaTensor.M33 + mass * (centerOfMass.X * centerOfMass.X + centerOfMass.Y * centerOfMass.Y); inertiaTensor.M12 = inertiaTensor.M21 = inertiaTensor.M12 - mass * centerOfMass.X * centerOfMass.Y; inertiaTensor.M23 = inertiaTensor.M32 = inertiaTensor.M23 - mass * centerOfMass.Y * centerOfMass.Z; inertiaTensor.M31 = inertiaTensor.M13 = inertiaTensor.M31 - mass * centerOfMass.Z * centerOfMass.X; }
/// <summary> /// Returns the mass, center of mass, and intertia tensor around the origin /// </summary> /// <param name="primitiveProperties"></param> /// <param name="mass"></param> /// <param name="centerOfMass"></param> /// <param name="inertiaTensor"></param> public abstract void GetMassProperties(PrimitiveProperties primitiveProperties, out float mass, out Vector3 centerOfMass, out Matrix4 inertiaTensor);
public override void GetMassProperties(PrimitiveProperties primitiveProperties, out float mass, out Vector3 centerOfMass, out Matrix inertiaTensor) { mass = 0.0f; centerOfMass = Vector3.Zero; inertiaTensor = Matrix.Identity; }
/// <summary> /// Sets the mass of the body. Based on the objects properties we can determine it's other physical properties, like inertia, and the update the /// bodies properties accordingly. /// </summary> /// <param name="mass">The new mass we want applied to the body.</param> /// <returns>The center of mass for the body after the mass change.</returns> public Vector3 SetMass(float mass) { PrimitiveProperties primitiveProperties = new PrimitiveProperties( PrimitiveProperties.MassDistributionEnum.Solid, PrimitiveProperties.MassTypeEnum.Density, mass); float bodyMass; Vector3 centerOfMass; Matrix inertiaTensor; Matrix inertiaTensorCoM; CollisionSkin.GetMassProperties(primitiveProperties, out bodyMass, out centerOfMass, out inertiaTensor, out inertiaTensorCoM); Body.BodyInertia = inertiaTensorCoM; Body.Mass = bodyMass; return centerOfMass; }