/// <summary> /// This is a replacement for the stock API Property "vessel.MOI", which seems buggy when used /// with "control from here" on parts other than the default control part. /// <br/> /// Right now the stock Moment of Inertia Property returns values in inconsistent reference frames that /// don't make sense when used with "control from here". (It doesn't merely rotate the reference frame, as one /// would expect "control from here" to do.) /// </summary> /// TODO: Check this again after each KSP stock release to see if it's been changed or not. public Vector3 FindMoI() { var tensor = Matrix4x4.zero; Matrix4x4 partTensor = Matrix4x4.identity; Matrix4x4 inertiaMatrix = Matrix4x4.identity; Matrix4x4 productMatrix = Matrix4x4.identity; foreach (var part in Vessel.Parts) { if (part.rb != null) { KSPUtil.ToDiagonalMatrix2(part.rb.inertiaTensor, ref partTensor); Quaternion rot = Quaternion.Inverse(vesselRotation) * part.transform.rotation * part.rb.inertiaTensorRotation; Quaternion inv = Quaternion.Inverse(rot); Matrix4x4 rotMatrix = Matrix4x4.TRS(Vector3.zero, rot, Vector3.one); Matrix4x4 invMatrix = Matrix4x4.TRS(Vector3.zero, inv, Vector3.one); // add the part inertiaTensor to the ship inertiaTensor KSPUtil.Add(ref tensor, rotMatrix * partTensor * invMatrix); Vector3 position = vesselTransform.InverseTransformDirection(part.rb.position - centerOfMass); // add the part mass to the ship inertiaTensor KSPUtil.ToDiagonalMatrix2(part.rb.mass * position.sqrMagnitude, ref inertiaMatrix); KSPUtil.Add(ref tensor, inertiaMatrix); // add the part distance offset to the ship inertiaTensor OuterProduct2(position, -part.rb.mass * position, ref productMatrix); KSPUtil.Add(ref tensor, productMatrix); } } return(KSPUtil.Diag(tensor)); }