public static double CalculateMassInertia(Shape shape, out JVector centerOfMass, out JMatrix inertia) { double mass = 0.0f; centerOfMass = JVector.Zero; inertia = JMatrix.Zero; if (shape is Multishape) throw new ArgumentException("Can't calculate inertia of multishapes.", "shape"); // build a triangle hull around the shape List<JVector> hullTriangles = new List<JVector>(); shape.MakeHull(ref hullTriangles, 3); // create inertia of tetrahedron with vertices at // (0,0,0) (1,0,0) (0,1,0) (0,0,1) double a = 1.0f / 60.0f, b = 1.0f / 120.0f; JMatrix C = new JMatrix(a, b, b, b, a, b, b, b, a); for (int i = 0; i < hullTriangles.Count; i += 3) { JVector column0 = hullTriangles[i + 0]; JVector column1 = hullTriangles[i + 1]; JVector column2 = hullTriangles[i + 2]; JMatrix A = new JMatrix(column0.X, column1.X, column2.X, column0.Y, column1.Y, column2.Y, column0.Z, column1.Z, column2.Z); double detA = A.Determinant(); // now transform this canonical tetrahedron to the target tetrahedron // inertia by a linear transformation A JMatrix tetrahedronInertia = JMatrix.Multiply(A * C * JMatrix.Transpose(A), detA); JVector tetrahedronCOM = (1.0f / 4.0f) * (hullTriangles[i + 0] + hullTriangles[i + 1] + hullTriangles[i + 2]); double tetrahedronMass = (1.0f / 6.0f) * detA; inertia += tetrahedronInertia; centerOfMass += tetrahedronMass * tetrahedronCOM; mass += tetrahedronMass; } inertia = JMatrix.Multiply(JMatrix.Identity, inertia.Trace()) - inertia; centerOfMass = centerOfMass * (1.0f / mass); double x = centerOfMass.X; double y = centerOfMass.Y; double z = centerOfMass.Z; // now translate the inertia by the center of mass JMatrix t = new JMatrix( -mass * (y * y + z * z), mass * x * y, mass * x * z, mass * y * x, -mass * (z * z + x * x), mass * y * z, mass * z * x, mass * z * y, -mass * (x * x + y * y)); JMatrix.Add(ref inertia, ref t, out inertia); return mass; }
/// <summary> /// Calculates the inertia of the shape relative to the center of mass. /// </summary> /// <param name="shape"></param> /// <param name="centerOfMass"></param> /// <param name="inertia">Returns the inertia relative to the center of mass, not to the origin</param> /// <returns></returns> #region public static float CalculateMassInertia(Shape shape, out JVector centerOfMass, out JMatrix inertia) public static float CalculateMassInertia(Shape shape, out Vector3 centerOfMass, out Matrix3x3 inertia) { float mass = 0.0f; centerOfMass = Vector3.zero; inertia = Matrix3x3.Zero; if (shape is Multishape) { throw new ArgumentException("Can't calculate inertia of multishapes.", "shape"); } // build a triangle hull around the shape List <Vector3> hullTriangles = new List <Vector3>(); shape.MakeHull(ref hullTriangles, 3); // create inertia of tetrahedron with vertices at // (0,0,0) (1,0,0) (0,1,0) (0,0,1) float a = 1.0f / 60.0f, b = 1.0f / 120.0f; Matrix3x3 C = new Matrix3x3(a, b, b, b, a, b, b, b, a); for (int i = 0; i < hullTriangles.Count; i += 3) { Vector3 column0 = hullTriangles[i + 0]; Vector3 column1 = hullTriangles[i + 1]; Vector3 column2 = hullTriangles[i + 2]; Matrix3x3 A = new Matrix3x3(column0.x, column1.x, column2.x, column0.y, column1.y, column2.y, column0.z, column1.z, column2.z); float detA = A.Determinant(); // now transform this canonical tetrahedron to the target tetrahedron // inertia by a linear transformation A Matrix3x3 tetrahedronInertia = Matrix3x3.Multiply(A * C * Matrix3x3.Transpose(A), detA); Vector3 tetrahedronCOM = (1.0f / 4.0f) * (hullTriangles[i + 0] + hullTriangles[i + 1] + hullTriangles[i + 2]); float tetrahedronMass = (1.0f / 6.0f) * detA; inertia += tetrahedronInertia; centerOfMass += tetrahedronMass * tetrahedronCOM; mass += tetrahedronMass; } inertia = Matrix3x3.Multiply(Matrix3x3.Identity, inertia.Trace()) - inertia; centerOfMass = centerOfMass * (1.0f / mass); float x = centerOfMass.x; float y = centerOfMass.y; float z = centerOfMass.z; // now translate the inertia by the center of mass Matrix3x3 t = new Matrix3x3( -mass * (y * y + z * z), mass * x * y, mass * x * z, mass * y * x, -mass * (z * z + x * x), mass * y * z, mass * z * x, mass * z * y, -mass * (x * x + y * y)); Matrix3x3.Add(ref inertia, ref t, out inertia); return(mass); }
/// <summary> /// Calculates the inertia of the shape relative to the center of mass. /// </summary> /// <param name="shape"></param> /// <param name="centerOfMass"></param> /// <param name="inertia">Returns the inertia relative to the center of mass, not to the origin</param> /// <returns></returns> #region public static float CalculateMassInertia(Shape shape, out JVector centerOfMass, out JMatrix inertia) public static float CalculateMassInertia(Shape shape, out JVector centerOfMass, out JMatrix inertia) { float mass = 0.0f; centerOfMass = JVector.Zero; inertia = JMatrix.Zero; if (shape is Multishape) { throw new ArgumentException("Can't calculate inertia of multishapes.", "shape"); } // build a triangle hull around the shape List <JVector> hullTriangles = new List <JVector>(); shape.MakeHull(ref hullTriangles, 3); // create inertia of tetrahedron with vertices at // (0,0,0) (1,0,0) (0,1,0) (0,0,1) float a = 1.0f / 60.0f, b = 1.0f / 120.0f; JMatrix C = new JMatrix(a, b, b, b, a, b, b, b, a); for (int i = 0; i < hullTriangles.Count; i += 3) { JVector column0 = hullTriangles[i + 0]; JVector column1 = hullTriangles[i + 1]; JVector column2 = hullTriangles[i + 2]; JMatrix A = new JMatrix(column0.X, column1.X, column2.X, column0.Y, column1.Y, column2.Y, column0.Z, column1.Z, column2.Z); float detA = A.Determinant(); // now transform this canonical tetrahedron to the target tetrahedron // inertia by a linear transformation A JMatrix tetrahedronInertia = JMatrix.Multiply(A * C * JMatrix.Transpose(A), detA); JVector tetrahedronCOM = (1.0f / 4.0f) * (hullTriangles[i + 0] + hullTriangles[i + 1] + hullTriangles[i + 2]); float tetrahedronMass = (1.0f / 6.0f) * detA; inertia += tetrahedronInertia; centerOfMass += tetrahedronMass * tetrahedronCOM; mass += tetrahedronMass; } inertia = JMatrix.Multiply(JMatrix.Identity, inertia.Trace()) - inertia; centerOfMass = centerOfMass * (1.0f / mass); float x = centerOfMass.X; float y = centerOfMass.Y; float z = centerOfMass.Z; // now translate the inertia by the center of mass JMatrix t = new JMatrix( -mass * (y * y + z * z), mass * x * y, mass * x * z, mass * y * x, -mass * (z * z + x * x), mass * y * z, mass * z * x, mass * z * y, -mass * (x * x + y * y)); JMatrix.Add(ref inertia, ref t, out inertia); return(mass); }